Repository navigation
feat(schema): odds and standings models of P28 in schema v1 [FX-21] - #164
Merged
Merged
Conversation
Move Odds, OddsMarket, OddsChoice, OddsLine and StandingsRow from models.PENDING_MODELS into MODELS, and Odds, OddsLine and StandingsRow into RECORDS. The JSON Schema and ssc describe schemas now carry them. The five field tables of 04-schema-v1.md become generated, test-checked blocks (the tables were already equal to the models), with a checked example for each new record. The JSON Schema golden is regenerated: five new $defs and three more x-records, nothing else changes.
…lues Slice.key lists innings and the odds and owner slices of P28, which were missing; a test now checks that every key of the slice registry is a known value and every owner a known owner_kind. Slice.key is an open set, so this adds examples only. The JSON Schema golden and the Slice table of 04-schema-v1.md are regenerated.
None of its points is open since the approval of 2026-10-02. The test that pinned the old heading now pins the new one.
The texts of SetScore, SetsScore and PeriodsScore were written for tennis and basketball. They now say what each field counts in the other sports of the family: points or legs per set, the frames, legs or games won when the format has no sets, sets up to period7, tie-breaks and the match tie-break in tennis and padel only, goals in the goal sports of the periods family and which sports divide time how. No unit, type or name changes, so the schema version stays 1. Regenerated: the JSON Schema golden, the field tables of 04-schema-v1.md, docs/api/openapi-v1.json and the frontend types generated from it (descriptions only).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Behaviour change: the JSON Schema and
ssc describe schemasnow include the five modelsOdds,OddsMarket,OddsChoice,OddsLineandStandingsRow.Odds,OddsLineandStandingsRoware listed as records. The API v1 responses and the export files are unchanged; only the descriptions of some score fields in the API document change.Item: FX-21 in docs/design/03-implementation-plan.md, section 10 (order 61b, lane
contract). Design:04-schema-v1.mdsection 4, "Odds and standings". Depends on P28 (#140).What was done
Four commits. Each one passes on its own.
1. P28's models in schema v1 (
bd14bf5)src/schema/models.py:MODELSgainsOdds,OddsMarket,OddsChoice,OddsLineandStandingsRow, in that order, afterLiveEvent.RECORDSgainsOdds,OddsLineandStandingsRow.PENDING_MODELSis removed.04-schema-v1.md:<!-- fields:<Model> -->markers, so they are generated and test-checked blocks.REGEN_SCHEMA_DOC=1left the tables unchanged, because they already matched the models.json example:block each is added forOdds,OddsLineandStandingsRow. The document test requires an example for every record, and validates it against the JSON Schema. The values come from the mappers applied totests/fixtures/p28.tests/golden/schema/json_schema.jsonregenerated:$defs;x-recordsgainsOdds,OddsLineandStandingsRow;ssc describe schemasprintsschema.describe(), so itsdata.recordsanddata.schemachange in the same way. No CLI golden contains this output, so no other golden changed.2.
Slice.keyknown values (755e6da)inningsand the 13 keys of P28's odds and owner slices.Slice.keyis an open set, so this changes the examples only.test_slice_key_lists_every_registered_slice:registered_slices()must be a known value;event,seasonsandschedule;owner_kind.Slice.keyexamples in the JSON Schema golden, and theSlicetable of04-schema-v1.md.3. Heading of section 9 (
4a38394)## 9. Open questionsis renamed## 9. Decisions.4. Text pass over the score texts (
6b09d46)SCHEMA_VERSIONstays 1. Each claim below was checked againstsrc/status.py.SetScore.home/away: per set, the value is games in tennis and padel (points in a match tie-break), points in volleyball, badminton and table tennis, and legs in darts played in sets.SetScore.tiebreak: always null outside tennis and padel.SetsScore.home/away/sets_won: with the formatsframes,legs_wonandgames_won, the value is the frames, legs or games won.SetsScore.sets:period1toperiod7(tennis: toperiod5), with tie-breaks only in tennis and padel.SetsScore.match_tiebreak: always false outside tennis and padel.PeriodsScore:homeandawaycount goals in the goal sports (ice hockey, handball, futsal, minifootball, floorball);periods,regulation,overtimeandfinalsay "(goals in the goal sports)";formatnames which sports use quarters, halves and thirds.04-schema-v1.md,docs/api/openapi-v1.json(python -m src.web.openapi --write) andfrontend/src/api/v1/schema.ts(node frontend/scripts/gen-api-types.mjs).docs/api/openapi-v1.json: 15descriptionstrings in the componentsPeriodsScore,SetScoreandSetsScore. No path, operation or type changed.schema.ts: the same 15 doc comments.How it was verified
STORE_SHADOW_CHECK=1, run in the foreground, with TMPDIR and--basetempon~/.cache/fx21-tmp:bb7cf4f: 9735 passed, 33 skipped, 20 deselected;cc631ee(main after docs: user-facing docs match 3.0.0 behaviour #163): 9752 passed (+17), 33 skipped, 20 deselected.tests/test_schema_v1.py, and the pydantic mirror against the contract intests/test_api_v1_resources.py;test_slice_key_lists_every_registered_slice, andtest_odds_and_standings_records_follow_the_json_schema. The second maps the recordedodds_all,odds_featuredandstandings_totalbodies and validates everyOdds,OddsLineandStandingsRowrecord against the JSON Schema. It also checks that a wrong type and a missing field are refused, and that an unknowntablevalue is accepted.ruff check .is clean.python -m src.web.openapi --checkpasses, andnode frontend/scripts/gen-api-types.mjs --checkpasses.REGEN_SCHEMA_DOC=1andREGEN_SCHEMA_GOLDEN=1produce no further change.tests/snapshots/openapi-legacy.jsonare unchanged, and no route changed.node_modulesin the worktree;apiTypes.test.tsmakes the same check as--check), Windows, macOS.Existing tests changed
tests/test_odds_slices.py::test_the_new_models_carry_their_contract(outside ownership). It took its models frommodels.PENDING_MODELSand assertedmodel not in models.MODELS, which is exactly what this item reverses. It now names the five models and assertsmodel in models.MODELS. Its field-contract checks are unchanged.tests/test_schema_v1.py(owned):test_version_and_ids: the expectedRECORDSlist gains the three records. It also checks the five models at the end ofMODELSand thatPENDING_MODELSis gone.test_record_schema_and_describe: it used"Odds"as its example of an unknown record. It now uses"Standings"and checks thatrecord_schema("Odds")works.test_document_states_the_version_and_its_examples_are_valid: the heading assertion (step 3).Files outside ownership
tests/test_odds_slices.py: see above.docs/api/openapi-v1.json: a generated file (rule 2). It is regenerated because the score descriptions changed.frontend/src/api/v1/schema.ts: generated from that document. The frontend testapiTypes.test.tsfails if it is stale. Earlier items regenerated it the same way (P28, FX-13, FX-19). FX-20 ownsfrontend/**in parallel. If it also regenerates the file, the conflict is resolved by runningnode frontend/scripts/gen-api-types.mjsagain after the rebase. If that is not acceptable, commit6b09d46(the text pass) can be dropped on its own; the first three commits do not touch these files.docs/design/04-schema-v1.md: beyond the generated blocks and the heading, I added the threejson example:blocks and removed the five "copied from the model" notes (see Deviations).Deviations and why
04-schema-v1.md. The brief allows only the generated blocks and the heading. Buttest_document_states_the_version_and_its_examples_are_validrequires ajson example:for every model inRECORDS, so the brief's move intoRECORDScannot pass without them. The test validates them against the JSON Schema.frames) has no set list:_COUNT_ONLY_UNITSinsrc/status.py, and itsperiod1repeatscurrent. TheSetScoretext therefore names games, points and legs. The frames appear inSetsScore.home,awayandsets_won.PENDING_MODELSremoved, not left as an empty tuple. An empty tuple would leave the parametrized test intests/test_odds_slices.pywith no cases, so it would be skipped without failing.src/schema/__init__.py. They are reached assrc.schema.models.Odds, as before. The brief did not ask for it, and the file is not owned.Design mismatches
04-schema-v1.mdprose that this item makes stale. A batch PR may not edit it, so it is left for the docs PR:models.PENDING_MODELS, not inMODELSandRECORDS" and thatdescribe schemasand the golden do not show them.MODELSyet (FX-21)". The table "Records of version 1" has no rows forOdds,OddsLineandStandingsRow. Suggested "Given out by" values:Odds:/events/{id}/odds/{key};OddsLine: export datasetodds;StandingsRow:/seasons/{id}/standings, export datasetstandings.Slice.keyin the field table above do not listinningsyet …" and "… do not list them, norinnings; FX-21 adds them": both are now done.models.PENDING_MODELS(src/schema/models.py:845) …".models.PENDING_MODELS… outside the JSON Schema and the generated tables until FX-21".PeriodsScoreprose still say "basketball" in places (the SP-1 note in 03 section 10). That is prose, not a generated block.03-implementation-plan.mdcitestests/test_schema_v1.py:1112for the heading assertion. It is at:1172after this PR.02-services.md(:2416) says "The P28 models are not in it yet (models.PENDING_MODELS; FX-21)".00-platform.md(:159) andREADME.mdof docs/design (:25,:89) mention FX-21 as still to do.Notes for the next items
src/schema/models.pyno longer hasPENDING_MODELS. Every model of the schema is inMODELS, and every model inMODELSmust have a generated block in04-schema-v1.md. Every model inRECORDSmust also have ajson example:there.test_slice_key_lists_every_registered_sliceuntil it is added to the known values ofSlice.key. This only adds an example; no version change.RECORDS, add the block and an example to04-schema-v1.md, then runREGEN_SCHEMA_DOC=1andREGEN_SCHEMA_GOLDEN=1.Oddsrecord still has no country field (meta.countryonly, FX-15). That would be a schema change outside this item.Changelog entry
Under
[Unreleased], "Changed":