{"id":"raiven4ever/luce","name":"luce","scope":"raiven4ever","platform":"roblox","description":"A small Luau implementation of Weng-Lin Bayesian ratings using the Plackett-Luce model","version":"1.0.0","latest":"1.0.0","versions":["0.1.0","1.0.0"],"license":"Unlicense","licenseRating":"safe","licenseCaveats":["The package archive does not include its license text; the license is declared in its manifest metadata."],"licenseVerified":false,"dependencies":{},"integrity":"ba2b509eede8b988665760e136659c142a4b6629751d04019a2cab082342c007","likes":0,"downloads":0,"install":"forest install raiven4ever/luce","url":"https://forest.dev/p/roblox/raiven4ever/luce","files":"https://api.forest.dev/ai/package/roblox/raiven4ever/luce/files","readme":"# Luce\n\nLuce is a small, dependency-free Luau implementation of the Weng–Lin Bayesian\nrating system using the Plackett–Luce model. It supports individual and team\nratings, ranked matches, ties, win probabilities, and draw probabilities.\n\n> [!WARNING]\n> Luce was made primarily for learning and curiosity. It has not received the\n> testing or real-world validation of an established rating library, so use it\n> at your own risk. For production or otherwise intensive use, consider\n> [openskill.lua](https://github.com/bstummer/openskill.lua/) instead.\n\nLuce may still suit smaller projects that want a focused, inspectable\nPlackett–Luce implementation with no runtime dependencies.\n\n## Installation\n\nAdd Luce to your `wally.toml`:\n\n```toml\n[dependencies]\nLuce = \"raiven4ever/luce@1.0.0\"\n```\n\nThen install it:\n\n```sh\nwally install\n```\n\n## Ratings\n\nA rating contains an estimated skill (`mu`), uncertainty (`sigma`), and an\noptional Roblox user ID:\n\n```luau\nexport type Rating = {\n\tmu: number,\n\tsigma: number,\n\tuserId: number?,\n}\n```\n\nThe conventional defaults are `mu = 25` and `sigma = 25 / 3`.\n\n```luau\nlocal alice = luce.rating()\nlocal bob = luce.rating(30, 6, 123456)\n```\n\n## Example\n\nEach inner array represents one team. Lower rank numbers indicate better\nplacements, while equal ranks indicate a tie.\n\n```luau\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\nlocal luce = require(ReplicatedStorage.Packages.Luce)\n\nlocal teams = {\n\t{ luce.rating(25, 25 / 3, 123456) },\n\t{ luce.rating(25, 25 / 3, 654321) },\n}\n\nlocal winProbabilities = luce.winProbabilities(teams)\nlocal drawProbability = luce.drawProbability(teams)\n\n-- Team 1 finished first and team 2 finished second.\nlocal updatedTeams = luce.rate(teams, { 1, 2 })\n\nlocal updatedWinner = updatedTeams[1][1]\nlocal updatedLoser = updatedTeams[2][1]\n```\n\n## API\n\n### `luce.rating(mu?, sigma?, userId?)`\n\nCreates a new rating. Omitted `mu` and `sigma` values use the conventional\ndefaults. `userId` is optional and is preserved when the rating is updated.\n\n### `luce.rate(teams, ranks)`\n\nUpdates the ratings after a match and returns a new array of teams in the same\norder as the input. The input ratings are not mutated.\n\n`ranks[i]` is the placement of `teams[i]`: lower numbers are better, and equal\nnumbers represent a tie. A match must contain at least two non-empty teams.\n\n```luau\nlocal updatedTeams = luce.rate(teams, { 1, 2, 2 })\n```\n\nHere, the first team won while the second and third teams tied for second.\n\n### `luce.winProbabilities(teams)`\n\nReturns one win probability per team in input order. The returned values sum\nto one.\n\n```luau\nlocal probabilities = luce.winProbabilities(teams)\nprint(probabilities[1])\n```\n\n### `luce.drawProbability(teams)`\n\nReturns the Plackett–Luce likelihood that all supplied teams tie.\n\nThis value is not a third mutually exclusive outcome alongside the values from\n`winProbabilities`, so the draw probability and win probabilities are not\nexpected to sum to one.\n\n## Model\n\nLuce follows the Plackett–Luce approximation described in\n[A Bayesian Approximation Method for Online Ranking](https://www.jmlr.org/papers/volume12/weng11a/weng11a.pdf)\nby Ruby C. Weng and Chih-Jen Lin. Version 1.0.0 uses the conventional values\n`beta = 25 / 6` and `tau = 25 / 300`.\n\n## License\n\nLuce is released into the public domain under the [Unlicense](UNLICENSE).\n","readmeTruncated":false}