mirror of
https://github.com/LucasKalil-Programador/world-2026-hub.git
synced 2026-07-04 17:41:28 -03:00
194 lines
8 KiB
Markdown
194 lines
8 KiB
Markdown
# How to Refresh Data — Daily Tournament Updates
|
||
|
||
Self-contained runbook (can be pasted as a prompt to an AI agent) for keeping the
|
||
hub current **during** the World Cup (2026-06-11 → 2026-07-19). The full mock→real
|
||
migration is done (2026-06-12, see `.agents/project-memory.md`) — this guide covers
|
||
only what changes **day after day** from here on.
|
||
|
||
---
|
||
|
||
## TL;DR — what changes vs what never changes
|
||
|
||
| File | Changes? | When |
|
||
|---|---|---|
|
||
| `data/results.json` | ✅ **Daily** | After every matchday — scores + status |
|
||
| `data/bracket-config.json` → `thirdPlaceAssignment` | ✅ **Once** | After the group stage ends (last matches ~2026-06-27, ids 61–72) |
|
||
| `data/matches.json` | ⚠️ Rare | Only if FIFA officially reschedules a kickoff/venue |
|
||
| `data/stadiums.json` | ❌ Never | Venues are fixed for the whole tournament |
|
||
| `data/teams.json` | ❌ Never | The 48 qualifiers are final |
|
||
| `data/groups.json` | ❌ Never | The draw is final |
|
||
| `data/bracket-config.json` → `round32` | ❌ Never | Official bracket structure, already encoded |
|
||
| `assets/`, code, `index.html` | ❌ Never | Data-only updates by design |
|
||
|
||
If you find yourself editing anything in the ❌ rows, stop — something is wrong.
|
||
|
||
---
|
||
|
||
## Daily routine: update `results.json`
|
||
|
||
### 1. Find which matches happened since the last update
|
||
|
||
Match ids in `matches.json`: **1–72 = group stage, chronological by UTC kickoff**;
|
||
**73–104 = knockout, FIFA official match numbers**. Look up matches by `date`
|
||
(UTC — a 9 p.m. PDT game lands on the *next* UTC day) and team ids, never assume
|
||
id ranges by group.
|
||
|
||
```
|
||
Group stage runs Jun 11–28 (UTC dates) · R32 Jun 28–Jul 4 · R16 Jul 4–7
|
||
QF Jul 9–12 · SF Jul 14–15 · 3rd place Jul 18 · Final Jul 19 (UTC dates)
|
||
```
|
||
|
||
### 2. Get real scores — never invent
|
||
|
||
Web-search each played match and cross-check **two sources** (Wikipedia group/
|
||
knockout articles update fast; ESPN/FOX/olympics.com as second source). If a
|
||
result can't be confirmed in two sources, leave it `scheduled` and tell the user.
|
||
|
||
### 3. Edit the entries
|
||
|
||
Keep the exact schema — only flip these fields:
|
||
|
||
```json
|
||
{ "matchId": 4, "homeScore": null, "awayScore": null, "status": "scheduled" } ← before
|
||
{ "matchId": 4, "homeScore": 2, "awayScore": 1, "status": "finished" } ← after full-time
|
||
{ "matchId": 5, "homeScore": 1, "awayScore": 0, "status": "live" } ← only if in progress right now
|
||
```
|
||
|
||
Rules:
|
||
- `status` enum is exactly `"scheduled"` | `"live"` | `"finished"` — nothing else.
|
||
- Only `finished` feeds standings and bracket resolution; `live` is display-only.
|
||
- **Knockout matches only:** if decided on penalties, keep `homeScore`/`awayScore`
|
||
as the 90+30-min score (can be equal) and add
|
||
`"penalties": { "home": 4, "away": 3 }`. Never add `penalties` to group matches.
|
||
- Never delete/reorder entries; never change a `matchId`.
|
||
|
||
> ⚠️ First pending item: **match id 4 (USA vs Paraguay)** kicked off 2026-06-13
|
||
> 01:00 UTC and is still `scheduled` in the data.
|
||
|
||
### 4. Cache-busting (no longer a manual step)
|
||
|
||
There is **no `DATA_VERSION` to bump**. `loadData()` appends `?t=${Date.now()}`
|
||
to every `data/*.json` fetch, so each page load gets a fresh URL and Hostinger
|
||
can never serve a stale `results.json`. Just edit the data and ship — nothing
|
||
to bump.
|
||
|
||
---
|
||
|
||
## One-time: `thirdPlaceAssignment` (after ~Jun 27–28)
|
||
|
||
When all 72 group matches are `finished`, FIFA publishes the ranking of
|
||
third-placed teams and which group's 3rd goes to which R32 slot. Fill
|
||
`data/bracket-config.json`:
|
||
|
||
```json
|
||
"thirdPlaceAssignment": { "1": "C", "2": "G", ... } // slot → group LETTER, not team id
|
||
```
|
||
|
||
Each slot only accepts certain groups (official draw constraint — use FIFA's
|
||
published allocation, it will respect this):
|
||
|
||
| Slot | Feeds (FIFA match) | Allowed groups |
|
||
|---|---|---|
|
||
| 1 | M74 (vs Winner E) | A/B/C/D/F |
|
||
| 2 | M77 (vs Winner I) | C/D/F/G/H |
|
||
| 3 | M81 (vs Winner D) | B/E/F/I/J |
|
||
| 4 | M82 (vs Winner G) | A/E/H/I/J |
|
||
| 5 | M79 (vs Winner A) | C/E/F/H/I |
|
||
| 6 | M80 (vs Winner L) | E/H/I/J/K |
|
||
| 7 | M85 (vs Winner B) | E/F/G/I/J |
|
||
| 8 | M87 (vs Winner K) | D/E/I/J/L |
|
||
|
||
Each group letter appears in **at most one** slot. Slots without a published
|
||
assignment stay `null` (the UI shows "Best 3rd #N" — that's correct).
|
||
|
||
Partially-finished group stage: you can fill slots early only if FIFA has; do
|
||
not derive assignments yourself.
|
||
|
||
---
|
||
|
||
## Rare: schedule changes in `matches.json`
|
||
|
||
Only if FIFA officially changes a kickoff time or venue:
|
||
- `date`/`time` are **UTC** — convert from the announced local time yourself.
|
||
- `stadium`/`city` must exactly match a `name`/`city` pair in `stadiums.json`.
|
||
- Never touch `id`, `phase`, `homeTeam`/`awayTeam`, `bracketRef`.
|
||
|
||
Known caveat to re-verify near Jul 6: **match 94** (R16, Lumen Field) kickoff was
|
||
single-source (Wikipedia 17:00 PDT vs one ESPN summary implying 14:00 PDT).
|
||
|
||
---
|
||
|
||
## Verify after every refresh
|
||
|
||
1. Quick integrity scan of `results.json`: exactly 104 entries, `matchId` 1–104
|
||
unique, every entry has a valid `status`, `penalties` only on ids 73–104.
|
||
2. Serve the app (Claude Preview `worldcup2026`, port 8126 — never `file://`),
|
||
hard-reload with cache bypass (browser caches JSON aggressively):
|
||
```js
|
||
Promise.all(['data/results.json','data/bracket-config.json']
|
||
.map(f => fetch(f, { cache: 'reload' }))).then(() => location.reload())
|
||
```
|
||
3. Spot-check: **Groups** standings of the groups that played vs a real-world
|
||
table; **Home** hero shows the right live/next match; after
|
||
`thirdPlaceAssignment` is filled, **Knockout** R32 shows real team names.
|
||
4. Console must stay free of errors.
|
||
|
||
## Commit convention (standardized)
|
||
|
||
Every `/update-worldcup` run produces **two commits**, in this order, with these
|
||
exact subject formats — do not improvise per run.
|
||
|
||
### 1. Data commit — `results.json` (+ `bracket-config.json` when the third-place fill happens)
|
||
|
||
- **One match:**
|
||
```
|
||
data: update DD/MM/YYYY HH:MM HOMExAWAY HxA
|
||
```
|
||
e.g. `data: update 15/06/2026 18:00 BELxEGY 1x1`
|
||
- **Multiple matches:** short subject, one body line per match:
|
||
```
|
||
data: update DD/MM/YYYY — N jogos
|
||
|
||
HH:MM HOMExAWAY HxA
|
||
HH:MM HOMExAWAY HxA
|
||
```
|
||
|
||
Rules:
|
||
- `DD/MM/YYYY` and `HH:MM` are the match's **UTC** date/kickoff (same UTC used in
|
||
`matches.json` — a 9 p.m. PDT game is the next UTC day).
|
||
- Team codes are the 3-letter uppercase ids; separators are lowercase `x`
|
||
(`HOMExAWAY` and `HxA`).
|
||
- **Penalties** (knockout only): append `(pen HxA)`, e.g.
|
||
`data: update 04/07/2026 20:00 BRAxARG 1x1 (pen 4x3)`.
|
||
- (No `DATA_VERSION` bump rides along anymore — cache-busting is automatic via `?t=Date.now()`.)
|
||
- The one-time `thirdPlaceAssignment` fill rides in the same data commit; note it
|
||
in the body line (`+ thirdPlaceAssignment filled`).
|
||
|
||
### 2. Docs commit — `.agents/` memory + TODO log
|
||
|
||
```
|
||
docs: log daily refresh DD/MM/YYYY
|
||
```
|
||
|
||
`.agents/` is excluded from the FTP deploy, so keeping it a separate commit keeps
|
||
the data commit (the one that actually changes the live site) a clean diff.
|
||
|
||
> The previous habit of letting `/git-semantic-commit` invent a fresh subject
|
||
> each run (`data: update match 13 result and stats`, `data: update match 12 …`)
|
||
> is **retired** — use the formats above verbatim.
|
||
|
||
## After finishing
|
||
|
||
Update `.agents/project-memory.md` → **Current State** section (do **not** append a new dated
|
||
section — that habit bloated the file and duplicated git):
|
||
|
||
1. Refresh the header line: data through match id N, finished count, `APP_VERSION`.
|
||
2. Update the **"Recent refreshes (rolling — keep the last 3)"** list: add today's entry at the top
|
||
and **delete the oldest** so only the last 3 dated entries remain. Each entry is one compact line
|
||
(`DD/MM or YYYY-MM-DD (revN) — matches X–Y: HOME H–A AWAY, …`); per-match sources live in the git
|
||
commit, not here.
|
||
3. Adjust **Pending / next** if a milestone was reached (e.g. `thirdPlaceAssignment` filled).
|
||
4. Tick anything completed in `.agents/TODO.md` §6.
|
||
|
||
Only **durable** new facts (a new gotcha, a decision) go into
|
||
the other sections of `project-memory.md` — never a daily refresh log.
|