feat: add ranked season rollover policy

This commit is contained in:
Josh Creek
2026-08-31 20:29:11 +01:00
parent 1793eb7621
commit cc2cd80a01
16 changed files with 688 additions and 249 deletions
+27 -9
View File
@@ -18,9 +18,15 @@ func TestSelectCandidatesNeverCrossesRTTOrMutualRatingCeilings(t *testing.T) {
candidate("d", 1800, 70*time.Second, 40, 40, now),
}
selection, err := SelectCandidates(anchor, players, 3, now)
if err != nil { t.Fatal(err) }
if selection.Region != "EU" || selection.WorstRTT > MaxPlacementRTT { t.Fatalf("bad region/RTT: %+v", selection) }
if ticketIDs(selection.Players) != "a\x00b\x00c\x00" { t.Fatalf("selected incompatible or non-optimal set: %q", ticketIDs(selection.Players)) }
if err != nil {
t.Fatal(err)
}
if selection.Region != "EU" || selection.WorstRTT > MaxPlacementRTT {
t.Fatalf("bad region/RTT: %+v", selection)
}
if ticketIDs(selection.Players) != "a\x00b\x00c\x00" {
t.Fatalf("selected incompatible or non-optimal set: %q", ticketIDs(selection.Players))
}
}
func TestSelectCandidatesRequiresAnchorAndUsesDeterministicTieBreak(t *testing.T) {
@@ -32,19 +38,31 @@ func TestSelectCandidatesRequiresAnchorAndUsesDeterministicTieBreak(t *testing.T
candidate("x", 1500, 10*time.Second, 50, 50, now),
}
selection, err := SelectCandidates(anchor, players, 3, now)
if err != nil { t.Fatal(err) }
if !containsTicket(selection.Players, "anchor") { t.Fatal("anchor was omitted") }
if ticketIDs(selection.Players) != "anchor\x00x\x00y\x00" { t.Fatalf("tie break was not lexical: %q", ticketIDs(selection.Players)) }
if err != nil {
t.Fatal(err)
}
if !containsTicket(selection.Players, "anchor") {
t.Fatal("anchor was omitted")
}
if ticketIDs(selection.Players) != "anchor\x00x\x00y\x00" {
t.Fatalf("tie break was not lexical: %q", ticketIDs(selection.Players))
}
}
func TestRatingToleranceWideningIsCapped(t *testing.T) {
if RatingTolerance(29) != 100 || RatingTolerance(30) != 125 { t.Fatal("30-second widening boundary is wrong") }
if RatingTolerance(1000) != MaxRatingTolerance { t.Fatal("rating tolerance is not capped") }
if RatingTolerance(29) != 100 || RatingTolerance(30) != 125 {
t.Fatal("30-second widening boundary is wrong")
}
if RatingTolerance(1000) != MaxRatingTolerance {
t.Fatal("rating tolerance is not capped")
}
}
func TestSelectCandidatesRejectsNoCommonRegion(t *testing.T) {
now := time.Unix(100000, 0)
anchor := candidate("a", 1500, 0, 101, 40, now)
other := candidate("b", 1500, 0, 40, 101, now)
if _, err := SelectCandidates(anchor, []Candidate{other}, 2, now); err == nil { t.Fatal("selected players without a common <=100ms region") }
if _, err := SelectCandidates(anchor, []Candidate{other}, 2, now); err == nil {
t.Fatal("selected players without a common <=100ms region")
}
}