• Stars
    star
    190
  • Rank 199,653 (Top 4 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 4 years ago
  • Updated 3 days ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A faster, open-license alternative to Microsoft TrueSkill

Version Tests Coverage Status Downloads License

Javascript implementation of Weng-Lin Rating, as described at https://www.csie.ntu.edu.tw/~cjlin/papers/online_ranking/online_journal.pdf

Speed

Up to 20x faster than TrueSkill!

Model Speed (higher is better) Variance Samples
Openskill/bradleyTerryFull 62,643 ops/sec ยฑ1.09% 91 runs sampled
Openskill/bradleyTerryPart 40,152 ops/sec ยฑ0.73% 91 runs sampled
Openskill/thurstoneMostellerFull 59,336 ops/sec ยฑ0.74% 93 runs sampled
Openskill/thurstoneMostellerPart 38,666 ops/sec ยฑ1.21% 92 runs sampled
Openskill/plackettLuce 23,492 ops/sec ยฑ0.26% 91 runs sampled
TrueSkill 2,962 ops/sec ยฑ3.23% 82 runs sampled

See this post for more.

Installation

Add openskill to your list of dependencies in package.json:

npm install --save openskill

Usage

If you're writing ES6, you can import, otherwise use CommonJS's require

import { rating, rate, ordinal } from 'openskill'

Ratings are kept as an object which represent a gaussian curve, with properties where mu represents the mean, and sigma represents the spread or standard deviation. Create these with:

> const { rating } = require('openskill')
> const a1 = rating()
{ mu: 25, sigma: 8.333333333333334 }
> const a2 = rating({ mu: 32.444, sigma: 5.123 })
{ mu: 32.444, sigma: 5.123 }
> const b1 = rating({ mu: 43.381, sigma: 2.421 })
{ mu: 43.381, sigma: 2.421 }
> const b2 = rating({ mu: 25.188, sigma: 6.211 })
{ mu: 25.188, sigma: 6.211 }

If a1 and a2 are on a team, and wins against a team of b1 and b2, send this into rate

> const { rate } = require('openskill')
> const [[x1, x2], [y1, y2]] = rate([[a1, a2], [b1, b2]])
[
  [
    { mu: 28.67..., sigma: 8.07...},
    { mu: 33.83..., sigma: 5.06...}
  ],
  [
    { mu: 43.07..., sigma: 2.42...},
    { mu: 23.15..., sigma: 6.14...}
  ]
]

Teams can be asymmetric, too! For example, a game like Axis and Allies can be 3 vs 2, and this can be modeled here.

Ranking

When displaying a rating, or sorting a list of ratings, you can use ordinal

> const { ordinal } = require('openskill')
> ordinal({ mu: 43.07, sigma: 2.42})
35.81

By default, this returns mu - 3*sigma, showing a rating for which there's a 99.7% likelihood the player's true rating is higher, so with early games, a player's ordinal rating will usually go up and could go up even if that player loses.

Artificial Ranking

If your teams are listed in one order but your ranking is in a different order, for convenience you can specify a ranks option, such as

> const a1 = b1 = c1 = d1 = rating()
> const [[a2], [b2], [c2], [d2]] = rate([[a1], [b1], [c1], [d1]], {
    rank: [4, 1, 3, 2] // ๐ŸŒ ๐Ÿฅ‡ ๐Ÿฅ‰ ๐Ÿฅˆ
  })
[
  [{ mu: 20.963, sigma: 8.084 }], // ๐ŸŒ
  [{ mu: 27.795, sigma: 8.263 }], // ๐Ÿฅ‡
  [{ mu: 24.689, sigma: 8.084 }], // ๐Ÿฅ‰
  [{ mu: 26.553, sigma: 8.179 }], // ๐Ÿฅˆ
]

It's assumed that the lower ranks are better (wins), while higher ranks are worse (losses). You can provide a score instead, where lower is worse and higher is better. These can just be raw scores from the game, if you want.

Ties should have either equivalent rank or score.

> const a1 = b1 = c1 = d1 = rating()
> const [[a2], [b2], [c2], [d2]] = rate([[a1], [b1], [c1], [d1]], {
    score: [37, 19, 37, 42] // ๐Ÿฅˆ ๐ŸŒ ๐Ÿฅˆ ๐Ÿฅ‡
  })
[
  [{ mu: 24.689, sigma: 8.179 }], // ๐Ÿฅˆ
  [{ mu: 22.826, sigma: 8.179 }], // ๐ŸŒ
  [{ mu: 24.689, sigma: 8.179 }], // ๐Ÿฅˆ
  [{ mu: 27.795, sigma: 8.263 }], // ๐Ÿฅ‡
]

Predicting Winners

For a given match of any number of teams, using predictWin you can find a relative odds that each of those teams will win.

> const { predictWin } = require('openskill')
> const a1 = rating()
> const a2 = rating({mu:33.564, sigma:1.123})
> const predictions = predictWin([[a1], [a2]])
[ 0.45110899943132493, 0.5488910005686751 ]
> predictions[0] + predictions[1]
1

Predicting Draws

Also for a given match, using predictDraw you can get the relative chance that these teams will draw. The number returned here should be treated as relative to other matches, but in reality the odds of an actual legal draw will be impacted by some meta-function based on the rules of the game.

> const { predictDraw } = require('openskill')
> const prediction = predictDraw([[a1], [a2]])
0.09025530533015186

This can be used in a similar way that you might use quality in TrueSkill if you were optimizing a matchmaking system, or optimizing an tournament tree structure for exciting finals and semi-finals such as in the NCAA.

Alternative Models

By default, we use a Plackett-Luce model, which is probably good enough for most cases. When speed is an issue, the library runs faster with other models

import { bradleyTerryFull } from './models'
const [[a2], [b2]] = rate([[a1], [b1]], {
  model: bradleyTerryFull,
})
  • Bradley-Terry rating models follow a logistic distribution over a player's skill, similar to Glicko.
  • Thurstone-Mosteller rating models follow a gaussian distribution, similar to TrueSkill. Gaussian CDF/PDF functions differ in implementation from system to system (they're all just chebyshev approximations anyway). The accuracy of this model isn't usually as great either, but tuning this with an alternative gamma function can improve the accuracy if you really want to get into it.
  • Full pairing should have more accurate ratings over partial pairing, however in high k games (like a 100+ person marathon race), Bradley-Terry and Thurstone-Mosteller models need to do a calculation of joint probability which involves is a k-1 dimensional integration, which is computationally expensive. Use partial pairing in this case, where players only change based on their neighbors.
  • Plackett-Luce (default) is a generalized Bradley-Terry model for k โ‰ฅ 3 teams. It scales best.

Implementations in other languages

More Repositories

1

Jubilee

Software for controlling an LED hula hoop
Processing
24
star
2

R2

A Swift macOS application which turns your keystrokes into music
Swift
21
star
3

fields-of-arle

Fields of Arle Simulator
JavaScript
19
star
4

nanbox

Encode non-numerical data as NaNs
JavaScript
18
star
5

fast-shuffle

A fast, pure, side-effect-free, and deterministic implementation of Fisher-Yates Shuffle
TypeScript
18
star
6

weblabora

Ora et Labora boardgame simulation library
Java
11
star
7

openskill.ex

Elixir implementation of Weng-Lin Bayesian ranking, a better, license-free alternative to TrueSkill
Elixir
9
star
8

play-java-react-seed

Java
5
star
9

wakatime-zprezto

Shell
4
star
10

sort-unwind

Retain the stochastic tenet of a sort to revert original sort orders
TypeScript
3
star
11

philihp.github.io

HTML
3
star
12

WebHavre

Website based Le Havre board game persistence
3
star
13

LTC-4027JR

EAGLE Library for 4-Digit 7-Segment LED Display
3
star
14

score

Boardgames and bayesian probability
JavaScript
3
star
15

pcg

A functional implementation of the PCG family random number generators, written in TypeScript.
TypeScript
3
star
16

tarot

Kingdomino Monte Carlo Tree Search in Ruby
Ruby
2
star
17

pcg-gen

Permuted Congruential Generator Generator
TypeScript
2
star
18

pgp.philihp.com

JavaScript
2
star
19

deneg-zero

Enterprise software to protect from negative zero with IEEE 754 precision
JavaScript
2
star
20

Blackjack

Monte Carlo Blackjack Simulator
Java
2
star
21

Tracker

GPS Tracking scraper and Wordpress map widget
Java
2
star
22

welcome2_umbrella

Play the Boardgame "Welcome To" from CLI or in a browser
Elixir
1
star
23

eslint-config

Opinionated ESLint Rules and Dependency Umbrella
JavaScript
1
star
24

eve-industry

TypeScript
1
star
25

fn-pcg

TypeScript
1
star
26

diycap

JavaScript
1
star
27

Manhattan

The Manhattan Project Online
Java
1
star
28

week-date

JavaScript
1
star
29

BOATSWAG

A dynamic map of attendees of Holy Ship, pulled from their current city on Facebook
Java
1
star
30

eighteen54

1854 On Rails
Ruby
1
star
31

prettier-config

1
star
32

hathora

Multiplayer game framework
Handlebars
1
star
33

goonql

JavaScript
1
star
34

eighteen30

1830 on Rails
Ruby
1
star
35

between-two-cities

Between Two Cities Simulator
JavaScript
1
star
36

kennerspiel

Uwe Rosenberg's Ora et Labora
TypeScript
1
star