TTS-Arena-V2 / packages /shared /src /elo.test.ts
GitHub Actions
Deploy from github.com/TTS-AGI/TTS-Arena@f49eded
374bcb6
Raw
History Blame Contribute Delete
2.93 kB
import { describe, expect, test } from "bun:test";
import {
BASE_ELO,
ELO_K,
ESTABLISHED_THRESHOLD,
RANK_THRESHOLD,
applyElo,
eloChange,
expectedScore,
isEstablished,
isRanked,
tierFor,
} from "./elo";
describe("isEstablished", () => {
test("flips at the established threshold", () => {
expect(isEstablished(ESTABLISHED_THRESHOLD - 1)).toBe(false);
expect(isEstablished(ESTABLISHED_THRESHOLD)).toBe(true);
expect(isEstablished(0)).toBe(false);
expect(isEstablished(10_000)).toBe(true);
});
});
describe("constants match upstream", () => {
test("base, k-factor, and ranking threshold", () => {
expect(BASE_ELO).toBe(1500);
expect(ELO_K).toBe(2);
expect(RANK_THRESHOLD).toBe(100);
});
});
describe("expectedScore", () => {
test("equal ratings expect 0.5", () => {
expect(expectedScore(1500, 1500)).toBeCloseTo(0.5, 10);
});
test("the two sides sum to 1", () => {
expect(expectedScore(1700, 1300) + expectedScore(1300, 1700)).toBeCloseTo(
1,
10,
);
});
test("a 400-point gap is ~0.909 favourite", () => {
expect(expectedScore(1900, 1500)).toBeCloseTo(10 / 11, 6);
});
});
describe("applyElo", () => {
test("equal ratings: winner +k/2, loser -k/2", () => {
const { winner, loser } = applyElo(1500, 1500);
expect(winner).toBeCloseTo(1500 + ELO_K / 2, 10);
expect(loser).toBeCloseTo(1500 - ELO_K / 2, 10);
});
test("zero-sum: total rating is conserved", () => {
const { winner, loser } = applyElo(1620, 1480);
expect(winner + loser).toBeCloseTo(1620 + 1480, 6);
});
test("beating a stronger model gains more than beating a weaker one", () => {
const upset = applyElo(1400, 1600).winner - 1400;
const expected = applyElo(1600, 1400).winner - 1600;
expect(upset).toBeGreaterThan(expected);
});
test("honors a custom k-factor", () => {
expect(applyElo(1500, 1500, 32).winner).toBeCloseTo(1516, 10);
});
});
describe("eloChange", () => {
test("equal ratings give half the k-factor", () => {
expect(eloChange(1500, 1500)).toBeCloseTo(ELO_K / 2, 10);
});
test("delta stays within (0, k)", () => {
for (const [w, l] of [
[1500, 1500],
[1000, 2000],
[2000, 1000],
] as const) {
const d = eloChange(w, l);
expect(d).toBeGreaterThan(0);
expect(d).toBeLessThan(ELO_K);
}
});
});
describe("tierFor", () => {
test("maps ranks to S/A/B then null", () => {
expect(tierFor(1)).toBe("S");
expect(tierFor(2)).toBe("S");
expect(tierFor(3)).toBe("A");
expect(tierFor(4)).toBe("A");
expect(tierFor(5)).toBe("B");
expect(tierFor(7)).toBe("B");
expect(tierFor(8)).toBeNull();
});
});
describe("isRanked", () => {
test("at least the threshold", () => {
expect(isRanked(RANK_THRESHOLD)).toBe(true);
expect(isRanked(RANK_THRESHOLD - 1)).toBe(false);
expect(isRanked(0)).toBe(false);
});
});