Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions fixtures/season-2026/practice/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,13 @@ identities replaced. Concretely:
pseudonyms read off the published corpus. That join produced a 1:1 map with
**zero ambiguity** on all four axes: 6 venues, 22 fields, 136 team codes, and
215 coach assignments resolving to 196 distinct people — the same 215/196 the
game corpus states. No corpus pseudonym was changed.
game corpus states. No corpus pseudonym was changed. The 215/196 reconcile.
The 6 / 22 / 136 are **unreconciled** against the published game corpus,
which has 7 venues and 24 field ids in play in `../combined_schedule.csv`
and 132 roster teams. 136 admits two readings: (a) 131 roster teams with a
game plus 5 visiting-club labels, or (b) 132 roster teams plus 4 Minis
sessions. No reading of 6 or 22 was found.
`tests/season2026PracticeCorpus.test.js` records this rather than choosing.
- **People not in the game corpus** (registrants who coach no team, all players)
were minted fresh with unique surnames, so a shared surname never implies a
family that the source did not state. The 53 shared surnames in the combined
Expand Down Expand Up @@ -61,7 +67,14 @@ The real→pseudonym map is **not** in this repo and must not be committed.
## Known-good invariants (assert these)

- 457 practice rows across 7 source sheets; 88 distinct teams hold a practice
slot; 65 teams that play a game hold none in the parsed sheets.
slot. The source claimed **65** teams that play a game hold none in the
parsed sheets; that figure does not derive from the corpus. Enumerated from
`../coach_roster.csv` (131 roster teams appear in `../combined_schedule.csv`,
87 of them hold a slot) it is **44**; enumerated from every named side of
`../combined_schedule.csv`, Minis sessions and visiting-club labels included
(140 sides), it is **53**. The loader emits the 44 as
`ROSTER_TEAM_HOLDS_NO_PRACTICE` findings; the 53 is computed in
`tests/season2026PracticeCorpus.test.js`, which asserts both.
- Exactly one practice team (`16BSelect02`) plays no game in
`../combined_schedule.csv` — it is a Select team whose league layer is
unassigned slots.
Expand Down
47 changes: 47 additions & 0 deletions packages/core/src/fixtures/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,55 @@ export {
resolveSunsetMinutes,
scheduledOccupancyMinutes,
toNaiveIso,
trim,
weekdayCode,
PLACEHOLDER_TOKEN,
REC_FORMATS,
SEASON_2026_ROW_KIND,
} from './season2026Parsers.js';

export {
computePracticeFixtureChecksums,
crossCorpusFindings,
loadPracticeFile,
loadSeason2026Practice,
practiceFixtureFilePath,
readPracticeFixtureFile,
SEASON_2026_PRACTICE_FILES,
SEASON_LONG_CLOSURE_MIN_FRACTION,
ALL_DAY_CLOSE_MINUTES,
} from './season2026PracticeLoader.js';

export {
compareDecoderRings,
expectCsvColumns,
inclusiveSpanDays,
makePracticeFinding,
parseClock24Minutes,
parseCoachRegistration,
parseFieldCodeNames,
parseFieldConstraints,
parseFieldEquipment,
parseFieldInventory,
parseGameChangeLog,
parseMonthDayDate,
parsePermitReservations,
parsePermits,
parsePlayerRegistration,
parsePracticeFieldAliases,
parsePracticeGrid,
parseSelectCoaches,
parseWeeklyAvailability,
selectTeamCode,
weekdayCodeOfDayName,
AVAILABILITY_INTERPRETATIONS,
DECODER_DISAGREEMENT_KIND,
PracticeFindingSchema,
REGISTRATION_REF_CLASSES,
SEASON_2026_PRACTICE_COLUMNS,
SEASON_2026_PRACTICE_FINDING,
SEASON_2026_PRACTICE_FINDING_SEVERITY,
SEASON_2026_PRACTICE_PARSERS,
SEASON_2026_PRACTICE_SCHEMAS,
UNRESOLVED_VENUE_TOKEN,
} from './season2026PracticeParsers.js';
7 changes: 4 additions & 3 deletions packages/core/src/fixtures/season2026Loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,16 @@ export function readFixtureFile(fileName, dir = DEFAULT_FIXTURE_DIR) {

/**
* SHA-256 of every corpus file, so a test can prove a load left the sources
* byte-identical.
* byte-identical. The practice corpus loader reuses it with its own file list.
*
* @param {string} [dir]
* @param {ReadonlyArray<string>} [files]
* @returns {Record<string, string>}
*/
export function computeFixtureChecksums(dir = DEFAULT_FIXTURE_DIR) {
export function computeFixtureChecksums(dir = DEFAULT_FIXTURE_DIR, files = SEASON_2026_FILES) {
/** @type {Record<string, string>} */
const out = {};
for (const fileName of SEASON_2026_FILES) {
for (const fileName of files) {
const bytes = readFileSync(fixtureFilePath(fileName, dir));
out[fileName] = createHash('sha256').update(bytes).digest('hex');
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/fixtures/season2026Parsers.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ export function parseCsv(text, label = 'csv') {
return /** @type {Array<Record<string, string>>} */ (result.data);
}

const trim = (value) => String(value ?? '').trim();
export const trim = (value) => String(value ?? '').trim();

/* -------------------------------------------------------------------------- */
/* game_formats.csv */
Expand Down
Loading
Loading