Skip to content

Commit

Permalink
babel + typescript (#240)
Browse files Browse the repository at this point in the history
* add tsconfig

* update package libs

* rename everything to *.ts

* add jest types

* tell eslint about typescript

* fix issue where eslint doesnt resolve ty pescript

* eslint lets you have unused _vars

* the fun part of typescript migration

* fix build

* have jest ask babel to transpile typescript before running tests

* no tsx files

* pin eslint typescript import resolver module

* remove support for node 15

* allow esmodules
  • Loading branch information
philihp authored Jul 15, 2022
1 parent 4939717 commit 8e46c2a
Show file tree
Hide file tree
Showing 51 changed files with 199 additions and 78 deletions.
5 changes: 4 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"presets": ["@babel/preset-env"]
"presets": [
["@babel/preset-env", {"targets": {"node": "current"}}],
"@babel/preset-typescript"
]
}
5 changes: 3 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,13 @@ jobs:
matrix:
node-version:
- 11.x # deprecated
- 12.x # maintainence ends 2022-04-30
- 12.x # deprecated
- 13.x # deprecated
- 14.x # maintainence ends 2023-04-30
- 15.x # deprecated
- 16.x # maintainence ends 2024-04-30
- 17.x # maintainence ends 2022-06-01
- 17.x # deprecated
- 18.x # maintainence ends 2025-04-30
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
Expand Down
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ benchmark/*
.husky/
CONTRIBUTING.md
.editorconfig
tsconfig.json
63 changes: 59 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "2.1.0",
"description": "Weng-Lin Bayesian approximation method for online skill-ranking.",
"scripts": {
"build": "babel src -d dist",
"build": "babel src --out-dir dist --extensions \".js,.ts\" --source-maps inline",
"lint": "eslint src",
"prepare": "husky install && npm run build",
"release": "np",
Expand Down Expand Up @@ -31,9 +31,16 @@
"@babel/cli": "7.18.6",
"@babel/core": "7.18.6",
"@babel/preset-env": "7.18.6",
"@babel/preset-typescript": "7.16.7",
"@babel/register": "7.18.6",
"@philihp/eslint-config": "5.1.2",
"husky": "8.0.1"
"@types/jest": "27.4.1",
"@typescript-eslint/eslint-plugin": "5.18.0",
"@typescript-eslint/parser": "5.18.0",
"eslint": "8.13.0",
"eslint-import-resolver-typescript": "2.7.1",
"husky": "7.0.4",
"typescript": "4.6.3"
},
"lint-staged": {
"src/**/*.{js,jsx,json}": [
Expand All @@ -51,12 +58,60 @@
]
},
"eslintConfig": {
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": [
"@typescript-eslint"
],
"extends": [
"@philihp",
"plugin:jest/all"
]
"plugin:jest/all",
"plugin:@typescript-eslint/recommended"
],
"settings": {
"import/extensions": [
".js",
".ts"
],
"import/parsers": {
"@typescript-eslint/parser": [
".ts"
]
},
"import/resolver": {
"typescript": {},
"node": {
"extensions": [
".js",
".ts"
]
}
}
},
"rules": {
"import/extensions": [
"error",
"ignorePackages",
{
"js": "never",
"ts": "never"
}
],
"@typescript-eslint/no-unused-vars": [
"warn",
{
"argsIgnorePattern": "^_",
"varsIgnorePattern": "^_",
"caughtErrorsIgnorePattern": "^_"
}
]
}
},
"dependencies": {
"@types/gaussian": "1.2.0",
"@types/ramda": "0.28.12",
"gaussian": "1.2.0",
"ramda": "0.28.0",
"sort-unwind": "1.0.0"
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
15 changes: 0 additions & 15 deletions src/constants.js

This file was deleted.

18 changes: 18 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Options } from './types'

export const z = (options: Options) => options?.z ?? 3
export const mu = (options: Options) => options?.mu ?? 25
export const sigma = (options: Options) =>
options?.sigma ?? mu(options) / z(options)

export const epsilon = (options: Options) => options?.epsilon ?? 0.0001
export const beta = (options: Options) => options?.beta ?? sigma(options) / 2
export const betaSq = (options: Options) => beta(options) ** 2

export default (options: Options) => ({
EPSILON: epsilon(options),
TWOBETASQ: 2 * betaSq(options),
BETA: beta(options),
BETASQ: betaSq(options),
Z: z(options),
})
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import util, { score } from '../util'
import constants from '../constants'
import { Rating, Options } from '../types'

export default (game, options = {}) => {
export default (game: Rating[][], options: Options = {}) => {
const { TWOBETASQ, EPSILON } = constants(options)
const { teamRating, gamma } = util(options)
const teamRatings = teamRating(game)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { zip } from 'ramda'
import util, { score, ladderPairs } from '../util'
import constants from '../constants'
import { Rating } from '../types'

export default (game, options = {}) => {
export default (game: Rating[][], options = {}) => {
const { TWOBETASQ, EPSILON } = constants(options)
const { teamRating, gamma } = util(options)

Expand Down
File renamed without changes.
3 changes: 2 additions & 1 deletion src/models/plackett-luce.js → src/models/plackett-luce.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import util, { utilSumQ, utilA } from '../util'
import constants from '../constants'
import { Rating, Options } from '../types'

export default (game, options = {}) => {
export default (game: Rating[][], options: Options = {}) => {
const { EPSILON } = constants(options)
const { utilC, teamRating, gamma } = util(options)
const teamRatings = teamRating(game)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import util from '../util'
import constants from '../constants'
import { w, v, vt, wt } from '../statistics'
import { Rating, Options } from '../types'

export default (game, options = {}) => {
export default (game: Rating[][], options: Options = {}) => {
const { TWOBETASQ, EPSILON } = constants(options)
const { teamRating, gamma } = util(options)
const teamRatings = teamRating(game)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { zip } from 'ramda'
import util, { ladderPairs } from '../util'
import { w, v, vt, wt } from '../statistics'
import constants from '../constants'
import { Rating, Options } from '../types'

export default (game, options = {}) => {
export default (game: Rating[][], options: Options = {}) => {
const { TWOBETASQ, EPSILON } = constants(options)
const { teamRating, gamma } = util(options)
const teamRatings = teamRating(game)
Expand Down
8 changes: 0 additions & 8 deletions src/ordinal.js

This file was deleted.

10 changes: 10 additions & 0 deletions src/ordinal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import constants from './constants'
import { Rating, Options } from './types'

const ordinal = (rating: Rating, options: Options = {}) => {
const { sigma, mu } = rating
const { Z } = constants(options)
return mu - Z * sigma
}

export default ordinal
3 changes: 2 additions & 1 deletion src/predict-draw.js → src/predict-draw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { flatten } from 'ramda'
import constants from './constants'
import util, { sum } from './util'
import { phiMajor, phiMajorInverse } from './statistics'
import { Rating, Options } from './types'

const predictWin = (teams, options = {}) => {
const predictWin = (teams: Rating[][], options: Options = {}) => {
const { teamRating } = util(options)
const { BETASQ, BETA } = constants(options)

Expand Down
3 changes: 2 additions & 1 deletion src/predict-win.js → src/predict-win.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import constants from './constants'
import util, { sum } from './util'
import { phiMajor } from './statistics'
import { Rating, Options } from './types'

const predictWin = (teams, options = {}) => {
const predictWin = (teams: Rating[][], options: Options = {}) => {
const { teamRating } = util(options)
const { BETASQ } = constants(options)

Expand Down
5 changes: 3 additions & 2 deletions src/rate.js → src/rate.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { sortBy, identity, range } from 'ramda'
import unwind from 'sort-unwind'
import models from './models'
import { Rating, Options } from './types'

const rate = (teams, options = {}) => {
const rate = (teams: Rating[][], options: Options = {}) => {
const model = models[options.model || 'plackettLuce']
let processedTeams = teams

Expand Down Expand Up @@ -34,7 +35,7 @@ const rate = (teams, options = {}) => {
// preventSigmaIncrease prevents sigma from ever going up which can happen when using a tau value.
// this helps prevent ordinal from ever dropping after winning a game which can feel unfair
if (options.tau && options.preventSigmaIncrease) {
reorderedTeams = reorderedTeams.map((team, i) =>
reorderedTeams = reorderedTeams.map((team: Rating[], i: number) =>
team.map((p, j) => ({
...p,
sigma: Math.min(p.sigma, teams[i][j].sigma),
Expand Down
8 changes: 0 additions & 8 deletions src/rating.js

This file was deleted.

9 changes: 9 additions & 0 deletions src/rating.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { mu as defaultMu, sigma as defaultSigma } from './constants'
import { Rating } from './types'

const rating = (init?: Rating, options = {}) => ({
mu: init?.mu ?? defaultMu(options),
sigma: init?.sigma ?? defaultSigma({ ...options, mu: init?.mu }),
})

export default rating
14 changes: 7 additions & 7 deletions src/statistics.js → src/statistics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import gaussian from 'gaussian'
// use a standard normal distribution - mean of zero, stddev/variance of one
const normal = gaussian(0, 1)

export const phiMajor = (x) => normal.cdf(x)
export const phiMajor = (x: number) => normal.cdf(x)

export const phiMajorInverse = (x) => normal.ppf(x)
export const phiMajorInverse = (x: number) => normal.ppf(x)

export const phiMinor = (x) => normal.pdf(x)
export const phiMinor = (x: number) => normal.pdf(x)

export const v = (x, t) => {
export const v = (x: number, t: number) => {
const xt = x - t
const denom = phiMajor(xt)
return denom < Number.EPSILON ? -xt : phiMinor(xt) / denom
}

export const w = (x, t) => {
export const w = (x: number, t: number) => {
const xt = x - t
const denom = phiMajor(xt)
if (denom < Number.EPSILON) {
Expand All @@ -24,7 +24,7 @@ export const w = (x, t) => {
return v(x, t) * (v(x, t) + xt)
}

export const vt = (x, t) => {
export const vt = (x: number, t: number) => {
const xx = Math.abs(x)
const b = phiMajor(t - xx) - phiMajor(-t - xx)
if (b < 1e-5) {
Expand All @@ -35,7 +35,7 @@ export const vt = (x, t) => {
return (x < 0 ? -a : a) / b
}

export const wt = (x, t) => {
export const wt = (x: number, t: number) => {
const xx = Math.abs(x)
const b = phiMajor(t - xx) - phiMajor(-t - xx)
return b < Number.EPSILON
Expand Down
25 changes: 25 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export type Rating = {
mu: number
sigma: number
}

export type Model =
| 'thurstoneMostellerPart'
| 'thurstoneMostellerFull'
| 'bradleyTerryPart'
| 'bradleyTerryFull'
| 'plackettLuce'

export type Options = {
z?: number
mu?: number
sigma?: number
epsilon?: number
gamma?: number
beta?: number
model?: Model
rank?: number[]
score?: number[]
tau?: number
preventSigmaIncrease?: boolean
}
Loading

0 comments on commit 8e46c2a

Please sign in to comment.