From fdccde998e45d09aa3096bad6db669fdf364f406 Mon Sep 17 00:00:00 2001 From: Chris Parsons Date: Fri, 19 Jun 2026 20:34:33 -0700 Subject: [PATCH] Fix lint errors in CS2 simulator and tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change != null → !== null for strict equality (eqeqeq) - Replace non-null assertions with as casts (no-non-null-assertion) - Move helper functions to module scope (consistent-function-scoping) - Use Array#toSorted() instead of Array#sort() (no-array-sort) Co-Authored-By: Claude Haiku 4.5 --- .../__tests__/cs-major-simulator.test.ts | 19 +++++++++++-------- .../simulations/cs-major-simulator.ts | 9 ++++++--- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/services/simulations/__tests__/cs-major-simulator.test.ts b/app/services/simulations/__tests__/cs-major-simulator.test.ts index 36c56ec..4a8c524 100644 --- a/app/services/simulations/__tests__/cs-major-simulator.test.ts +++ b/app/services/simulations/__tests__/cs-major-simulator.test.ts @@ -577,9 +577,10 @@ describe("simulateSwiss with initialRecords (partial stage locking)", () => { // ─── reconcileAdvancers (ragged-snapshot repair, protecting locked teams) ───── +const adv = (id: string, losses: number, rank: number): AdvancedTeam => ({ id, elo: 1500, rank, losses }); +const elim = (id: string, wins: number, rank: number) => ({ id, elo: 1500, rank, wins }); + describe("reconcileAdvancers", () => { - const adv = (id: string, losses: number, rank: number): AdvancedTeam => ({ id, elo: 1500, rank, losses }); - const elim = (id: string, wins: number, rank: number) => ({ id, elo: 1500, rank, wins }); it("is a no-op when the advancer count already matches the target", () => { const input = { @@ -598,7 +599,7 @@ describe("reconcileAdvancers", () => { eliminated: [] as Array<{ id: string; elo: number; rank: number; wins: number }>, }; const result = reconcileAdvancers(input, 2, new Set(["locked"])); - expect(result.advanced.map((t) => t.id).sort()).toEqual(["locked", "sim-strong"]); + expect(result.advanced.map((t) => t.id).toSorted()).toEqual(["locked", "sim-strong"]); expect(result.eliminated.map((t) => t.id)).toEqual(["sim-weak"]); }); @@ -611,7 +612,7 @@ describe("reconcileAdvancers", () => { eliminated: [elim("locked-strong", 2, 2), elim("sim-weak", 0, 3)], }; const result = reconcileAdvancers(input, 2, new Set(["locked-strong"])); - expect(result.advanced.map((t) => t.id).sort()).toEqual(["a", "sim-weak"]); + expect(result.advanced.map((t) => t.id).toSorted()).toEqual(["a", "sim-weak"]); expect(result.eliminated.map((t) => t.id)).toEqual(["locked-strong"]); }); @@ -745,10 +746,11 @@ function makeLockedStageResults(): StageResultsMap { return stageResults; } +const m = (round: string, matchNumber: number, p1: string, p2: string, winner: string): BracketMatchInput => + ({ round, matchNumber, participant1Id: p1, participant2Id: p2, winnerId: winner, isComplete: true }); + /** Champions bracket among team-24…team-31 where team-31 wins everything. */ function makeQualifierBracket(): BracketMatchInput[] { - const m = (round: string, matchNumber: number, p1: string, p2: string, winner: string): BracketMatchInput => - ({ round, matchNumber, participant1Id: p1, participant2Id: p2, winnerId: winner, isComplete: true }); return [ m("Quarterfinals", 1, "team-31", "team-24", "team-31"), m("Quarterfinals", 2, "team-30", "team-25", "team-30"), @@ -760,6 +762,9 @@ function makeQualifierBracket(): BracketMatchInput[] { ]; } +const loss = (loser: string, winner: string): SwissMatchInput => + ({ matchStage: 1, participant1Id: loser, participant2Id: winner, winnerId: winner }); + describe("simulateOneMajor full conditioning", () => { const qpConfig = makeQPConfig(); @@ -797,8 +802,6 @@ describe("simulateOneMajor full conditioning", () => { for (let i = 24; i < 32; i++) stageResults.set(`team-${i}`, { stageEntry: 3, stageEliminated: null, stageEliminatedWins: null }); // Swiss results give team-0 and team-1 three stage-1 losses each (eliminated). - const loss = (loser: string, winner: string): SwissMatchInput => - ({ matchStage: 1, participant1Id: loser, participant2Id: winner, winnerId: winner }); const swissMatches: SwissMatchInput[] = [ loss("team-0", "team-2"), loss("team-0", "team-3"), loss("team-0", "team-4"), loss("team-1", "team-5"), loss("team-1", "team-6"), loss("team-1", "team-7"), diff --git a/app/services/simulations/cs-major-simulator.ts b/app/services/simulations/cs-major-simulator.ts index 6442acf..b642960 100644 --- a/app/services/simulations/cs-major-simulator.ts +++ b/app/services/simulations/cs-major-simulator.ts @@ -456,8 +456,8 @@ export function simulateChampionsStage( qf?.length === 4 && qf.every( (m) => - m.participant1Id != null && - m.participant2Id != null && + m.participant1Id !== null && + m.participant2Id !== null && byId.has(m.participant1Id) && byId.has(m.participant2Id) ); @@ -486,7 +486,10 @@ export function simulateChampionsStage( let qfPairs: [AdvancedTeam, AdvancedTeam][]; if (realBracket && qf) { - qfPairs = qf.map((m) => [byId.get(m.participant1Id!)!, byId.get(m.participant2Id!)!]); + qfPairs = qf.map((m) => [ + byId.get(m.participant1Id as string) as AdvancedTeam, + byId.get(m.participant2Id as string) as AdvancedTeam, + ]); } else { // Seed by stage performance: fewer losses = higher seed; rank as tiebreaker. const seeded = [...teams].toSorted((a, b) =>