Start typing to search packages!
luce
By @raiven4ever
Roblox
MirroredLuce
Luce is a small, dependency-free Luau implementation of the Weng–Lin Bayesian rating system using the Plackett–Luce model. It supports individual and team ratings, ranked matches, ties, win probabilities, and draw probabilities.
[!WARNING] Luce was made primarily for learning and curiosity. It has not received the testing or real-world validation of an established rating library, so use it at your own risk. For production or otherwise intensive use, consider openskill.lua instead.
Luce may still suit smaller projects that want a focused, inspectable Plackett–Luce implementation with no runtime dependencies.
Installation
Add Luce to your wally.toml:
[dependencies]
Luce = "raiven4ever/luce@1.0.0"
Then install it:
wally install
Ratings
A rating contains an estimated skill (mu), uncertainty (sigma), and an
optional Roblox user ID:
export type Rating = {
mu: number,
sigma: number,
userId: number?,
}
The conventional defaults are mu = 25 and sigma = 25 / 3.
local alice = luce.rating()
local bob = luce.rating(30, 6, 123456)
Example
Each inner array represents one team. Lower rank numbers indicate better placements, while equal ranks indicate a tie.
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local luce = require(ReplicatedStorage.Packages.Luce)
local teams = {
{ luce.rating(25, 25 / 3, 123456) },
{ luce.rating(25, 25 / 3, 654321) },
}
local winProbabilities = luce.winProbabilities(teams)
local drawProbability = luce.drawProbability(teams)
-- Team 1 finished first and team 2 finished second.
local updatedTeams = luce.rate(teams, { 1, 2 })
local updatedWinner = updatedTeams[1][1]
local updatedLoser = updatedTeams[2][1]
API
luce.rating(mu?, sigma?, userId?)
Creates a new rating. Omitted mu and sigma values use the conventional
defaults. userId is optional and is preserved when the rating is updated.
luce.rate(teams, ranks)
Updates the ratings after a match and returns a new array of teams in the same order as the input. The input ratings are not mutated.
ranks[i] is the placement of teams[i]: lower numbers are better, and equal
numbers represent a tie. A match must contain at least two non-empty teams.
local updatedTeams = luce.rate(teams, { 1, 2, 2 })
Here, the first team won while the second and third teams tied for second.
luce.winProbabilities(teams)
Returns one win probability per team in input order. The returned values sum to one.
local probabilities = luce.winProbabilities(teams)
print(probabilities[1])
luce.drawProbability(teams)
Returns the Plackett–Luce likelihood that all supplied teams tie.
This value is not a third mutually exclusive outcome alongside the values from
winProbabilities, so the draw probability and win probabilities are not
expected to sum to one.
Model
Luce follows the Plackett–Luce approximation described in
A Bayesian Approximation Method for Online Ranking
by Ruby C. Weng and Chih-Jen Lin. Version 1.0.0 uses the conventional values
beta = 25 / 6 and tau = 25 / 300.
License
Luce is released into the public domain under the Unlicense.
Package Details
Install command (Click to copy)
Version
1.0.0
License
Unlicense
Safe for commercial use
The package archive does not include its license text; the license is declared in its manifest metadata.
Automated license review — not legal advice.
