football-docs 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -21
- package/bin/serve.js +6 -1
- package/data/docs.db +0 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +25 -5
- package/dist/tools.d.ts +12 -1
- package/dist/tools.js +309 -18
- package/docs/fotmob/identity-surfaces.md +3 -4
- package/docs/free-sources/contextual-story-joins.md +110 -0
- package/docs/free-sources/overview.md +60 -13
- package/docs/free-sources/understat.md +15 -6
- package/docs/free-sources/xg-timelines.md +123 -0
- package/docs/impect/identity-surfaces.md +3 -4
- package/docs/kloppy/event-derived-metrics.md +337 -0
- package/docs/kloppy/tracking-rendering.md +420 -0
- package/docs/mplsoccer/visualizations.md +363 -6
- package/docs/opta/charting-game-state.md +216 -0
- package/docs/opta/charting-lineups.md +90 -0
- package/docs/opta/charting-passmaps.md +130 -0
- package/docs/opta/charting-set-pieces.md +106 -0
- package/docs/opta/charting-shot-placement.md +233 -0
- package/docs/opta/event-types.md +44 -0
- package/docs/opta/identity-surfaces.md +4 -4
- package/docs/opta/qualifiers.md +16 -7
- package/docs/skillcorner/identity-surfaces.md +4 -4
- package/docs/skillcorner/physical-data.md +35 -0
- package/docs/socceraction/spadl.md +21 -0
- package/docs/soccerdata/data-sources.md +37 -0
- package/docs/soccerdonna/identity-surfaces.md +6 -6
- package/docs/sportmonks/charting-season-stories.md +125 -0
- package/docs/sportmonks/data-model.md +35 -12
- package/docs/sportmonks/event-types.md +1 -1
- package/docs/sportmonks/identity-surfaces.md +4 -4
- package/docs/sportradar/api-access.md +75 -0
- package/docs/sportradar/api-endpoints.md +92 -0
- package/docs/sportradar/charting-and-stories.md +57 -0
- package/docs/sportradar/data-model.md +84 -0
- package/docs/sportradar/integration-notes.md +58 -0
- package/docs/statsbomb/charting-lineups.md +79 -0
- package/docs/statsbomb/identity-surfaces.md +5 -4
- package/docs/statsbomb/player-mapping.md +6 -7
- package/docs/thesportsdb/api-access.md +68 -0
- package/docs/thesportsdb/api-endpoints.md +55 -0
- package/docs/thesportsdb/identity-surfaces.md +49 -0
- package/docs/thesportsdb/livescore.md +70 -0
- package/docs/transfermarkt/identity-surfaces.md +51 -6
- package/docs/transferroom/charting-availability.md +74 -0
- package/docs/wyscout/charting-analysis-metrics.md +124 -0
- package/docs/wyscout/identity-surfaces.md +4 -4
- package/package.json +3 -2
- package/providers.json +127 -2
|
@@ -54,9 +54,8 @@ endpoint family, and snapshot date alongside any bridge evidence.
|
|
|
54
54
|
- Public endpoints may be undocumented. Treat access and response shape as
|
|
55
55
|
mutable unless the provider documents the contract.
|
|
56
56
|
|
|
57
|
-
##
|
|
57
|
+
## Implementation Notes
|
|
58
58
|
|
|
59
59
|
Use this page as the public provider-fact reference for FotMob identity
|
|
60
|
-
surfaces, public URL families, and matching cautions.
|
|
61
|
-
|
|
62
|
-
review outcomes, and register decisions belong outside football-docs.
|
|
60
|
+
surfaces, public URL families, and matching cautions. Keep access implementation
|
|
61
|
+
details, review outcomes, and register decisions outside football-docs.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Contextual Story Joins
|
|
2
|
+
|
|
3
|
+
Use free and public sources to enrich football fixture data with context that
|
|
4
|
+
commercial event feeds do not always provide: opponent strength, travel distance,
|
|
5
|
+
weather, venue geography, historical baselines, and independent xG.
|
|
6
|
+
|
|
7
|
+
## Base fixture authority
|
|
8
|
+
|
|
9
|
+
Choose one provider as the authority for fixture identity, final scores, and match
|
|
10
|
+
status before joining context.
|
|
11
|
+
|
|
12
|
+
| Need | Good base source |
|
|
13
|
+
|---|---|
|
|
14
|
+
| in-season fixture ids and live status | SportMonks, Opta, TheSportsDB, Sportradar |
|
|
15
|
+
| historical result grids | football-data.co.uk, engsoccerdata |
|
|
16
|
+
| shot-level xG enrichment | Understat, StatsBomb Open Data where covered |
|
|
17
|
+
| broad season stats | FBref / soccerdata |
|
|
18
|
+
|
|
19
|
+
Do not let an enrichment source silently override the base fixture score or status.
|
|
20
|
+
If an enrichment feed lags behind the fixture authority, preserve the base fixture
|
|
21
|
+
and mark the enrichment fields unavailable.
|
|
22
|
+
|
|
23
|
+
## Strength controls with ClubElo
|
|
24
|
+
|
|
25
|
+
ClubElo is useful for match-day team-strength controls and fixture-difficulty
|
|
26
|
+
stories. Join by the fixture date and a maintained team-name map:
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
home_elo = ClubElo(home_team, fixture_date)
|
|
30
|
+
away_elo = ClubElo(away_team, fixture_date)
|
|
31
|
+
elo_diff = home_elo - away_elo
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
ClubElo names are not guaranteed to match provider team labels. Keep the alias
|
|
35
|
+
map in project code, and treat promoted, renamed, and abbreviated clubs as normal
|
|
36
|
+
data-quality cases.
|
|
37
|
+
|
|
38
|
+
## Weather and climate context
|
|
39
|
+
|
|
40
|
+
Weather can be joined at venue and kickoff time:
|
|
41
|
+
|
|
42
|
+
| Field | Join key |
|
|
43
|
+
|---|---|
|
|
44
|
+
| observed match weather | venue latitude/longitude + kickoff timestamp |
|
|
45
|
+
| climate normal | venue latitude/longitude + month |
|
|
46
|
+
| weather anomaly | observed value minus climate normal |
|
|
47
|
+
| condition bucket | rain, snow, fog, clear, wind, heat, cold |
|
|
48
|
+
|
|
49
|
+
For public weather APIs, store the fetched timestamp, timezone, and units. Weather
|
|
50
|
+
observations are contextual features, not football-provider facts, so label them
|
|
51
|
+
separately from official match data.
|
|
52
|
+
|
|
53
|
+
## Travel and venue geography
|
|
54
|
+
|
|
55
|
+
For travel-distance stories, maintain a venue table with club, stadium,
|
|
56
|
+
latitude/longitude, city, and country. Calculate away travel with a geodesic
|
|
57
|
+
distance such as haversine:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
away_travel_km = distance(away_venue_lat_lon, home_venue_lat_lon)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Use travel bands for stable charts, for example `<50 km`, `50-100 km`, `100-200 km`,
|
|
64
|
+
`200-300 km`, and `300+ km`. Distances are approximations of geography, not actual
|
|
65
|
+
team travel logistics.
|
|
66
|
+
|
|
67
|
+
## Independent xG enrichment
|
|
68
|
+
|
|
69
|
+
Understat can add independent xG to result stories for the top European leagues.
|
|
70
|
+
Join by date plus home/away team aliases, not by Understat match id alone. Keep
|
|
71
|
+
fields such as:
|
|
72
|
+
|
|
73
|
+
| Field | Meaning |
|
|
74
|
+
|---|---|
|
|
75
|
+
| `xg` | team's Understat expected goals |
|
|
76
|
+
| `xga` | opponent Understat expected goals |
|
|
77
|
+
| `xg_model` | `understat` |
|
|
78
|
+
| `xg_join_status` | exact, alias, manual, missing |
|
|
79
|
+
|
|
80
|
+
If the base provider also supplies expected goals, do not average the values unless
|
|
81
|
+
the chart explicitly describes a blended model. Expose both model names instead.
|
|
82
|
+
|
|
83
|
+
## Additive factor stories
|
|
84
|
+
|
|
85
|
+
For home-advantage, away-day, and match-context stories, build factors from
|
|
86
|
+
explicit rules:
|
|
87
|
+
|
|
88
|
+
| Factor | Example rule |
|
|
89
|
+
|---|---|
|
|
90
|
+
| long away trip | `away_travel_km >= 300` |
|
|
91
|
+
| local derby | `away_travel_km < 30` |
|
|
92
|
+
| evening kickoff | kickoff hour `>= 18` |
|
|
93
|
+
| midweek fixture | Tuesday, Wednesday, or Thursday |
|
|
94
|
+
| severe weather | heavy rain, snow, fog, high wind, or extreme heat/cold |
|
|
95
|
+
| strength control | Elo difference at fixture date |
|
|
96
|
+
|
|
97
|
+
Keep the raw fields and the factor flags. This lets users inspect the story logic
|
|
98
|
+
and lets agents reproduce the chart without guessing which thresholds were used.
|
|
99
|
+
|
|
100
|
+
## Join hygiene
|
|
101
|
+
|
|
102
|
+
For public data-story pipelines:
|
|
103
|
+
|
|
104
|
+
- keep provider ids, team aliases, and venue aliases as explicit mapping tables;
|
|
105
|
+
- record whether each joined field came from exact id, alias, date/team match, or
|
|
106
|
+
manual override;
|
|
107
|
+
- never overwrite official scores with scraped enrichment data;
|
|
108
|
+
- cache public-source responses and respect rate limits;
|
|
109
|
+
- label sample-size limits when slicing by rare conditions such as snow or fog;
|
|
110
|
+
- separate observed facts from modelled controls such as Elo-adjusted residuals.
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
| Understat | xG, shot-level | Web scrape / soccerdata | Top 5 European leagues | Moderate |
|
|
10
10
|
| ClubElo | Historical Elo ratings | HTTP API | All top European leagues, 1946-present | Generous |
|
|
11
11
|
| football-data.co.uk | Match results + odds | CSV download | 25+ leagues, 20+ seasons | None |
|
|
12
|
+
| engsoccerdata | Historical league results | R package / GitHub data | England 1888+, Spain 1928+, other leagues | None |
|
|
12
13
|
| Transfermarkt | Market values, transfers, injuries | Web scrape | All professional leagues | Strict |
|
|
13
14
|
| WhoScored | Match ratings, event-level (limited) | Web scrape (headed browser) | Top leagues | Strict, requires JS rendering |
|
|
14
15
|
| European Football Statistics | Historical results | CSV download | Many European leagues | None |
|
|
@@ -97,7 +98,11 @@ Rank,Club,Country,Level,Elo,From,To
|
|
|
97
98
|
1,Liverpool,ENG,1,2050,2024-11-30,2024-12-07
|
|
98
99
|
```
|
|
99
100
|
|
|
100
|
-
**
|
|
101
|
+
**Project use**: For run-in, fixture-difficulty, and season-story surfaces,
|
|
102
|
+
ClubElo is useful as a lightweight strength prior. Join by a maintained club
|
|
103
|
+
name map rather than assuming site labels match your canonical team labels.
|
|
104
|
+
ClubElo is a rating source, not a fixture/result source, so combine it with
|
|
105
|
+
fixtures from Opta, SportMonks, football-data.co.uk, or another schedule feed.
|
|
101
106
|
|
|
102
107
|
## football-data.co.uk
|
|
103
108
|
|
|
@@ -118,6 +123,50 @@ Season format: `2425` for 2024/25. League codes: `E0` (Premier League), `E1` (Ch
|
|
|
118
123
|
- `HC`, `AC` (Corners), `HF`, `AF` (Fouls), `HY`, `AY` (Yellows), `HR`, `AR` (Reds)
|
|
119
124
|
- Betting odds from multiple bookmakers (B365H, B365D, B365A, etc.)
|
|
120
125
|
|
|
126
|
+
**Project use**: Excellent for scorigami, scoreline grids, baseline baking,
|
|
127
|
+
result-history charts, odds-history backfills, and simple match-stat trend
|
|
128
|
+
stories. For scorigami baselines, use full-time fields (`FTHG`, `FTAG`, `FTR`)
|
|
129
|
+
and ignore half-time or bookmaker columns unless the chart explicitly needs
|
|
130
|
+
them. Keep a league-code map in project code (`E0`, `E1`, `SP1`, etc.) and a
|
|
131
|
+
team-name map because historical labels and promoted/relegated club names can
|
|
132
|
+
drift from canonical names.
|
|
133
|
+
|
|
134
|
+
## engsoccerdata
|
|
135
|
+
|
|
136
|
+
**What it provides**: Historical football result datasets packaged for R by
|
|
137
|
+
James P. Curley. The GitHub package includes English league data, FA Cup data,
|
|
138
|
+
playoff data, and several European leagues including Spain, Germany, Italy,
|
|
139
|
+
France, Netherlands, Belgium, Portugal, Turkey, Scotland, Greece, South Africa,
|
|
140
|
+
and MLS.
|
|
141
|
+
|
|
142
|
+
**Useful datasets**:
|
|
143
|
+
|
|
144
|
+
| Dataset | Notes |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `england` | English league results, top four tiers, from 1888/89 in the classic package docs |
|
|
147
|
+
| `englandplayoffs` | English playoff matches |
|
|
148
|
+
| `facup` | FA Cup results |
|
|
149
|
+
| `spain` | Spanish league results from 1928/29 in the classic package docs |
|
|
150
|
+
|
|
151
|
+
**Common fields**:
|
|
152
|
+
|
|
153
|
+
| Field | Meaning |
|
|
154
|
+
|---|---|
|
|
155
|
+
| `Date` | match date |
|
|
156
|
+
| `Season` | season start year |
|
|
157
|
+
| `home` / `visitor` | home and away teams |
|
|
158
|
+
| `FT` | full-time score string |
|
|
159
|
+
| `hgoal` / `vgoal` | home and away full-time goals |
|
|
160
|
+
| `division` | division label |
|
|
161
|
+
| `tier` | football pyramid tier |
|
|
162
|
+
| `result` | `H`, `A`, or `D` |
|
|
163
|
+
|
|
164
|
+
**Project use**: Useful as a deep historical baseline for scorigami and
|
|
165
|
+
marcadorigami-style scoreline grids. Pair with football-data.co.uk for recent
|
|
166
|
+
season gap fills or in-season updates. The package was formerly on CRAN and is
|
|
167
|
+
now best treated as a GitHub/open-data source; cite James P. Curley when using
|
|
168
|
+
it in public analysis.
|
|
169
|
+
|
|
121
170
|
## Transfermarkt
|
|
122
171
|
|
|
123
172
|
**What it provides**: Player market values, transfer history, contract details, injury history, squad information, manager history.
|
|
@@ -156,8 +205,6 @@ Season format: `2425` for 2024/25. League codes: `E0` (Premier League), `E1` (Ch
|
|
|
156
205
|
- Rate limiting is strict; adding delays between requests is essential
|
|
157
206
|
- Data is Opta-sourced, so event types and qualifier IDs match Opta's system
|
|
158
207
|
|
|
159
|
-
**Used in**: myTeam's passmap data pipeline (`scripts/fetch-whoscored-events.ts` stores events in Postgres, `scripts/generate-passmap-data.ts` processes them).
|
|
160
|
-
|
|
161
208
|
## European Football Statistics
|
|
162
209
|
|
|
163
210
|
**What it provides**: Historical match results for European leagues.
|
|
@@ -168,13 +215,13 @@ Season format: `2425` for 2024/25. League codes: `E0` (Premier League), `E1` (Ch
|
|
|
168
215
|
|
|
169
216
|
## Comparison Matrix
|
|
170
217
|
|
|
171
|
-
| Feature | StatsBomb Open | FBref | Understat | ClubElo | football-data.co.uk | Transfermarkt | WhoScored |
|
|
172
|
-
|
|
173
|
-
| Event-level data | Full | No | Shot-level | No | No | No | Full |
|
|
174
|
-
| Aggregated stats | Via events | Yes | Yes | No | Basic | No | Yes |
|
|
175
|
-
| xG | Yes | Yes (Opta) | Yes (own model) | No | No | No | No |
|
|
176
|
-
| Coordinates | Yes | No | Shot coords | No | No | No | Yes |
|
|
177
|
-
| Historical depth | Limited | 2017+ detailed | 2014+ | 1946+ | 1993+ | 2004+ | ~2010+ |
|
|
178
|
-
| League coverage | Select | Top 5+ | Top 5 | Europe | 25+ | Global | Top 5+ |
|
|
179
|
-
| Commercial use | No | No | Unclear | Yes | Yes | No | No |
|
|
180
|
-
| API available | GitHub | No | No | Yes (CSV) | CSV download | No | No |
|
|
218
|
+
| Feature | StatsBomb Open | FBref | Understat | ClubElo | football-data.co.uk | engsoccerdata | Transfermarkt | WhoScored |
|
|
219
|
+
|---|---|---|---|---|---|---|---|---|
|
|
220
|
+
| Event-level data | Full | No | Shot-level | No | No | No | No | Full |
|
|
221
|
+
| Aggregated stats | Via events | Yes | Yes | No | Basic | No | No | Yes |
|
|
222
|
+
| xG | Yes | Yes (Opta) | Yes (own model) | No | No | No | No | No |
|
|
223
|
+
| Coordinates | Yes | No | Shot coords | No | No | No | No | Yes |
|
|
224
|
+
| Historical depth | Limited | 2017+ detailed | 2014+ | 1946+ | 1993+ | 1888+ England | 2004+ | ~2010+ |
|
|
225
|
+
| League coverage | Select | Top 5+ | Top 5 | Europe | 25+ | England + selected global leagues | Global | Top 5+ |
|
|
226
|
+
| Commercial use | No | No | Unclear | Yes | Yes | Non-commercial attribution expected | No | No |
|
|
227
|
+
| API available | GitHub | No | No | Yes (CSV) | CSV download | R/GitHub data | No | No |
|
|
@@ -197,12 +197,21 @@ Their xG model is independent from StatsBomb and Opta. Values will differ. The m
|
|
|
197
197
|
- xG model methodology is not fully published. It's a black box.
|
|
198
198
|
- No event data beyond shots. No passes, tackles, etc.
|
|
199
199
|
- Data updates can lag 1-2 days after matches.
|
|
200
|
-
- Match IDs are
|
|
200
|
+
- Match IDs are source-specific and don't map to other providers. Match by teams + date.
|
|
201
201
|
- Player names may differ from other sources (transliterations, shortened forms).
|
|
202
202
|
|
|
203
|
-
##
|
|
203
|
+
## Project use
|
|
204
204
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
-
|
|
208
|
-
|
|
205
|
+
Understat is useful as an xG enrichment source for match-result, season-story,
|
|
206
|
+
and game-state surfaces when the primary fixture provider does not include
|
|
207
|
+
shot-level or match-level xG. Cache by competition, season, team names, and match
|
|
208
|
+
date rather than by Understat match ID alone, because Understat IDs are not
|
|
209
|
+
portable across providers.
|
|
210
|
+
|
|
211
|
+
When joining to Opta, SportMonks, football-data.co.uk, or another fixture source:
|
|
212
|
+
|
|
213
|
+
- match by date plus home/away team aliases;
|
|
214
|
+
- keep the provider's final score as the fixture authority;
|
|
215
|
+
- store Understat `xG` and `xGA` as an enrichment layer;
|
|
216
|
+
- expose the xG model name so it is not confused with StatsBomb, Opta, or
|
|
217
|
+
provider-supplied expected-goals values.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# xG Timeline Recipes
|
|
2
|
+
|
|
3
|
+
Use an xG timeline when the product question is "when did each team create
|
|
4
|
+
danger?" rather than only "what was the final xG total?". The chart should be a
|
|
5
|
+
cumulative step view built from shot-level xG rows plus match-state annotations.
|
|
6
|
+
|
|
7
|
+
## Required shot fields
|
|
8
|
+
|
|
9
|
+
Normalise provider shots into one row per shot before building the timeline:
|
|
10
|
+
|
|
11
|
+
| Field | Required | Notes |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `minute` | yes | Regular match minute; exclude shots without a usable time |
|
|
14
|
+
| `second` | optional | Tie-breaker within a minute when available |
|
|
15
|
+
| `added_time` | optional | Preserve stoppage time for labels such as `45+2` |
|
|
16
|
+
| `period` | optional | Needed for extra-time guides and precise halftime handling |
|
|
17
|
+
| `team_id` | yes | Must resolve to home or away team |
|
|
18
|
+
| `player_name` | optional | Tooltip/label only |
|
|
19
|
+
| `xg` | yes | Provider/model xG value for the shot |
|
|
20
|
+
| `outcome` | optional | Goal, saved, post, missed, blocked, etc. |
|
|
21
|
+
| `is_penalty` | optional | Useful for filters or marker styling |
|
|
22
|
+
| `shot_id` | optional | Stable ordering and deduplication |
|
|
23
|
+
| `xg_model` | yes | `understat`, `statsbomb`, `opta`, or another named model |
|
|
24
|
+
|
|
25
|
+
Do not mix xG models silently. Understat, StatsBomb, Opta, and FBref/Opta values
|
|
26
|
+
come from different models and can disagree for the same shot. If a story blends
|
|
27
|
+
or compares models, expose the model name in the data and chart notes.
|
|
28
|
+
|
|
29
|
+
## Source-specific inputs
|
|
30
|
+
|
|
31
|
+
| Source | Timeline inputs |
|
|
32
|
+
|---|---|
|
|
33
|
+
| Understat | `minute`, `X`, `Y`, `xG`, `result`, `h_a`, `player`, `situation`, `shotType` |
|
|
34
|
+
| StatsBomb | shot event `minute`/`second`, `team`, `shot.statsbomb_xg`, `shot.outcome`, `shot.type`, `shot.body_part` |
|
|
35
|
+
| Opta / WhoScored-style events | shot event types `13`-`16`, xG qualifier where licensed, body-part/context qualifiers, goal-mouth qualifiers where available |
|
|
36
|
+
| FBref | season/match aggregates only; not enough for a shot-by-shot timeline |
|
|
37
|
+
|
|
38
|
+
For Opta-derived feeds, distinguish shot outcomes from score attribution. Type
|
|
39
|
+
`16` with own-goal qualifier `28` should update the score for the opposing team,
|
|
40
|
+
not the event contestant. Disallowed goals should be marked but should not change
|
|
41
|
+
the running scoreline.
|
|
42
|
+
|
|
43
|
+
## Cumulative step construction
|
|
44
|
+
|
|
45
|
+
Sort shots by period, minute, second, and a stable shot id if available. For each
|
|
46
|
+
shot, add the current xG value only to the shooting team's cumulative total and
|
|
47
|
+
carry the other team's total forward:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
home_cum_xg_after_shot =
|
|
51
|
+
previous_home_cum_xg + (shot.team_id == home_team_id ? shot.xg : 0)
|
|
52
|
+
away_cum_xg_after_shot =
|
|
53
|
+
previous_away_cum_xg + (shot.team_id == away_team_id ? shot.xg : 0)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Render the lines as steps, not smoothed curves. A shot changes the value at a
|
|
57
|
+
specific match moment; smoothing implies chance quality accrued continuously.
|
|
58
|
+
|
|
59
|
+
For a static chart, emit enough points to draw flat sections:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
(time_before_shot, previous_total)
|
|
63
|
+
(shot_time, previous_total)
|
|
64
|
+
(shot_time, new_total)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This keeps long quiet periods visible and avoids diagonal interpolation between
|
|
68
|
+
unrelated shots.
|
|
69
|
+
|
|
70
|
+
## Match-time guides
|
|
71
|
+
|
|
72
|
+
Add guide marks from match structure, not from shot distribution:
|
|
73
|
+
|
|
74
|
+
| Guide | Typical position |
|
|
75
|
+
|---|---|
|
|
76
|
+
| halftime | 45 minutes |
|
|
77
|
+
| full time | 90 minutes |
|
|
78
|
+
| extra-time halftime | 105 minutes |
|
|
79
|
+
| extra-time full time | 120 minutes |
|
|
80
|
+
|
|
81
|
+
If stoppage-time placement is flattened into minute values, say so in the output
|
|
82
|
+
or chart notes. Do not invent precise stoppage-time spacing when the source only
|
|
83
|
+
has minute-level timing.
|
|
84
|
+
|
|
85
|
+
## Running score strip
|
|
86
|
+
|
|
87
|
+
A score strip helps readers connect chance quality to actual goals. Build it from
|
|
88
|
+
goal events, not from xG values:
|
|
89
|
+
|
|
90
|
+
| Case | Score handling |
|
|
91
|
+
|---|---|
|
|
92
|
+
| normal goal | increment scoring team |
|
|
93
|
+
| own goal | increment the opponent of the event contestant when the provider encodes own goals that way |
|
|
94
|
+
| penalty goal | increment scoring team and optionally style the marker |
|
|
95
|
+
| disallowed goal | annotate separately; do not increment score |
|
|
96
|
+
| shootout penalty | keep outside the regular xG timeline unless the chart explicitly covers shootouts |
|
|
97
|
+
|
|
98
|
+
Keep goal markers visually distinct from all-shot dots. A goal is an outcome, not
|
|
99
|
+
a larger xG value.
|
|
100
|
+
|
|
101
|
+
## Sparse and empty matches
|
|
102
|
+
|
|
103
|
+
The fallback behaviour should be honest:
|
|
104
|
+
|
|
105
|
+
| Input state | Recommended output |
|
|
106
|
+
|---|---|
|
|
107
|
+
| no shots with xG | empty state; do not invent a flat 0-0 narrative |
|
|
108
|
+
| one team's shots only | that team's step line plus a flat zero baseline for the opponent |
|
|
109
|
+
| very sparse match | preserve the stepped geometry and show the low-event nature |
|
|
110
|
+
| missing team assignment | exclude the affected shot and record a data-quality warning |
|
|
111
|
+
| missing xG value | exclude from xG totals or render as an unvalued shot marker, but do not add `0` silently |
|
|
112
|
+
|
|
113
|
+
## Data contract for agents
|
|
114
|
+
|
|
115
|
+
When generating data for a reusable xG timeline, include:
|
|
116
|
+
|
|
117
|
+
- `match_id`, `home_team_id`, `away_team_id`;
|
|
118
|
+
- a sorted `shots[]` array with raw provider id where available;
|
|
119
|
+
- `xg_model` and provider/source for every xG value;
|
|
120
|
+
- `score_events[]` for running score reconstruction;
|
|
121
|
+
- `time_guides[]` for halftime/full-time/extra-time markers;
|
|
122
|
+
- `data_quality[]` warnings for excluded shots, missing xG, missing teams, or
|
|
123
|
+
source/model mismatches.
|
|
@@ -78,9 +78,8 @@ is globally stable until that is confirmed in the contract or repeated exports.
|
|
|
78
78
|
- If profile attributes are thin, keep Impect as a corroborator rather than a
|
|
79
79
|
canonical mint source.
|
|
80
80
|
|
|
81
|
-
##
|
|
81
|
+
## Implementation Notes
|
|
82
82
|
|
|
83
83
|
Use this page as the public provider-fact reference for Impect identity field
|
|
84
|
-
families and matching cautions.
|
|
85
|
-
|
|
86
|
-
review outcomes belong outside football-docs.
|
|
84
|
+
families and matching cautions. Keep customer deliveries, non-public IDs, raw feed
|
|
85
|
+
payloads, and register review outcomes outside football-docs.
|