Calculate a player's skill level using Elo, DWZ, Ingo, TrueSkill, Glicko and Glicko-2 algorithms known from their usage in chess and online games.

Overview

skillratings

Skillratings allows you to calculate the player's skill instantly in 1v1 matches or after tournaments/rating periods with a list of results using a variety of known and lesser known skill rating algorithms.

Currently supported algorithms:

They are mainly known from their usage in chess and online games.

Installation

Add the following to your Cargo.toml file:

[dependencies]
skillratings = "0.9.1"

Basic Usage

Below is the most basic use case for each supported algorithm, in a 1-vs-1 format.
Each rating algorithm has many more associated functions, for example getting a rating using a list of outcomes or getting expected scores.

Head over to the documentation for more information.

Elo rating system

Wikipedia article

extern crate skillratings;

use skillratings::{
    elo::elo, outcomes::Outcomes, rating::EloRating, config::EloConfig
};

let player_one = EloRating { rating: 1000.0 };
let player_two = EloRating { rating: 1000.0 };

// The outcome is from the perspective of player one.
let outcome = Outcomes::WIN;

// The config allows you to change certain adjustable values in the algorithms.
let config = EloConfig::new();

let (player_one_new, player_two_new) = elo(player_one, player_two, outcome, &config);
assert!((player_one_new.rating - 1016.0).abs() < f64::EPSILON);
assert!((player_two_new.rating - 984.0).abs() < f64::EPSILON);

Glicko rating system

Wikipedia article

use skillratings::{
    config::Glicko2Config, glicko::glicko, outcomes::Outcomes, rating::GlickoRating,
};


let player_one = GlickoRating {
    rating: 1500.0,
    deviation: 350.0,
};
let player_two = GlickoRating {
    rating: 1500.0,
    deviation: 350.0,
};

let outcome = Outcomes::WIN;

// The config allows you to change certain adjustable values in the algorithms.
let config = GlickoConfig::new();

let (player_one_new, player_two_new) = glicko(player_one, player_two, outcome, &config);

assert!((player_one_new.rating.round() - 1662.0).abs() < f64::EPSILON);
assert!((player_one_new.deviation.round() - 290.0).abs() < f64::EPSILON);

assert!((player_two_new.rating.round() - 1338.0).abs() < f64::EPSILON);
assert!((player_two_new.deviation.round() - 290.0).abs() < f64::EPSILON);

Glicko-2 rating system

Wikipedia article

extern crate skillratings;

use skillratings::{
    glicko2::glicko2, outcomes::Outcomes, rating::Glicko2Rating, config::Glicko2Config
};

let player_one = Glicko2Rating { 
    rating: 1500.0, 
    deviation: 350.0, 
    volatility: 0.06 
};
let player_two = Glicko2Rating { 
    rating: 1500.0, 
    deviation: 350.0, 
    volatility: 0.06 
};

let outcome = Outcomes::WIN;

// The config allows you to change certain adjustable values in the algorithms.
let config = Glicko2Config::new();

let (player_one_new, player_two_new) = glicko2(player_one, player_two, outcome, &config);

assert!((player_one_new.rating.round() - 1662.0).abs() < f64::EPSILON);
assert!((player_one_new.deviation.round() - 290.0).abs() < f64::EPSILON);

assert!((player_two_new.rating.round() - 1338.0).abs() < f64::EPSILON);
assert!((player_two_new.deviation.round() - 290.0).abs() < f64::EPSILON);

TrueSkill rating system

Wikipedia article

Caution regarding usage of TrueSkill: Microsoft permits only Xbox Live games or non-commercial projects to use TrueSkill(TM). If your project is commercial, you should use another rating system included here.

use skillratings::{
    trueskill::trueskill, outcomes::Outcomes, rating::TrueSkillRating, config::TrueSkillConfig
};

let player_one = TrueSkillRating::new();
let player_two = TrueSkillRating {
    rating: 30.0,
    uncertainty: 1.2,
};

// The config allows you to change certain adjustable values in the algorithms.
let config = TrueSkillConfig::new();

let (p1, p2) = trueskill(player_one, player_two, Outcomes::WIN, &config);

assert!(((p1.rating * 100.0).round() - 3300.0).abs() < f64::EPSILON);
assert!(((p1.uncertainty * 100.0).round() - 597.0).abs() < f64::EPSILON);

assert!(((p2.rating * 100.0).round() - 2983.0).abs() < f64::EPSILON);
assert!(((p2.uncertainty * 100.0).round() - 120.0).abs() < f64::EPSILON);

DWZ (Deutsche Wertungszahl) rating system

Wikipedia article

use skillratings::{dwz::dwz, outcomes::Outcomes, rating::DWZRating};

let player_one = DWZRating {
    rating: 1500.0,
    index: 42,
    // The actual age of the player, if unavailable set this to >25.
    // The lower the age, the more the rating will fluctuate.
    age: 42,
};
let player_two = DWZRating {
    rating: 1500.0,
    index: 12,
    age: 12,
};

let outcome = Outcomes::WIN;

let (player_one_new, player_two_new) = dwz(player_one, player_two, outcome);

assert!((player_one_new.rating.round() - 1519.0).abs() < f64::EPSILON);
assert_eq!(player_one_new.index, 43);

assert!((player_two_new.rating.round() - 1464.0).abs() < f64::EPSILON);
assert_eq!(player_two_new.index, 13);

Ingo rating system

Wikipedia article (in german, no english version available)

use skillratings::{ingo::ingo, outcomes::Outcomes, rating::IngoRating};

let player_one = IngoRating {
    // Note that a lower rating is more desirable.
    rating: 130.0,
    // The actual age of the player, if unavailable set this to >25.
    // The lower the age, the more the rating will fluctuate.
    age: 40,
};
let player_two = IngoRating {
    rating: 160.0,
    age: 40,
};

let (p1, p2) = ingo(player_one, player_two, Outcomes::WIN);

assert!((p1.rating.round() - 129.0).abs() < f64::EPSILON);
assert!((p2.rating.round() - 161.0).abs() < f64::EPSILON);

License

This project is licensed under the MIT License.

Comments
  • Implement Weng-Lin for more than two teams

    Implement Weng-Lin for more than two teams

    This implements Weng-Lin rating system for games with more than two teams, as well as free-for-all games by introducing a new function, weng_lin_multi_team and a new struct MultiTeamOutcome, which is used for specifying what place did a team take (a rank), with lower rank being better for the team.

    Closes #5.

    opened by asyncth 14
  • Perform step 1 calculations in Glicko functions

    Perform step 1 calculations in Glicko functions

    This fixes an issue which caused Glicko functions such as glicko and glicko_rating_period not to perform calculations from the step 1 of the original Glicko paper. Those calculations are used to increase the rating deviation at the beginning of every rating period.

    Fixes #3.

    The results between test_glicko_rating_period and test_glicko are not exactly as similar as the comment on line 523 says they should be, someone probably should check carefully to make sure I didn't mess anything up.

    Formatting changes were done by rustfmt.

    opened by asyncth 13
  • `glicko_rating_period` is probably supposed to imply `decay_deviation`

    `glicko_rating_period` is probably supposed to imply `decay_deviation`

    As far as I understand it, Glicko paper requires to increase RD at the beginning of every rating period in Step 1 before changing it again in Step 2, regardless of whether the player played games in previous rating period or not, since it is said that Step 1 should be done for each player and Step 2 specifies RD as a rating deviation from Step 1:

    Step 1. Determine the rating and RD for each player at the start of the new rating period based on their rating and RD at the end of the previous period.

    [In Step 2] Assume that the player’s pre-period rating is r, and the ratings deviation is RD determined from Step 1.

    Which I believe means that glicko_rating_period needs to run step 1 as well, the same equation that decay_deviation uses. This would be similar to Glicko-2 where Step 6 is ran in both glicko2 and glicko2_rating_period.

    bug 
    opened by asyncth 7
  • Support for more than two teams in Weng-Lin

    Support for more than two teams in Weng-Lin

    Probably shouldn't be that difficult to do, my primary reason to want this is to be able to calculate ratings for free-for-all matches. I probably can implement this myself, not sure what the API should look like though.

    opened by asyncth 6
  • Doc comment of `WengLinConfig::beta` is probably incorrect

    Doc comment of `WengLinConfig::beta` is probably incorrect

    use skillratings::weng_lin::{self, WengLinConfig, WengLinRating};
    
    fn main() {
        let config = WengLinConfig::default();
    
        let player = WengLinRating {
            rating: 25.0 + config.beta,
            uncertainty: f64::EPSILON,
        };
        let player_2 = WengLinRating {
            rating: 25.0,
            uncertainty: f64::EPSILON,
        };
    
        println!(
            "{}",
            weng_lin::expected_score(&player, &player_2, &config).0
        );
    }
    

    Output:

    0.6697615493266569
    

    That's not 80%

    documentation 
    opened by asyncth 2
  • Support multiple teams in TrueSkill algorithms

    Support multiple teams in TrueSkill algorithms

    TrueSkill has the capability of supporting multiple teams just like the WengLin algorithm, and we should implement this.

    This means that these functions should be implemented for the TrueSkill algorithm:

    • trueskill_multi_team
    • draw_probability_multi_team
    • expected_score_multi_team

    Resources:

    • https://www.moserware.com/assets/computing-your-skill/The%20Math%20Behind%20TrueSkill.pdf
    • https://www.microsoft.com/en-us/research/wp-content/uploads/2006/01/TR-2006-80.pdf
    enhancement help wanted 
    opened by atomflunder 0
  • [feat. req.] Inverse update (undo)?

    [feat. req.] Inverse update (undo)?

    In some cases the user may wish to retroactively invalidate a game and reverse the effects it had on the ratings of the players involved. For example when:

    • a game's result was recorded incorrectly;
    • a player was retroactively disqualified;
    • the tournament in which the game was played was cancelled;
    • etc.

    So I think it would be a good idea to provide the inverse of an "update" function, an "undo" if you will.

    As far as I know the update algorithm for Elo is invertible, but I'm not sure about other rating systems. Do you think this is something that can be implemented without substantial effort?

    enhancement 
    opened by cyqsimon 1
Releases(v0.24.0)
A CLI tool to aid Dungeons and Dragons players with math(tm).

calcdnd A CLI tool to aid Dungeons and Dragons players with math(tm). Character Joe imported sucessfully. +--------------------------+----------------

Peter Kos 5 Dec 28, 2021
Utilites for working with `bevy_ecs` when not all types are known at compile time

bevy_ecs_dynamic Utilities for working with bevy_ecs in situations where the types you're dealing with might not be known at compile time (e.g. script

Jakob Hellermann 17 Dec 9, 2022
a chess engine written in rust. not even close to being done

Goals improve at the rust programming language. my first major project tought me how to do things in rust. I hope for this project to teach me how to

null 6 Apr 2, 2024
Mini Rust CLI to deploy sites to Netlify using their API

This is a Rust CLI that uses the Netlify API to deploy sites.

Benjamin Lannon 10 May 12, 2022
Core lightning (CLN) plugin to watch channel health, gossip health and ping amboss for online status

vitality Core lightning (CLN) plugin to watch channel health, gossip health and ping amboss for online status Installation Building Usage Telegram Opt

null 4 Oct 6, 2023
mdBook is a utility to create modern online books from Markdown files.

Create book from markdown files. Like Gitbook but implemented in Rust

The Rust Programming Language 11.6k Jan 4, 2023
CLI client for the Jagiellonian University's BaCa online judge

baca-cli CLI client for the Jagiellonian University's BaCa online judge Installation The latest release can be downloaded here. Windows users can use

Hubert Jaremko 20 Nov 14, 2022
An uncluttered blackboard, ideal for simple sketches during online meetings

lavagna It's a blackboard, not a lasagna. Lavagna is a "no frills" blackboard, ideal for simple sketches during online meetings. You have just a black

Alessandro Pezzato 6 Dec 15, 2022
An online judge system written in Rust.

MROJ - Making a Rust Oneline Judge Background This repo was initially a homework of Tsinghua University Programing and Training Course, but I found it

hjsjhn 6 Nov 29, 2022
Mafa is a command-line tool that helps people interact with online websites in a terminal(tty).

Table of Contents A Small Demo Installation Prerequisite Option 1: Cargo install (recommended) Option 2: Build from source Option 3: Prebuilt binaries

Michael Lee 6 Jul 10, 2023
an online arcade tic-tac-toe written in rust

Leptos Starter Template This is a template for use with the Leptos web framework and the cargo-leptos tool. Creating your template repo If you don't h

byCrookie 2 Jul 16, 2023
Mafa is a command-line tool that helps people interact with online websites in a terminal(tty).

A Small Demo Installation Prerequisite Option 1: Cargo install (recommended) Option 2: Build from source Option 3: Prebuilt binaries Mafa is for me? W

Michael Lee 6 Jul 23, 2023
Rust implementation of TARA archive format, used in Tanki Online.

Tanki Online archive format Rust implementation of .tara archive format, developed by Alternativa Platform, used in Tanki Online. License Licensed und

Araumi TO 7 Aug 13, 2023
Blaze is a Rust script that continuously monitors server resource usage and sends real-time summaries and alerts to a Discord channel via Webhook.

Blaze Blaze is a Rust script designed to run 24/7 on a server, providing a summary of resource usage every 30 minutes (configurable) to a Discord chan

ShadowArcanist 18 Sep 23, 2024
TMM is a Linux native game modding tool. it allows to install and depoly mods for Linux native and wine games.

Tux Mod Manager TMM is a Linux native mod manager made with the Tauri toolkit. It can install, load, remove and deploy mods for both Linux native and

Mathiew May 119 Dec 27, 2022
Ember is a minimalistic Rust library for creating 2D graphics, games, and interactive visualizations with ease and simplicity.

Ember Ember is a simple and fun 2D rendering library for Rust, allowing you to quickly create graphics and interactive applications with ease. It uses

null 8 May 4, 2023
Zenith - sort of like top or htop but with zoom-able charts, CPU, GPU, network, and disk usage

Zenith - sort of like top or htop but with zoom-able charts, CPU, GPU, network, and disk usage

Benjamin Vaisvil 1.6k Jan 4, 2023
A CLI tool which can help you automatically kill process of your choice. Useful for freeing up memory and CPU usage!

Quickiller There are always programs such as chrome that keep eating up your resources even when closed! The only way to prevent this is to kill all o

Codingsquirrel 1 Dec 8, 2021
App to collect ram/cpu usage from OS and show it in pretty graphs

System info collector This is simple app to collect data about system cpu and memory usage over time. After collecting results into csv file, html fil

RafaƂ Mikrut 3 Jul 11, 2023