Files
game-scoreboard/src/lib/scoring/cell.ts
T
joshuaandClaude Opus 5.5 84dfe6a54b Phase 2: scoring engine with full branch coverage
Pure functions in src/lib/scoring implementing docs/SCORING.md: cell values
(override > judge average), weighted raw totals, raw and placement points
with tie averaging, and competition-ranked standings. Coverage thresholds
are enforced at 100% for the module. Also silences the hydration warning
caused by browser extensions modifying <html>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 13:33:21 +02:00

39 lines
1.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { CellResult, ScoreInput, ScoringMode } from "./types";
/**
* SCORING.md §1: the value of one team × criterion cell.
* `cellScores` are all score rows for that cell; `activeJudgeIds` are the game's non-revoked judges.
*/
export function computeCell(
mode: ScoringMode,
cellScores: ScoreInput[],
activeJudgeIds: ReadonlySet<string>,
): CellResult {
const adminRow = cellScores.find((score) => score.judgeId === null);
if (mode === "direct") {
// Judge rows are ignored in direct games (e.g. left over from a mode switch).
return adminRow
? { value: adminRow.value, source: "admin", judgeAverage: null, judgeCount: 0 }
: { value: null, source: "none", judgeAverage: null, judgeCount: 0 };
}
// Missing judges are ignored, not counted as zero.
const judgeValues = cellScores
.filter((score) => score.judgeId !== null && activeJudgeIds.has(score.judgeId))
.map((score) => score.value);
const judgeCount = judgeValues.length;
const judgeAverage =
judgeCount > 0 ? judgeValues.reduce((sum, value) => sum + value, 0) / judgeCount : null;
if (adminRow) {
return { value: adminRow.value, source: "override", judgeAverage, judgeCount };
}
return {
value: judgeAverage,
source: judgeAverage === null ? "none" : "judges",
judgeAverage,
judgeCount,
};
}