diff --git a/031_round_play_formats.sql b/031_round_play_formats.sql new file mode 100644 index 0000000..ec1bc9a --- /dev/null +++ b/031_round_play_formats.sql @@ -0,0 +1,68 @@ +-- ===================================================================== +-- TeeCup — ekte spillformer for frittstående runder (migrasjon 031, +-- ADR-039) +-- ===================================================================== +-- Utvider round.play_format (ADR-038) fra en ren HCP-eksklusjons-etikett +-- til å faktisk styre scoringsmodell + scorekort: match/fourball/ +-- foursome/greensome/scramble trenger et "sider"-konsept (Beslutning A), +-- og delt-ball-formatene (foursome/greensome/scramble) trenger én +-- kombinert score PER SIDE per hull i stedet for per spiller +-- (Beslutning C) -- gjenbruker samme nullable-nøkkel-mønster som +-- org-scopet `hole_score` (migrasjon 001) i stedet for en helt ny tabell. +-- ===================================================================== + +\set ON_ERROR_STOP on + +ALTER TABLE round DROP CONSTRAINT round_play_format_check; +ALTER TABLE round ADD CONSTRAINT round_play_format_check + CHECK (play_format IN ('stroke', 'match', 'skins', 'fourball', 'foursome', 'greensome', 'scramble_2', 'scramble_4')); + +-- Skins (Beslutning D) -- kun meningsfullt når play_format='skins', +-- håndheves i app-laget (samme "kun meningsfullt for..."-mønster som +-- resten av round -- ikke en tabellbasert CHECK på tvers av kolonner). +ALTER TABLE round ADD COLUMN skins_scoring text CHECK (skins_scoring IN ('net', 'gross')); +ALTER TABLE round ADD COLUMN skins_tie_handling text CHECK (skins_tie_handling IN ('carry', 'split')); + +-- --------------------------------------------------------------------- +-- Sider (Beslutning A) -- nøyaktig to per runde for match/fourball/ +-- foursome/greensome/scramble, håndhevet i app-laget (samme mønster som +-- ADR-011s to-lags-grense for org-turneringer), ikke en DB-constraint. +-- --------------------------------------------------------------------- + +CREATE TABLE round_side ( + id uuid PRIMARY KEY DEFAULT gen_random_uuid(), + round_id uuid NOT NULL REFERENCES round(id) ON DELETE CASCADE, + label text +); + +CREATE INDEX ON round_side (round_id); + +ALTER TABLE round_participant ADD COLUMN round_side_id uuid REFERENCES round_side(id) ON DELETE SET NULL; + +-- Playing Handicap (relativ til motparten via match_play_strokes) -- +-- course_handicap_snapshot (eksisterende) er ABSOLUTT og uendret i +-- betydning; playing_handicap er den format-avledede enheten, samme +-- to-kolonne-mønster som org-scopet match_participant. +ALTER TABLE round_participant ADD COLUMN playing_handicap smallint; + +-- --------------------------------------------------------------------- +-- round_hole: nøyaktig ÉN av round_participant_id/round_side_id +-- (Beslutning C) -- delt-ball-formater (foursome/greensome/scramble) +-- lagrer én rad PER SIDE per hull, ikke per spiller. Individuell-ball- +-- formater (slagspill/match/fourball/skins) er uendret -- én rad per +-- DELTAKER per hull, som i dag. +-- --------------------------------------------------------------------- + +ALTER TABLE round_hole ALTER COLUMN round_participant_id DROP NOT NULL; +ALTER TABLE round_hole ADD COLUMN round_side_id uuid REFERENCES round_side(id) ON DELETE CASCADE; +ALTER TABLE round_hole ADD CONSTRAINT round_hole_owner_xor CHECK ( + ((round_participant_id IS NOT NULL)::int + (round_side_id IS NOT NULL)::int) = 1 +); + +ALTER TABLE round_hole DROP CONSTRAINT round_hole_round_participant_id_hole_number_key; +CREATE UNIQUE INDEX round_hole_participant_unique + ON round_hole (round_participant_id, hole_number) WHERE round_participant_id IS NOT NULL; +CREATE UNIQUE INDEX round_hole_side_unique + ON round_hole (round_side_id, hole_number) WHERE round_side_id IS NOT NULL; + +GRANT SELECT, INSERT, UPDATE, DELETE ON round_side TO teecup_app; diff --git a/ARCHITECTURE_DECISIONS.md b/ARCHITECTURE_DECISIONS.md index a8b8128..55401e0 100644 --- a/ARCHITECTURE_DECISIONS.md +++ b/ARCHITECTURE_DECISIONS.md @@ -3482,6 +3482,128 @@ er etablert), ikke behandlet som en feil. --- +## ADR-039: Ekte spillformer for frittstående runder (match/skins/par-lag) + +**Kontekst:** reist 2026-07-28, rett etter ADR-038: "Når en singlerunde +settes opp: Er dette en slagspillsrunde, en match mellom to spillere, +skins, eller en par- eller lag-konkurranse. Avhengig av svaret så må hcp +beregnes forskjellig, og også scorekortet vil se annerledes ut." Viktig +presisering: `round.play_format` (ADR-038) styrer i dag KUN et +HCP-eksklusjonsforslag — ikke selve scorings- eller scorekort-modellen. +Dette utvider `play_format` til å faktisk STYRE begge deler. + +Fire load-bærende beslutninger avklart eksplisitt med bruker +(AskUserQuestion, to runder) før denne ADR-en ble skrevet. + +### Beslutning A — To sider per runde, gjenbruker ADR-011s antakelse + +Match/fourball/foursome/greensome/scramble trenger et «hvem spiller +mot hvem»-konsept `round_participant` ikke har i dag (en flat liste +uten gruppering). Løst med nøyaktig TO SIDER per runde (ny +`round_side`-tabell), håndhevet i app-laget — samme mønster som +ADR-011s to-lags-grense for organisasjons-turneringer, ikke en +DB-constraint. En side er 1 spiller (match) eller 2+ (fourball/ +foursome/greensome/scramble_2/scramble_4). `round_participant. +round_side_id` (nullable — kun satt for to-sidede formater) knytter +deltakeren til sin side. + +### Beslutning B — Alle fire par-/lag-underformater fra start, samme motor som turneringer + +Bruker valgte bredt omfang: fourball, foursome, greensome OG begge +scramble-variantene (`scramble_2`/`scramble_4`) — ikke bare fourball +(som alene ville passet uendret inn i dagens skjema). + +**Gjenbruker den EKSISTERENDE, testede match-play-motoren fullstendig +uendret** (`handicap_engine.py` sin `Format`-enum, +`AllowanceStrategy`-familien, `match_play_strokes`, +`allocate_over_played_holes`, `compute_match_state`, `HoleResult`) — +ingen ny motorkode for disse fire formatene. Selve API-laget +(`app/routers/rounds.py`) porterer det allerede bevisste, +produksjonskjørte mønsteret fra `app/handicap.py`/`app/routers/ +scoring.py` (`compute_and_store_side_handicaps` → +`relative_strokes_for_match` → `_side_net`/`_compute_hole_results` → +`recompute_and_cache_match_state`), tilpasset `round`/`round_side` i +stedet for `match`/`team_side`. Samme `_SIDE_IS_UNIT`/`FORMAT_UNIT_SIZE`- +tabeller (hvor mange spillere som kreves per side før handicap kan +beregnes) gjenbrukes identisk. + +### Beslutning C — Delt-ball-formater: `round_hole` gjenbruker `hole_score`s nullable-nøkkel-mønster + +Foursome/greensome/scramble har ÉN kombinert score per SIDE per hull, +ikke én per spiller — akkurat samme situasjon som org-scopet +`hole_score` allerede løser (`match_participant_id` NULLABLE, delt-ball- +rader identifisert av `team_side` alene, to partielle unike indekser). +`round_hole.round_participant_id` gjøres NULLABLE, ny +`round_hole.round_side_id` lagt til, med samme +`(participant XOR side)`-CHECK og to partielle unike indekser som +originalen. For fourball/match (individuell ball) forblir `round_hole` +uendret, én rad per DELTAKER per hull, akkurat som i dag. + +**Konsekvens for statistikk (ADR-033 Beslutning B):** de detaljerte +per-hull-feltene (kølle/retning/chip/bunker/straffeslag/putt-lengde) gir +ingen entydig mening for en DELT ball (hvem sitt slag var det?) — for +delt-ball-formater lagres derfor KUN selve slagtallet på siderraden, +ingen av de andre detalj-feltene (samme "et fast sett felt, ikke fri +logg"-prinsipp, bare at feltsettet er tynnere for denne raden). + +### Beslutning D — Skins: konfigurerbar netto/brutto OG rullerer/deles, ny motorfunksjon + +Ingen eksisterende motorstøtte for skins i det hele tatt (ikke et +turnering-format). Bruker valgte at DEN SOM SETTER OPP runden skal +kunne velge BEGGE akser uavhengig — ikke ett fastlåst standardvalg: +- `round.skins_scoring`: `'net'` (HCP-slag trekkes fra, WHS-vanlig) | + `'gross'`. +- `round.skins_tie_handling`: `'carry'` (uavgjort hulls "skin" ruller + til neste hull, vinneren der tar hele potten) | `'split'` (uavgjort + hulls skin deles likt mellom de tied spillerne i stedet). + +Ny, ren, testbar motorfunksjon `compute_skins(scores_by_hole, +tie_handling)` i `handicap_engine.py` — tar allerede netto-ELLER-brutto- +avgjorte per-hull-scorer (kalleren bestemmer hvilket FØR kall, motoren +vet ikke selv om input er netto eller brutto), returnerer +`{participant_id: antall skins vunnet}` (float, siden 'split' kan gi +brøkdeler). Ingen sider trengs for skins — rent individuelt, som +slagspill. + +### Beslutning E — HCP-telling per format + +- **Slagspill, fourball, skins** (individuell ball — hver spiller har + en FULL, ekte brutto-score per hull): teller normalt mot faktisk HCP, + samme pipeline som i dag (Score Differential fra AGS). Bekreftet + eksplisitt av bruker for skins — "krever fullt utspilte hull (ingen + konsedering som i match) -- samme grunnlagsproblem som gjorde match + upålitelig gjelder ikke her." +- **Match** (uendret fra ADR-038): fortsatt "spør, anbefal + ekskludering" — Rule 3.3-problemet (konsederte hull) gjelder fortsatt + uendret. +- **Foursome/greensome/scramble** (delt ball — INGEN individuell score + finnes å telle): `counts_for_handicap` forblir usann for disse + deltakerne i disse rundene, alltid, uansett antall spilte hull. + Bekreftet eksplisitt av bruker som riktig løsning — matcher for + øvrig hvordan WHS i praksis også behandler delt-ball-formater (ikke + indeks-byggende på samme måte som individuell/fourball-spill). + +### Beslutning F — Scorekort-presentasjon (frontend, ikke bygget i denne runden) + +Notert for senere: match/fourball/foursome/greensome/scramble trenger +en løpende matchstatus-visning (gjenbruk av `describe()`-språket fra +`MatchState`, samme som `session-scorecard.tsx` allerede viser for +turnering-matcher) i stedet for rå slagsummer. Skins trenger en +skins-tavle (skins vunnet per spiller + hvilke hull som fortsatt er +"i potten"). Presist UI-design ikke gjort i denne runden — kun +backend/motor/skjema. + +### Konsekvens — hva som bygges i DENNE runden vs. senere + +Bruker valgte å gå rett til migrasjon + motor (ikke bare dokumentere). +Bygget: skjema (migrasjon 031), `compute_skins`-motorfunksjon + tester, +og backend-API for sider/delt-ball-scoring/format-resultat. Frontend +(nye skjermer for sideoppsett og de nye scorekort-presentasjonene, +Beslutning F) er en egen, senere runde — samme lagdeling som ADR-038 +(backend/motor FØR frontend). + +--- + ## Åpne spørsmål (ikke besluttet ennå) Disse må avklares før eller under de relevante fasene: @@ -3513,6 +3635,16 @@ Disse må avklares før eller under de relevante fasene: (sesong-sammenlagt på tvers av flere turneringer) — bekreftet som et beslektet, men SISTE steg, ikke designet ennå. Ingen migrasjon skrevet — ADR-037 er ren struktur-beslutning. +7. **Frittstående runder: ekte spillformer** (slagspill/match/skins/ + par-lag-konkurranse, reist 2026-07-28) — **AVKLART OG BACKEND BYGGET + SAMME DAG, se ADR-039.** `round.play_format` styrer nå faktisk både + HCP-beregning (via en portert versjon av turnering-motoren) og et + nytt `format-result`-lese-endepunkt for scorekort-presentasjon. + Fortsatt IKKE utrullet mot ekte systemer, og frontend (sideoppsett/ + skins-konfig/matchstatus-visning) fortsatt ikke bygget — se + FEATURE_BACKLOG.md. "Flere flighter i én frittstående runde" (egen + seksjon i FEATURE_BACKLOG.md) forblir et adskilt, ikke-relatert + spørsmål (grupperer RUNDER, ikke deltakere innad i én runde). --- diff --git a/CLAUDE.md b/CLAUDE.md index b6c6f9b..1ac1c07 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4071,6 +4071,226 @@ Ferdig og verifisert: ADR-037-arbeid), ingen egen "aging"-bakgrunnsjobb utover at spørringen alltid henter kun de 20 nyeste differensialene. +- **Ekte spillformer for frittstående runder (match/skins/fourball/ + foursome/greensome/scramble), BACKEND BYGGET OG SCRATCH-VERIFISERT, + IKKE ENNÅ RULLET UT MOT EKTE SYSTEMER (2026-07-28, ADR-039):** reist av + brukeren rett etter ADR-038: "Er dette en slagspillsrunde, en match + mellom to spillere, skins, eller en par- eller lag-konkurranse. + Avhengig av svaret så må hcp beregnes forskjellig, og også scorekortet + vil se annerledes ut." Fire load-bærende avklaringer (AskUserQuestion, + to runder) FØR bygging — bruker valgte det bredeste omfanget i alle + runder: to sider (Beslutning A), ALLE fire par-/lag-underformater fra + start inkl. de to delt-ball-krevende (Beslutning B), skins med BEGGE + akser konfigurerbare av oppsetteren (netto/brutto OG rullerer/deles, + Beslutning D), og gå rett til migrasjon+motor samme økt (ikke bare + dokumentere). + **Kjerneinnsikt som gjorde dette trygt å bygge fort:** hele match-play- + motoren (`handicap_engine.py` sin `Format`/`AllowanceStrategy`-familie/ + `match_play_strokes`/`compute_match_state`) og hele "delt-ball vs. + individuell"-mønsteret (`hole_score.match_participant_id` NULLABLE, + delt-ball-rader identifisert av `team_side` alene) fantes ALLEREDE, + bygget og produksjonskjørt for org-scopede turnering-matcher. Denne + runden PORTERER dette mønsteret til frittstående runder (nye + `round_side`/`round_participant.round_side_id`/`round_participant. + playing_handicap`/`round_hole.round_side_id`) i stedet for å finne opp + noe nytt — kun skins (ingen turnering-motstykke) fikk EKTE ny + motorkode (`compute_skins`, 7 nye tester, 50/50 i `test_handicap_ + engine.py`). `app/handicap.py` sin `_SIDE_IS_UNIT` omdøpt til + `SIDE_IS_UNIT` (gjort delt for gjenbruk, samme "fjern understrek når + et andre bruksted dukker opp"-mønster som tidligere runder). + **Skjema, migrasjon `031_round_play_formats.sql`:** `round.play_format` + utvidet til 8 verdier, nye `round.skins_scoring`/`skins_tie_handling`, + ny `round_side`-tabell (nøyaktig to per runde, håndhevet i app-laget + som ADR-011s to-lags-grense), `round_participant.round_side_id`/ + `playing_handicap` (sistnevnte ALDRI det samme som det eksisterende + `course_handicap_snapshot` — den absolutte WHS-verdien rørt av INGEN + av denne rundens kode), `round_hole.round_participant_id` gjort + NULLABLE + ny `round_hole.round_side_id` + XOR-CHECK + to partielle + unike indekser (samme mønster som org-scopet `hole_score`, migrasjon + 001). + **Reelt, bekreftet funn UNDER selve designet (ikke antatt), avklart + eksplisitt med bruker FØR bygging:** foursome/greensome/scramble har + ÉN kombinert score per SIDE per hull -- INGEN individuell score + finnes i det hele tatt å bygge en Score Differential fra. Løst + (Beslutning E, bekreftet av bruker): disse deltakerne får + `counts_for_handicap` ALDRI sann for disse rundene -- og viste seg, + presist verifisert i scratch, å følge HELT AUTOMATISK av den + eksisterende `complete_round`-logikken uten noen kodeendring i det + hele tatt (en delt-ball-deltaker har null individuelle `round_hole`- + rader, så `played_count` blir alltid 0, som `round_counts_for_ + handicap` allerede tolker som "teller ikke" for både 9- og + 18-hulls-intensjon). + **API (`app/routers/rounds.py`):** `POST/DELETE .../sides` (eier-only, + maks to, avvist for slagspill/skins), `ParticipantCreate`/ + `ParticipantUpdate` fikk `round_side_id` (eier-only reassignment, + validerer siden hører til samme runde), `_recompute_side_handicaps` + (porterer `compute_and_store_side_handicaps` — venter på at siden når + forventet spillerantall FØR den skriver noe, samme + "ikke komplett ennå = ikke skriv"-filosofi som originalen), + `_relative_strokes_for_round` (porterer `relative_strokes_for_match`), + nye `GET/PATCH .../sides/{id}/holes/{n}` (delt-ball-scoring, kun + slagtall — ingen av de andre detalj-feltene gir mening for en delt + ball), og et nytt lese-endepunkt `GET .../format-result` som regner + løpende matchstatus (gjenbruker `compute_match_state`/`HoleResult` + uendret) for de to-sidede formatene, eller en skins-tavle + (`compute_skins`) for skins — aldri lagret, alltid avledet ved lesing. + **To reelle bugs funnet OG fikset UNDER scratch-testing, ingen nådde + produksjon:** (1) side-tildelings-recompute kjørte FØR responsen ble + hentet i stedet for ETTER — testen fanget dette presist (forventet + `playing_handicap` i responsen, fikk `null` fra FØR omregningen); (2) + individuell-ball-gren i format-result-spørringen nøkkel-forvekslet + "enhet" (satte `round_side_id` som nøkkel i stedet for + `round_participant_id`, mens `side_net()`-oppslaget forventet + deltaker-id) — ga et tomt `hole_results` til tross for gyldige + registrerte scorer, fanget da `match_holes_played` kom ut som 0 i + stedet for det forventede 3. + **Scratch-verifisert grundig, 96/96 sjekker** (isolert + `teecup_app_scratch`-rolle + isolert scratch-MinIO + engangs API- + container via ekte HTTP, samme mønster som hele prosjektet): en + hånd-utregnet 3-hulls singles-match (hcp 5 vs. 10, riktig slagmottak + på de fem vanskeligste hullene) ga eksakt `lead=0`/"AS"/riktig + hole-for-hole-mønster; fourball bekreftet INDIVIDUELL (ikke kombinert) + 90 %-beregning per spiller, korrekt "ikke komplett ennå" før andre + spiller på siden var tildelt; foursome bekreftet 18 round_hole-rader + opprettet på SIDEN ved side-opprettelse (før noen deltaker lagt til), + korrekt kombinert 50 %-Playing-Handicap først når begge var tildelt, + ekte delt-ball-scoring via det nye sub-endepunktet, OG at + `counts_for_handicap` ble `False` for begge etter fullføring; skins + (netto+carry) ga eksakt `{sk3: 2.0}` for et 2-hulls scenario med et + bevisst konstruert uavgjort-så-carry-så-outright-vinn-mønster, OG + bekreftet skins teller NORMALT mot faktisk HCP etter full fullføring + (ulikt match). `test_isolation.sql` 12/12 uendret (additiv migrasjon). + Alle 50 handicap_engine-tester (43 eksisterende + 7 nye skins) grønne. + **IKKE bygget i denne runden, bevisst utsatt (Beslutning F):** + frontend — ingen skjerm for å opprette sider, tildele deltakere, + konfigurere skins, eller vise løpende matchstatus/skins-tavle. Backend + er fullt funksjonelt og testet, men ubrukelig fra selve appen inntil + frontend bygges i en egen, senere runde (samme lagdelings-mønster som + ADR-038: motor/skjema/API FØR frontend). + **Rullet ut mot ekte systemer 2026-07-28**, bruker bekreftet + eksplisitt: migrasjon 031 kjørt mot ekte `teecup_db` (nye kolonner/ + `round_side`-tabell bekreftet, `test_isolation.sql` fortsatt 12/12), + deretter `docker compose up -d --build teecup_api`. Ren boot, + `/health`/`/dashboard` → 200, ny rute bekreftet nåbar (anonymt + `POST .../sides` → 401, ikke en rå 404), `teeoff.no` upåvirket. + +- **Oppfølging samme dag: manglende minimums-spiller-håndhevelse fanget + og fikset, BYGGET OG SCRATCH-VERIFISERT, RULLET UT LIVE (2026-07-28):** + brukeren påpekte presist et hull ADR-039 selv ikke fanget opp: "Er det + match-spill, skins eller lagspill så MÅ det jo være flere spillere. + Dette fanges ikke opp." Riktig — ingenting hindret å fullføre en + "match" med kun eieren, eller la flere spillere enn formatet tillater + havne på samme side. Bekreftet med bruker (AskUserQuestion): skins + krever minst 3 spillere (2 gjør skins i praksis identisk med en vanlig + match — 3+ er der en oppsamlet, uavgjort pott faktisk gir mening). + **Bygget, ren Python-logikk, INGEN migrasjon:** ny + `_format_setup_status()` — slagspill alltid klar; skins krever minst + 3 deltakere; to-sidede formater (match/fourball/foursome/greensome/ + scramble) krever NØYAKTIG to sider, INGEN uassignerte deltakere, og + hver side nøyaktig riktig spillerantall for formatet + (`_SIDE_PLAYER_COUNT`, allerede definert). Ny `setup_complete`/ + `setup_message` på `RoundOut` (alltid synlig, uansett format/status). + `complete_round` avviser nå (409 `SETUP_INCOMPLETE`) hvis oppsettet + ikke er komplett — FØR noe regnes ut. Ny `_check_side_capacity()` + avviser (409 `SIDE_FULL`) proaktivt ved SELVE tildelingen (både + `POST .../participants` med `round_side_id` og `PATCH .../ + participants/{id}`), i stedet for å først oppdage overtallet ved + fullføring — med eksplisitt unntak for en no-op-reassignment til + samme side (en deltaker teller ikke seg selv ut av plassen sin egen + side har). + **Scratch-verifisert grundig, 122/122 sjekker** (samme isolerte + scratch-oppsett som resten av runden — full regresjon av alle + tidligere 96 sjekker PLUSS 26 nye): 3. spiller avvist på en full + match-/foursome-side (409 SIDE_FULL), `setup_complete` korrekt False + ved kun 1 av 2 sider / uassignerte deltakere / for få skins-spillere, + fullføring korrekt avvist (409 SETUP_INCOMPLETE) i alle disse + tilstandene, og korrekt True (+ vellykket fullføring) først når + oppsettet faktisk er komplett for formatet. `test_isolation.sql` + uendret (ingen skjemaendring). + **Rullet ut live 2026-07-28**, ingen migrasjon, kun + `docker compose up -d --build teecup_api`. Ren boot, `/health`/ + `/dashboard` → 200, `teeoff.no` upåvirket. +- **Frontend for ADR-039 (sider/skins/delt-ball-scoring) BYGGET, BROWSER- + VERIFISERT OG LIVE (2026-07-28), samme dag:** ingen backend-endring i + denne runden (alt allerede live) — ren frontend-jobb, testet reelt i + nettleser mot en isolert scratch-backend (Chrome DevTools), ikke bare + typesjekk. + **`new-round.tsx`:** spilleform-velgeren utvidet fra to (Slagspill/ + Match) til alle åtte format (Skins/Fourball/Foursome/Greensome/ + Scramble 2/4 lagt til), med en ny skins-konfigurasjonsseksjon (netto/ + brutto, rullerer/deles) som kun vises for `play_format="skins"` og et + forklarende "du setter opp sidene inni runden etterpå"-notat for de + to-sidede formatene (ADR-039 Beslutning A -- sider kan ikke opprettes + før deltakerne finnes). + **`round-detail.tsx` (hoveddelen):** ny `SidesPanel` (manage-fanen) -- + opprett/slett de to sidene, tildel/fjern deltakere (kompakte + "→ Side"-hurtigknapper, deaktivert når siden er full), viser + `playing_handicap` per side. Ny `FormatResultPanel` -- henter + `GET .../format-result`, viser løpende matchstatus (oversetter + motorens bokstavelige "(A)"/"(B)" til faktiske side-navn via + `round.sides[0]/[1]`, samme sorteringsrekkefølge som backend) eller en + skins-tavle (sortert synkende). `setup_complete`/`setup_message` + gater nå "Fullfør runde"-knappen klientside også (server er fortsatt + autoritativ). For delt-ball-formatene (foursome/greensome/scramble): + ny `SideScorecardGrid` (rader = sider, ikke spillere) + ny, forenklet + `SideScoreWizard` (kun slagtall, ingen putt/detalj-steg) mot de + eksisterende `GET/PATCH .../sides/{id}/holes/{n}`-endepunktene. + **To reelle stale-state-bugs funnet UNDER selve browserverifiseringen + (ikke i kodegjennomgang), begge fikset før utrulling:** + 1. `SidesPanel` sin `assign()` oppdaterte kun deltaker-listen lokalt + (via `onPatchParticipant`) -- `setup_complete`/`setup_message` + (server-beregnet) ble stående utdatert etter en vellykket + side-tildeling ("ikke tildelt en side" fortsatte å vises til tross + for at begge var tildelt). Fikset: `assign()` kaller nå + `onSidesChanged()` (full runde-refetch) etter en vellykket PATCH. + 2. `FormatResultPanel` sin refetch var kun koblet til hull-registrering + og WebSocket-signaler, ikke til side-/deltaker-tildeling -- + matchstatus ble stående på "venter..." selv etter at oppsettet var + komplett og "Fullfør runde" allerede var aktivert. Fikset ved å + bumpe `formatResultRefreshTick` ved HVER vellykket `loadRound()` + (enklere og mer robust enn å spore hvert enkelt kallsted som kan + påvirke handicap-beregningen). + **Verifisert grundig i en isolert scratch-nettleserøkt** (fersk + `teecup_scratch`-database, isolert scratch-MinIO, engangs API- + container, ekte `next dev` mot scratch-backend, Chrome DevTools MCP -- + ekte innlogging via magic-link, ekte profil-fullføring): tre komplette + runder bygget og spilt gjennom UI-et alene, ende-til-ende: + - **Match:** opprettet med eksklusjons-avkrysning forhåndshuket, + opprettet to sider, tildelte eier+gjest, bekreftet `playing_handicap` + (60/20) vist riktig, scoret hull 1 (4 mot 6) via `ScoringWizard` + (ubrørt komponent), bekreftet `FormatResultPanel` viste "1 UP + (Erol)" + riktig fargede hull-merker -- kryssjekket med + `aria-label`-attributtet direkte via `evaluate_script` for å bekrefte + semantisk korrekt side-navn bak den rå A/B-bokstaven. + - **Skins:** konfigurasjons-UI-et (netto/brutto, rullerer/deles) bekreftet + visuelt, opprettet med kun 1 spiller (satte-message "krever minst 3"), + la til to gjester til (meldingen forsvant idet den tredje ble lagt til, + "Fullfør runde" aktivert), scoret hull 1 for alle tre (via direkte + API-kall for hastighet, samme kontrakt som UI-et bruker), bekreftet + skins-tavlen -- **hånd-regnet og kryssjekket eksakt**: netto 1/4/3 for + de tre spillerne (course handicap 60/12/6, alle mottar 1 slag på + hull 1 unntatt eieren som mottar 4) ga korrekt "1 skin" til laveste + netto. + - **Foursome:** bekreftet "Opprett begge sidene..."-meldingen i Score- + fanen FØR sidene fantes (ingen krasj), opprettet to sider, la til tre + gjester, scoret hull 1 via `SideScorecardGrid`/`SideScoreWizard` + (5 mot 5 -- observerte LIVE at gridet oppdaterte seg bak selve + veiviseren), fant OG fikset de to stale-state-bugene over midt i + denne runden (glemte først å tildele spillerne til sider -- avdekket + nettopp fordi UI-et da IKKE viste feil tilstand, men en ekte utdatert + en), bekreftet til slutt `playing_handicap` kombinert riktig per side + (38/38 og 17/17) og at `FormatResultPanel` viste "1 UP (Rødt lag)" + -- kryssjekket for hånd at Rødt lag (høyere kombinert CH) mottar + slag på det vanskeligste hullet og derfor vinner nettoduellen 5 mot 5. + Ekte typesjekket + full produksjonsbuild kjørt på nytt ETTER + bug-fiksene (ikke bare før), alle 24 ruter listet. + **Rullet ut live 2026-07-28**, bruker bekreftet eksplisitt: ingen + migrasjon (ren frontend), `docker compose up -d --build + teecup_frontend` (gjenskapte også `teecup_api` som vanlig bivirkning, + ingen backend-kode rørt). Begge containere boot-et rent, `/health`/ + `/dashboard` → 200, `teeoff.no` upåvirket. **ADR-039 er dermed + fullstendig ferdig, backend og frontend, live.** + Neste steg: 0a. **Spillerliste-redesign — nå FAKTISK nettleser-bekreftet (2026-07-27, full 22-skjerms gjennomgang):** rendrer korrekt, ingen @@ -4286,3 +4506,12 @@ Neste steg: flighter i én frittstående runde fortsatt kun drøftet (se FEATURE_BACKLOG.md); (e) varsler koblet til venneforespørsler, ikke til rundehendelser ennå. +11. **Ferdig, kun for historikk:** ekte spillformer (match/skins/fourball/ + foursome/greensome/scramble) for frittstående runder — backend + (ADR-039 + minimums-spiller-håndhevelse) OG frontend (sideoppsett, + skins-konfig i `/my-rounds/new`, matchstatus-/skins-tavle-visning, + delt-ball-scorekort/-veiviser, `setup_complete`-gating) er nå BEGGE + bygget, browserverifisert og live (se status 2026-07-28). Mulig + fremtidig finpuss (ikke bedt om ennå): redigere et sidenavn i + etterkant (kun opprett/slett finnes i dag), en tydeligere + skins-poeng-forklaring i UI-et. diff --git a/FEATURE_BACKLOG.md b/FEATURE_BACKLOG.md index 97407f5..39ea85d 100644 --- a/FEATURE_BACKLOG.md +++ b/FEATURE_BACKLOG.md @@ -2916,6 +2916,108 @@ hvilke "første handling"-alternativer dashbordet bør vise i fremtiden. --- +## Frittstående runder: ekte spillformer (slagspill/match/skins/par-lag) — ✅ BACKEND BYGGET OG SCRATCH-VERIFISERT (ADR-039), IKKE ENNÅ rullet ut mot ekte systemer, frontend fortsatt ikke bygget + +**Oppdatering 2026-07-28 (ADR-039):** design + backend er ferdig samme +dag som punktet ble reist. Se CLAUDE.md-status 2026-07-28 for full +detalj (migrasjon `031`, nye endepunkter, 96/96 scratch-sjekker). Kort: +alle fire load-bærende spørsmål (sider/gruppering, omfang av par-/lag- +underformater, skins-regler, HCP-tellestatus for delt-ball) avklart med +bruker, hele match-play-motoren fra org-turneringer PORTERT uendret +(ingen ny regnelogikk for match/fourball/foursome/greensome/scramble), +kun skins fikk ekte ny motorkode. **Gjenstår:** frontend (ingen skjerm +for sideoppsett/skins-konfig/matchstatus-visning ennå) og selve +utrullingen mot ekte `teecup_db`/`teecup_api` — begge egne, separate +neste steg. + +Opprinnelig reist av brukeren rett etter at ADR-038 (faktisk HCP) ble +rullet ut: +"Når en singlerunde settes opp: Er dette en slagspillsrunde, en match +mellom to spillere, skins, eller en par- eller lag-konkurranse. Avhengig +av svaret så må hcp beregnes forskjellig, og også scorekortet vil se +annerledes ut." + +**Viktig presisering av hva som FINNES i dag, for å unngå forveksling:** +`round.play_format` (`'stroke'`/`'match'`, ADR-038) er i dag KUN en +selvdeklarert ETIKETT som styrer én ting — et forslag om å ekskludere +runden fra faktisk-HCP-grunnlaget. Den endrer INGENTING ved selve +scoringsmodellen eller scorekortet — en "matchspill"-runde i dag +registreres og vises identisk med en slagspill-runde (rå slag per hull +per spiller). Dette nye punktet ber om noe vesentlig større: at +spilleform faktisk STYRER både HCP-beregningen og scorekort- +presentasjonen, for fire distinkte typer. + +**De fire spillformene, og hva som mangler for hver:** +1. **Slagspill** — dagens modell, uendret. Allerede fullt bygget + (Score Differential/AGS, ADR-033 Beslutning G). +2. **Match (to spillere)** — trenger match-play-slagfordeling + (`match_play_strokes` i `handicap_engine.py`, allerede bygget/testet + for turnering-matcher) i stedet for `allocate_strokes_by_index`, og et + scorekort som viser løpende matchstatus (hull for hull vunnet/tapt/ + delt + "X UP"/"AS", samme presentasjonsspråk som + `session-scorecard.tsx` allerede har for turnering-matcher) i stedet + for rå slagsummer. **Reelt skjemahull:** `round_participant` har i dag + INGEN "hvem spiller mot hvem"-kobling — en runde med 3+ deltakere har + ingen måte å si at akkurat to av dem utgjør matchen. +3. **Skins** — hull-for-hull-konkurranse der laveste (netto eller + brutto) score på hullet vinner en "skin", uavgjort hull ruller + premien videre til neste hull. **Ingen eksisterende motorstøtte i det + hele tatt** — verken en beregningsfunksjon eller noen skjema-plass for + "skins vunnet"/gjeldende premieverdi. Må designes fra bunnen + (inkl. avklaring: netto eller brutto skins, rullerer uavgjort-verdien + videre eller deles, minst 3 spillere). +4. **Par- eller lag-konkurranse** — fourball/foursome/greensome/scramble- + type spill blant rundens deltakere. Motoren for AKKURAT dette + (`Format`-enum, `AllowanceStrategy`-familien, `unit_playing_handicap`) + er allerede bygget og testet — men KUN brukt av den org-scopede + turnering-modellen (`match`/`match_participant` under `session`). + **Reelt skjemahull, samme klasse som punkt 2:** frittstående + `round_participant`-rader er i dag rene individer uten noe + par-/lag-konsept — ingen kobling for "disse to er makkere denne + runden." + +**Sentral arkitektur-spenning, verdt å legge merke til FØR design +starter:** punkt 2 og 4 er strukturelt nesten IDENTISKE med det +`app/routers/matches.py`/`scoring.py` allerede gjør for org-scopede +turneringer (samme `Format`-enum, samme match-play-motor) — bare uten en +organisasjon rundt. Dette overlapper direkte med det ennå ubesluttede +spørsmålet i ADR-037 ("individuelle turneringer") og det tidligere +presiserte "flere flighter i én frittstående runde"-spørsmålet (se egen +seksjon over) — tre beslektede, men foreløpig separat behandlede +problemstillinger som alle til slutt lander på "hvordan grupperer/ +parer vi deltakere, og hvilken motor regner poeng fra rå slag." Bør +trolig avklares SAMMEN, ikke som tre uavhengige design-runder, for å +unngå tre parallelle, litt ulike implementasjoner av i bunn og grunn +samme idé. + +**Åpne spørsmål, ingen besvart ennå:** +- Skal `round.play_format` utvides med `'skins'`/`'pair_team'` (ny + migrasjon, ny CHECK-verdi), eller er dette en helt egen entitet + parallelt med `round`? +- Match/par-lag: hvordan velges/lagres hvem som spiller mot/med hvem — + ved oppsett (som blind draw for turneringer), eller fritt valgt av + eieren i etterkant? +- Skins: netto eller brutto, og hvordan behandles uavgjorte hull + (rullerer premien, eller deles)? +- Skal scorekortets NYE presentasjoner (matchstatus, skins-tavle, + side-score) bygges som varianter av eksisterende komponenter + (`round-scorecard.tsx`/`round-detail.tsx`), eller gjenbruke turnering- + sidens `session-scorecard.tsx`-språk direkte? +- Hvordan påvirker dette allerede byggede ADR-038 (faktisk HCP)? Match/ + skins/par-lag-runder trenger sannsynligvis EGNE regler for om/hvordan + de teller mot faktisk HCP (samme "matchspill telles vanligvis ikke"- + resonnement som allerede finnes for `'match'`, men skins/par-lag er + ikke vurdert i det hele tatt ennå). + +**Ingen kode skrevet** — dette er bevisst kun fanget/dokumentert nå, på +brukerens eksplisitte instruks. Trenger en egen, dedikert design-/ +ADR-runde (samme skala som ADR-033/036/037) før noe bygges, gitt at +punkt 2-4 hver krever nytt skjema, ny motorlogikk (for skins) eller +gjenbruk av eksisterende turnering-motor (for match/par-lag), og en +egen scorekort-presentasjon per format. + +--- + ## Én person, flere e-postadresser — DEL 1 (det enkle tilfellet) ✅ BYGGET OG LIVE 2026-07-21, DEL 2 (kontosammenslåing) fortsatt 📋 NOTERT Reist av brukeren rett etter ADR-032 (verifisert e-postbytte). Et beslektet, diff --git a/__pycache__/handicap_engine.cpython-312.pyc b/__pycache__/handicap_engine.cpython-312.pyc index a0355fa..4b62741 100644 Binary files a/__pycache__/handicap_engine.cpython-312.pyc and b/__pycache__/handicap_engine.cpython-312.pyc differ diff --git a/app/handicap.py b/app/handicap.py index 31f6e62..503f796 100644 --- a/app/handicap.py +++ b/app/handicap.py @@ -31,7 +31,7 @@ from handicap_engine import ( # Formater der ENHETEN som deler én Playing Handicap er SIDEN (foursome-paret, # greensome-paret, hele scramble-laget) -- ikke spilleren. Singles/fourball er # ikke med her: der er enheten spilleren, og beregnes individuelt. -_SIDE_IS_UNIT = {"foursome", "greensome", "scramble_2", "scramble_4"} +SIDE_IS_UNIT = {"foursome", "greensome", "scramble_2", "scramble_4"} FORMAT_UNIT_SIZE: dict[str, int] = { "singles": 1, @@ -134,7 +134,7 @@ async def compute_and_store_side_handicaps( team_side, ) - if format_ in _SIDE_IS_UNIT: + if format_ in SIDE_IS_UNIT: expected = FORMAT_UNIT_SIZE[format_] total_on_side = await conn.fetchval( "SELECT count(*) FROM match_participant WHERE match_id = $1 AND team_side = $2::team_side", @@ -162,7 +162,7 @@ async def compute_and_store_side_handicaps( for p in participants ] - if format_ in _SIDE_IS_UNIT: + if format_ in SIDE_IS_UNIT: playing = config.strategy.playing_handicap(course_handicaps) for p, ch in zip(participants, course_handicaps): await conn.execute( @@ -196,7 +196,7 @@ async def relative_strokes_for_match( ennå (se compute_and_store_side_handicaps) -- kalleren tolker det som "kan ikke avgjøre noen hull ennå". """ - if format_ in _SIDE_IS_UNIT: + if format_ in SIDE_IS_UNIT: rows = await conn.fetch( """ SELECT DISTINCT ON (team_side) team_side::text AS unit, playing_handicap diff --git a/app/routers/rounds.py b/app/routers/rounds.py index f258bf5..c6dcb7e 100644 --- a/app/routers/rounds.py +++ b/app/routers/rounds.py @@ -43,18 +43,28 @@ from .. import teeoff_client from ..auth import CurrentUser, get_current_user, get_current_user_from_websocket from ..db import plain_connection from ..errors import app_error, translate_db_errors +from ..handicap import SIDE_IS_UNIT, parse_allowance_config from ..realtime import broadcast_round_update, live_sockets_for_round from handicap_engine import ( + HoleResult, adjusted_gross_score, + allocate_over_played_holes, allocate_strokes_by_index, apply_index_caps, + compute_match_state, + compute_skins, course_handicap, + course_handicap_raw, handicap_index_from_differentials, low_handicap_index, + match_play_strokes, round_counts_for_handicap, + round_half_up, score_differential, ) +_RESULT_LABEL = {HoleResult.SIDE_A: "a", HoleResult.SIDE_B: "b", HoleResult.HALVED: "halved"} + router = APIRouter(tags=["rounds"]) @@ -399,6 +409,148 @@ async def _resolve_personal_course(personal_course_id: str) -> _ResolvedCourse: return resolved +async def _resolve_round_course(round_row) -> _ResolvedCourse: + if round_row["course_source"] == "teeoff": + return await _resolve_teeoff_course(round_row["teeoff_facility_slug"], int(round_row["teeoff_course_id"])) + return await _resolve_personal_course(round_row["personal_course_id"]) + + +# --------------------------------------------------------------------------- +# Sider og match-play-håndtering (ADR-039) -- porterer det allerede +# bevisste, produksjonskjørte mønsteret fra `app/handicap.py` sin +# `compute_and_store_side_handicaps`/`relative_strokes_for_match` +# (org-scopede turnering-matcher) til frittstående runder. SAMME motor +# (handicap_engine.py), samme allowance-familie -- ingen ny regnelogikk +# for match/fourball/foursome/greensome/scramble, kun andre tabeller. +# Ingen allowance_override-støtte i v1 (kun DEFAULT_MATCHPLAY_ALLOWANCES). +# --------------------------------------------------------------------------- + +async def _recompute_side_handicaps(conn, round_id: str, play_format: str) -> None: + """Beregn og lagre round_participant.playing_handicap for begge sider. + + Rører ALDRI course_handicap_snapshot (den absolutte, individuelle WHS- + verdien -- brukt uendret av slagspill-pipelinen) -- playing_handicap er + en egen, ny kolonne kun for den format-relative match-play-enheten. + """ + engine_format = _ROUND_FORMAT_TO_ENGINE_FORMAT[play_format] + config = parse_allowance_config(engine_format, None) + expected = _SIDE_PLAYER_COUNT[play_format] + + sides = await conn.fetch("SELECT id::text AS id FROM round_side WHERE round_id = $1", round_id) + for side in sides: + participants = await conn.fetch( + "SELECT id::text AS id, course_handicap_snapshot FROM round_participant WHERE round_side_id = $1", + side["id"], + ) + if len(participants) != expected or any(p["course_handicap_snapshot"] is None for p in participants): + continue # ikke komplett ennå, eller mangler HCP-sporing for noen + + if not config.use_handicap: + for p in participants: + await conn.execute("UPDATE round_participant SET playing_handicap = 0 WHERE id = $1", p["id"]) + continue + + course_handicaps = [float(p["course_handicap_snapshot"]) for p in participants] + if engine_format in SIDE_IS_UNIT: + playing = config.strategy.playing_handicap(course_handicaps) + for p in participants: + await conn.execute("UPDATE round_participant SET playing_handicap = $1 WHERE id = $2", playing, p["id"]) + else: + for p, ch in zip(participants, course_handicaps): + playing = config.strategy.playing_handicap([ch]) + await conn.execute("UPDATE round_participant SET playing_handicap = $1 WHERE id = $2", playing, p["id"]) + + +async def _relative_strokes_for_round(conn, round_id: str, play_format: str) -> dict[str, int]: + """Relative slag per scoringsenhet (porterer relative_strokes_for_match). + + Nøkkel = round_participant_id for match/fourball (fourball: begge sidene + samlet i ÉN liste før match_play_strokes, jf. R&A-regelen om at laveste + av alle fire spiller av scratch). Nøkkel = round_side_id for foursome/ + greensome/scramble. Returnerer {} hvis playing_handicap ikke er klart + for én eller flere enheter ennå. + """ + engine_format = _ROUND_FORMAT_TO_ENGINE_FORMAT[play_format] + config = parse_allowance_config(engine_format, None) + + if engine_format in SIDE_IS_UNIT: + rows = await conn.fetch( + """ + SELECT DISTINCT ON (round_side_id) round_side_id::text AS unit, playing_handicap + FROM round_participant WHERE round_id = $1 AND round_side_id IS NOT NULL + ORDER BY round_side_id + """, + round_id, + ) + else: + rows = await conn.fetch( + "SELECT id::text AS unit, playing_handicap FROM round_participant " + "WHERE round_id = $1 AND round_side_id IS NOT NULL", + round_id, + ) + + if not rows or any(r["playing_handicap"] is None for r in rows): + return {} + + absolutes = [r["playing_handicap"] for r in rows] + relative = match_play_strokes(absolutes) if config.use_matchplay_handicap else absolutes + return {r["unit"]: v for r, v in zip(rows, relative)} + + +async def _check_side_capacity( + conn, side_id: str, play_format: str, exclude_participant_id: str | None = None +) -> None: + """Avvis tydelig FØR en deltaker tildeles en side som allerede har + forventet antall spillere for formatet (2026-07-28 oppfølging) -- i + stedet for å oppdage overtallet først ved fullføring. `exclude_ + participant_id` unngår at en deltaker som allerede ER på siden (f.eks. + en no-op-reassignment til samme side) teller seg selv ut av plass.""" + expected = _SIDE_PLAYER_COUNT[play_format] + current_count = await conn.fetchval( + "SELECT count(*) FROM round_participant WHERE round_side_id = $1 AND id != $2", + side_id, exclude_participant_id or "00000000-0000-0000-0000-000000000000", + ) + if current_count >= expected: + raise app_error( + 409, "SIDE_FULL", + f"Denne siden har allerede {expected} spiller(e) -- maks for {play_format}.", + ) + + +async def _format_setup_status(conn, round_id: str, play_format: str) -> tuple[bool, str | None]: + """Er rundens deltaker-/side-oppsett komplett for FORMATET (2026-07-28 + oppfølging): match/skins/fourball/foursome/greensome/scramble krever + flere spillere enn slagspill -- ingenting fanget dette opp før nå. + Returnerer (komplett, forklarende melding hvis ikke).""" + if play_format == "stroke": + return True, None + + if play_format == "skins": + total = await conn.fetchval("SELECT count(*) FROM round_participant WHERE round_id = $1", round_id) + if total < _SKINS_MIN_PARTICIPANTS: + return False, f"Skins krever minst {_SKINS_MIN_PARTICIPANTS} spillere -- runden har {total}." + return True, None + + # To-sidede formater (match/fourball/foursome/greensome/scramble_*). + expected = _SIDE_PLAYER_COUNT[play_format] + sides = await conn.fetch("SELECT id::text AS id, label FROM round_side WHERE round_id = $1 ORDER BY id", round_id) + if len(sides) != 2: + return False, "Denne spilleformen krever nøyaktig to sider -- opprett begge før runden fullføres." + + unassigned = await conn.fetchval( + "SELECT count(*) FROM round_participant WHERE round_id = $1 AND round_side_id IS NULL", round_id + ) + if unassigned > 0: + return False, f"{unassigned} deltaker(e) er ikke tildelt noen side ennå." + + for side in sides: + count = await conn.fetchval("SELECT count(*) FROM round_participant WHERE round_side_id = $1", side["id"]) + if count != expected: + label = side["label"] or "En side" + return False, f"{label} har {count} spiller(e), men trenger nøyaktig {expected}." + return True, None + + # --------------------------------------------------------------------------- # Runder # --------------------------------------------------------------------------- @@ -408,6 +560,29 @@ async def _resolve_personal_course(personal_course_id: str) -> _ResolvedCourse: # av som default. GIR krever putts og vises derfor ikke i strokes_only. StatLevel = Literal["strokes_only", "strokes_and_putts", "full"] +# ADR-039: formater som bruker et to-siders-konsept (Beslutning A). "match" +# er rundens eget navn for singles match play -- mappes til motorens eget +# Format-enum-navn ("singles") kun når handicap_engine.py/app.handicap +# kalles, ikke noe sted ellers. +_TWO_SIDED_FORMATS = {"match", "fourball", "foursome", "greensome", "scramble_2", "scramble_4"} +_ROUND_FORMAT_TO_ENGINE_FORMAT = { + "match": "singles", + "fourball": "fourball", + "foursome": "foursome", + "greensome": "greensome", + "scramble_2": "scramble_2", + "scramble_4": "scramble_4", +} +# Antall SPILLERE forventet per side -- IKKE det samme som app.handicap sin +# FORMAT_UNIT_SIZE (som er HCP-BEREGNINGS-enheten: fourball beregnes +# individuelt der, men har likevel 2 spillere per side for selve +# matchresultat-sammenligningen). +_SIDE_PLAYER_COUNT = {"match": 1, "fourball": 2, "foursome": 2, "greensome": 2, "scramble_2": 2, "scramble_4": 4} +# Bekreftet av bruker (2026-07-28): 2 spillere gjør skins i praksis +# identisk med en vanlig match -- 3+ er der en oppsamlet, uavgjort pott +# faktisk gir mening som eget spillformat. +_SKINS_MIN_PARTICIPANTS = 3 + class RoundCreate(BaseModel): course_source: Literal["teeoff", "custom"] @@ -425,12 +600,21 @@ class RoundCreate(BaseModel): # Utslagstidspunkt (2026-07-24) -- valgfritt, brukt til å beregne # tidsbruk (completed_at - started_at) når runden fullføres. started_at: datetime | None = None - # Selvdeklarert spilleform (ADR-038 Beslutning D) -- ingen egen - # match-motor for frittstående runder, så dette taes brukerens ord for. - play_format: Literal["stroke", "match"] = "stroke" + # Selvdeklarert spilleform (ADR-038 Beslutning D, utvidet ADR-039) -- + # ingen egen "oppdag selv"-motor for frittstående runder, så dette taes + # brukerens ord for. match/fourball/foursome/greensome/scramble_* + # trenger sider (opprettes separat via POST .../sides, se ADR-039 + # Beslutning A) -- IKKE noe som settes opp i selve opprett-kallet. + play_format: Literal[ + "stroke", "match", "skins", "fourball", "foursome", "greensome", "scramble_2", "scramble_4" + ] = "stroke" # Frontend forhåndsutfyller denne til True når play_format='match' # (anbefalt, men overstyrbart) -- eierens EGEN rad ved opprettelse. exclude_owner_from_handicap: bool = False + # KUN meningsfulle (og påkrevd) når play_format='skins' -- ADR-039 + # Beslutning D. Brukeren som setter opp runden velger begge uavhengig. + skins_scoring: Literal["net", "gross"] | None = None + skins_tie_handling: Literal["carry", "split"] | None = None class RoundParticipantOut(BaseModel): @@ -461,6 +645,18 @@ class RoundParticipantOut(BaseModel): # counts_for_handicap. Kontrolleres av DENNE deltakeren selv (eller # runde-eieren), se update_participant. exclude_from_handicap: bool + # ADR-039 Beslutning A -- hvilken side deltakeren er på (match/fourball/ + # foursome/greensome/scramble_*), null for slagspill/skins (ingen sider). + round_side_id: str | None + # ADR-039 Beslutning B -- den format-avledede, RELATIVE match-play- + # enheten (fra AllowanceStrategy), IKKE samme som course_handicap_ + # snapshot (som forblir den absolutte, individuelle WHS-verdien). + playing_handicap: int | None + + +class RoundSideOut(BaseModel): + id: str + label: str | None class RoundOut(BaseModel): @@ -473,9 +669,18 @@ class RoundOut(BaseModel): start_hole: int holes_planned: int play_format: str + skins_scoring: str | None + skins_tie_handling: str | None started_at: str | None completed_at: str | None participants: list[RoundParticipantOut] + # ADR-039 Beslutning A -- tom liste for formater uten sider (slagspill/skins). + sides: list[RoundSideOut] + # 2026-07-28 oppfølging -- match/skins/fourball/foursome/greensome/ + # scramble krever flere spillere enn slagspill, håndhevet i + # complete_round. setup_message er None når setup_complete er sann. + setup_complete: bool + setup_message: str | None # Den SPØRRENDE brukerens (eier ELLER en lenket medspiller, ADR-036 # fase 3-utvidelsen 2026-07-26) egen fremdrift/score, utledet fra # round_hole (aldri lagret) -- omdøpt fra `owner_*` til `my_*` samme @@ -490,7 +695,8 @@ async def _load_round_out(conn, round_id: str, viewer_user_id: str) -> RoundOut: round_row = await conn.fetchrow( """ SELECT id::text AS id, course_source, name, course_name_snapshot, tee_name_snapshot, - played_at, start_hole, holes_planned, play_format, started_at, completed_at + played_at, start_hole, holes_planned, play_format, skins_scoring, skins_tie_handling, + started_at, completed_at FROM round WHERE id = $1 """, round_id, @@ -503,13 +709,17 @@ async def _load_round_out(conn, round_id: str, viewer_user_id: str) -> RoundOut: rp.handicap_index_snapshot::float AS handicap_index_snapshot, rp.course_handicap_snapshot, rp.counts_for_handicap, rp.score_differential::float AS score_differential, rp.stat_level, - rp.exclude_from_handicap + rp.exclude_from_handicap, rp.round_side_id::text AS round_side_id, + rp.playing_handicap FROM round_participant rp LEFT JOIN app_user au ON au.id = rp.user_id WHERE rp.round_id = $1 ORDER BY rp.is_owner DESC, rp.created_at """, round_id, ) + side_rows = await conn.fetch( + "SELECT id::text AS id, label FROM round_side WHERE round_id = $1 ORDER BY id", round_id + ) # Viewer-relativt (ADR-036 fase 3-utvidelsen 2026-07-26): en lenket # medspiller som ser SIN EGEN "Egne runder"-liste skal se SIN EGEN # fremdrift her, ikke alltid eierens. Faller tilbake til eierens rad @@ -532,6 +742,7 @@ async def _load_round_out(conn, round_id: str, viewer_user_id: str) -> RoundOut: my_score_to_par = ( viewer_agg["total_score"] - viewer_agg["total_par"] if my_holes_played > 0 else None ) + setup_complete, setup_message = await _format_setup_status(conn, round_id, round_row["play_format"]) return RoundOut( id=round_row["id"], course_source=round_row["course_source"], @@ -542,9 +753,14 @@ async def _load_round_out(conn, round_id: str, viewer_user_id: str) -> RoundOut: start_hole=round_row["start_hole"], holes_planned=round_row["holes_planned"], play_format=round_row["play_format"], + skins_scoring=round_row["skins_scoring"], + skins_tie_handling=round_row["skins_tie_handling"], started_at=round_row["started_at"].isoformat() if round_row["started_at"] else None, completed_at=round_row["completed_at"].isoformat() if round_row["completed_at"] else None, participants=[RoundParticipantOut(**dict(r)) for r in participant_rows], + sides=[RoundSideOut(**dict(r)) for r in side_rows], + setup_complete=setup_complete, + setup_message=setup_message, my_holes_played=my_holes_played, my_total_score=my_total_score, my_score_to_par=my_score_to_par, @@ -565,6 +781,8 @@ async def _create_participant( stat_level: StatLevel = "strokes_only", guest_email: str | None = None, exclude_from_handicap: bool = False, + round_side_id: str | None = None, + individual_round_hole: bool = True, ) -> str: rating = resolved.rating_for(tee_name, gender) course_rating = slope_rating = tee_par = None @@ -579,8 +797,8 @@ async def _create_participant( INSERT INTO round_participant (round_id, user_id, guest_name, guest_email, is_owner, gender, tee_name_snapshot, handicap_index_snapshot, course_rating_snapshot, slope_rating_snapshot, tee_par_snapshot, course_handicap_snapshot, - stat_level, exclude_from_handicap) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) + stat_level, exclude_from_handicap, round_side_id) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) RETURNING id::text AS id """, round_id, @@ -597,17 +815,23 @@ async def _create_participant( course_handicap_snapshot, stat_level, exclude_from_handicap, + round_side_id, ) participant_id = participant_row["id"] - for hole_number, par, stroke_index in resolved.holes: - await conn.execute( - "INSERT INTO round_hole (round_participant_id, hole_number, par, stroke_index) VALUES ($1, $2, $3, $4)", - participant_id, - hole_number, - par, - stroke_index, - ) + # ADR-039 Beslutning C -- delt-ball-formater (foursome/greensome/ + # scramble) lagrer scoren PÅ SIDEN (round_hole.round_side_id, opprettet + # samtidig med selve siden, se create_round_side), ikke per deltaker -- + # ingen individuelle round_hole-rader for disse. + if individual_round_hole: + for hole_number, par, stroke_index in resolved.holes: + await conn.execute( + "INSERT INTO round_hole (round_participant_id, hole_number, par, stroke_index) VALUES ($1, $2, $3, $4)", + participant_id, + hole_number, + par, + stroke_index, + ) return participant_id @@ -625,6 +849,17 @@ async def create_round( raise app_error(400, "VALIDATION_FAILED", "personal_course_id er påkrevd.") resolved = await _resolve_personal_course(body.personal_course_id) + # ADR-039 Beslutning D -- skins-konfigurasjon er påkrevd for skins, og + # gir ikke mening for noe annet format. + if body.play_format == "skins": + if body.skins_scoring is None or body.skins_tie_handling is None: + raise app_error( + 400, "VALIDATION_FAILED", + "skins_scoring og skins_tie_handling er påkrevd når play_format='skins'.", + ) + elif body.skins_scoring is not None or body.skins_tie_handling is not None: + raise app_error(400, "VALIDATION_FAILED", "skins_scoring/skins_tie_handling gir kun mening for play_format='skins'.") + async with plain_connection() as conn: owner_row = await conn.fetchrow( "SELECT gender, handicap_index::float AS handicap_index FROM app_user WHERE id = $1", @@ -645,8 +880,9 @@ async def create_round( INSERT INTO round (owner_user_id, course_source, teeoff_facility_slug, teeoff_course_id, personal_course_id, course_name_snapshot, tee_name_snapshot, played_at, - start_hole, holes_planned, started_at, name, play_format) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13) + start_hole, holes_planned, started_at, name, play_format, + skins_scoring, skins_tie_handling) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) RETURNING id::text AS id """, user.user_id, @@ -662,6 +898,8 @@ async def create_round( body.started_at, body.name.strip() if body.name and body.name.strip() else None, body.play_format, + body.skins_scoring, + body.skins_tie_handling, ) round_id = round_row["id"] @@ -671,6 +909,7 @@ async def create_round( gender=owner_row["gender"], handicap_index=owner_row["handicap_index"], stat_level=body.stat_level, exclude_from_handicap=body.exclude_owner_from_handicap, + individual_round_hole=body.play_format not in SIDE_IS_UNIT, ) return await _load_round_out(conn, round_id, user.user_id) @@ -1289,6 +1528,10 @@ class ParticipantCreate(BaseModel): # gjest har ingen computed_handicap_index å beskytte). Frontend # forhåndsutfyller True når rundens play_format='match'. exclude_from_handicap: bool = False + # ADR-039 Beslutning A -- valgfritt, kun gyldig når rundens play_format + # bruker sider (match/fourball/foursome/greensome/scramble_*). Kan også + # settes/endres senere via PATCH .../participants/{id}. + round_side_id: str | None = None @router.post("/rounds/{round_id}/participants", response_model=RoundParticipantOut, status_code=201) @@ -1305,7 +1548,8 @@ async def add_participant( async with plain_connection() as conn: round_row = await conn.fetchrow( "SELECT owner_user_id::text AS owner_user_id, course_source, teeoff_facility_slug, " - "teeoff_course_id, personal_course_id, tee_name_snapshot FROM round WHERE id = $1", + "teeoff_course_id, personal_course_id, tee_name_snapshot, play_format, completed_at " + "FROM round WHERE id = $1", round_id, ) if round_row is None: @@ -1313,10 +1557,17 @@ async def add_participant( if round_row["owner_user_id"] != user.user_id: raise app_error(403, "NOT_AUTHORIZED", "Du eier ikke denne runden.") - if round_row["course_source"] == "teeoff": - resolved = await _resolve_teeoff_course(round_row["teeoff_facility_slug"], int(round_row["teeoff_course_id"])) - else: - resolved = await _resolve_personal_course(round_row["personal_course_id"]) + if body.round_side_id is not None: + if round_row["play_format"] not in _TWO_SIDED_FORMATS: + raise app_error(400, "VALIDATION_FAILED", "Denne spilleformen bruker ikke sider.") + side_exists = await conn.fetchval( + "SELECT 1 FROM round_side WHERE id = $1 AND round_id = $2", body.round_side_id, round_id + ) + if not side_exists: + raise app_error(404, "NOT_FOUND", "Siden finnes ikke på denne runden.") + await _check_side_capacity(conn, body.round_side_id, round_row["play_format"]) + + resolved = await _resolve_round_course(round_row) if body.user_id is not None: if body.user_id == round_row["owner_user_id"]: @@ -1359,7 +1610,11 @@ async def add_participant( stat_level=body.stat_level, guest_email=body.guest_email, exclude_from_handicap=body.exclude_from_handicap, + round_side_id=body.round_side_id, + individual_round_hole=round_row["play_format"] not in SIDE_IS_UNIT, ) + if body.round_side_id is not None: + await _recompute_side_handicaps(conn, round_id, round_row["play_format"]) row = await conn.fetchrow( """ SELECT rp.id::text AS id, rp.user_id::text AS user_id, rp.guest_name, rp.guest_email, @@ -1368,7 +1623,8 @@ async def add_participant( rp.handicap_index_snapshot::float AS handicap_index_snapshot, rp.course_handicap_snapshot, rp.counts_for_handicap, rp.score_differential::float AS score_differential, rp.stat_level, - rp.exclude_from_handicap + rp.exclude_from_handicap, rp.round_side_id::text AS round_side_id, + rp.playing_handicap FROM round_participant rp LEFT JOIN app_user au ON au.id = rp.user_id WHERE rp.id = $1 @@ -1379,6 +1635,81 @@ async def add_participant( return RoundParticipantOut(**dict(row)) +# --------------------------------------------------------------------------- +# Sider (ADR-039 Beslutning A) -- nøyaktig to per runde, kun for formater +# som faktisk bruker sider. Håndhevet i app-laget (samme mønster som +# ADR-011s to-lags-grense for org-turneringer), ikke en DB-constraint. +# --------------------------------------------------------------------------- + +class RoundSideCreate(BaseModel): + label: str | None = Field(default=None, max_length=100) + + +@router.post("/rounds/{round_id}/sides", response_model=RoundSideOut, status_code=201) +async def create_round_side( + round_id: str, + body: RoundSideCreate, + user: CurrentUser = Depends(get_current_user), +) -> RoundSideOut: + async with plain_connection() as conn: + await _get_owned_round_or_404(conn, round_id, user.user_id) + round_row = await conn.fetchrow( + "SELECT play_format, course_source, teeoff_facility_slug, teeoff_course_id, " + "personal_course_id, completed_at FROM round WHERE id = $1", + round_id, + ) + if round_row["play_format"] not in _TWO_SIDED_FORMATS: + raise app_error(400, "VALIDATION_FAILED", "Denne spilleformen bruker ikke sider.") + if round_row["completed_at"] is not None: + raise app_error(409, "ALREADY_COMPLETED", "Runden er allerede fullført.") + existing_count = await conn.fetchval("SELECT count(*) FROM round_side WHERE round_id = $1", round_id) + if existing_count >= 2: + raise app_error(409, "LIMIT_REACHED", "En runde kan maks ha to sider.") + + async with conn.transaction(): + side_row = await conn.fetchrow( + "INSERT INTO round_side (round_id, label) VALUES ($1, $2) RETURNING id::text AS id, label", + round_id, body.label, + ) + # Delt-ball-formater (ADR-039 Beslutning C): siden får sine + # round_hole-rader med en gang -- rating trengs ikke her, kun + # par/stroke-index-snapshot, uavhengig av om siden har fått + # noen deltakere ennå. + engine_format = _ROUND_FORMAT_TO_ENGINE_FORMAT[round_row["play_format"]] + if engine_format in SIDE_IS_UNIT: + resolved = await _resolve_round_course(round_row) + for hole_number, par, stroke_index in resolved.holes: + await conn.execute( + "INSERT INTO round_hole (round_side_id, hole_number, par, stroke_index) VALUES ($1, $2, $3, $4)", + side_row["id"], hole_number, par, stroke_index, + ) + await broadcast_round_update(round_id) + return RoundSideOut(**dict(side_row)) + + +@router.delete("/rounds/{round_id}/sides/{side_id}", status_code=204) +async def delete_round_side( + round_id: str, + side_id: str, + user: CurrentUser = Depends(get_current_user), +) -> None: + async with plain_connection() as conn: + await _get_owned_round_or_404(conn, round_id, user.user_id) + round_row = await conn.fetchrow("SELECT completed_at FROM round WHERE id = $1", round_id) + if round_row["completed_at"] is not None: + raise app_error(409, "ALREADY_COMPLETED", "Runden er allerede fullført.") + side_exists = await conn.fetchval( + "SELECT 1 FROM round_side WHERE id = $1 AND round_id = $2", side_id, round_id + ) + if not side_exists: + raise app_error(404, "NOT_FOUND", "Siden finnes ikke.") + # Kaskade fjerner sidens round_hole-rader; deltakere som var på + # denne siden faller tilbake til round_side_id = NULL (ON DELETE + # SET NULL) -- de forblir i runden, bare uten side-tilhørighet. + await conn.execute("DELETE FROM round_side WHERE id = $1", side_id) + await broadcast_round_update(round_id) + + @router.get("/rounds/{round_id}/tee-options", response_model=list[TeeOption]) async def get_round_tee_options(round_id: str, user: CurrentUser = Depends(get_current_user)) -> list[TeeOption]: """Utslagene tilgjengelig på RUNDENS bane -- brukt av 'rediger spiller'- @@ -1421,11 +1752,17 @@ class ParticipantUpdate(BaseModel): # ADR-038 Beslutning C -- eneste feltet en IKKE-eier (en lenket # medspiller som redigerer SIN EGEN rad) får sende her. exclude_from_handicap: bool | None = None + # ADR-039 Beslutning A -- (re)tildel/fjern en deltakers side. Sendes som + # `null` for å fjerne fra en side. Eier-only (se _OWNER_ONLY_ + # PARTICIPANT_FIELDS under). + round_side_id: str | None = None # Felt en ikke-eier ALDRI kan sende her, uansett hvilken rad det gjelder -- # eier-only, se update_participant sin autorisasjonssjekk. -_OWNER_ONLY_PARTICIPANT_FIELDS = {"stat_level", "tee_name", "handicap_index", "guest_name", "gender", "guest_email"} +_OWNER_ONLY_PARTICIPANT_FIELDS = { + "stat_level", "tee_name", "handicap_index", "guest_name", "gender", "guest_email", "round_side_id", +} @router.patch("/rounds/{round_id}/participants/{participant_id}", response_model=RoundParticipantOut) @@ -1450,7 +1787,7 @@ async def update_participant( rp.counts_for_handicap, r.owner_user_id::text AS round_owner_user_id, r.completed_at, r.course_source, r.teeoff_facility_slug, - r.teeoff_course_id, r.personal_course_id + r.teeoff_course_id, r.personal_course_id, r.play_format FROM round_participant rp JOIN round r ON r.id = rp.round_id WHERE rp.id = $1 AND rp.round_id = $2 @@ -1499,6 +1836,19 @@ async def update_participant( if "exclude_from_handicap" in updates: values.append(updates["exclude_from_handicap"]) set_clauses.append(f"exclude_from_handicap = ${len(values)}") + if "round_side_id" in updates: + new_side_id = updates["round_side_id"] + if new_side_id is not None: + if current["play_format"] not in _TWO_SIDED_FORMATS: + raise app_error(400, "VALIDATION_FAILED", "Denne spilleformen bruker ikke sider.") + side_exists = await conn.fetchval( + "SELECT 1 FROM round_side WHERE id = $1 AND round_id = $2", new_side_id, round_id + ) + if not side_exists: + raise app_error(404, "NOT_FOUND", "Siden finnes ikke på denne runden.") + await _check_side_capacity(conn, new_side_id, current["play_format"], exclude_participant_id=participant_id) + values.append(new_side_id) + set_clauses.append(f"round_side_id = ${len(values)}") if rating_changed: if current["course_source"] == "teeoff": @@ -1546,6 +1896,13 @@ async def update_participant( f"UPDATE round_participant SET {', '.join(set_clauses)} WHERE id = ${len(values)} RETURNING id", *values, ) + + # Side-tildeling endret (ADR-039) -- regn playing_handicap for begge + # sider på nytt FØR raden under leses, slik at responsen reflekterer + # den ferske verdien (billig no-op hvis fortsatt ikke komplett). + if "round_side_id" in updates and current["play_format"] in _TWO_SIDED_FORMATS: + await _recompute_side_handicaps(conn, round_id, current["play_format"]) + row = await conn.fetchrow( """ SELECT rp.id::text AS id, rp.user_id::text AS user_id, rp.guest_name, rp.guest_email, @@ -1554,7 +1911,8 @@ async def update_participant( rp.handicap_index_snapshot::float AS handicap_index_snapshot, rp.course_handicap_snapshot, rp.counts_for_handicap, rp.score_differential::float AS score_differential, rp.stat_level, - rp.exclude_from_handicap + rp.exclude_from_handicap, rp.round_side_id::text AS round_side_id, + rp.playing_handicap FROM round_participant rp LEFT JOIN app_user au ON au.id = rp.user_id WHERE rp.id = $1 @@ -1671,6 +2029,278 @@ async def list_holes( ] +# --------------------------------------------------------------------------- +# Delt-ball-scoring (ADR-039 Beslutning C) -- foursome/greensome/scramble +# lagrer ÉN score PER SIDE per hull, ikke per spiller. Ingen av de andre +# detalj-feltene (kølle/retning/chip/bunker/straffeslag/putt-lengde) gir +# entydig mening for en delt ball -- kun selve slagtallet. +# --------------------------------------------------------------------------- + +class RoundSideHoleOut(BaseModel): + hole_number: int + par: int + stroke_index: int + played: bool + score: int | None + + +@router.get("/rounds/{round_id}/sides/{side_id}/holes", response_model=list[RoundSideHoleOut]) +async def list_side_holes( + round_id: str, + side_id: str, + user: CurrentUser = Depends(get_current_user), +) -> list[RoundSideHoleOut]: + async with plain_connection() as conn: + await _get_accessible_round_or_404(conn, round_id, user.user_id) + side_exists = await conn.fetchval("SELECT 1 FROM round_side WHERE id = $1 AND round_id = $2", side_id, round_id) + if not side_exists: + raise app_error(404, "NOT_FOUND", "Siden finnes ikke.") + rows = await conn.fetch( + "SELECT hole_number, par, stroke_index, played, score FROM round_hole " + "WHERE round_side_id = $1 ORDER BY hole_number", + side_id, + ) + return [RoundSideHoleOut(**dict(r)) for r in rows] + + +class SideHoleUpdate(BaseModel): + played: bool = True + score: int | None = Field(default=None, ge=1, le=20) + + +@router.patch("/rounds/{round_id}/sides/{side_id}/holes/{hole_number}", response_model=RoundSideHoleOut) +async def update_side_hole( + round_id: str, + side_id: str, + hole_number: int, + body: SideHoleUpdate, + user: CurrentUser = Depends(get_current_user), +) -> RoundSideHoleOut: + async with plain_connection() as conn: + # Samme begrunnelse som update_hole -- en medspiller som fører + # score for flighten skal også kunne føre for en delt-ball-side. + await _get_accessible_round_or_404(conn, round_id, user.user_id) + side_exists = await conn.fetchval("SELECT 1 FROM round_side WHERE id = $1 AND round_id = $2", side_id, round_id) + if not side_exists: + raise app_error(404, "NOT_FOUND", "Siden finnes ikke.") + row = await conn.fetchrow( + """ + UPDATE round_hole SET played = $3, score = $4 + WHERE round_side_id = $1 AND hole_number = $2 + RETURNING hole_number, par, stroke_index, played, score + """, + side_id, hole_number, body.played, body.score, + ) + if row is None: + raise app_error(404, "NOT_FOUND", "Hullet finnes ikke på denne siden.") + await broadcast_round_update(round_id) + return RoundSideHoleOut(**dict(row)) + + +# --------------------------------------------------------------------------- +# Format-resultat (ADR-039) -- løpende matchstatus (match/fourball/foursome/ +# greensome/scramble) eller skins-tavle, avledet ved LESING (aldri lagret), +# samme "cache aldri det som kan regnes ut fra rå data"-filosofi som resten +# av appen. Slagspill trenger ingen egen visning her -- eksisterende +# scorekort/leaderboard dekker det allerede. +# --------------------------------------------------------------------------- + +class RoundFormatResultOut(BaseModel): + play_format: str + ready: bool # False = handicap ikke klart for én eller begge sider ennå + # Match/fourball/foursome/greensome/scramble: + match_lead: int | None = None + match_holes_played: int | None = None + match_holes_remaining: int | None = None + match_is_closed: bool | None = None + match_is_dormie: bool | None = None + match_status_text: str | None = None + hole_results: list[str] | None = None # "a"/"b"/"halved" per avgjort hull, i spillerekkefølge + # Skins: + skins_won: dict[str, float] | None = None + + +def _round_hole_order(start_hole: int, holes_planned: int) -> list[int]: + """Samme sirkulære spillerekkefølge som frontend allerede bruker + (round-detail.tsx) -- starter på start_hole, ruller rundt 1-18.""" + return [((start_hole - 1 + i) % 18) + 1 for i in range(holes_planned)] + + +@router.get("/rounds/{round_id}/format-result", response_model=RoundFormatResultOut) +async def get_round_format_result( + round_id: str, + user: CurrentUser = Depends(get_current_user), +) -> RoundFormatResultOut: + async with plain_connection() as conn: + await _get_accessible_round_or_404(conn, round_id, user.user_id) + round_row = await conn.fetchrow( + "SELECT play_format, skins_scoring, skins_tie_handling, start_hole, holes_planned " + "FROM round WHERE id = $1", + round_id, + ) + play_format = round_row["play_format"] + + if play_format in _TWO_SIDED_FORMATS: + relative = await _relative_strokes_for_round(conn, round_id, play_format) + if not relative: + return RoundFormatResultOut(play_format=play_format, ready=False) + + engine_format = _ROUND_FORMAT_TO_ENGINE_FORMAT[play_format] + play_order = _round_hole_order(round_row["start_hole"], round_row["holes_planned"]) + + if engine_format in SIDE_IS_UNIT: + # Delt ball -- én rad per SIDE per hull. + rows = await conn.fetch( + """ + SELECT rh.round_side_id::text AS unit, rh.hole_number, rh.stroke_index, rh.played, rh.score + FROM round_hole rh + JOIN round_side rs ON rs.id = rh.round_side_id + WHERE rs.round_id = $1 + """, + round_id, + ) + else: + # Individuell ball -- nøkkelen ("unit") er DELTAKEREN selv + # (samme som _relative_strokes_for_round sin nøkkel for + # disse formatene), IKKE siden -- hvilken side hver deltaker + # tilhører slås opp separat via unit_to_side under. + rows = await conn.fetch( + """ + SELECT rp.id::text AS unit, rh.hole_number, rh.stroke_index, rh.played, rh.score + FROM round_hole rh + JOIN round_participant rp ON rp.id = rh.round_participant_id + WHERE rp.round_id = $1 AND rp.round_side_id IS NOT NULL + """, + round_id, + ) + + by_unit_hole: dict[tuple[str, int], list] = {} + stroke_index_by_hole: dict[int, int] = {} + for r in rows: + if r["played"] and r["score"] is not None: + by_unit_hole.setdefault((r["unit"], r["hole_number"]), []).append(r["score"]) + stroke_index_by_hole[r["hole_number"]] = r["stroke_index"] + all_18_si = [stroke_index_by_hole[h] for h in range(1, 19)] if len(stroke_index_by_hole) == 18 else None + + side_ids = sorted(relative.keys()) if engine_format in SIDE_IS_UNIT else None + if side_ids is None: + # Individuelle enheter er round_participant_id-er -- hent + # hvilken side hver enhet faktisk tilhører for å vite "a"/"b". + unit_side = await conn.fetch( + "SELECT id::text AS id, round_side_id::text AS side_id FROM round_participant WHERE round_id = $1", + round_id, + ) + unit_to_side = {r["id"]: r["side_id"] for r in unit_side} + side_ids = sorted({s for s in unit_to_side.values() if s is not None}) + + if len(side_ids) != 2 or all_18_si is None: + return RoundFormatResultOut(play_format=play_format, ready=False) + + strokes_per_hole = { + unit: dict(zip(range(1, 19), allocate_over_played_holes(v, all_18_si, list(range(1, 19))))) + for unit, v in relative.items() + } + side_a_id, side_b_id = side_ids + expected_players = _SIDE_PLAYER_COUNT[play_format] + + def side_net(hole_number: int, side_id: str) -> int | None: + if engine_format in SIDE_IS_UNIT: + scores = by_unit_hole.get((side_id, hole_number), []) + if len(scores) != 1: + return None + per_hole = strokes_per_hole.get(side_id) + if per_hole is None: + return None + return scores[0] - per_hole[hole_number] + nets = [] + for unit_id, unit_side_id in unit_to_side.items(): + if unit_side_id != side_id: + continue + scores = by_unit_hole.get((unit_id, hole_number), []) + if len(scores) != 1: + return None + per_hole = strokes_per_hole.get(unit_id) + if per_hole is None: + return None + nets.append(scores[0] - per_hole[hole_number]) + if len(nets) != expected_players: + return None + return min(nets) + + hole_results: list[HoleResult] = [] + for hole_number in play_order: + net_a = side_net(hole_number, side_a_id) + net_b = side_net(hole_number, side_b_id) + if net_a is None or net_b is None: + break + if net_a < net_b: + hole_results.append(HoleResult.SIDE_A) + elif net_b < net_a: + hole_results.append(HoleResult.SIDE_B) + else: + hole_results.append(HoleResult.HALVED) + + state = compute_match_state(hole_results, total_holes=round_row["holes_planned"]) + return RoundFormatResultOut( + play_format=play_format, + ready=True, + match_lead=state.lead, + match_holes_played=state.holes_played, + match_holes_remaining=state.holes_remaining, + match_is_closed=state.is_closed, + match_is_dormie=state.is_dormie, + match_status_text=state.describe(), + hole_results=[_RESULT_LABEL[r] for r in hole_results], + ) + + if play_format == "skins": + participant_rows = await conn.fetch( + "SELECT id::text AS id, course_handicap_snapshot FROM round_participant WHERE round_id = $1", + round_id, + ) + hole_rows = await conn.fetch( + """ + SELECT rp.id::text AS participant_id, rh.hole_number, rh.stroke_index, rh.played, rh.score + FROM round_hole rh JOIN round_participant rp ON rp.id = rh.round_participant_id + WHERE rp.round_id = $1 + ORDER BY rh.hole_number + """, + round_id, + ) + strokes_by_participant: dict[str, dict[int, int]] = {} + if round_row["skins_scoring"] == "net": + by_participant_holes: dict[str, list] = {} + for r in hole_rows: + by_participant_holes.setdefault(r["participant_id"], []).append(r) + ch_by_participant = {p["id"]: p["course_handicap_snapshot"] for p in participant_rows} + for pid, holes in by_participant_holes.items(): + ch = ch_by_participant.get(pid) + if ch is None: + continue + allocation = allocate_strokes_by_index(ch, [h["stroke_index"] for h in holes]) + strokes_by_participant[pid] = {h["hole_number"]: a for h, a in zip(holes, allocation)} + + scores_by_hole_number: dict[int, list[tuple[str, int]]] = {} + for r in hole_rows: + if not r["played"] or r["score"] is None: + continue + if round_row["skins_scoring"] == "net": + per_hole = strokes_by_participant.get(r["participant_id"]) + if per_hole is None: + continue + value = r["score"] - per_hole[r["hole_number"]] + else: + value = r["score"] + scores_by_hole_number.setdefault(r["hole_number"], []).append((r["participant_id"], value)) + + play_order = _round_hole_order(round_row["start_hole"], round_row["holes_planned"]) + scores_by_hole = [scores_by_hole_number.get(h, []) for h in play_order] + skins_won = compute_skins(scores_by_hole, tie_handling=round_row["skins_tie_handling"]) + return RoundFormatResultOut(play_format=play_format, ready=True, skins_won=skins_won) + + return RoundFormatResultOut(play_format=play_format, ready=True) + + class LeaderboardHoleOut(BaseModel): hole_number: int par: int @@ -1890,7 +2520,15 @@ async def complete_round(round_id: str, user: CurrentUser = Depends(get_current_ # Samme begrunnelse som update_hole -- en medspiller som fører # score for flighten skal også kunne markere runden ferdig. await _get_accessible_round_or_404(conn, round_id, user.user_id) - round_row = await conn.fetchrow("SELECT holes_planned FROM round WHERE id = $1", round_id) + round_row = await conn.fetchrow("SELECT holes_planned, play_format FROM round WHERE id = $1", round_id) + + # 2026-07-28 oppfølging: match/skins/fourball/foursome/greensome/ + # scramble krever flere spillere enn slagspill -- ingenting fanget + # dette opp før nå. Avvis tydelig FØR noe regnes ut, i stedet for å + # stille fullføre en runde som er strukturelt umulig for formatet. + setup_complete, setup_message = await _format_setup_status(conn, round_id, round_row["play_format"]) + if not setup_complete: + raise app_error(409, "SETUP_INCOMPLETE", setup_message) participants = await conn.fetch( """ diff --git a/frontend/components/new-round.tsx b/frontend/components/new-round.tsx index 3d4904b..f109d4d 100644 --- a/frontend/components/new-round.tsx +++ b/frontend/components/new-round.tsx @@ -71,9 +71,24 @@ type CourseMeta = type Gender = "m" | "f" type StatLevel = "strokes_only" | "strokes_and_putts" | "full" -// ADR-038 -- selvdeklarert spilleform. Ingen egen match-motor for -// frittstående runder, så dette taes brukerens ord for. -type PlayFormat = "stroke" | "match" +// ADR-038/ADR-039 -- selvdeklarert spilleform. Ingen egen match-/skins-motor +// for frittstående runder, så dette taes brukerens ord for. Sider (for de +// to-sidede formatene) opprettes IKKE her -- det skjer i selve runden +// (POST .../sides), siden det krever at deltakerne allerede finnes. +type PlayFormat = "stroke" | "match" | "skins" | "fourball" | "foursome" | "greensome" | "scramble_2" | "scramble_4" +type SkinsScoring = "net" | "gross" +type SkinsTieHandling = "carry" | "split" + +const PLAY_FORMAT_OPTIONS: { value: PlayFormat; label: string; desc: string }[] = [ + { value: "stroke", label: "Slagspill", desc: "Vanlig individuell runde." }, + { value: "match", label: "Match", desc: "To sider, hull mot hull." }, + { value: "skins", label: "Skins", desc: "Hvert hull er en egen premie -- minst 3 spillere." }, + { value: "fourball", label: "Fourball", desc: "To mot to, beste ball per side." }, + { value: "foursome", label: "Foursome", desc: "To mot to, én delt ball, annenhver slår." }, + { value: "greensome", label: "Greensome", desc: "To mot to, begge slår ut, velger så én ball." }, + { value: "scramble_2", label: "Scramble (2)", desc: "To mot to, velger beste slag hver gang." }, + { value: "scramble_4", label: "Scramble (4)", desc: "Fire mot fire, velger beste slag hver gang." }, +] // --- API-typer --------------------------------------------------------------- @@ -203,36 +218,35 @@ export function NewRound() { statLevel: StatLevel playFormat: PlayFormat excludeFromHandicap: boolean + skinsScoring: SkinsScoring | null + skinsTieHandling: SkinsTieHandling | null }): Promise<{ id: string }> { if (!courseMeta) throw new Error("Mangler valgt bane") + const shared = { + tee_name: payload.teeName, + name: payload.name || null, + played_at: payload.date, + started_at: payload.startedAt, + start_hole: payload.startHole, + holes_planned: payload.holes, + stat_level: payload.statLevel, + play_format: payload.playFormat, + exclude_owner_from_handicap: payload.excludeFromHandicap, + skins_scoring: payload.skinsScoring, + skins_tie_handling: payload.skinsTieHandling, + } const body = courseMeta.source === "teeoff" ? { course_source: "teeoff", teeoff_facility_slug: courseMeta.facilitySlug, teeoff_course_id: courseMeta.teeoffCourseId, - tee_name: payload.teeName, - name: payload.name || null, - played_at: payload.date, - started_at: payload.startedAt, - start_hole: payload.startHole, - holes_planned: payload.holes, - stat_level: payload.statLevel, - play_format: payload.playFormat, - exclude_owner_from_handicap: payload.excludeFromHandicap, + ...shared, } : { course_source: "custom", personal_course_id: courseMeta.personalCourseId, - tee_name: payload.teeName, - name: payload.name || null, - played_at: payload.date, - started_at: payload.startedAt, - start_hole: payload.startHole, - holes_planned: payload.holes, - stat_level: payload.statLevel, - play_format: payload.playFormat, - exclude_owner_from_handicap: payload.excludeFromHandicap, + ...shared, } const res = await fetch("/rounds", { method: "POST", @@ -1121,6 +1135,8 @@ function ConfirmStep({ statLevel: StatLevel playFormat: PlayFormat excludeFromHandicap: boolean + skinsScoring: SkinsScoring | null + skinsTieHandling: SkinsTieHandling | null }) => Promise<{ id: string }> onCreated: (roundId: string) => void }) { @@ -1134,17 +1150,27 @@ function ConfirmStep({ const [statLevel, setStatLevel] = useState("strokes_only") const [playFormat, setPlayFormat] = useState("stroke") const [excludeFromHandicap, setExcludeFromHandicap] = useState(false) + // ADR-039 Beslutning D -- kun meningsfullt (og påkrevd av backend) for + // play_format="skins". Fornuftige forhåndsvalg, begge overstyrbare. + const [skinsScoring, setSkinsScoring] = useState("net") + const [skinsTieHandling, setSkinsTieHandling] = useState("carry") const [submitting, setSubmitting] = useState(false) const [error, setError] = useState(null) function choosePlayFormat(next: PlayFormat) { setPlayFormat(next) - // ADR-038 Beslutning D -- foreslå (ikke tving) eksklusjon når - // matchspill velges. Brukeren kan uansett overstyre under. + // ADR-038 Beslutning D -- foreslå (ikke tving) eksklusjon når match + // velges. De andre formatene har egne HCP-regler (ADR-039 Beslutning E) + // som ikke bruker dette feltet -- nullstill det da for å unngå et + // misvisende forhåndsvalg som likevel ikke sendes videre meningsfullt. setExcludeFromHandicap(next === "match") } const selectedTee = compatibleTees.find((t) => t.id === teeId) + // ADR-039 Beslutning A -- match/fourball/foursome/greensome/scramble + // krever sider, opprettet ETTERPÅ inne i selve runden (deltakerne må + // finnes først). Vises som en forklarende note her, ikke et skjema. + const needsSidesSetup = playFormat !== "stroke" && playFormat !== "skins" async function handleStart() { if (!selectedTee) return @@ -1165,6 +1191,8 @@ function ConfirmStep({ statLevel, playFormat, excludeFromHandicap, + skinsScoring: playFormat === "skins" ? skinsScoring : null, + skinsTieHandling: playFormat === "skins" ? skinsTieHandling : null, }) onCreated(created.id) } catch { @@ -1311,32 +1339,33 @@ function ConfirmStep({ - {/* Spilleform (ADR-038) -- selvdeklarert, ingen egen match-motor */} + {/* Spilleform (ADR-038/ADR-039) -- selvdeklarert, ingen egen match-/ + skins-motor. match/fourball/foursome/greensome/scramble krever + sider -- opprettes i selve runden etter at deltakerne er lagt til. */}
Spilleform -
- {( - [ - { value: "stroke" as const, label: "Slagspill" }, - { value: "match" as const, label: "Matchspill" }, - ] - ).map((opt) => ( +
+ {PLAY_FORMAT_OPTIONS.map((opt) => ( ))}
+

+ {PLAY_FORMAT_OPTIONS.find((o) => o.value === playFormat)?.desc} +

+ {playFormat === "match" && ( )} + + {playFormat === "skins" && ( +
+
+ Poengberegning +
+ {( + [ + { value: "net" as const, label: "Netto (m/HCP)" }, + { value: "gross" as const, label: "Brutto" }, + ] + ).map((opt) => ( + + ))} +
+
+
+ Ved uavgjort hull +
+ {( + [ + { value: "carry" as const, label: "Rullerer over" }, + { value: "split" as const, label: "Deles likt" }, + ] + ).map((opt) => ( + + ))} +
+
+

+ Skins krever minst 3 spillere i runden -- legg til medspillere etter at runden er opprettet. +

+
+ )} + + {needsSidesSetup && ( +

+ Du setter opp sidene (og fordeler spillerne) inne i runden, etter at medspillerne er + lagt til. +

+ )}
{/* Hole count */} diff --git a/frontend/components/round-detail.tsx b/frontend/components/round-detail.tsx index e7fc0f2..a939c49 100644 --- a/frontend/components/round-detail.tsx +++ b/frontend/components/round-detail.tsx @@ -72,6 +72,10 @@ type Player = { // ADR-038 -- manuell opt-out fra faktisk HCP, uavhengig av // countsForHandicap (den automatiske kvalifiseringen). excludeFromHandicap: boolean + // ADR-039 -- hvilken side (match/fourball/foursome/greensome/scramble), + // og den format-relative match-play-enheten (ikke samme som courseHandicap). + roundSideId: string | null + playingHandicap: number | null } type HoleStat = { @@ -167,6 +171,17 @@ type ApiParticipant = { score_differential: number | null stat_level: StatLevel exclude_from_handicap: boolean + // ADR-039 -- hvilken side deltakeren er på (match/fourball/foursome/ + // greensome/scramble), null for slagspill/skins (ingen sider). + round_side_id: string | null + // ADR-039 -- format-avledet, RELATIV match-play-enhet, ikke samme som + // course_handicap_snapshot (den absolutte WHS-verdien). + playing_handicap: number | null +} + +type ApiSide = { + id: string + label: string | null } type PersonMatch = { @@ -192,9 +207,39 @@ type ApiRound = { start_hole: number holes_planned: number play_format: string + skins_scoring: string | null + skins_tie_handling: string | null started_at: string | null completed_at: string | null participants: ApiParticipant[] + sides: ApiSide[] + setup_complete: boolean + setup_message: string | null +} + +// ADR-039 -- speiler backend sine konstanter i app/routers/rounds.py +// (_TWO_SIDED_FORMATS/_SIDE_PLAYER_COUNT/SIDE_IS_UNIT) klientside, kun for +// å vite hvilken oppsett-UI som skal vises. Selve håndhevelsen skjer alltid +// server-side -- disse styrer bare presentasjon. +const TWO_SIDED_FORMATS = new Set(["match", "fourball", "foursome", "greensome", "scramble_2", "scramble_4"]) +const SHARED_BALL_FORMATS = new Set(["foursome", "greensome", "scramble_2", "scramble_4"]) +const SIDE_PLAYER_COUNT: Record = { + match: 1, + fourball: 2, + foursome: 2, + greensome: 2, + scramble_2: 2, + scramble_4: 4, +} +const FORMAT_LABELS: Record = { + stroke: "Slagspill", + match: "Match", + skins: "Skins", + fourball: "Fourball", + foursome: "Foursome", + greensome: "Greensome", + scramble_2: "Scramble (2)", + scramble_4: "Scramble (4)", } // Utslagstid vises i klokkeslett-format, og tidsbruk beregnes som @@ -235,6 +280,17 @@ type ApiHole = { strokes_received: number | null } +// ADR-039 Beslutning C -- delt-ball-formater (foursome/greensome/scramble) +// har ÉN score PER SIDE per hull, ikke per spiller -- ingen av de andre +// detalj-feltene gir entydig mening for en delt ball. +type ApiSideHole = { + hole_number: number + par: number + stroke_index: number + played: boolean + score: number | null +} + function apiHoleToStat(h: ApiHole): HoleStat { return { played: h.played, @@ -302,6 +358,10 @@ export function RoundDetail({ roundId }: { roundId: string }) { // lenger ned til en no-op (funnet 2026-07-24: runden åpnet alltid på // hull 1 uansett faktisk starthull). const [currentHole, setCurrentHole] = useState(null) + // ADR-039 -- bumpes hver gang noe som kan ha endret matchstatus/skins- + // tavlen skjer (hull-registrering, websocket-signal), slik at + // FormatResultPanel vet den skal hente på nytt. + const [formatResultRefreshTick, setFormatResultRefreshTick] = useState(0) const [showAddGuest, setShowAddGuest] = useState(false) // Administrasjon (leaderboard-forhåndsvisning/Rediger/Fullfør/Slett/ // spillerliste) og selve scoringen er nå to ADSKILTE faner (2026-07-26, @@ -323,6 +383,10 @@ export function RoundDetail({ roundId }: { roundId: string }) { // HULL, om noen (2026-07-26 -- erstatter den tidligere "vis alt inline for // aktiv spiller"-flyten, inspirert av en konkurrentapps samlebåndsflyt). const [wizardPlayerId, setWizardPlayerId] = useState(null) + // ADR-039 -- delt-ball-formater (foursome/greensome/scramble) scorer PER + // SIDE, ikke per spiller -- egen, enklere veiviser-tilstand for dette. + const [wizardSideId, setWizardSideId] = useState(null) + const [holesBySide, setHolesBySide] = useState>({}) // Hull-panelet gjenbrukes ved bytte av hull -- "Forrige"/"Neste hull" ligger // NEDERST i panelet, så uten dette ville brukeren blitt stående scrollet // helt ned (der knappene er) mens det NYE hullets Slag-felt (øverst i @@ -344,6 +408,13 @@ export function RoundDetail({ roundId }: { roundId: string }) { setRound(data) setActivePlayerId((prev) => prev ?? data.participants.find((p) => p.is_owner)?.id ?? data.participants[0]?.id ?? null) setCurrentHole((prev) => prev ?? data.start_hole) + // ADR-039 -- sider/deltaker-tildeling kan ha endret seg (SidesPanel + // kaller denne som onSidesChanged), som igjen kan gjøre FormatResultPanel + // sitt tidligere "ikke klart"-svar utdatert. Bump ved HVER runde-refetch + // (billig, og runde-refetch skjer uansett ikke ofte nok til at det er en + // reell kostnad) i stedet for å spore hver enkelt kallsted som kan + // påvirke handicap-beregningen. + setFormatResultRefreshTick((n) => n + 1) } catch { setError("Klarte ikke å hente runden. Prøv igjen om litt.") } @@ -391,13 +462,36 @@ export function RoundDetail({ roundId }: { roundId: string }) { } }, [round, holesByParticipant, loadHoles]) - // Alltid gjeldende deltaker-id-er tilgjengelig INNI WebSocket-handleren - // under, uten å måtte koble socket-en til/fra ved hver ny runde-lasting - // (en vanlig closure over `round` i effektens dependency-array ville - // krevd det). + // ADR-039 -- delt-ball-formater (foursome/greensome/scramble) scorer per + // SIDE, ikke per deltaker (se holesBySide over). + const loadSideHoles = useCallback( + async (sideId: string) => { + const res = await fetch(`/rounds/${roundId}/sides/${sideId}/holes`, { credentials: "include" }) + if (!res.ok) return + const data: ApiSideHole[] = await res.json() + setHolesBySide((prev) => ({ ...prev, [sideId]: data })) + }, + [roundId], + ) + + useEffect(() => { + if (!round) return + for (const s of round.sides) { + if (!holesBySide[s.id]) { + void loadSideHoles(s.id) + } + } + }, [round, holesBySide, loadSideHoles]) + + // Alltid gjeldende deltaker-/side-id-er tilgjengelig INNI WebSocket- + // handleren under, uten å måtte koble socket-en til/fra ved hver ny + // runde-lasting (en vanlig closure over `round` i effektens + // dependency-array ville krevd det). const participantIdsRef = useRef([]) + const sideIdsRef = useRef([]) useEffect(() => { participantIdsRef.current = round?.participants.map((p) => p.id) ?? [] + sideIdsRef.current = round?.sides.map((s) => s.id) ?? [] }, [round]) // Sanntid (2026-07-26, oppfølging av ADR-027): et rent "noe endret seg"- @@ -413,9 +507,13 @@ export function RoundDetail({ roundId }: { roundId: string }) { for (const id of participantIdsRef.current) { void loadHoles(id) } + for (const id of sideIdsRef.current) { + void loadSideHoles(id) + } + setFormatResultRefreshTick((n) => n + 1) } return () => socket.close() - }, [roundId, loadRound, loadHoles]) + }, [roundId, loadRound, loadHoles, loadSideHoles]) const completed = round?.completed_at != null const readOnly = completed @@ -436,6 +534,8 @@ export function RoundDetail({ roundId }: { roundId: string }) { scoreDifferential: p.score_differential, statLevel: p.stat_level, excludeFromHandicap: p.exclude_from_handicap, + roundSideId: p.round_side_id, + playingHandicap: p.playing_handicap, })) ?? [] // Kun eieren kan forvalte runden (rediger/slett/legge til/fjerne @@ -483,6 +583,7 @@ export function RoundDetail({ roundId }: { roundId: string }) { ...prev, [wizardPlayerId]: (prev[wizardPlayerId] ?? []).map((h) => (h.hole_number === updated.hole_number ? updated : h)), })) + setFormatResultRefreshTick((n) => n + 1) } function goPrev() { @@ -514,6 +615,52 @@ export function RoundDetail({ roundId }: { roundId: string }) { } } + // ADR-039 Beslutning C -- delt-ball-formater (foursome/greensome/scramble) + // scorer PER SIDE, ikke per spiller. Egen, enklere veiviser-tilstand og + // -oppdatering (kun slagtall, ingen putt/detalj-steg -- gir ikke entydig + // mening for en delt ball). + const isSharedBall = round ? SHARED_BALL_FORMATS.has(round.play_format) : false + const wizardSide = round?.sides.find((s) => s.id === wizardSideId) ?? null + const wizardSideHole = wizardSideId ? (holesBySide[wizardSideId]?.find((h) => h.hole_number === activeHole) ?? null) : null + // Par/index for aktivt hull -- samme for begge sider (samme bane), henter + // fra hvilken som helst av de to som allerede har lastet inn hullene sine. + const sharedHole: Hole | null = (() => { + for (const s of round?.sides ?? []) { + const h = holesBySide[s.id]?.find((x) => x.hole_number === activeHole) + if (h) return { holeNumber: h.hole_number, par: h.par, index: h.stroke_index } + } + return null + })() + + async function updateWizardSideScore(score: number | null) { + if (readOnly || !wizardSideId) return + const res = await fetch(`/rounds/${roundId}/sides/${wizardSideId}/holes/${activeHole}`, { + method: "PATCH", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify({ played: true, score }), + }) + if (!res.ok) return + const updated: ApiSideHole = await res.json() + setHolesBySide((prev) => ({ + ...prev, + [wizardSideId]: (prev[wizardSideId] ?? []).map((h) => (h.hole_number === updated.hole_number ? updated : h)), + })) + setFormatResultRefreshTick((n) => n + 1) + } + + function advanceWizardSide() { + if (!round) return + const idx = round.sides.findIndex((s) => s.id === wizardSideId) + const isLast = idx === -1 || idx === round.sides.length - 1 + if (!isLast) { + setWizardSideId(round.sides[idx + 1].id) + } else { + setWizardSideId(null) + goNext() + } + } + async function addGuest(name: string, gender: Gender, hcp: number | null, statLevel: StatLevel) { const res = await fetch(`/rounds/${roundId}/participants`, { method: "POST", @@ -754,6 +901,10 @@ export function RoundDetail({ roundId }: { roundId: string }) { null ellers), lenke til hele leaderboardet. */} + {/* Løpende matchstatus (to-sidede formater) eller skins-tavle + (ADR-039) -- avledet ved lesing, aldri lagret. */} + +
{isOwnerViewer && ( @@ -771,8 +922,9 @@ export function RoundDetail({ roundId }: { roundId: string }) { {!completed && (
+ {/* Sider (ADR-039 Beslutning A) -- kun for formater som faktisk + bruker sider (match/fourball/foursome/greensome/scramble). + Opprett/slett sider + fordel deltakerne. */} + {TWO_SIDED_FORMATS.has(round.play_format) && ( + + )} + + {!round.setup_complete && !completed && ( +

+ {round.setup_message ?? "Oppsettet er ikke komplett ennå."} +

+ )} + {/* Spillerliste (2026-07-26, erstatter tidligere horisontal fane-rad) -- vertikal, ett kort per spiller. Utslag/HCP/ statistikknivå + "Rediger" ligger nå INNI hvert kort (samme @@ -806,6 +978,7 @@ export function RoundDetail({ roundId }: { roundId: string }) { )} - {/* Scorekort-grid (§1 i teecup-scorekort-og-entry-spec.md, bygget - 2026-07-27 -- erstatter den forrige rundens ett-hull-om-gangen- - liste, bruker eksplisitt bekreftet "JA" på at grid-redesignet er - en egen, større runde). Spillere som rader (sticky venstre - navnekolonne), hull som horisontalt scrollbare kolonner -- - HELE runden synlig samtidig, ikke bare det aktive hullet. */} - {holes.length === 0 ? ( -
- - ) : ( -
- { - setCurrentHole(n) - scrollToHolePanel() - }} - onOpenEntry={(playerId, holeNumber) => { - setCurrentHole(holeNumber) - setActivePlayerId(playerId) - setWizardPlayerId(playerId) - }} - /> - - {/* Rask sekvensiell hull-navigasjon -- gridet viser allerede - alle hull som kolonner (tapp en kolonneoverskrift for å - velge), men disse to gir en rask vei videre uten å måtte - scrolle bredt for hvert eneste hull. */} -
- - + {/* ADR-039 Beslutning C -- delt-ball-formater scorer PER SIDE, ikke + per spiller. Vises kun når begge sider faktisk er opprettet + (SidesPanel i "Spillere og runde" setter dette opp). */} + {isSharedBall && round.sides.length < 2 ? ( +

+ Opprett begge sidene under "Spillere og runde" før du kan registrere score. +

+ ) : isSharedBall ? ( + round.sides.some((s) => !holesBySide[s.id]) ? ( +
+ -
+ ) : ( +
+ { + setCurrentHole(n) + scrollToHolePanel() + }} + onOpenEntry={(sideId, holeNumber) => { + setCurrentHole(holeNumber) + setWizardSideId(sideId) + }} + /> +
+ + +
+
+ ) + ) : ( + <> + {/* Scorekort-grid (§1 i teecup-scorekort-og-entry-spec.md, bygget + 2026-07-27 -- erstatter den forrige rundens ett-hull-om-gangen- + liste, bruker eksplisitt bekreftet "JA" på at grid-redesignet er + en egen, større runde). Spillere som rader (sticky venstre + navnekolonne), hull som horisontalt scrollbare kolonner -- + HELE runden synlig samtidig, ikke bare det aktive hullet. */} + {holes.length === 0 ? ( +
+ + ) : ( +
+ { + setCurrentHole(n) + scrollToHolePanel() + }} + onOpenEntry={(playerId, holeNumber) => { + setCurrentHole(holeNumber) + setActivePlayerId(playerId) + setWizardPlayerId(playerId) + }} + /> + + {/* Rask sekvensiell hull-navigasjon -- gridet viser allerede + alle hull som kolonner (tapp en kolonneoverskrift for å + velge), men disse to gir en rask vei videre uten å måtte + scrolle bredt for hvert eneste hull. */} +
+ + +
+
+ )} + )} )} @@ -896,6 +1116,18 @@ export function RoundDetail({ roundId }: { roundId: string }) { {/* Skjermovertagende scoringsveiviser (2026-07-26) -- rendres HELT UTENFOR
, øverst i DOM-treet, slik at den dekker hele skjermen uavhengig av hvor langt man har skrollet i bakgrunnen. */} + {wizardSide && sharedHole && ( + setWizardSideId(null)} + onAdvance={advanceWizardSide} + readOnly={readOnly} + /> + )} {wizardPlayer && hole && ( Promise + onPatchParticipant: (participantId: string, body: Record) => Promise<{ ok: true } | { ok: false; message: string }> +}) { + const [labelDrafts, setLabelDrafts] = useState>({}) + const [busy, setBusy] = useState(false) + const [error, setError] = useState(null) + + const expected = SIDE_PLAYER_COUNT[round.play_format] ?? 1 + const slots: (ApiSide | null)[] = [round.sides[0] ?? null, round.sides[1] ?? null] + const unassigned = players.filter((p) => p.roundSideId === null) + + async function createSide(slotIndex: number) { + setBusy(true) + setError(null) + const res = await fetch(`/rounds/${roundId}/sides`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + credentials: "include", + body: JSON.stringify({ label: labelDrafts[slotIndex]?.trim() || null }), + }) + if (!res.ok) { + const body = await res.json().catch(() => null) + setError(body?.detail?.message ?? "Klarte ikke å opprette siden.") + setBusy(false) + return + } + await onSidesChanged() + setBusy(false) + } + + async function deleteSide(sideId: string) { + if (!confirm("Slette denne siden? Deltakerne blir liggende i runden, uten side-tilhørighet.")) return + setBusy(true) + setError(null) + const res = await fetch(`/rounds/${roundId}/sides/${sideId}`, { method: "DELETE", credentials: "include" }) + if (!res.ok) { + const body = await res.json().catch(() => null) + setError(body?.detail?.message ?? "Klarte ikke å slette siden.") + } + await onSidesChanged() + setBusy(false) + } + + async function assign(participantId: string, sideId: string | null) { + setBusy(true) + setError(null) + const result = await onPatchParticipant(participantId, { round_side_id: sideId }) + if (!result.ok) { + setError(result.message) + } else { + // patchParticipant oppdaterer kun deltaker-listen lokalt -- setup_complete/ + // setup_message/playing_handicap er beregnet SERVER-side og krever en + // full runde-refetch for å ikke bli stående utdatert (2026-07-28, funnet + // under browserverifisering: meldingen "ikke tildelt en side" ble + // stående etter en vellykket tildeling). + await onSidesChanged() + } + setBusy(false) + } + + if (!canManage && round.sides.length === 0) return null + + return ( +
+
+ + Sider · {expected} spiller{expected !== 1 ? "e" : ""} per side + +
+ + {error &&

{error}

} + +
+ {slots.map((side, slotIndex) => { + const assignedPlayers = side ? players.filter((p) => p.roundSideId === side.id) : [] + return ( +
+ {side ? ( + <> +
+ + {side.label?.trim() || `Side ${slotIndex === 0 ? "A" : "B"}`} + + {canManage && ( + + )} +
+ + {assignedPlayers.length}/{expected} spillere + {assignedPlayers.some((p) => p.playingHandicap !== null) && ( + <> + {" · "} + Match-hcp{" "} + {assignedPlayers + .filter((p) => p.playingHandicap !== null) + .map((p) => p.playingHandicap) + .join("/")} + + )} + + {assignedPlayers.length === 0 ? ( +

Ingen spillere ennå.

+ ) : ( +
    + {assignedPlayers.map((p) => ( +
  • + {p.name} + {canManage && ( + + )} +
  • + ))} +
+ )} + + ) : canManage ? ( +
+ setLabelDrafts((prev) => ({ ...prev, [slotIndex]: e.target.value }))} + placeholder={`Navn på side (valgfritt)`} + className="h-10 rounded-xl text-sm" + /> + +
+ ) : ( +

Ikke opprettet ennå.

+ )} +
+ ) + })} +
+ + {canManage && unassigned.length > 0 && ( +
+ Ikke tildelt en side +
    + {unassigned.map((p) => ( +
  • + {p.name} + {slots.map((side, slotIndex) => { + if (!side) return null + const count = players.filter((x) => x.roundSideId === side.id).length + const full = count >= expected + return ( + + ) + })} +
  • + ))} +
+
+ )} +
+ ) +} + +// --- Løpende matchstatus / skins-tavle (ADR-039) ---------------------------- +// Avledet ved LESING (aldri lagret) fra GET .../format-result -- samme +// filosofi som resten av appen (leaderboard/HCP m.fl.). Slagspill trenger +// ingen egen visning her (eksisterende leaderboard dekker det). + +type ApiFormatResult = { + play_format: string + ready: boolean + match_lead: number | null + match_holes_played: number | null + match_holes_remaining: number | null + match_is_closed: boolean | null + match_is_dormie: boolean | null + match_status_text: string | null + hole_results: string[] | null + skins_won: Record | null +} + +// match_status_text bruker bokstavelig "(A)"/"(B)" -- disse tilsvarer alltid +// round.sides[0]/[1] (begge sortert på id, samme rekkefølge som backend sin +// egen sortering av side-id-er). Erstatt med det faktiske side-navnet. +function substituteSideLabels(text: string, sides: ApiSide[]): string { + const labelFor = (idx: number) => sides[idx]?.label?.trim() || `Side ${idx === 0 ? "A" : "B"}` + return text.replace(/\(A\)/, `(${labelFor(0)})`).replace(/\(B\)/, `(${labelFor(1)})`) +} + +function FormatResultPanel({ + roundId, + round, + players, + refreshTick, +}: { + roundId: string + round: ApiRound + players: Player[] + refreshTick: number +}) { + const [result, setResult] = useState(null) + + useEffect(() => { + if (round.play_format === "stroke") return + let cancelled = false + fetch(`/rounds/${roundId}/format-result`, { credentials: "include" }) + .then((res) => (res.ok ? res.json() : null)) + .then((data: ApiFormatResult | null) => { + if (!cancelled) setResult(data) + }) + .catch(() => {}) + return () => { + cancelled = true + } + }, [roundId, round.play_format, refreshTick]) + + if (round.play_format === "stroke" || !result) return null + + if (round.play_format === "skins") { + const won = result.skins_won ?? {} + const rows = players + .map((p) => ({ player: p, skins: won[p.id] ?? 0 })) + .sort((a, b) => b.skins - a.skins) + const totalAwarded = Object.values(won).reduce((sum, v) => sum + v, 0) + return ( +
+
+ Skins-tavle + + {totalAwarded} skin{totalAwarded !== 1 ? "s" : ""} avgjort + +
+
    + {rows.map(({ player, skins }) => ( +
  • + {player.name} + {skins} +
  • + ))} +
+
+ ) + } + + // To-sidede formater (match/fourball/foursome/greensome/scramble). + if (!result.ready) { + return ( +
+ Venter på at begge sider er komplette og har beregnet handicap før {FORMAT_LABELS[round.play_format] ?? round.play_format}-status kan vises. +
+ ) + } + + const statusText = result.match_status_text ? substituteSideLabels(result.match_status_text, round.sides) : null + + return ( +
+
+ {FORMAT_LABELS[round.play_format] ?? round.play_format} + {result.match_is_closed && ( + + Avgjort + + )} + {result.match_is_dormie && !result.match_is_closed && ( + + Dormie + + )} +
+ {statusText && {statusText}} + + {result.match_holes_played} hull spilt + {result.match_holes_remaining !== null && result.match_holes_remaining > 0 && `, ${result.match_holes_remaining} igjen`} + + {result.hole_results && result.hole_results.length > 0 && ( +
    + {result.hole_results.map((r, i) => ( +
  • + {r === "halved" ? "½" : r.toUpperCase()} +
  • + ))} +
+ )} +
+ ) +} + // --- Player tabs ----------------------------------------------------------- // --- Spillerliste (2026-07-26, erstatter tidligere horisontal fane-rad) --- @@ -1516,6 +2096,7 @@ function DistributionBar({ segments }: { segments: { label: string; count: numbe function PlayerList({ roundId, players, + sides, activePlayerId, onSelect, onRemove, @@ -1531,6 +2112,9 @@ function PlayerList({ }: { roundId: string players: Player[] + // ADR-039 -- kun brukt til å slå opp side-LABEL for badgen; selve + // tildelingen skjer i SidesPanel, ikke her. + sides: ApiSide[] activePlayerId: string onSelect: (id: string) => void onRemove: (id: string) => void @@ -1595,6 +2179,15 @@ function PlayerList({ Eier )} + {player.roundSideId && ( + + {(() => { + const idx = sides.findIndex((s) => s.id === player.roundSideId) + const side = sides[idx] + return side?.label?.trim() || `Side ${idx === 0 ? "A" : "B"}` + })()} + + )} Utslag: {player.teeName} @@ -2911,6 +3504,328 @@ function golfTermForScore(n: number, par: number): string | null { return null } +// --- Delt-ball-scorekort (ADR-039 Beslutning C) ----------------------------- +// Samme grid-idé som ScorecardGrid, men rader = SIDER (ikke spillere) -- kun +// ett tall per hull (ingen putt/netto-linje, en delt ball har ingen entydig +// netto-visning per spiller her). + +function SideScorecardGrid({ + sides, + players, + holesBySide, + holeOrder, + holesPlanned, + currentHole, + readOnly, + onSelectHole, + onOpenEntry, +}: { + sides: ApiSide[] + players: Player[] + holesBySide: Record + holeOrder: number[] + holesPlanned: number + currentHole: number + readOnly: boolean + onSelectHole: (holeNumber: number) => void + onOpenEntry: (sideId: string, holeNumber: number) => void +}) { + const holeMeta: Record = {} + for (const list of Object.values(holesBySide)) { + for (const h of list) { + if (!(h.hole_number in holeMeta)) holeMeta[h.hole_number] = { par: h.par, index: h.stroke_index } + } + } + + const showSplit = holesPlanned === 18 + const front = holeOrder.filter((n) => n <= 9) + const back = holeOrder.filter((n) => n >= 10) + + function sumFor(sideId: string, numbers: number[]): { strokes: number; par: number } | null { + const list = holesBySide[sideId] + if (!list || numbers.length === 0) return null + const played = numbers + .map((n) => list.find((h) => h.hole_number === n)) + .filter((h): h is ApiSideHole => Boolean(h) && h!.played && h!.score !== null) + if (played.length === 0) return null + return { + strokes: played.reduce((sum, h) => sum + (h.score as number), 0), + par: played.reduce((sum, h) => sum + h.par, 0), + } + } + + const parRowTotal = holeOrder.reduce((sum, n) => sum + (holeMeta[n]?.par ?? 0), 0) + + return ( +
+ + + + {holeOrder.map((n) => ( + + ))} + {showSplit && } + {showSplit && } + + + + + + {holeOrder.map((n) => { + const active = n === currentHole + return ( + + ) + })} + {showSplit && ( + + )} + {showSplit && ( + + )} + + + + + + + {holeOrder.map((n) => ( + + ))} + {showSplit && + + + {holeOrder.map((n) => ( + + ))} + {showSplit && ( + + )} + {showSplit && ( + + )} + + + + {sides.map((side, sideIndex) => { + const list = holesBySide[side.id] + const frontSum = showSplit ? sumFor(side.id, front) : null + const backSum = showSplit ? sumFor(side.id, back) : null + const totalSum = sumFor(side.id, holeOrder) + const assignedNames = players.filter((p) => p.roundSideId === side.id).map((p) => p.name) + return ( + + + {holeOrder.map((n) => { + const apiHole = list?.find((h) => h.hole_number === n) ?? null + const meta = holeMeta[n] + const hasScore = Boolean(apiHole?.played) && apiHole?.score !== null + const diff = hasScore && meta ? (apiHole!.score as number) - meta.par : null + return ( + + ) + })} + {showSplit && ( + + )} + {showSplit && ( + + )} + + + ) + })} + +
+ Side + + + + Ut + + Inn + + Sum +
+ Hcp + + {holeMeta[n]?.index ?? "–"} + } + {showSplit && } + +
+ Par + + {holeMeta[n]?.par ?? "–"} + + {front.reduce((sum, n) => sum + (holeMeta[n]?.par ?? 0), 0) || "–"} + + {back.reduce((sum, n) => sum + (holeMeta[n]?.par ?? 0), 0) || "–"} + + {parRowTotal || "–"} +
+ + + + + {frontSum ? frontSum.strokes : "–"} + + {backSum ? backSum.strokes : "–"} + + {totalSum ? ( + + {totalSum.strokes} + + {formatToPar(totalSum.strokes - totalSum.par)} + + + ) : ( + "–" + )} +
+
+ ) +} + +// --- Delt-ball-scoreveiviser (ADR-039 Beslutning C) -------------------------- +// Enklere enn ScoringWizard -- kun ett tall (slagtall for hele siden), ingen +// putt-/detalj-steg. Samme "Neste side" → "Neste hull"-samlebåndsprinsipp. + +function SideScoreWizard({ + sides, + side, + hole, + score, + onSave, + onClose, + onAdvance, + readOnly, +}: { + sides: ApiSide[] + side: ApiSide + hole: Hole + score: number | null + onSave: (score: number | null) => void + onClose: () => void + onAdvance: () => void + readOnly: boolean +}) { + const sideIndex = sides.findIndex((s) => s.id === side.id) + const isLast = sideIndex === -1 || sideIndex === sides.length - 1 + const nextSide = !isLast ? sides[sideIndex + 1] : null + + function sideLabel(s: ApiSide, idx: number) { + return s.label?.trim() || `Side ${idx === 0 ? "A" : "B"}` + } + + return ( +
+
+ +
+ + Hull {hole.holeNumber} · Par {hole.par} + + {sideLabel(side, sideIndex)} +
+
+ +
+ {sides.map((s, i) => ( + + {sideLabel(s, i)} + + ))} +
+ +
+
+ onSave(v)} + readOnly={readOnly} + /> +
+
+ + +
+ ) +} + function NumberPicker({ label, value, diff --git a/frontend/tsconfig.tsbuildinfo b/frontend/tsconfig.tsbuildinfo new file mode 100644 index 0000000..9d908fe --- /dev/null +++ b/frontend/tsconfig.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es5.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2016.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2018.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2019.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2021.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2022.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2023.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.esnext.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.dom.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.core.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.date.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.object.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.string.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2019.array.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2019.object.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2019.string.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.date.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.string.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2020.number.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2021.string.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2022.array.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2022.error.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2022.object.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2022.string.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2022.regexp.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2023.array.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2023.collection.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2023.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.arraybuffer.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.collection.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.object.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.promise.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.regexp.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.sharedmemory.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.es2024.string.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.esnext.array.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.esnext.collection.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.esnext.intl.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.esnext.disposable.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.esnext.decorators.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.esnext.iterator.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.decorators.d.ts","./node_modules/.pnpm/typescript@5.7.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","./node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/global.d.ts","./node_modules/.pnpm/csstype@3.2.3/node_modules/csstype/index.d.ts","./node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/styled-jsx/types/css.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/styled-jsx/types/macro.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/styled-jsx/types/style.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/styled-jsx/types/global.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/styled-jsx/types/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/get-page-files.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/ts5.7/compatibility/float16array.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/compatibility/iterators.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/globals.typedarray.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/buffer.buffer.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/globals.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/abortcontroller.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/crypto.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/domexception.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/events.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/utility.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/header.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/readable.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/fetch.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/formdata.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/connector.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/client-stats.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/client.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/errors.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/dispatcher.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/global-dispatcher.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/global-origin.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/pool-stats.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/pool.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/handlers.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/balanced-pool.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/h2c-client.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/agent.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/mock-interceptor.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/mock-call-history.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/mock-agent.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/mock-client.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/mock-pool.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/snapshot-agent.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/mock-errors.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/proxy-agent.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/env-http-proxy-agent.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/retry-handler.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/retry-agent.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/api.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/cache-interceptor.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/interceptors.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/util.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/cookies.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/patch.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/websocket.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/eventsource.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/diagnostics-channel.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/content-type.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/cache.d.ts","./node_modules/.pnpm/undici-types@7.16.0/node_modules/undici-types/index.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/fetch.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/navigator.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/storage.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/web-globals/streams.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/assert.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/assert/strict.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/async_hooks.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/buffer.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/child_process.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/cluster.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/console.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/constants.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/crypto.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/dgram.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/diagnostics_channel.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/dns.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/dns/promises.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/domain.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/events.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/fs.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/fs/promises.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/http.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/http2.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/https.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/inspector.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/inspector.generated.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/module.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/net.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/os.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/path.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/perf_hooks.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/process.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/punycode.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/querystring.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/readline.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/readline/promises.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/repl.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/sea.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/sqlite.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/stream.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/stream/promises.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/stream/consumers.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/stream/web.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/string_decoder.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/test.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/timers.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/timers/promises.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/tls.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/trace_events.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/tty.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/url.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/util.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/v8.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/vm.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/wasi.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/worker_threads.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/zlib.d.ts","./node_modules/.pnpm/@types+node@24.10.4/node_modules/@types/node/ts5.7/index.d.ts","./node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/canary.d.ts","./node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/experimental.d.ts","./node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.14/node_modules/@types/react-dom/index.d.ts","./node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.14/node_modules/@types/react-dom/canary.d.ts","./node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.14/node_modules/@types/react-dom/experimental.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/fallback.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/compiled/webpack/webpack.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/modern-browserslist-target.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/entry-constants.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/constants.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/bundler.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/config.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/load-custom-routes.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/image-config.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/plugins/subresource-integrity-plugin.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/body-streams.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request/search-params.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/segment-cache/vary-params-decoding.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/vary-params.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request/params.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-kind.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-definitions/route-definition.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-matches/route-match.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/app-router-headers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/cache-control.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/app-router-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/cache-handlers/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/use-cache/use-cache-wrapper.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/resume-data-cache/cache-store.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/resume-data-cache/resume-data-cache.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/constants.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/render-result.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/response-cache/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/response-cache/index.d.ts","./node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/jsx-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/userspace/pages/pages-dev-overlay-setup.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/static-paths/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-definitions/app-page-route-definition.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/adapter/setup-node-env.external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/instrumentation/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/setup-exception-listeners.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/worker.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/experimental/ppr.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/page-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/segment-config/app/app-segment-config.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/segment-config/pages/pages-segment-config.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/analysis/get-page-static-info.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/loaders/get-module-build-info.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/plugins/middleware-plugin.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/require-hook.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-polyfill-crypto.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-baseline.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/error-inspect.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/console-file.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/console-exit.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/console-dim.external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/unhandled-rejection.external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/random.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/date.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/web-crypto.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/node-crypto.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment-extensions/fast-set-immediate.external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/node-environment.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/page-extensions-type.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-page/module.compiled.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-definitions/app-route-route-definition.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/i18n-provider.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/next-url.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/compiled/@edge-runtime/cookies/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/cookies.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/request.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/deep-readonly.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/incremental-cache/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router/utils/middleware-route-matcher.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/plugins/flight-manifest-plugin.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/plugins/next-font-manifest-plugin.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-definitions/locale-route-definition.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-definitions/pages-route-definition.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/mitt.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/with-router.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/router.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/route-loader.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/page-loader.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/bloom-filter.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router/router.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router-context.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/loadable-context.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/loadable.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/image-config-context.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/readonly-url-search-params.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/hooks-client-context.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/head-manager-context.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/flight-data-helpers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/segment-cache/cache-key.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/router-reducer/fetch-server-response.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/segment-cache/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/segment-cache/segment-value-encoding.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/segment-cache/scheduler.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/segment-cache/cache-map.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/segment-cache/vary-path.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/segment-cache/cache.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/router-reducer/ppr-navigations.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/segment-cache/navigation.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/router-reducer/router-reducer-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/app-router-context.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/server-inserted-html.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/pages/vendored/contexts/entrypoints.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/pages/module.compiled.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/templates/pages.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/pages/module.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/render.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/plugins/pages-manifest-plugin.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-definitions/pages-api-route-definition.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-matches/pages-api-route-match.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-matchers/route-matcher.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-matcher-providers/route-matcher-provider.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-matcher-managers/route-matcher-manager.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/normalizers/normalizer.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/normalizers/locale-route-normalizer.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/normalizers/request/pathname-normalizer.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/normalizers/request/suffix.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/normalizers/request/rsc.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/normalizers/request/next-data.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/after/builtin-request-context.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/normalizers/request/segment-prefix-rsc.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/pages/builtin/_error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/load-default-error-components.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/base-server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/after/after.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/after/after-context.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/use-cache/cache-life.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/work-async-storage-instance.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/lazy-result.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/create-error-handler.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/action-revalidation-kind.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/work-async-storage.external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/async-storage/work-store.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/http.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/hooks-server-context.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-route/shared-modules.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/redirect-status-code.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/redirect-error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/adapters/request-cookies.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/async-storage/draft-mode-provider.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/adapters/headers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/cache-signal.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/instant-validation/boundary-tracking.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/instant-validation/instant-validation-error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router/utils/parse-relative-url.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/instant-validation/instant-samples.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/dynamic-rendering.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/work-unit-async-storage-instance.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/implicit-tags.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/staged-rendering.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/work-unit-async-storage.external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/templates/app-route.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/action-async-storage-instance.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/action-async-storage.external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-route/module.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-route/module.compiled.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/segment-config/app/app-segments.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/get-supported-browsers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/utils.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/rendering-mode.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/router-utils/build-prefetch-segment-data-route.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/cpu-profile.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/turborepo-access-trace/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/turborepo-access-trace/result.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/turborepo-access-trace/helpers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/turborepo-access-trace/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/export/routes/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/export/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/export/worker.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/worker.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/coalesced-function.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/router-utils/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/trace/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/trace/trace.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/trace/shared.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/trace/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/load-jsconfig.d.ts","./node_modules/.pnpm/@next+env@16.2.6/node_modules/@next/env/dist/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/plugins/telemetry-plugin/use-cache-tracker-utils.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/plugins/telemetry-plugin/telemetry-plugin.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/telemetry/storage.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/build-context.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack-config.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/swc/generated-native.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/define-env.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/swc/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/swc/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/dev/parse-version-info.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/shared/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/dev/dev-indicator-server-state.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/dev-overlay/cache-indicator.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/parse-stack.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/server/shared.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/shared/stack-frame.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/dev-overlay/utils/get-error-by-type.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/dev-overlay/container/runtime-error/render-error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/dev-overlay/shared.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/dev/debug-channel.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/dev/hot-reloader-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/fetch-event.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/response.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/segment-config/middleware/middleware-config.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router/utils/parse-url.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/base-http/node.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/async-callback-set.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router/utils/route-regex.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router/utils/route-matcher.d.ts","./node_modules/.pnpm/sharp@0.34.5/node_modules/sharp/lib/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/image-optimizer.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/next-server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/lru-cache.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/dev-bundler-service.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/dev/static-paths-worker.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/dev/next-dev-server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/next.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/render-server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/router-server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/router/utils/path-match.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/router-utils/filesystem.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/router-utils/setup-dev-bundler.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/router-utils/router-server-context.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/route-module.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/load-components.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/adapter.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/loaders/metadata/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/webpack/loaders/next-app-loader/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/lib/app-dir-module.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/app-render.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-page/vendored/contexts/entrypoints.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/error-boundary.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/layout-router.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/render-from-template-context.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/client-page.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/client-segment.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/http-access-fallback/error-boundary.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/alternative-urls-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/extra-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/metadata-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/manifest-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/opengraph-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/twitter-types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/metadata-interface.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/resolvers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/types/icons.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/resolve-metadata.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/metadata/metadata.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/lib/framework/boundary-components.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/rsc/preloads.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/rsc/postpone.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/rsc/taint.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/collect-segment-data.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/instant-validation/instant-validation.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/next-devtools/userspace/app/segment-explorer-node.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/app-render/entry-base.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/templates/app-page.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-page/helpers/prerender-manifest-matcher.d.ts","./node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/jsx-dev-runtime.d.ts","./node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/compiler-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-page/vendored/rsc/entrypoints.d.ts","./node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.14/node_modules/@types/react-dom/client.d.ts","./node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.14/node_modules/@types/react-dom/static.d.ts","./node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.14/node_modules/@types/react-dom/server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-page/vendored/ssr/entrypoints.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/route-modules/app-page/module.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request/fallback-params.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/image-response.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/user-agent.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/url-pattern.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/after/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request/connection.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/exports/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request-meta.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/cli/next-test.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/size-limit.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/config-shared.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/base-http/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/api-utils/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/build/adapter/build-complete.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/html-context.shared-runtime.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/utils.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/pages/_app.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/app.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/unstable-cache.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/revalidate.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/web/spec-extension/unstable-no-store.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/use-cache/cache-tag.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/cache.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/pages/_document.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/document.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/dynamic.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dynamic.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/pages/_error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/catch-error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/api/error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/head.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/head.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request/cookies.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request/headers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/server/request/draft-mode.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/headers.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/get-img-props.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/image-component.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/shared/lib/image-external.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/image.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/link.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/link.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/unrecognized-action-error.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/redirect.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/not-found.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/forbidden.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/unauthorized.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/unstable-rethrow.server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/unstable-rethrow.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/navigation.react-server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/components/navigation.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/navigation.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/router.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/client/script.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/script.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/compiled/@edge-runtime/primitives/url.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/compiled/@vercel/og/satori/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/compiled/@vercel/og/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/server.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/types/global.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/types/compiled.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/image-types/global.d.ts","./.next/dev/types/routes.d.ts","./next-env.d.ts","./app/manifest.ts","./lib/offline-queue.ts","./node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/clsx.d.mts","./node_modules/.pnpm/tailwind-merge@3.4.0/node_modules/tailwind-merge/dist/types.d.ts","./lib/utils.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/compiled/@next/font/dist/types.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/dist/compiled/@next/font/dist/google/index.d.ts","./node_modules/.pnpm/next@16.2.6_@babel+core@7.29.7_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/next/font/google/index.d.ts","./components/sw-register.tsx","./app/layout.tsx","./node_modules/.pnpm/lucide-react@1.17.0_react@19.2.4/node_modules/lucide-react/dist/lucide-react.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/reason-parts.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/reasons.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/createBaseUIEventDetails.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/types/index.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/types.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/button/Button.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/button/index.d.ts","./node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/types.d.ts","./node_modules/.pnpm/class-variance-authority@0.7.1/node_modules/class-variance-authority/dist/index.d.ts","./components/ui/button.tsx","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/form-context/FormContext.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/form/Form.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/form/index.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/root/FieldRoot.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/label/FieldLabel.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/useTransitionStatus.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/error/FieldError.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/description/FieldDescription.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/control/FieldControl.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/validity/FieldValidity.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/item/FieldItem.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/index.parts.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/field/index.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/input/Input.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/input/index.d.ts","./components/ui/input.tsx","./components/ui/label.tsx","./components/two-factor-flow.tsx","./components/login-form.tsx","./components/wordmark.tsx","./app/page.tsx","./components/account-settings.tsx","./app/account/page.tsx","./node_modules/.pnpm/@floating-ui+utils@0.2.11/node_modules/@floating-ui/utils/dist/floating-ui.utils.d.mts","./node_modules/.pnpm/@floating-ui+core@1.7.5/node_modules/@floating-ui/core/dist/floating-ui.core.d.mts","./node_modules/.pnpm/@floating-ui+utils@0.2.11/node_modules/@floating-ui/utils/dist/floating-ui.utils.dom.d.mts","./node_modules/.pnpm/@floating-ui+dom@1.7.6/node_modules/@floating-ui/dom/dist/floating-ui.dom.d.mts","./node_modules/.pnpm/@floating-ui+react-dom@2.1.8_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@floating-ui/react-dom/dist/floating-ui.react-dom.d.mts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/components/FloatingTreeStore.d.ts","./node_modules/.pnpm/reselect@5.2.0/node_modules/reselect/dist/reselect.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/store/createSelector.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/store/createSelectorMemoized.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/fastHooks.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/store/Store.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/store/useStore.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/store/ReactStore.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/store/StoreInspector.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/store/index.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/popups/inlineRect.d.ts","./node_modules/.pnpm/@base-ui+utils@0.2.9_@types+react@19.2.14_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/utils/esm/useEnhancedClickHandler.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/popups/popupTriggerMap.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/popups/store.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/popups/popupStoreUtils.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/popups/index.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/components/FloatingRootStore.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/components/FloatingFocusManager.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/getStateAttributesProps.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/useRenderElement.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/components/FloatingPortal.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useClientPoint.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useDismiss.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useFocus.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/internals/shadowDom.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/utils/element.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useHoverShared.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useHover.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useHoverFloatingInteraction.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useHoverReferenceInteraction.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useListNavigation.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useTypeahead.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useFloatingRootContext.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/safePolygon.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/components/FloatingTree.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/types.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/components/FloatingDelayGroup.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useClick.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useFloating.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/hooks/useSyncedFloatingRootContext.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/floating-ui-react/index.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/utils/useAnchorPositioning.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/arrow/MenuArrow.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/backdrop/MenuBackdrop.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/store/MenuStore.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/root/MenuRootContext.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menubar/MenubarContext.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/context-menu/root/ContextMenuRoot.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/context-menu/root/ContextMenuRootContext.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/store/MenuHandle.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/root/MenuRoot.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/checkbox-item/MenuCheckboxItem.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/checkbox-item-indicator/MenuCheckboxItemIndicator.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/group/MenuGroup.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/group-label/MenuGroupLabel.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/item/MenuItem.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/link-item/MenuLinkItem.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/popup/MenuPopup.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/portal/MenuPortal.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/positioner/MenuPositioner.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/radio-group/MenuRadioGroup.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/radio-item/MenuRadioItem.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/radio-item-indicator/MenuRadioItemIndicator.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/submenu-root/MenuSubmenuRootContext.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/submenu-root/MenuSubmenuRoot.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/trigger/MenuTrigger.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/viewport/MenuViewport.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/separator/Separator.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/submenu-trigger/MenuSubmenuTrigger.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/index.parts.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/menu/index.d.ts","./components/ui/dropdown-menu.tsx","./components/tournament-status-badge.tsx","./components/tournament-card.tsx","./components/public-club.tsx","./app/clubs/[slug]/page.tsx","./components/round-card.tsx","./components/dashboard.tsx","./app/dashboard/page.tsx","./components/friends.tsx","./app/my-friends/page.tsx","./components/notifications.tsx","./app/my-notifications/page.tsx","./components/own-rounds.tsx","./app/my-rounds/page.tsx","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/merge-props/mergeProps.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/merge-props/index.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/use-render/useRender.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/use-render/index.d.ts","./components/ui/badge.tsx","./components/round-leaderboard.tsx","./components/round-detail.tsx","./app/my-rounds/[id]/page.tsx","./app/my-rounds/[id]/leaderboard/page.tsx","./components/round-scorecard.tsx","./app/my-rounds/[id]/scorecard/page.tsx","./components/round-stats.tsx","./app/my-rounds/[id]/stats/page.tsx","./components/course-rounds.tsx","./app/my-rounds/course/[name]/page.tsx","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/switch/root/SwitchRoot.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/switch/thumb/SwitchThumb.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/switch/index.parts.d.ts","./node_modules/.pnpm/@base-ui+react@1.5.0_@date-fns+tz@1.4.1_@types+react@19.2.14_date-fns@4.1.0_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@base-ui/react/esm/switch/index.d.ts","./components/ui/switch.tsx","./components/new-round.tsx","./app/my-rounds/new/page.tsx","./components/rounds-stats-summary.tsx","./app/my-rounds/stats/page.tsx","./components/org-members.tsx","./app/organizations/[id]/members/page.tsx","./components/public-tournament.tsx","./app/t/[id]/page.tsx","./components/public-live.tsx","./app/t/[id]/live/page.tsx","./components/tournament-detail.tsx","./app/tournaments/[id]/page.tsx","./components/tournament-leaderboard.tsx","./app/tournaments/[id]/leaderboard/page.tsx","./components/tournament-program.tsx","./app/tournaments/[id]/program/page.tsx","./components/session-blind-draw.tsx","./app/tournaments/[id]/sessions/[sessionId]/page.tsx","./components/session-scorecard.tsx","./app/tournaments/[id]/sessions/[sessionId]/matches/[matchId]/page.tsx","./components/team-chat.tsx","./app/tournaments/[id]/teams/[teamId]/chat/page.tsx","./components/verify-form.tsx","./app/verify/page.tsx","./components/verify-email-form.tsx","./app/verify-email/page.tsx","./components/ui/card.tsx","./.next/types/cache-life.d.ts","./.next/types/routes.d.ts","./.next/types/validator.ts","./.next/dev/types/cache-life.d.ts","./.next/dev/types/validator.ts"],"fileIdsList":[[91,145,162,163,487,488,489,490,717],[91,145,162,163,717,720],[91,145,162,163,230,531,534,545,577,579,660,663,665,667,669,677,678,680,682,684,691,693,695,697,699,701,703,705,707,709,711,713,715,717,720],[91,145,162,163,487,488,489,490,720],[91,145,162,163,230,531,545,577,579,660,663,665,667,669,677,678,680,682,684,691,693,695,697,699,701,703,705,707,709,711,713,715,717,718,720],[91,145,162,163,230,578,717,720],[91,145,162,163,230,532,659,717,720],[91,145,162,163,230,662,717,720],[91,145,162,163,230,529,532,543,544,717,720],[91,145,162,163,230,532,717,720],[91,145,162,163,230,664,717,720],[91,145,162,163,230,666,717,720],[91,145,162,163,230,675,717,720],[91,145,162,163,230,676,717,720],[91,145,162,163,230,679,717,720],[91,145,162,163,230,681,717,720],[91,145,162,163,230,683,717,720],[91,145,162,163,230,690,717,720],[91,145,162,163,230,668,717,720],[91,145,162,163,230,692,717,720],[91,145,162,163,230,694,717,720],[91,145,162,163,230,505,521,575,576,717,720],[91,145,162,163,230,698,717,720],[91,145,162,163,230,532,696,717,720],[91,145,162,163,230,702,717,720],[91,145,162,163,230,700,717,720],[91,145,162,163,230,704,717,720],[91,145,162,163,230,708,717,720],[91,145,162,163,230,706,717,720],[91,145,162,163,230,710,717,720],[81,91,145,162,163,230,576,714,717,720],[81,91,145,162,163,230,576,712,717,720],[81,91,145,162,163,230,511,521,546,556,572,573,574,576,717,720],[81,91,145,162,163,230,511,521,546,576,661,717,720],[81,91,145,162,163,230,511,521,540,546,556,572,573,576,656,657,658,661,717,720],[81,91,145,162,163,230,511,521,540,546,572,576,717,720],[81,91,145,162,163,230,521,546,556,572,573,574,717,720],[81,91,145,162,163,230,511,521,540,546,556,572,573,576,689,717,720],[81,91,145,162,163,230,511,521,540,546,576,717,720],[81,91,145,162,163,230,511,546,556,572,573,717,720],[81,91,145,162,163,230,511,521,546,556,576,661,717,720],[81,91,145,162,163,230,546,576,658,717,720],[81,91,145,162,163,230,511,540,546,576,717,720],[81,91,145,162,163,230,511,540,546,556,572,573,576,717,720],[91,145,162,163,230,511,540,546,717,720],[81,91,145,162,163,230,511,521,540,546,556,572,573,674,675,717,720],[81,91,145,162,163,230,511,540,546,674,717,720],[81,91,145,162,163,230,511,540,546,717,720],[81,91,145,162,163,230,511,521,546,717,720],[81,91,145,162,163,230,511,540,546,556,717,720],[81,91,145,162,163,230,511,537,540,546,556,717,720],[81,91,145,162,163,230,717,720],[91,145,162,163,230,511,546,657,717,720],[81,91,145,162,163,230,511,540,546,556,572,573,656,657,717,720],[81,91,145,162,163,230,511,540,546,556,572,573,656,689,717,720],[91,145,162,163,230,540,546,656,717,720],[81,91,145,162,163,230,546,556,572,573,717,720],[91,145,162,163,230,540,555,671,673,717,720],[91,145,162,163,230,540,553,555,717,720],[81,91,145,162,163,230,540,717,720],[81,91,145,162,163,230,540,546,655,717,720],[81,91,145,162,163,230,540,571,717,720],[91,145,162,163,230,540,688,717,720],[91,145,162,163,230,540,546,717,720],[91,145,162,163,230,717,720],[91,145,162,163,230,538,539,717,720],[91,145,162,163,532,533,534,717,720],[81,91,145,162,163,551,717,720],[91,145,162,163,552,717,720],[91,145,162,163,230,550,635,655,717,720],[81,91,145,162,163,632,717,720],[81,91,145,162,163,548,549,551,560,717,720],[81,91,145,162,163,551,560,717,720],[81,91,145,162,163,551,560,562,717,720],[91,145,162,163,560,561,563,564,565,566,567,568,717,720],[91,145,162,163,560,561,563,564,565,566,567,717,720],[81,91,145,162,163,551,559,717,720],[81,91,145,162,163,560,562,717,720],[81,91,145,162,163,620,717,720],[81,91,145,162,163,585,596,620,717,720],[81,91,145,162,163,551,604,717,720],[81,91,145,162,163,549,562,594,600,620,717,720],[81,91,145,162,163,585,620,717,720],[91,145,162,163,620,717,720],[91,145,162,163,548,620,717,720],[91,145,162,163,585,620,717,720],[91,145,162,163,549,601,620,717,720],[91,145,162,163,611,620,717,720],[81,91,145,162,163,551,585,611,620,717,720],[91,145,162,163,610,620,717,720],[91,145,162,163,550,594,600,601,717,720],[91,145,162,163,584,585,602,605,606,607,608,612,613,614,615,616,617,618,619,620,621,622,623,624,717,720],[91,145,162,163,611,717,720],[81,91,145,162,163,549,584,585,601,602,605,606,607,608,611,612,613,614,615,616,617,618,619,621,625,717,720],[91,145,162,163,600,609,717,720],[81,91,145,162,163,548,549,551,557,717,720],[91,145,162,163,558,717,720],[81,91,145,162,163,551,569,717,720],[91,145,162,163,570,717,720],[91,145,162,163,548,717,720],[81,91,145,162,163,558,560,717,720],[91,145,162,163,547,717,720],[81,91,145,162,163,550,717,720],[81,91,145,162,163,551,603,717,720],[81,91,145,162,163,717,720],[81,91,145,162,163,551,626,717,720],[81,91,145,162,163,551,562,717,720],[81,91,145,162,163,551,635,717,720],[91,145,162,163,627,628,635,636,637,638,639,640,641,642,643,644,645,646,647,649,650,651,653,654,717,720],[91,145,162,163,627,628,634,635,636,637,638,639,640,641,642,643,644,645,646,647,649,650,651,652,653,717,720],[81,91,145,162,163,551,562,596,626,717,720],[81,91,145,162,163,625,717,720],[81,91,145,162,163,230,548,549,600,629,630,631,633,634,717,720],[81,91,145,162,163,629,635,717,720],[91,145,162,163,629,717,720],[81,91,145,162,163,551,562,585,594,596,600,601,625,635,655,717,720],[91,145,162,163,230,635,648,717,720],[81,91,145,162,163,629,717,720],[81,91,145,162,163,551,634,717,720],[81,91,145,162,163,635,717,720],[91,145,162,163,670,717,720],[91,145,162,163,685,686,687,717,720],[91,145,162,163,685,686,717,720],[81,91,145,162,163,548,550,551,560,717,720],[81,91,145,162,163,551,685,717,720],[81,91,145,162,163,549,717,720],[91,145,162,163,551,672,717,720],[91,145,162,163,595,597,598,599,717,720],[81,91,145,162,163,584,717,720],[81,91,145,162,163,549,562,594,596,598,717,720],[91,145,162,163,551,562,597,601,625,717,720],[81,91,145,162,163,580,625,717,720],[91,145,162,163,590,717,720],[81,91,145,162,163,230,590,717,720],[91,145,162,163,586,717,720],[91,145,162,163,587,717,720],[91,145,162,163,587,588,590,591,592,593,717,720],[91,145,162,163,589,590,717,720],[91,145,162,163,580,717,720],[91,145,162,163,581,582,717,720],[81,91,145,162,163,583,717,720],[91,142,143,145,162,163,717,720],[91,144,145,162,163,717,720],[145,162,163,717,720],[91,145,150,162,163,180,717,720],[91,145,146,151,156,162,163,165,177,188,717,720],[91,145,146,147,156,162,163,165,717,720],[91,145,148,162,163,189,717,720],[91,145,149,150,157,162,163,166,717,720],[91,145,150,162,163,177,185,717,720],[91,145,151,153,156,162,163,165,717,720],[91,144,145,152,162,163,717,720],[91,145,153,154,162,163,717,720],[91,145,155,156,162,163,717,720],[91,144,145,156,162,163,717,720],[91,145,156,157,158,162,163,177,188,717,720],[91,145,156,157,158,162,163,172,177,180,717,720],[91,137,145,153,156,159,162,163,165,177,188,717,720],[91,145,156,157,159,160,162,163,165,177,185,188,717,720],[91,145,159,161,162,163,177,185,188,717,720],[91,145,156,162,163,717,720],[91,145,162,163,164,188,717,720],[91,145,153,156,162,163,165,177,717,720],[91,145,162,163,166,717,720],[91,145,162,163,167,717,720],[91,144,145,162,163,168,717,720],[91,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,717,720],[91,145,162,163,170,717,720],[91,145,162,163,171,717,720],[91,145,156,162,163,172,173,717,720],[91,145,162,163,172,174,189,191,717,720],[91,145,157,162,163,717,720],[91,145,156,162,163,177,178,180,717,720],[91,145,162,163,179,180,717,720],[91,145,162,163,177,178,717,720],[91,145,162,163,180,717,720],[91,145,162,163,181,717,720],[91,142,145,162,163,177,182,717,720],[91,145,156,162,163,183,184,717,720],[91,145,162,163,183,184,717,720],[91,145,150,162,163,165,177,185,717,720],[91,145,162,163,186,717,720],[88,89,90,91,92,93,94,95,96,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,717,720],[91,145,162,163,165,187,717,720],[91,145,159,162,163,171,188,717,720],[91,145,150,162,163,189,717,720],[91,145,162,163,177,190,717,720],[91,145,162,163,164,191,717,720],[91,145,162,163,192,717,720],[91,145,150,162,163,717,720],[91,137,145,162,163,717,720],[91,145,162,163,193,717,720],[91,137,145,156,158,162,163,168,177,180,188,190,191,193,717,720],[91,145,162,163,177,194,717,720],[81,85,91,145,162,163,196,197,198,200,482,527,717,720],[81,85,91,145,162,163,196,197,198,199,463,482,527,717,720],[81,85,91,145,162,163,196,197,199,200,482,527,717,720],[81,91,145,162,163,200,463,464,717,720],[81,91,145,162,163,200,463,717,720],[81,85,91,145,162,163,197,198,199,200,482,527,717,720],[81,85,91,145,162,163,196,198,199,200,482,527,717,720],[79,80,91,145,162,163,717,720],[91,145,162,163,538,554,717,720],[91,145,162,163,538,717,720],[91,145,162,163,485,717,720],[91,145,162,163,487,488,489,490,717,720],[91,145,162,163,433,496,497,717,720],[91,145,162,163,205,206,208,220,244,359,370,478,717,720],[91,145,162,163,208,239,240,241,243,478,717,720],[91,145,162,163,208,376,378,380,381,383,478,480,717,720],[91,145,162,163,208,242,279,478,717,720],[91,145,162,163,206,208,219,220,226,232,237,358,359,360,369,478,480,717,720],[91,145,162,163,478,717,720],[91,145,162,163,215,221,240,260,355,717,720],[91,145,162,163,208,717,720],[91,145,162,163,201,215,221,717,720],[91,145,162,163,387,717,720],[91,145,162,163,384,385,387,717,720],[91,145,162,163,384,386,478,717,720],[91,145,159,162,163,260,457,475,717,720],[91,145,159,162,163,331,334,350,355,475,717,720],[91,145,159,162,163,303,475,717,720],[91,145,162,163,363,717,720],[91,145,162,163,362,363,364,717,720],[91,145,162,163,362,717,720],[87,91,145,159,162,163,201,208,220,226,232,238,240,244,245,258,259,326,356,357,370,478,482,717,720],[91,145,162,163,205,208,242,279,376,377,382,478,530,717,720],[91,145,162,163,242,530,717,720],[91,145,162,163,205,259,428,478,530,717,720],[91,145,162,163,530,717,720],[91,145,162,163,208,242,243,530,717,720],[91,145,162,163,379,530,717,720],[91,145,162,163,245,358,361,368,717,720],[81,91,145,162,163,433,717,720],[91,145,162,163,171,215,230,717,720],[91,145,162,163,215,230,717,720],[81,91,145,162,163,300,717,720],[81,91,145,162,163,221,230,433,717,720],[91,145,162,163,215,286,300,301,512,519,717,720],[91,145,162,163,285,513,514,515,516,518,717,720],[91,145,162,163,336,717,720],[91,145,162,163,336,337,717,720],[91,145,162,163,219,221,288,289,717,720],[91,145,162,163,221,295,296,717,720],[91,145,162,163,221,290,298,717,720],[91,145,162,163,295,717,720],[91,145,162,163,213,221,288,289,290,291,292,293,294,295,298,717,720],[91,145,162,163,221,288,295,296,297,299,717,720],[91,145,162,163,221,289,291,292,717,720],[91,145,162,163,289,291,294,296,717,720],[91,145,162,163,517,717,720],[91,145,162,163,221,717,720],[81,91,145,162,163,209,506,717,720],[81,91,145,162,163,188,717,720],[81,91,145,162,163,242,277,717,720],[81,91,145,162,163,242,370,717,720],[91,145,162,163,275,280,717,720],[81,91,145,162,163,276,484,717,720],[91,145,162,163,541,717,720],[81,85,91,145,159,162,163,196,197,198,199,200,482,526,717,720],[91,145,159,162,163,221,717,720],[91,145,159,162,163,220,225,306,323,365,366,370,425,427,478,479,717,720],[91,145,162,163,258,367,717,720],[91,145,162,163,482,717,720],[91,145,162,163,207,717,720],[81,91,145,162,163,212,215,430,446,448,717,720],[91,145,162,163,171,215,430,445,446,447,529,717,720],[91,145,162,163,439,440,441,442,443,444,717,720],[91,145,162,163,441,717,720],[91,145,162,163,445,717,720],[91,145,162,163,230,394,395,397,717,720],[81,91,145,162,163,221,388,389,390,391,396,717,720],[91,145,162,163,394,396,717,720],[91,145,162,163,392,717,720],[91,145,162,163,393,717,720],[81,91,145,162,163,230,276,484,717,720],[81,91,145,162,163,230,483,484,717,720],[81,91,145,162,163,230,484,717,720],[91,145,162,163,323,324,717,720],[91,145,162,163,324,717,720],[91,145,159,162,163,479,484,717,720],[91,145,162,163,353,717,720],[91,144,145,162,163,352,717,720],[91,145,162,163,215,221,227,229,331,344,348,350,427,430,467,468,475,479,717,720],[91,145,162,163,221,270,292,717,720],[91,145,162,163,331,342,345,350,717,720],[81,91,145,162,163,212,215,331,334,350,353,387,434,435,436,437,438,449,450,451,452,453,454,455,456,530,717,720],[91,145,162,163,212,215,240,331,338,339,340,343,344,717,720],[91,145,162,163,177,221,240,342,349,430,431,475,717,720],[91,145,162,163,346,717,720],[91,145,159,162,163,171,209,221,225,235,267,268,271,323,326,391,425,426,467,478,479,480,482,530,717,720],[91,145,162,163,212,213,215,717,720],[91,145,162,163,331,717,720],[91,144,145,162,163,240,267,268,325,326,327,328,329,330,479,717,720],[91,145,162,163,350,717,720],[91,144,145,162,163,214,215,225,229,265,331,338,339,340,341,342,345,346,347,348,349,468,717,720],[91,145,159,162,163,265,266,338,479,480,717,720],[91,145,162,163,240,268,323,326,331,427,479,717,720],[91,145,159,162,163,478,480,717,720],[91,145,159,162,163,177,475,479,480,717,720],[91,145,159,162,163,171,201,215,220,227,229,232,235,242,262,267,268,269,270,271,306,307,309,312,314,317,318,319,320,322,370,425,427,475,478,479,480,717,720],[91,145,159,162,163,177,717,720],[91,145,162,163,208,209,210,238,475,476,477,482,484,530,717,720],[91,145,162,163,205,206,478,717,720],[91,145,162,163,399,717,720],[91,145,159,162,163,177,188,217,383,387,388,389,390,391,397,398,530,717,720],[91,145,162,163,171,188,201,215,217,229,232,268,307,312,322,323,376,403,404,405,411,414,415,425,427,475,478,717,720],[91,145,162,163,232,238,245,258,268,326,478,717,720],[91,145,159,162,163,188,209,220,229,268,409,475,478,717,720],[91,145,162,163,429,717,720],[91,145,159,162,163,399,412,413,422,717,720],[91,145,162,163,475,478,717,720],[91,145,162,163,328,468,717,720],[91,145,162,163,229,267,370,484,717,720],[91,145,159,162,163,171,207,312,372,376,405,411,414,417,475,717,720],[91,145,159,162,163,245,258,376,418,717,720],[91,145,162,163,208,269,370,420,478,480,717,720],[91,145,159,162,163,188,391,478,717,720],[91,145,159,162,163,242,269,370,371,372,381,399,419,421,478,717,720],[87,91,145,159,162,163,267,424,482,484,717,720],[91,145,162,163,321,425,717,720],[91,145,159,162,163,171,215,218,220,221,227,229,235,244,245,258,268,271,307,309,319,322,323,370,403,404,405,406,408,410,425,427,475,484,717,720],[91,145,159,162,163,177,245,411,416,422,475,717,720],[91,145,162,163,248,249,250,251,252,253,254,255,256,257,717,720],[91,145,162,163,262,313,717,720],[91,145,162,163,315,717,720],[91,145,162,163,313,717,720],[91,145,162,163,315,316,717,720],[91,145,159,162,163,219,220,221,225,226,479,717,720],[91,145,159,162,163,171,207,209,227,231,267,270,271,305,425,475,480,482,484,717,720],[91,145,159,162,163,171,188,211,218,219,229,231,268,423,468,474,479,717,720],[91,145,162,163,338,717,720],[91,145,162,163,339,717,720],[91,145,162,163,221,232,467,717,720],[91,145,162,163,340,717,720],[91,145,162,163,214,717,720],[91,145,162,163,216,228,717,720],[91,145,159,162,163,216,220,227,717,720],[91,145,162,163,223,228,717,720],[91,145,162,163,224,717,720],[91,145,162,163,216,217,717,720],[91,145,162,163,216,272,717,720],[91,145,162,163,216,717,720],[91,145,162,163,218,262,311,717,720],[91,145,162,163,310,717,720],[91,145,162,163,215,217,218,717,720],[91,145,162,163,218,308,717,720],[91,145,162,163,215,217,717,720],[91,145,162,163,267,370,717,720],[91,145,162,163,467,717,720],[91,145,159,162,163,188,227,229,233,267,370,424,427,430,431,432,458,459,462,466,468,475,479,717,720],[91,145,162,163,281,284,286,287,300,301,717,720],[81,91,145,162,163,198,200,230,460,461,717,720],[81,91,145,162,163,198,200,230,460,461,465,717,720],[91,145,162,163,354,717,720],[91,145,162,163,240,261,266,267,331,332,333,334,335,337,350,351,353,356,424,427,478,480,717,720],[91,145,162,163,300,717,720],[91,145,159,162,163,305,475,717,720],[91,145,162,163,305,717,720],[91,145,159,162,163,227,273,302,304,306,424,475,482,484,717,720],[91,145,162,163,281,282,283,284,286,287,300,301,483,717,720],[87,91,145,159,162,163,171,188,216,217,229,235,267,268,271,370,422,423,425,475,478,479,482,717,720],[91,145,162,163,212,215,222,717,720],[91,145,162,163,266,268,400,403,717,720],[91,145,162,163,266,401,469,470,471,472,473,717,720],[91,145,159,162,163,262,478,717,720],[91,145,159,162,163,717,720],[91,145,162,163,265,350,717,720],[91,145,162,163,264,717,720],[91,145,162,163,266,319,717,720],[91,145,162,163,263,265,478,717,720],[91,145,159,162,163,211,266,400,401,402,475,478,479,717,720],[81,91,145,162,163,215,221,299,717,720],[81,91,145,162,163,213,717,720],[91,145,162,163,203,204,717,720],[81,91,145,162,163,209,717,720],[81,91,145,162,163,215,285,717,720],[81,87,91,145,162,163,267,271,482,484,717,720],[91,145,162,163,209,506,507,717,720],[81,91,145,162,163,280,717,720],[81,91,145,162,163,171,188,207,274,276,278,279,484,717,720],[91,145,162,163,215,242,479,717,720],[91,145,162,163,215,407,717,720],[81,91,145,157,159,162,163,171,205,207,280,378,482,483,717,720],[81,91,145,162,163,196,197,198,199,200,482,527,717,720],[81,82,83,84,85,91,145,162,163,717,720],[91,145,162,163,373,374,375,717,720],[91,145,162,163,373,717,720],[81,85,91,145,159,161,162,163,171,195,196,197,198,199,200,201,207,235,240,417,445,480,481,484,527,717,720],[91,145,162,163,492,717,720],[91,145,162,163,494,717,720],[91,145,162,163,498,717,720],[91,145,162,163,542,717,720],[91,145,162,163,500,717,720],[91,145,162,163,502,503,504,717,720],[91,145,162,163,508,717,720],[86,91,145,162,163,486,491,493,495,499,501,505,509,511,521,522,524,528,529,530,531,717,720],[91,145,162,163,510,717,720],[91,145,162,163,520,717,720],[91,145,162,163,276,717,720],[91,145,162,163,523,717,720],[91,144,145,162,163,266,400,401,403,469,470,472,473,525,527,717,720],[91,145,162,163,195,717,720],[91,145,162,163,177,195,717,720],[91,103,106,109,110,145,162,163,188,717,720],[91,106,145,162,163,177,188,717,720],[91,106,110,145,162,163,188,717,720],[91,145,162,163,177,717,720],[91,100,145,162,163,717,720],[91,104,145,162,163,717,720],[91,102,103,106,145,162,163,188,717,720],[91,145,162,163,165,185,717,720],[91,100,145,162,163,195,717,720],[91,102,106,145,162,163,165,188,717,720],[91,97,98,99,101,105,145,156,162,163,177,188,717,720],[91,106,114,122,145,162,163,717,720],[91,98,104,145,162,163,717,720],[91,106,131,132,145,162,163,717,720],[91,98,101,106,145,162,163,180,188,195,717,720],[91,106,145,162,163,717,720],[91,102,106,145,162,163,188,717,720],[91,97,145,162,163,717,720],[91,100,101,102,104,105,106,107,108,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,132,133,134,135,136,145,162,163,717,720],[91,106,124,127,145,153,162,163,717,720],[91,106,114,115,116,145,162,163,717,720],[91,104,106,115,117,145,162,163,717,720],[91,105,145,162,163,717,720],[91,98,100,106,145,162,163,717,720],[91,106,110,115,117,145,162,163,717,720],[91,110,145,162,163,717,720],[91,104,106,109,145,162,163,188,717,720],[91,98,102,106,114,145,162,163,717,720],[91,106,124,145,162,163,717,720],[91,117,145,162,163,717,720],[91,100,106,131,145,162,163,180,193,195,717,720]],"fileInfos":[{"version":"e41c290ef7dd7dab3493e6cbe5909e0148edf4a8dad0271be08edec368a0f7b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"8fd575e12870e9944c7e1d62e1f5a73fcf23dd8d3a321f2a2c74c20d022283fe","impliedFormat":1},{"version":"e12a46ce14b817d4c9e6b2b478956452330bf00c9801b79de46f7a1815b5bd40","impliedFormat":1},{"version":"4fd3f3422b2d2a3dfd5cdd0f387b3a8ec45f006c6ea896a4cb41264c2100bb2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"69e65d976bf166ce4a9e6f6c18f94d2424bf116e90837ace179610dbccad9b42","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"62bb211266ee48b2d0edf0d8d1b191f0c24fc379a82bd4c1692a082c540bc6b1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"f1e2a172204962276504466a6393426d2ca9c54894b1ad0a6c9dad867a65f876","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"b5ce7a470bc3628408429040c4e3a53a27755022a32fd05e2cb694e7015386c7","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"bab26767638ab3557de12c900f0b91f710c7dc40ee9793d5a27d32c04f0bf646","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"87dc0f382502f5bbce5129bdc0aea21e19a3abbc19259e0b43ae038a9fc4e326","affectsGlobalScope":true,"impliedFormat":1},{"version":"b1cb28af0c891c8c96b2d6b7be76bd394fddcfdb4709a20ba05a7c1605eea0f9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2fef54945a13095fdb9b84f705f2b5994597640c46afeb2ce78352fab4cb3279","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac77cb3e8c6d3565793eb90a8373ee8033146315a3dbead3bde8db5eaf5e5ec6","affectsGlobalScope":true,"impliedFormat":1},{"version":"56e4ed5aab5f5920980066a9409bfaf53e6d21d3f8d020c17e4de584d29600ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ece9f17b3866cc077099c73f4983bddbcb1dc7ddb943227f1ec070f529dedd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a6282c8827e4b9a95f4bf4f5c205673ada31b982f50572d27103df8ceb8013c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1c9319a09485199c1f7b0498f2988d6d2249793ef67edda49d1e584746be9032","affectsGlobalScope":true,"impliedFormat":1},{"version":"e3a2a0cee0f03ffdde24d89660eba2685bfbdeae955a6c67e8c4c9fd28928eeb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811c71eee4aa0ac5f7adf713323a5c41b0cf6c4e17367a34fbce379e12bbf0a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51ad4c928303041605b4d7ae32e0c1ee387d43a24cd6f1ebf4a2699e1076d4fa","affectsGlobalScope":true,"impliedFormat":1},{"version":"d4b1d2c51d058fc21ec2629fff7a76249dec2e36e12960ea056e3ef89174080f","affectsGlobalScope":true,"impliedFormat":1},{"version":"61d6a2092f48af66dbfb220e31eea8b10bc02b6932d6e529005fd2d7b3281290","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e29f41b158de217f94cb9676bf9cbd0cd9b5a46e1985141ed36e075c52bf6ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"dc0a7f107690ee5cd8afc8dbf05c4df78085471ce16bdd9881642ec738bc81fe","impliedFormat":1},{"version":"acd8fd5090ac73902278889c38336ff3f48af6ba03aa665eb34a75e7ba1dccc4","impliedFormat":1},{"version":"d6258883868fb2680d2ca96bc8b1352cab69874581493e6d52680c5ffecdb6cc","impliedFormat":1},{"version":"1b61d259de5350f8b1e5db06290d31eaebebc6baafd5f79d314b5af9256d7153","impliedFormat":1},{"version":"f258e3960f324a956fc76a3d3d9e964fff2244ff5859dcc6ce5951e5413ca826","impliedFormat":1},{"version":"643f7232d07bf75e15bd8f658f664d6183a0efaca5eb84b48201c7671a266979","impliedFormat":1},{"version":"21da358700a3893281ce0c517a7a30cbd46be020d9f0c3f2834d0a8ad1f5fc75","impliedFormat":1},{"version":"cebfeedf63623d54f7423d58cae1ec204c0d8d97a66d5fb17579e26a902085e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"378281aa35786c27d5811af7e6bcaa492eebd0c7013d48137c35bbc69a2b9751","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"1b2dd1cbeb0cc6ae20795958ba5950395ebb2849b7c8326853dd15530c77ab0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"387a023d363f755eb63450a66c28b14cdd7bc30a104565e2dbf0a8988bb4a56c","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"cdcf9ea426ad970f96ac930cd176d5c69c6c24eebd9fc580e1572d6c6a88f62c","impliedFormat":1},{"version":"23cd712e2ce083d68afe69224587438e5914b457b8acf87073c22494d706a3d0","impliedFormat":1},{"version":"487b694c3de27ddf4ad107d4007ad304d29effccf9800c8ae23c2093638d906a","impliedFormat":1},{"version":"3a80bc85f38526ca3b08007ee80712e7bb0601df178b23fbf0bf87036fce40ce","impliedFormat":1},{"version":"ccf4552357ce3c159ef75f0f0114e80401702228f1898bdc9402214c9499e8c0","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"68834d631c8838c715f225509cfc3927913b9cc7a4870460b5b60c8dbdb99baf","impliedFormat":1},{"version":"2931540c47ee0ff8a62860e61782eb17b155615db61e36986e54645ec67f67c2","impliedFormat":1},{"version":"ccab02f3920fc75c01174c47fcf67882a11daf16baf9e81701d0a94636e94556","impliedFormat":1},{"version":"f6faf5f74e4c4cc309a6c6a6c4da02dbb840be5d3e92905a23dcd7b2b0bd1986","impliedFormat":1},{"version":"ea6bc8de8b59f90a7a3960005fd01988f98fd0784e14bc6922dde2e93305ec7d","impliedFormat":1},{"version":"36107995674b29284a115e21a0618c4c2751b32a8766dd4cb3ba740308b16d59","impliedFormat":1},{"version":"914a0ae30d96d71915fc519ccb4efbf2b62c0ddfb3a3fc6129151076bc01dc60","impliedFormat":1},{"version":"33e981bf6376e939f99bd7f89abec757c64897d33c005036b9a10d9587d80187","impliedFormat":1},{"version":"7fd1b31fd35876b0aa650811c25ec2c97a3c6387e5473eb18004bed86cdd76b6","impliedFormat":1},{"version":"b41767d372275c154c7ea6c9d5449d9a741b8ce080f640155cc88ba1763e35b3","impliedFormat":1},{"version":"3bacf516d686d08682751a3bd2519ea3b8041a164bfb4f1d35728993e70a2426","impliedFormat":1},{"version":"7fb266686238369442bd1719bc0d7edd0199da4fb8540354e1ff7f16669b4323","impliedFormat":1},{"version":"0a60a292b89ca7218b8616f78e5bbd1c96b87e048849469cccb4355e98af959a","impliedFormat":1},{"version":"0b6e25234b4eec6ed96ab138d96eb70b135690d7dd01f3dd8a8ab291c35a683a","impliedFormat":1},{"version":"9666f2f84b985b62400d2e5ab0adae9ff44de9b2a34803c2c5bd3c8325b17dc0","impliedFormat":1},{"version":"40cd35c95e9cf22cfa5bd84e96408b6fcbca55295f4ff822390abb11afbc3dca","impliedFormat":1},{"version":"b1616b8959bf557feb16369c6124a97a0e74ed6f49d1df73bb4b9ddf68acf3f3","impliedFormat":1},{"version":"5b03a034c72146b61573aab280f295b015b9168470f2df05f6080a2122f9b4df","impliedFormat":1},{"version":"40b463c6766ca1b689bfcc46d26b5e295954f32ad43e37ee6953c0a677e4ae2b","impliedFormat":1},{"version":"249b9cab7f5d628b71308c7d9bb0a808b50b091e640ba3ed6e2d0516f4a8d91d","impliedFormat":1},{"version":"80aae6afc67faa5ac0b32b5b8bc8cc9f7fa299cff15cf09cc2e11fd28c6ae29e","impliedFormat":1},{"version":"f473cd2288991ff3221165dcf73cd5d24da30391f87e85b3dd4d0450c787a391","impliedFormat":1},{"version":"499e5b055a5aba1e1998f7311a6c441a369831c70905cc565ceac93c28083d53","impliedFormat":1},{"version":"54c3e2371e3d016469ad959697fd257e5621e16296fa67082c2575d0bf8eced0","impliedFormat":1},{"version":"beb8233b2c220cfa0feea31fbe9218d89fa02faa81ef744be8dce5acb89bb1fd","impliedFormat":1},{"version":"c183b931b68ad184bc8e8372bf663f3d33304772fb482f29fb91b3c391031f3e","impliedFormat":1},{"version":"5d0375ca7310efb77e3ef18d068d53784faf62705e0ad04569597ae0e755c401","impliedFormat":1},{"version":"59af37caec41ecf7b2e76059c9672a49e682c1a2aa6f9d7dc78878f53aa284d6","impliedFormat":1},{"version":"addf417b9eb3f938fddf8d81e96393a165e4be0d4a8b6402292f9c634b1cb00d","impliedFormat":1},{"version":"48cc3ec153b50985fb95153258a710782b25975b10dd4ac8a4f3920632d10790","impliedFormat":1},{"version":"adf27937dba6af9f08a68c5b1d3fce0ca7d4b960c57e6d6c844e7d1a8e53adae","impliedFormat":1},{"version":"e1528ca65ac90f6fa0e4a247eb656b4263c470bb22d9033e466463e13395e599","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"866078923a56d026e39243b4392e282c1c63159723996fa89243140e1388a98d","impliedFormat":1},{"version":"830171b27c5fdf9bcbe4cf7d428fcf3ae2c67780fb7fbdccdf70d1623d938bc4","affectsGlobalScope":true,"impliedFormat":1},{"version":"1cf059eaf468efcc649f8cf6075d3cb98e9a35a0fe9c44419ec3d2f5428d7123","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d97fb21da858fb18b8ae72c314e9743fd52f73ebe2764e12af1db32fc03f853f","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ea15fd99b2e34cb25fe8346c955000bb70c8b423ae4377a972ef46bfb37f595","impliedFormat":1},{"version":"7cf69dd5502c41644c9e5106210b5da7144800670cbe861f66726fa209e231c4","impliedFormat":1},{"version":"72c1f5e0a28e473026074817561d1bc9647909cf253c8d56c41d1df8d95b85f7","impliedFormat":1},{"version":"f9b4137a0d285bd77dba2e6e895530112264310ae47e07bf311feae428fb8b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"8b21e13ed07d0df176ae31d6b7f01f7b17d66dbeb489c0d31d00de2ca14883da","impliedFormat":1},{"version":"51aecd2df90a3cffea1eb4696b33b2d78594ea2aa2138e6b9471ec4841c6c2ee","impliedFormat":1},{"version":"9d8f9e63e29a3396285620908e7f14d874d066caea747dc4b2c378f0599166b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"f929f0b6b3421a2d34344b0f421f45aeb2c84ad365ebf29d04312023b3accc58","impliedFormat":1},{"version":"db9ada976f9e52e13f7ae8b9a320f4b67b87685938c5879187d8864b2fbe97f3","impliedFormat":1},{"version":"9f39e70a354d0fba29ac3cdf6eca00b7f9e96f64b2b2780c432e8ea27f133743","impliedFormat":1},{"version":"0dace96cc0f7bc6d0ee2044921bdf19fe42d16284dbcc8ae200800d1c9579335","impliedFormat":1},{"version":"a2e2bbde231b65c53c764c12313897ffdfb6c49183dd31823ee2405f2f7b5378","impliedFormat":1},{"version":"ad1cc0ed328f3f708771272021be61ab146b32ecf2b78f3224959ff1e2cd2a5c","impliedFormat":1},{"version":"c64e1888baaa3253ca4405b455e4bf44f76357868a1bd0a52998ade9a092ad78","affectsGlobalScope":true,"impliedFormat":1},{"version":"d8cf132379078d0974a59df26069689a2d33c7dc826b5be56231841cb2f32e58","impliedFormat":1},{"version":"fbf413fc617837453c878a9174a1f1b383616857a3f8366bc41cf30df4aea7d5","impliedFormat":1},{"version":"148c73ec11318850f571172ceae3e55ce479d850fe18ec8eae0abd99d9f6c319","impliedFormat":1},{"version":"230bdc111d7578276e4a3bb9d075d85c78c6b68f428c3a9935e2eaa10f4ae1f5","impliedFormat":1},{"version":"e8aabbee5e7b9101b03bb4222607d57f38859b8115a8050a4eb91b4ee43a3a73","impliedFormat":1},{"version":"bbf42f98a5819f4f06e18c8b669a994afe9a17fe520ae3454a195e6eabf7700d","impliedFormat":1},{"version":"c0bb1b65757c72bbf8ddf7eaa532223bacf58041ff16c883e76f45506596e925","impliedFormat":1},{"version":"c8b85f7aed29f8f52b813f800611406b0bfe5cf3224d20a4bdda7c7f73ce368e","affectsGlobalScope":true,"impliedFormat":1},{"version":"145dcf25fd4967c610c53d93d7bc4dce8fbb1b6dd7935362472d4ae49363c7ba","impliedFormat":1},{"version":"ff65b8a8bd380c6d129becc35de02f7c29ad7ce03300331ca91311fb4044d1a9","impliedFormat":1},{"version":"04bf1aa481d1adfb16d93d76e44ce71c51c8ef68039d849926551199489637f6","impliedFormat":1},{"version":"9043daec15206650fa119bad6b8d70136021ea7d52673a71f79a87a42ee38d44","affectsGlobalScope":true,"impliedFormat":1},{"version":"0b055dae40c0e27154f109c4ff771ae748db161c503a1687e3d4b9c91ba20de3","affectsGlobalScope":true,"impliedFormat":1},{"version":"a58a15da4c5ba3df60c910a043281256fa52d36a0fcdef9b9100c646282e88dd","impliedFormat":1},{"version":"b36beffbf8acdc3ebc58c8bb4b75574b31a2169869c70fc03f82895b93950a12","impliedFormat":1},{"version":"de263f0089aefbfd73c89562fb7254a7468b1f33b61839aafc3f035d60766cb4","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"8c81fd4a110490c43d7c578e8c6f69b3af01717189196899a6a44f93daa57a3a","impliedFormat":1},{"version":"5fb39858b2459864b139950a09adae4f38dad87c25bf572ce414f10e4bd7baab","impliedFormat":1},{"version":"65faec1b4bd63564aeec33eab9cacfaefd84ce2400f03903a71a1841fbce195f","impliedFormat":1},{"version":"b33b74b97952d9bf4fbd2951dcfbb5136656ddb310ce1c84518aaa77dbca9992","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"6b306cd4282bbb54d4a6bb23cfb7a271160983dfc38c67b5a132504cfcc34896","affectsGlobalScope":true,"impliedFormat":1},{"version":"c119835edf36415081dfd9ed15fc0cd37aaa28d232be029ad073f15f3d88c323","impliedFormat":1},{"version":"450172a56b944c2d83f45cc11c9a388ea967cd301a21202aa0a23c34c7506a18","impliedFormat":1},{"version":"9705cd157ffbb91c5cab48bdd2de5a437a372e63f870f8a8472e72ff634d47c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ae86f30d5d10e4f75ce8dcb6e1bd3a12ecec3d071a21e8f462c5c85c678efb41","impliedFormat":1},{"version":"72f8936aebf0c4a1adab767b97d34ba7d3a308afcf76de4417b9c16fb92ed548","impliedFormat":1},{"version":"e03460fe72b259f6d25ad029f085e4bedc3f90477da4401d8fbc1efa9793230e","impliedFormat":1},{"version":"4286a3a6619514fca656089aee160bb6f2e77f4dd53dc5a96b26a0b4fc778055","impliedFormat":1},{"version":"69e0a41d620fb678a899c65e073413b452f4db321b858fe422ad93fd686cd49a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3585d6891e9ea18e07d0755a6d90d71331558ba5dc5561933553209f886db106","affectsGlobalScope":true,"impliedFormat":1},{"version":"86be71cbb0593468644932a6eb96d527cfa600cecfc0b698af5f52e51804451d","impliedFormat":1},{"version":"84dd6b0fd2505135692935599d6606f50a421389e8d4535194bcded307ee5cf2","impliedFormat":1},{"version":"0d5b085f36e6dc55bc6332ecb9c733be3a534958c238fb8d8d18d4a2b6f2a15a","impliedFormat":1},{"version":"db19ea066fdc5f97df3f769e582ae3000380ab7942e266654bdb1a4650d19eaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"2a034894bf28c220a331c7a0229d33564803abe2ac1b9a5feee91b6b9b6e88ea","impliedFormat":1},{"version":"63228283eda38338f98e629d8033bffe727d2247ba2f3a1cbd1273a6827a1ec4","impliedFormat":1},{"version":"2beff543f6e9a9701df88daeee3cdd70a34b4a1c11cb4c734472195a5cb2af54","impliedFormat":1},{"version":"2e07abf27aa06353d46f4448c0bbac73431f6065eef7113128a5cd804d0c384d","impliedFormat":1},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1},{"version":"42bc0e1a903408137c3df2b06dfd7e402cdab5bbfa5fcfb871b22ebfdb30bd0b","impliedFormat":1},{"version":"9894dafe342b976d251aac58e616ac6df8db91fb9d98934ff9dd103e9e82578f","impliedFormat":1},{"version":"413df52d4ea14472c2fa5bee62f7a40abd1eb49be0b9722ee01ee4e52e63beb2","impliedFormat":1},{"version":"db6d2d9daad8a6d83f281af12ce4355a20b9a3e71b82b9f57cddcca0a8964a96","impliedFormat":1},{"version":"446a50749b24d14deac6f8843e057a6355dd6437d1fac4f9e5ce4a5071f34bff","impliedFormat":1},{"version":"182e9fcbe08ac7c012e0a6e2b5798b4352470be29a64fdc114d23c2bab7d5106","impliedFormat":1},{"version":"2f4e6b4d39426a1b85ecf4bdeb9dddbf4d9b3397d95d8555d46f925c9519ec7d","impliedFormat":1},{"version":"78a2869ad0cbf3f9045dda08c0d4562b7e1b2bfe07b19e0db072f5c3c56e9584","impliedFormat":1},{"version":"89d5d28d4f57e000b836ac273079be1b75710e28ce14750d081fb420d37e2ca5","impliedFormat":1},{"version":"fd4e24ccff3966390600d7f5d6aa1fed5a512e92ada735ea5fbc933d313ad3d3","impliedFormat":1},{"version":"b7cddfe1aa6b86b5fad3c9ccb30d05b3ccb165aebbf112f48d2d8a5f69dd98b1","impliedFormat":1},{"version":"a86f82d646a739041d6702101afa82dcb935c416dd93cbca7fd754fd0282ce1f","impliedFormat":1},{"version":"ad0d1d75d129b1c80f911be438d6b61bfa8703930a8ff2be2f0e1f8a91841c64","impliedFormat":1},{"version":"bd2c7ada3dee03653d3f601011d30072194bc3970cd93208f9588fbdc0c69347","impliedFormat":1},{"version":"e480da45d32313e7174b265674da504f075f59ef326852f0c5a5d863b438ae85","impliedFormat":1},{"version":"ad54850f61fcf5d014e11be80d2f46fea9265cfa7e77456da876f7833ef81769","impliedFormat":1},{"version":"6f7c9e8bd2b5b6a080b07080065f94900bd3c7e5ebbd3047bc33fcce2fab1dd8","impliedFormat":1},{"version":"3e7efde639c6a6c3edb9847b3f61e308bf7a69685b92f665048c45132f51c218","impliedFormat":1},{"version":"df45ca1176e6ac211eae7ddf51336dc075c5314bc5c253651bae639defd5eec5","impliedFormat":1},{"version":"8a0e762ceb20c7e72504feef83d709468a70af4abccb304f32d6b9bac1129b2c","impliedFormat":1},{"version":"da5950ee2a90721df6f3fba45f5d05308f7e4c35835392215dd2cd404505e2de","impliedFormat":1},{"version":"ce75b1aebb33d510ff28af960a9221410a3eaf7f18fc5f21f9404075fba77256","impliedFormat":1},{"version":"f42d5fed19610d485c646a0c430e768115567d078c7fc855c57b0c578b3d6cd3","impliedFormat":1},{"version":"ee8df1cb8d0faaca4013a1b442e99130769ce06f438d18d510fed95890067563","impliedFormat":1},{"version":"d5630f2ad9b4541e5ce891648121022f9412ecdca1820baa1f0104f70fd7eff7","impliedFormat":1},{"version":"4d15375ab13497104bc8fe56fdef2b5fd6853f29255737d23a33fa306ff7fd69","impliedFormat":1},{"version":"2cd3fc1d0d6a1e85baffd2d4f50f5efb192b5446eef567e97c94765402f0aad4","impliedFormat":1},{"version":"e4cbf2f1e89ecccaddd2c045e600ae41b732295953fb06247c7dcbc2d281ed30","impliedFormat":1},{"version":"6dcedaef57dff0d79a05ab0ab602cde74db803d1e765468bf91263786a383e1b","impliedFormat":1},{"version":"8c1697d90c394a6fd955b98eae01238eff628e129b987a68aea10f898a48e7da","impliedFormat":1},{"version":"7580e62139cb2b44a0270c8d01abcbfcba2819a02514a527342447fa69b34ef1","impliedFormat":1},{"version":"42c169fb8c2d42f4f668c624a9a11e719d5d07dacbebb63cbcf7ef365b0a75b3","impliedFormat":1},{"version":"f374cb24e93e7798c4d9e83ff872fa52d2cdb36306392b840a6ddf46cb925cb6","impliedFormat":1},{"version":"d10d63718e1646c2279e3b33831f82c60e31f622b2b7020f1196409ca4c09242","impliedFormat":1},{"version":"106c6025f1d99fd468fd8bf6e5bda724e11e5905a4076c5d29790b6c3745e50c","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"148679c6d0f449210a96e7d2e562d589e56fcde87f843a92808b3ff103f1a774","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"02436d7e9ead85e09a2f8e27d5f47d9464bced31738dec138ca735390815c9f0","impliedFormat":1},{"version":"f8d5ff8eafd37499f2b6a98659dd9b45a321de186b8db6b6142faed0fea3de77","impliedFormat":1},{"version":"c86fe861cf1b4c46a0fb7d74dffe596cf679a2e5e8b1456881313170f092e3fa","impliedFormat":1},{"version":"a22dd55aa4d39906252000ab8e8a1b83b195eef7f4274eb51e457c1f11cf6580","impliedFormat":1},{"version":"540cc83ab772a2c6bc509fe1354f314825b5dba3669efdfbe4693ecd3048e34f","impliedFormat":1},{"version":"121b0696021ab885c570bbeb331be8ad82c6efe2f3b93a6e63874901bebc13e3","impliedFormat":1},{"version":"612d9da66bb046a9c1e2e8d026245ded881fc4b9f98cbfae714415d57ee0ae0b","impliedFormat":1},{"version":"32c2ad9494dad5d11b0564a619fee18f388db6c1e9e2cd3c360b3122549691eb","impliedFormat":1},{"version":"6c301d40aec56a74ec7bd7324e31a728dadf9bfba3e96def02938d3d973534ec","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"aa14cee20aa0db79f8df101fc027d929aec10feb5b8a8da3b9af3895d05b7ba2","impliedFormat":1},{"version":"493c700ac3bd317177b2eb913805c87fe60d4e8af4fb39c41f04ba81fae7e170","impliedFormat":1},{"version":"aeb554d876c6b8c818da2e118d8b11e1e559adbe6bf606cc9a611c1b6c09f670","impliedFormat":1},{"version":"acf5a2ac47b59ca07afa9abbd2b31d001bf7448b041927befae2ea5b1951d9f9","impliedFormat":1},{"version":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":1},{"version":"d71291eff1e19d8762a908ba947e891af44749f3a2cbc5bd2ec4b72f72ea795f","impliedFormat":1},{"version":"c0480e03db4b816dff2682b347c95f2177699525c54e7e6f6aa8ded890b76be7","impliedFormat":1},{"version":"25a5f6fd3a2243c859eddc99ab5fba11d970af2fe7a5df9c32b7668f76f97b01","impliedFormat":1},{"version":"8d207e1f9d2c30d6f77dfa693f3827c3fbf0d89240297e10bdfe1041d433df68","impliedFormat":1},{"version":"b620391fe8060cf9bedc176a4d01366e6574d7a71e0ac0ab344a4e76576fcbb8","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"2652448ac55a2010a1f71dd141f828b682298d39728f9871e1cdf8696ef443fd","impliedFormat":1},{"version":"d682336018141807fb602709e2d95a192828fcb8d5ba06dda3833a8ea98f69e3","impliedFormat":1},{"version":"6124e973eab8c52cabf3c07575204efc1784aca6b0a30c79eb85fe240a857efa","impliedFormat":1},{"version":"0d891735a21edc75df51f3eb995e18149e119d1ce22fd40db2b260c5960b914e","impliedFormat":1},{"version":"3b414b99a73171e1c4b7b7714e26b87d6c5cb03d200352da5342ab4088a54c85","impliedFormat":1},{"version":"4fbd3116e00ed3a6410499924b6403cc9367fdca303e34838129b328058ede40","impliedFormat":1},{"version":"9c82171d836c47486074e4ca8e059735bf97b205e70b196535b5efd40cbe1bc5","impliedFormat":1},{"version":"8c70ddc0c22d85e56011d49fddfaae3405eb53d47b59327b9dd589e82df672e7","impliedFormat":1},{"version":"2f9c89cbb29d362290531b48880a4024f258c6033aaeb7e59fbc62db26819650","impliedFormat":1},{"version":"a365c4d3bed3be4e4e20793c999c51f5cd7e6792322f14650949d827fbcd170f","impliedFormat":1},{"version":"c5426dbfc1cf90532f66965a7aa8c1136a78d4d0f96d8180ecbfc11d7722f1a5","impliedFormat":1},{"version":"65a15fc47900787c0bd18b603afb98d33ede930bed1798fc984d5ebb78b26cf9","impliedFormat":1},{"version":"9d202701f6e0744adb6314d03d2eb8fc994798fc83d91b691b75b07626a69801","impliedFormat":1},{"version":"de9d2df7663e64e3a91bf495f315a7577e23ba088f2949d5ce9ec96f44fba37d","impliedFormat":1},{"version":"c7af78a2ea7cb1cd009cfb5bdb48cd0b03dad3b54f6da7aab615c2e9e9d570c5","impliedFormat":1},{"version":"1ee45496b5f8bdee6f7abc233355898e5bf9bd51255db65f5ff7ede617ca0027","impliedFormat":1},{"version":"273782b8454e78f6a8b30d2cfbf6860499c930595095fcc1689637115f0eddda","affectsGlobalScope":true,"impliedFormat":1},{"version":"3fbdd025f9d4d820414417eeb4107ffa0078d454a033b506e22d3a23bc3d9c41","affectsGlobalScope":true,"impliedFormat":1},{"version":"dba114fb6a32b355a9cfc26ca2276834d72fe0e94cd2c3494005547025015369","impliedFormat":1},{"version":"a8f8e6ab2fa07b45251f403548b78eaf2022f3c2254df3dc186cb2671fe4996d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fa6c12a7c0f6b84d512f200690bfc74819e99efae69e4c95c4cd30f6884c526e","impliedFormat":1},{"version":"f1c32f9ce9c497da4dc215c3bc84b722ea02497d35f9134db3bb40a8d918b92b","impliedFormat":1},{"version":"b73c319af2cc3ef8f6421308a250f328836531ea3761823b4cabbd133047aefa","affectsGlobalScope":true,"impliedFormat":1},{"version":"e433b0337b8106909e7953015e8fa3f2d30797cea27141d1c5b135365bb975a6","impliedFormat":1},{"version":"9f9bb6755a8ce32d656ffa4763a8144aa4f274d6b69b59d7c32811031467216e","impliedFormat":1},{"version":"5c32bdfbd2d65e8fffbb9fbda04d7165e9181b08dad61154961852366deb7540","impliedFormat":1},{"version":"ddff7fc6edbdc5163a09e22bf8df7bef75f75369ebd7ecea95ba55c4386e2441","impliedFormat":1},{"version":"0c05e9842ec4f8b7bfebfd3ca61604bb8c914ba8da9b5337c4f25da427a005f2","impliedFormat":1},{"version":"faed7a5153215dbd6ebe76dfdcc0af0cfe760f7362bed43284be544308b114cf","impliedFormat":1},{"version":"7029e566b8df176f703fb59fd437a38670c7a0e02c58b2d66dfb5b2e2b2defdb","impliedFormat":1},{"version":"7f2aa4d4989a82530aaac3f72b3dceca90e9c25bee0b1a327e8a08a1262435ad","impliedFormat":1},{"version":"d96b39301d0ded3f1a27b47759676a33a02f6f5049bfcbde81e533fd10f50dcb","impliedFormat":1},{"version":"e9f147ecca73d9346a4c073432843c159ccbe50bdcb678a78f6da10eae2cecf4","impliedFormat":1},{"version":"de061f7d72bd65c06fc1419f841dfdcb29a8e22fe6fa527d1e6eb20b897d4de0","impliedFormat":1},{"version":"663beafc2446079574570cba86e9b15f986f908ddb1b01274509970126fee945","impliedFormat":1},{"version":"a3102887d5058bf4cb5b37fa6964c09e9527c42053b3b5c642b89878620748de","impliedFormat":1},{"version":"0aaaa1727edd29673d85c9b26d7ca4d54e5407a48586903c51b48b7f7d196f61","impliedFormat":1},{"version":"d35bca0b261bff02635758c48e8ab99c61c420d0dfabbcf467e847171d876b7d","impliedFormat":1},{"version":"3bc12c40d90c342ff88a3d876996c555ed5cbee5fe8c3308a240b321f401ee46","impliedFormat":1},{"version":"ba130768aae855a5477e9e148e5c879548e6e7ccbcc56fd1934c8a18ea5b7569","impliedFormat":1},{"version":"2e4f37ffe8862b14d8e24ae8763daaa8340c0df0b859d9a9733def0eee7562d9","impliedFormat":1},{"version":"d38530db0601215d6d767f280e3a3c54b2a83b709e8d9001acb6f61c67e965fc","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"b499af2054a037a162b3b72cd886f48bbf32a3502c865c6e29fac7d2ab3ce0b5","impliedFormat":1},{"version":"b83cb14474fa60c5f3ec660146b97d122f0735627f80d82dd03e8caa39b4388c","impliedFormat":1},{"version":"48773ca557b0319c2ee62ae249cf52a81709e8be139920d6479a66274de7c4ed","impliedFormat":1},{"version":"7274fbffbd7c9589d8d0ffba68157237afd5cecff1e99881ea3399127e60572f","impliedFormat":1},{"version":"b73cbf0a72c8800cf8f96a9acfe94f3ad32ca71342a8908b8ae484d61113f647","impliedFormat":1},{"version":"bae6dd176832f6423966647382c0d7ba9e63f8c167522f09a982f086cd4e8b23","impliedFormat":1},{"version":"20865ac316b8893c1a0cc383ccfc1801443fbcc2a7255be166cf90d03fac88c9","impliedFormat":1},{"version":"c9958eb32126a3843deedda8c22fb97024aa5d6dd588b90af2d7f2bfac540f23","impliedFormat":1},{"version":"461d0ad8ae5f2ff981778af912ba71b37a8426a33301daa00f21c6ccb27f8156","impliedFormat":1},{"version":"e927c2c13c4eaf0a7f17e6022eee8519eb29ef42c4c13a31e81a611ab8c95577","impliedFormat":1},{"version":"fcafff163ca5e66d3b87126e756e1b6dfa8c526aa9cd2a2b0a9da837d81bbd72","impliedFormat":1},{"version":"70246ad95ad8a22bdfe806cb5d383a26c0c6e58e7207ab9c431f1cb175aca657","impliedFormat":1},{"version":"f00f3aa5d64ff46e600648b55a79dcd1333458f7a10da2ed594d9f0a44b76d0b","impliedFormat":1},{"version":"772d8d5eb158b6c92412c03228bd9902ccb1457d7a705b8129814a5d1a6308fc","impliedFormat":1},{"version":"802e797bcab5663b2c9f63f51bdf67eff7c41bc64c0fd65e6da3e7941359e2f7","impliedFormat":1},{"version":"b01bd582a6e41457bc56e6f0f9de4cb17f33f5f3843a7cf8210ac9c18472fb0f","impliedFormat":1},{"version":"8b4327413e5af38cd8cb97c59f48c3c866015d5d642f28518e3a891c469f240e","impliedFormat":1},{"version":"4cceef18d7f088e797a463e90b7a9dad10c6bc667724b7686e3e740ae00122be","impliedFormat":1},{"version":"7ee86fbb3754388e004de0ef9e6505485ddfb3be7640783d6d015711c03d302d","impliedFormat":1},{"version":"cc1954b539604b1e562319119ac7e888172208b32ca873f9a357a92c826bd046","impliedFormat":1},{"version":"a67b87d0281c97dfc1197ef28dfe397fc2c865ccd41f7e32b53f647184cc7307","impliedFormat":1},{"version":"771ffb773f1ddd562492a6b9aaca648192ac3f056f0e1d997678ff97dbb6bf9b","impliedFormat":1},{"version":"43e96a3d5d1411ab40ba2f61d6a3192e58177bcf3b133a80ad2a16591611726d","impliedFormat":1},{"version":"232f70c0cf2b432f3a6e56a8dc3417103eb162292a9fd376d51a3a9ea5fbbf6f","impliedFormat":1},{"version":"bb8f2dbc03533abca2066ce4655c119bff353dd4514375beb93c08590c03e023","impliedFormat":1},{"version":"706dd95827e7ebaabda91d5db2b755233e0952d98570e9c032b0f066a15c1177","affectsGlobalScope":true,"impliedFormat":1},{"version":"0b103e9abfe82d14c0ad06a55d9f91d6747154ef7cacc73cf27ecad2bfb3afcf","impliedFormat":1},{"version":"cd9304972e6d616197fb44fce00540a904f38b54306a1951b5dbeaf3c01ab5bd","impliedFormat":1},{"version":"77438e2c397a3db78407621cfc57241a305b310ddea2c185f1d555248297f587","impliedFormat":1},{"version":"120599fd965257b1f4d0ff794bc696162832d9d8467224f4665f713a3119078b","impliedFormat":1},{"version":"43ba4f2fa8c698f5c304d21a3ef596741e8e85a810b7c1f9b692653791d8d97a","impliedFormat":1},{"version":"5433f33b0a20300cca35d2f229a7fc20b0e8477c44be2affeb21cb464af60c76","impliedFormat":1},{"version":"db036c56f79186da50af66511d37d9fe77fa6793381927292d17f81f787bb195","impliedFormat":1},{"version":"a6805fcafed712aea7759f8bc731014f9d22738c1d6ef9d43b8091d1d48346d5","impliedFormat":1},{"version":"c49469a5349b3cc1965710b5b0f98ed6c028686aa8450bcb3796728873eb923e","impliedFormat":1},{"version":"4a889f2c763edb4d55cb624257272ac10d04a1cad2ed2948b10ed4a7fda2a428","impliedFormat":1},{"version":"7bb79aa2fead87d9d56294ef71e056487e848d7b550c9a367523ee5416c44cfa","impliedFormat":1},{"version":"d88ea80a6447d7391f52352ec97e56b52ebec934a4a4af6e2464cfd8b39c3ba8","impliedFormat":1},{"version":"142617b3cdf902b69c6464c9fbd942b60ab3e733ca18c032b19e0f7e2adbefe8","impliedFormat":1},{"version":"0b603555f1881f87256ffd6344d3e3ed6d466c2e701eabf381f28be8c2125892","impliedFormat":1},{"version":"897e4f7662488e3ecc79e743bdd3b78f13bdb69a97851afa5b440c4211e32ea9","impliedFormat":1},{"version":"e2e1c6d3b2d93add5200bd7bc1a8cccb4e446836b2111ece45db8683a2c765de","impliedFormat":1},{"version":"251b03d5cd243854ce870d9a9a39f491faf69898c5d6b5eee28cc7649c57417b","impliedFormat":1},{"version":"27ff4196654e6373c9af16b6165120e2dd2169f9ad6abb5c935af5abd8c7938c","impliedFormat":1},{"version":"2c4de79f406d137390608e8c0a44fba2ff8e00bacfcae7c9d1781fef10e9440d","impliedFormat":1},{"version":"07ba23a10465791be5d22deaf5ef7de7658774ddff53721e5ea17fedea1bc721","impliedFormat":1},{"version":"dca8c645c5afeb03b1ecedbf16323f33e7d0afaa6256c8e047e6e38087a97f53","impliedFormat":1},{"version":"775f181bd4a533d6f8b5e55ec1d9f1624559720ae8a70e9432258da26b38d27c","impliedFormat":1},{"version":"796273b2edc72e78a04e86d7c58ae94d370ab93a0ddf40b1aa85a37a1c29ecd7","impliedFormat":1},{"version":"5df15a69187d737d6d8d066e189ae4f97e41f4d53712a46b2710ff9f8563ec9f","impliedFormat":1},{"version":"7715134a0cf07dd41a9da2895d708625a3a303a0385e355ecaaf0b8bfaef2550","impliedFormat":1},{"version":"6ac6715916fa75a1f7ebdfeacac09513b4d904b667d827b7535e84ff59679aff","impliedFormat":1},{"version":"622694a8522b46f6310c2a9b5d2530dde1e2854cb5829354e6d1ff8f371cf469","impliedFormat":1},{"version":"cd8ce8d68567f62dd580b3c3c37777ac3f5b81944c7417f5ea83030eab533385","impliedFormat":1},{"version":"e5c939d896565dcac0f6fbdbada11284e7728ef26a069561c09aa5aa4a788393","impliedFormat":1},{"version":"9e2739b32f741859263fdba0244c194ca8e96da49b430377930b8f721d77c000","impliedFormat":1},{"version":"a9e6c0ff3f8186fccd05752cf75fc94e147c02645087ac6de5cc16403323d870","impliedFormat":1},{"version":"49af4b52f0d4d2304c5f2c6fe5fab3e153e0acc38830d0202821b877c097dd02","impliedFormat":1},{"version":"49c346823ba6d4b12278c12c977fb3a31c06b9ca719015978cb145eb86da1c61","impliedFormat":1},{"version":"bfac6e50eaa7e73bb66b7e052c38fdc8ccfc8dbde2777648642af33cf349f7f1","impliedFormat":1},{"version":"92f7c1a4da7fbfd67a2228d1687d5c2e1faa0ba865a94d3550a3941d7527a45d","impliedFormat":1},{"version":"f53b120213a9289d9a26f5af90c4c686dd71d91487a0aa5451a38366c70dc64b","impliedFormat":1},{"version":"e68b8e5a1df7c1be2bc105141456ecba70215806e1c28bfbc5c12bfce4be6e68","impliedFormat":1},{"version":"511c8f02329808d47d00b859c532ae9115590048b17325a946c74dac48428650","impliedFormat":1},{"version":"57d67b72e06059adc5e9454de26bbfe567d412b962a501d263c75c2db430f40e","impliedFormat":1},{"version":"b5f9e66625783eefcbe3d2da074b2e7ba2066d61ce3fc6ef4f22805ad946cab4","impliedFormat":1},{"version":"e37115962d284b9f7a37c2bdd2add50f88365dde41f5e0ff591ffc48a8ec7575","impliedFormat":1},{"version":"6459054aabb306821a043e02b89d54da508e3a6966601a41e71c166e4ea1474f","impliedFormat":1},{"version":"bb37588926aba35c9283fe8d46ebf4e79ffe976343105f5c6d45f282793352b2","impliedFormat":1},{"version":"f89488602bec98a142072fae7ea5ba99431a569ff580c64b7be39896474799d8","impliedFormat":1},{"version":"bbbc47961f39a57df103cf4ca3bb8f8732b4b6678a18225a0aa76d59c466956c","impliedFormat":1},{"version":"2e6114a7dd6feeef85b2c80120fdbfb59a5529c0dcc5bfa8447b6996c97a69f5","impliedFormat":1},{"version":"2ffb043dc5163458e473b7010859f86e01dc4edffcae0a93d885d028b426a546","impliedFormat":1},{"version":"c8f004e6036aa1c764ad4ec543cf89a5c1893a9535c80ef3f2b653e370de45e6","impliedFormat":1},{"version":"dd80b1e600d00f5c6a6ba23f455b84a7db121219e68f89f10552c54ba46e4dc9","impliedFormat":1},{"version":"b064c36f35de7387d71c599bfcf28875849a1dbc733e82bd26cae3d1cd060521","impliedFormat":1},{"version":"05c7280d72f3ed26f346cbe7cbbbb002fb7f15739197cbbee6ab3fd1a6cb9347","impliedFormat":1},{"version":"8de9fe97fa9e00ec00666fa77ab6e91b35d25af8ca75dabcb01e14ad3299b150","impliedFormat":1},{"version":"04b7b2e0832dfd3c31e81df3975e8d8fda28e7ff999b0aa2932608a8f6661d5c","impliedFormat":1},{"version":"ca2d34c6ed5cbd3070b8b6f32f42ae54adcc6499c1e4b99f0a5798b3f27cc653","impliedFormat":1},{"version":"9ec68995e66dd6b9dac834bf5ae85fde802714ea2e82151a5d1d53ef01b463ef","impliedFormat":1},{"version":"5c4d626b4902f2ef8a1cc146d761d276cef988016dc674e3b98fbad70e64bc9f","impliedFormat":1},{"version":"fdfaa0aad899524962e2955287b5b991ffe3be50f64e02eb60c933ca44644a94","impliedFormat":1},{"version":"53c972a0f9bc3a4ec70fff7314123ea8cfcf75b3703046f767d2dc1eea87b2fb","impliedFormat":1},{"version":"f974e4a06953682a2c15d5bd5114c0284d5abf8bc0fe4da25cb9159427b70072","impliedFormat":1},{"version":"50256e9c31318487f3752b7ac12ff365c8949953e04568009c8705db802776fb","impliedFormat":1},{"version":"7d73b24e7bf31dfb8a931ca6c4245f6bb0814dfae17e4b60c9e194a631fe5f7b","impliedFormat":1},{"version":"d130c5f73768de51402351d5dc7d1b36eaec980ca697846e53156e4ea9911476","impliedFormat":1},{"version":"413586add0cfe7369b64979d4ec2ed56c3f771c0667fbde1bf1f10063ede0b08","impliedFormat":1},{"version":"06472528e998d152375ad3bd8ebcb69ff4694fd8d2effaf60a9d9f25a37a097a","impliedFormat":1},{"version":"7303b45138d2511035056a5901a1490ebdcbf055cbb1276f8629c5121cbe733e","impliedFormat":1},{"version":"27f874cd5327507eeff699a74567f60c1215b94509f4308633a7b01922471ed2","impliedFormat":1},{"version":"a401617604fa1f6ce437b81689563dfdc377069e4c58465dbd8d16069aede0a5","impliedFormat":1},{"version":"2c6cf04bc525caf6546e859e8ef10bfb9573837ec0bc5ec7b53a7b1b8ca72781","impliedFormat":1},{"version":"8695dec09ad439b0ceef3776ea68a232e381135b516878f0901ed2ea114fd0fe","impliedFormat":1},{"version":"304b44b1e97dd4c94697c3313df89a578dca4930a104454c99863f1784a54357","impliedFormat":1},{"version":"0a437ae178f999b46b6153d79095b60c42c996bc0458c04955f1c996dc68b971","impliedFormat":1},{"version":"74b2a5e5197bd0f2e0077a1ea7c07455bbea67b87b0869d9786d55104006784f","impliedFormat":1},{"version":"4a7baeb6325920044f66c0f8e5e6f1f52e06e6d87588d837bdf44feb6f35c664","impliedFormat":1},{"version":"87cc05fe13108f02e12da7e3efd8e360fef78d96a0c9e11408ea1b1b9fb3e03d","impliedFormat":1},{"version":"1abbf67c218d23c2ce76887caac2df6c7dab3d97ba2b65348432b876f510002a","impliedFormat":1},{"version":"1a82deef4c1d39f6882f28d275cad4c01f907b9b39be9cbc472fcf2cf051e05b","impliedFormat":1},{"version":"4b20fcf10a5413680e39f5666464859fc56b1003e7dfe2405ced82371ebd49b6","impliedFormat":1},{"version":"c06ef3b2569b1c1ad99fcd7fe5fba8d466e2619da5375dfa940a94e0feea899b","impliedFormat":1},{"version":"f7d628893c9fa52ba3ab01bcb5e79191636c4331ee5667ecc6373cbccff8ae12","impliedFormat":1},{"version":"1d879125d1ec570bf04bc1f362fdbe0cb538315c7ac4bcfcdf0c1e9670846aa6","impliedFormat":1},{"version":"dad97c99382889e9c7d1a9d8275500ff71235130fae9f8916fdbf3641d56e592","impliedFormat":1},{"version":"a6dba407fc287f1e25454e75028c91bbc00675f2d1c4e8b3edcc36c08611a486","impliedFormat":1},{"version":"d663134457d8d669ae0df34eabd57028bddc04fc444c4bc04bc5215afc91e1f4","impliedFormat":1},{"version":"e91f7b1344577a02f051b9b471f33044fef8334a76dc9e1de003d17595a5219b","impliedFormat":1},{"version":"c0723195c85e19656d6b5b9fdb81d3f3403c1ae4679e722c6ea058c516b38d12","impliedFormat":1},{"version":"b55eb9f72166093b5460d34b34f5d8699c968de3bc3fc696e40f2c93f2ebf650","impliedFormat":1},{"version":"71d9eb4c4e99456b78ae182fb20a5dfc20eb1667f091dbb9335b3c017dd1c783","impliedFormat":1},{"version":"cfa846a7b7847a1d973605fbb8c91f47f3a0f0643c18ac05c47077ebc72e71c7","impliedFormat":1},{"version":"1594da19968752a22b2ac48c2d0e60575700e745c577a8a4a676b841238ad5bb","impliedFormat":1},{"version":"e0cee12109e0a10a4c3d6769fcc7644b7c1ea7f52365bea51728f5af29f8a137","impliedFormat":1},{"version":"7d4254b4c6c67a29d5e7f65e67d72540480ac2cfb041ca484847f5ae70480b62","impliedFormat":1},{"version":"3536968defef8a75514f547ead5e2e9c1e984820290ec9b00c5fdfb6ef786535","impliedFormat":1},{"version":"d83773870080c30a230e322ce13a9c6f3398e8dacea4ea8a83e26370f3bac23e","impliedFormat":1},{"version":"dcfeaf98d66314fec29a9076c4290e45d0b196a65827becc19138e9c7b855f37","impliedFormat":1},{"version":"6849fe9210fe4946d5f085bfed36758f33dc6ae15a751338d178dd4daa017c46","impliedFormat":1},{"version":"888cda0fa66d7f74e985a3f7b1af1f64b8ff03eb3d5e80d051c3cbdeb7f32ab7","impliedFormat":1},{"version":"60681e13f3545be5e9477acb752b741eae6eaf4cc01658a25ec05bff8b82a2ef","impliedFormat":1},{"version":"ffae4e1e06aa848a1e4bcef162cd1c48e5909b26223515981310af9c036bdfc7","impliedFormat":1},{"version":"a57b1802794433adec9ff3fed12aa79d671faed86c49b09e02e1ac41b4f1d33a","impliedFormat":1},{"version":"34e16eb7c31768a11a08aebcfb3d70d7b8f0b016197e98d8419e566ceae6d6c8","impliedFormat":1},{"version":"f94ec1f7e4b709d26960306c9082a7a1b728a6e13089346aa48ba57c74cbf47e","impliedFormat":1},{"version":"9a11cb4033405e96c247cd5aa29790212aaffdd127869e8a5219103f0b389fd5","impliedFormat":1},{"version":"01479d9d5a5dda16d529b91811375187f61a06e74be294a35ecce77e0b9e8d6c","impliedFormat":1},{"version":"aff5213585cb72e94054dfe17250ff315f3569b3919d1ef1ad235f37c4ee894e","impliedFormat":1},{"version":"fb2ea35e1be6388d722d7725e2b49c697d34d9c890c3b96758faaeb86d35cef8","impliedFormat":1},{"version":"ce0df82a9ae6f914ba08409d4d883983cc08e6d59eb2df02d8e4d68309e7848b","impliedFormat":1},{"version":"1a4dc28334a926d90ba6a2d811ba0ff6c22775fcc13679521f034c124269fd40","impliedFormat":1},{"version":"f05315ff85714f0b87cc0b54bcd3dde2716e5a6b99aedcc19cad02bf2403e08c","impliedFormat":1},{"version":"5fad3b31fc17a5bc58095118a8b160f5260964787c52e7eb51e3d4fcf5d4a6f0","impliedFormat":1},{"version":"72105519d0390262cf0abe84cf41c926ade0ff475d35eb21307b2f94de985778","impliedFormat":1},{"version":"456006a6975b26c0a1785feddae165f6d307e2d601ffde27e21fc4a790e448a4","impliedFormat":1},{"version":"c857e0aae3f5f444abd791ec81206020fbcc1223e187316677e026d1c1d6fe08","impliedFormat":1},{"version":"ccf6dd45b708fb74ba9ed0f2478d4eb9195c9dfef0ff83a6092fa3cf2ff53b4f","impliedFormat":1},{"version":"1fe0d18b111e1145a7e7601855bccd4ca20f24e3b9a5aba6bb1fa9d1a7059170","impliedFormat":1},{"version":"5632c3c26d420c063eebe64c45b1248b9492a67bf44f1d0c57e9dc8f6cf449bb","impliedFormat":1},{"version":"0df5aa619ab12993a39ea6dae062ee46eadbb4d738916460e636ada52bced75b","impliedFormat":1},{"version":"8fca3039857709484e5893c05c1f9126ab7451fa6c29e19bb8c2411a2e937345","impliedFormat":1},{"version":"35069c2c417bd7443ae7c7cafd1de02f665bf015479fec998985ffbbf500628c","impliedFormat":1},{"version":"10ab7be91f87ebe8916b62cf28af2e45b5601fc7b0e311adf838f912c6b31dd8","impliedFormat":1},{"version":"bc636fbc08e0979ceb7eb0731a33000283d77a33b62e1f71ee65be50394e40ba","impliedFormat":1},{"version":"7e0b7f91c5ab6e33f511efc640d36e6f933510b11be24f98836a20a2dc914c2d","impliedFormat":1},{"version":"045b752f44bf9bbdcaffd882424ab0e15cb8d11fa94e1448942e338c8ef19fba","impliedFormat":1},{"version":"2894c56cad581928bb37607810af011764a2f511f575d28c9f4af0f2ef02d1ab","impliedFormat":1},{"version":"0a72186f94215d020cb386f7dca81d7495ab6c17066eb07d0f44a5bf33c1b21a","impliedFormat":1},{"version":"75bbd3be047d539988a0ff0b56384ef7a6a25f3b676ad96bee547d44c31622a7","impliedFormat":1},{"version":"42960001a776b089ade681ab5cfddc936e0afb0615133ec1841f3dee89d3e1bf","impliedFormat":1},{"version":"0aedb02516baf3e66b2c1db9fef50666d6ed257edac0f866ea32f1aa05aa474f","impliedFormat":1},{"version":"da47712b394d944328245482603bc6f416d3949b67c9392279caab595076b510","affectsGlobalScope":true,"impliedFormat":1},{"version":"37d0071d8f0a06dc55c2c5e0ec3391affd4fd107c53410bf358196ec0bf3923f","impliedFormat":1},{"version":"b213dad76ca37fd552274c9499056e1c0d9c1bd38a55bb7f68b22ba6b84c3ad7","impliedFormat":1},{"version":"56ccb49443bfb72e5952f7012f0de1a8679f9f75fc93a5c1ac0bafb28725fc5f","impliedFormat":1},{"version":"20fa37b636fdcc1746ea0738f733d0aed17890d1cd7cb1b2f37010222c23f13e","impliedFormat":1},{"version":"d90b9f1520366d713a73bd30c5a9eb0040d0fb6076aff370796bc776fd705943","impliedFormat":1},{"version":"bc03c3c352f689e38c0ddd50c39b1e65d59273991bfc8858a9e3c0ebb79c023b","impliedFormat":1},{"version":"19df3488557c2fc9b4d8f0bac0fd20fb59aa19dec67c81f93813951a81a867f8","affectsGlobalScope":true,"impliedFormat":1},{"version":"b25350193e103ae90423c5418ddb0ad1168dc9c393c9295ef34980b990030617","affectsGlobalScope":true,"impliedFormat":1},{"version":"bef86adb77316505c6b471da1d9b8c9e428867c2566270e8894d4d773a1c4dc2","impliedFormat":1},{"version":"5a49adaef698b7ad7e6127949fa1b0bbd3d46b7cbd11c54e392a4dcdd51f5190","impliedFormat":1},{"version":"6ee598cdfdd0fa52039dca135b3dfff7b49035dc13292143e0a93843e3861967","impliedFormat":1},{"version":"27be6622e2922a1b412eb057faa854831b95db9db5035c3f6d4b677b902ab3b7","impliedFormat":1},{"version":"5c634644d45a1b6bc7b05e71e05e52ec04f3d73d9ac85d5927f647a5f965181a","impliedFormat":1},{"version":"2489bf04d77dc025ba67f49f1a56eb24b9db477d5ff88123d887e163ed1776aa","impliedFormat":1},{"version":"63a7595a5015e65262557f883463f934904959da563b4f788306f699411e9bac","impliedFormat":1},{"version":"4ba137d6553965703b6b55fd2000b4e07ba365f8caeb0359162ad7247f9707a6","impliedFormat":1},{"version":"0b77b819b5417775fccb20c678293cf614c054a5b1a65421a5b933a9124ba998","impliedFormat":1},{"version":"eb5acb58487367e502d994b57e2c58255d8241f481ea8efa8e79af23af3f41c2","impliedFormat":1},{"version":"9252d498a77517aab5d8d4b5eb9d71e4b225bbc7123df9713e08181de63180f6","impliedFormat":1},{"version":"b1f1d57fde8247599731b24a733395c880a6561ec0c882efaaf20d7df968c5af","impliedFormat":1},{"version":"6715dc4eb59c8ea9abe2b78c235ed331dc710a06fe56798868dbc4d40cd1b707","impliedFormat":1},{"version":"35e6379c3f7cb27b111ad4c1aa69538fd8e788ab737b8ff7596a1b40e96f4f90","impliedFormat":1},{"version":"1fffe726740f9787f15b532e1dc870af3cd964dbe29e191e76121aa3dd8693f2","impliedFormat":1},{"version":"5a3ea721d03a361ccbdd7390ccd75f6e84cbca3a3f01f4b331ecc9af31890c49","impliedFormat":1},{"version":"e7dfaee4af38d45b1cab8a1ee0b3bc1f85ddcf64545ed391d675d78ae6526274","affectsGlobalScope":true,"impliedFormat":1},{"version":"e8daa443eaf9a27fd382cc1f8ebe30330c0f4d89511cfb469166874806751d35","impliedFormat":1},{"version":"af48e58339188d5737b608d41411a9c054685413d8ae88b8c1d0d9bfabdf6e7e","impliedFormat":1},{"version":"616775f16134fa9d01fc677ad3f76e68c051a056c22ab552c64cc281a9686790","impliedFormat":1},{"version":"65c24a8baa2cca1de069a0ba9fba82a173690f52d7e2d0f1f7542d59d5eb4db0","impliedFormat":1},{"version":"f9fe6af238339a0e5f7563acee3178f51db37f32a2e7c09f85273098cee7ec49","impliedFormat":1},{"version":"1de8c302fd35220d8f29dea378a4ae45199dc8ff83ca9923aca1400f2b28848a","impliedFormat":1},{"version":"77e71242e71ebf8528c5802993697878f0533db8f2299b4d36aa015bae08a79c","impliedFormat":1},{"version":"98a787be42bd92f8c2a37d7df5f13e5992da0d967fab794adbb7ee18370f9849","impliedFormat":1},{"version":"332248ee37cca52903572e66c11bef755ccc6e235835e63d3c3e60ddda3e9b93","impliedFormat":1},{"version":"94e8cc88ae2ef3d920bb3bdc369f48436db123aa2dc07f683309ad8c9968a1e1","impliedFormat":1},{"version":"4545c1a1ceca170d5d83452dd7c4994644c35cf676a671412601689d9a62da35","impliedFormat":1},{"version":"320f4091e33548b554d2214ce5fc31c96631b513dffa806e2e3a60766c8c49d9","impliedFormat":1},{"version":"a2d648d333cf67b9aeac5d81a1a379d563a8ffa91ddd61c6179f68de724260ff","impliedFormat":1},{"version":"d90d5f524de38889d1e1dbc2aeef00060d779f8688c02766ddb9ca195e4a713d","impliedFormat":1},{"version":"07ed3ddab975995eea41b22f3010506fb9f5fb301d04820b07d7a1aee5477d7c","impliedFormat":1},{"version":"969d8b0965849f4bae7cab0ba90bd1e1220e95999c2c6f01117fa7500901c017","impliedFormat":1},{"version":"6ec840ee5e2bc103f557fe38b1d585ee250540468713d7634ee066de372bf332","impliedFormat":1},{"version":"b0309e1eda99a9e76f87c18992d9c3689b0938266242835dd4611f2b69efe456","impliedFormat":1},{"version":"47699512e6d8bebf7be488182427189f999affe3addc1c87c882d36b7f2d0b0e","impliedFormat":1},{"version":"6ceb10ca57943be87ff9debe978f4ab73593c0c85ee802c051a93fc96aaf7a20","impliedFormat":1},{"version":"1de3ffe0cc28a9fe2ac761ece075826836b5a02f340b412510a59ba1d41a505a","impliedFormat":1},{"version":"e46d6cc08d243d8d0d83986f609d830991f00450fb234f5b2f861648c42dc0d8","impliedFormat":1},{"version":"1c0a98de1323051010ce5b958ad47bc1c007f7921973123c999300e2b7b0ecc0","impliedFormat":1},{"version":"ff863d17c6c659440f7c5c536e4db7762d8c2565547b2608f36b798a743606ca","impliedFormat":1},{"version":"5412ad0043cd60d1f1406fc12cb4fb987e9a734decbdd4db6f6acf71791e36fe","impliedFormat":1},{"version":"ad036a85efcd9e5b4f7dd5c1a7362c8478f9a3b6c3554654ca24a29aa850a9c5","impliedFormat":1},{"version":"fedebeae32c5cdd1a85b4e0504a01996e4a8adf3dfa72876920d3dd6e42978e7","impliedFormat":1},{"version":"e297c0a524edee7677939122f90027bfbe5f2698939d9a85728e5044b39c7124","impliedFormat":1},{"version":"cdf21eee8007e339b1b9945abf4a7b44930b1d695cc528459e68a3adc39a622e","impliedFormat":1},{"version":"bc9ee0192f056b3d5527bcd78dc3f9e527a9ba2bdc0a2c296fbc9027147df4b2","impliedFormat":1},{"version":"b62381cae176db34f003cc6172ee8f3e0122014889d66391aa73698105cf4934","impliedFormat":1},{"version":"1d9c0a9a6df4e8f29dc84c25c5aa0bb1da5456ebede7a03e03df08bb8b27bae6","impliedFormat":1},{"version":"84380af21da938a567c65ef95aefb5354f676368ee1a1cbb4cae81604a4c7d17","impliedFormat":1},{"version":"1af3e1f2a5d1332e136f8b0b95c0e6c0a02aaabd5092b36b64f3042a03debf28","impliedFormat":1},{"version":"30d8da250766efa99490fc02801047c2c6d72dd0da1bba6581c7e80d1d8842a4","impliedFormat":1},{"version":"03566202f5553bd2d9de22dfab0c61aa163cabb64f0223c08431fb3fc8f70280","impliedFormat":1},{"version":"41eb514d9ce0a6e87957f08a4b7af70d93f87637f37dee706e2d92a6601c25a9","impliedFormat":1},{"version":"e7765aa8bcb74a38b3230d212b4547686eb9796621ffb4367a104451c3f9614f","impliedFormat":1},{"version":"1de80059b8078ea5749941c9f863aa970b4735bdbb003be4925c853a8b6b4450","impliedFormat":1},{"version":"1d079c37fa53e3c21ed3fa214a27507bda9991f2a41458705b19ed8c2b61173d","impliedFormat":1},{"version":"5bf5c7a44e779790d1eb54c234b668b15e34affa95e78eada73e5757f61ed76a","impliedFormat":1},{"version":"5835a6e0d7cd2738e56b671af0e561e7c1b4fb77751383672f4b009f4e161d70","impliedFormat":1},{"version":"4b7f74b772140395e7af67c4841be1ab867c11b3b82a51b1aeb692822b76c872","impliedFormat":1},{"version":"7bd01f0f28cd3aeb2046274d85208e245965f6f2948edf4f7b2057bcf9f22ccc","impliedFormat":99},{"version":"d2f2cf2b8cc92bea913cda4a076e0f790b23a21e84f989d12f0116a7fe3906e0","impliedFormat":99},{"version":"6de125ea94866c736c6d58d68eb15272cf7d1020a5b459fea1c660027eca9a90","affectsGlobalScope":true,"impliedFormat":1},{"version":"f5b20bc288ee49989c95b20847fc93b96bf61cc0845598897a6a53a967dd7d07","affectsGlobalScope":true,"impliedFormat":1},{"version":"064ac1c2ac4b2867c2ceaa74bbdce0cb6a4c16e7c31a6497097159c18f74aa7c","impliedFormat":1},{"version":"3dc14e1ab45e497e5d5e4295271d54ff689aeae00b4277979fdd10fa563540ae","impliedFormat":1},{"version":"d3b315763d91265d6b0e7e7fa93cfdb8a80ce7cdd2d9f55ba0f37a22db00bdb8","impliedFormat":1},{"version":"b789bf89eb19c777ed1e956dbad0925ca795701552d22e68fd130a032008b9f9","impliedFormat":1},{"version":"1eeae8882ff74a3b5bd8b3c23aa703241c675cd8661d675c032197482835b2eb","affectsGlobalScope":true},"7ad303e40d4fddf44f156129e397511953a71481c5cfd86b1862649aaaf240cc",{"version":"a78793bb6b4b642f2821eb60c9ddfa0d3dd186b28568b5f0f4c268ba2b250bd2","signature":"f5803d39603639ee91c7f21fbd6d792f12358eca4fcf74146d6c2f1343b0c135"},{"version":"eccc6b88a6c5c3815e21afbafc1991ee4066019645d20ed3d05aafc9e54d0f58","signature":"5b3beb9e110c494b12be107c3cece59af336b53d20e481c9bdd7eb554799bde6"},{"version":"c57b441e0c0a9cbdfa7d850dae1f8a387d6f81cbffbc3cd0465d530084c2417d","impliedFormat":99},{"version":"51954e948be6a5b728fcfaf561f12331b4f54f068934c77adfc8f70eea17d285","impliedFormat":1},{"version":"e46429536f43f5910f5b2b0c50bb2769b510a4558bb4b5d20a3b0a9091dbf7c3","signature":"400b40fe5d5f4140993b0ac871686d2b7611ab791e8810b2e14f2d89701fc49e"},{"version":"fe93c474ab38ac02e30e3af073412b4f92b740152cf3a751fdaee8cbea982341","impliedFormat":1},{"version":"3255b97f3f24af29c79cc1aa88004efb13b6285ebdde0a567bf32e19bb65250d","impliedFormat":1},{"version":"1e00b8bf9e3766c958218cd6144ffe08418286f89ff44ba5a2cc830c03dd22c7","impliedFormat":1},{"version":"cf471be64a7239a87f0b874b06ecefb9cbc76b83f511883cdf7392afa4cf4cd2","signature":"ea0a7def22250c96963ab5de115c944676e0841797a7edc114d470925252c2a0"},{"version":"e78f1ff29c9175e7e451629df69f06b52e729cfa0d64fb6b0a6555142275b078","signature":"4ef8b0b2f91fee53ff8b0ee7f69fd93b8a294bd7da4c44e40057bf1e14aa0763"},{"version":"166c048927c78e0ca166de2df67186fd3bd3fa9c28092d332370122a54a4b66f","impliedFormat":1},{"version":"44dafc547130d69f8f3ff19973b00a4443a133ceb8cb24c03e0ca9b01626aee6","impliedFormat":99},{"version":"c24ab9ac84d65b417a807ada25456697bb2adf1189fa80cb240625dfb3e61c42","impliedFormat":99},{"version":"d6d57aa3e60250a8526871b3e14abc5a12dc5bb7891512628ffa5c40de369d62","impliedFormat":99},{"version":"0d121799b2cbac398e84a4708fcd82f980f33bf3ac7721a3cf9db9f28d9eb2b2","impliedFormat":99},{"version":"8aed22221e416e7811335f9518690ea0db873de1d0286602e644e1700cd166a4","impliedFormat":99},{"version":"9c3663fa36fb976609d8fc43372ae38dc2e066dab014a955f40ae6430733fb71","impliedFormat":99},{"version":"e38a172f8912eebc79671e07b81687a304a9d366a47933fde9f97ad79f8ac08a","impliedFormat":99},{"version":"2fbe402f0ee5aa8ab55367f88030f79d46211c0a0f342becaa9f648bf8534e9d","impliedFormat":1},{"version":"b94258ef37e67474ac5522e9c519489a55dcb3d4a8f645e335fc68ea2215fe88","impliedFormat":1},{"version":"4e679215c9c8480ea8b876cf74d77c1225da544adaf6acba43634a434275a69d","signature":"c53d99a41e9fed46a0c325bcb83e7d82b734852da2c0210b7bf1f55067aa6e2c"},{"version":"539bede51b7dfa42c5168884f8f2075ee38d50fb900da46436f2855e46e84af4","impliedFormat":99},{"version":"4244c6a12dc14768ddc3ee2737ccf1c6c0d07353785d5979df7d250eda461a61","impliedFormat":99},{"version":"cce820aba9ba9d1984461c67d0d543d8eba7ea25c6a1be7a47c31cc18907a631","impliedFormat":99},{"version":"3e7e929f14bc384ed6da8ef0c7dc3aae5ea191494c9554e4327186ef40db2573","impliedFormat":99},{"version":"9d28b54569f4cd1c0c21d95d0e70f6fdbfd792121604b95d7c2d067ee0f0fd11","impliedFormat":99},{"version":"4d857105510df8011cfb5b3769dec55624a1df92e85d399cd03bc82bb89d090c","impliedFormat":99},{"version":"b92dbe495c1dee9f3cd7c1466fdf02476f19ae18a7ecc829e3ed8a380b2d597f","impliedFormat":99},{"version":"bd3e3a447a34cf3dd875ed550ea349589b2dfcd6b3a14abebdc946366bd812a4","impliedFormat":99},{"version":"6b100282ebfd5bfa4d8c72ad5dd3e9d325aa32d0a53623d6171fc2cc2899fbc4","impliedFormat":99},{"version":"31e0d88a23043e61cff5cb8e9bab319b5ca680f2b663e8582d4800a19da8600c","impliedFormat":99},{"version":"5cf87865e3a8b12bb8ddfb311846ff2eae24983faa365f53d9224fb182cd0269","impliedFormat":99},{"version":"98ef9c3f5f15c18abcd6fa9f12e93e1bbd608225501151603cce97642dbc961d","impliedFormat":99},{"version":"c80a56a10f1a8e01c4b7f08df6e9260ae076c910402dae8173fa6c7dcacc51fe","impliedFormat":99},{"version":"becca0fa1bbcc55ad69918f65f771b76904ac98b2563cb34f26fbe240c3d4db3","impliedFormat":99},{"version":"32b344c3765dc7c383516f3326c108ca84c33df44ece8ac789fce47d47ba8810","impliedFormat":99},{"version":"f7d6ecff9a4d631feeaf401c02bb87e26ddb38131c55d15a43b9290747390847","signature":"f774a7e8875649db68f5952801f001f3c316560ede472e5663af7a8c9c18f938"},{"version":"7f19b8476658d25ff197c84030e58cd7395059d876a54630e025951e474ebdae","signature":"cbb6e618cfae37c1feb246b78260428cf2bcba79a0c9bf1ac60d511a4158692d"},{"version":"40d9f91205363cbf3980e39fa205b55065dfbe6bf8c6ad18c23f27495d9e9454","signature":"d4e4eb785403cd7ffa1eb9afe44d7601b52a99cb205972508f2ef4ff5739bd7d"},{"version":"0e59458db17310dac1942e100a118bae2727028f90024a5b4320606bdf37b860","signature":"5cec2d5111000faf9f06f8fa85b11b747c2fb4db35ada617f019f80de10790b5"},{"version":"2ba6dd2fc6a213bef7e1dba18791da6e83992ff17f6bbd50f2c8f7f4b6fa2d82","signature":"132db3de92d2a718bd41fe3f47e75fb6916b1af96d1289347316ee1abc358b06"},{"version":"d7cf0c57d486631e50b1aab49548676dc9b51d9da48f5f533db0967f23ed2cd9","signature":"cde8c57cf796fc88faa8ed92f02bb868c64100eb22c6bcf935487bd8eeb1ed08"},{"version":"b32ad2dcd8fdba39f610dc21b2c2277c563b9d0e213edad758364181ddc69e60","signature":"f03c9fc060940404460998108d975d541cbef8644269862a531d5b41edb0ac40"},{"version":"9800c238da31c600373883bb7a1a3ddb431684992dfd2b3112fbc1983403c427","signature":"c1c0fdbb129948e18a8b11c893490ee3ce0055631ad8de1eee247343d8359ce6"},{"version":"2b4276dde46aa2faf0dd86119999c76b81e6488cd6b0d0fcf9fb985769cd11c0","impliedFormat":99},{"version":"38d4cff03e87dc58bfd50ffe5a3fb25e6e6d4136a1282883285baf71d35967c5","impliedFormat":99},{"version":"5ecea63968444d55f7c3cf677cbec9525db9229953b34f06be0386a24b0fffd2","impliedFormat":99},{"version":"6ea9c8bf2ae4d47a0dbc2a1f9ac1e36c639b2ac9225c4d271c2f63a2faf24831","impliedFormat":99},{"version":"a3d603c46b55d51493799241b8a456169d36301cc926ff72c75f5480e7eb25bf","impliedFormat":99},{"version":"773c18e2bcc18598df8f8b2be930eb26b22608edf368e42e9ca3484828ec4122","impliedFormat":99},{"version":"9eb8e1320fc0ecbfba15c0f3452dfc1957543dfbd466aaf8b67ddb0f2ad0f217","impliedFormat":1},{"version":"4faca872dbd194a17b3ee267bd8ddc3daf3d16df96f4e43a02c7d9a862022c4f","impliedFormat":99},{"version":"f89aeba83b1744a0d697c1b7fb8a06d8dc4cf7c0d469d2419772121f499efa8e","impliedFormat":99},{"version":"144a4e5780b800c0553949169f50be285eccbdb0298afd83ef2ae03fef77e2d2","impliedFormat":99},{"version":"66aeb47bf8638d6767f7b4ff684c2d794391c981590073025e98f98e1afed499","impliedFormat":99},{"version":"26748898fec8579096c776866e8e6f07754845b3d08f5ae98c3a59baa9e85c2e","impliedFormat":99},{"version":"6d805abd62920edbd9ed4b20be26d040d01529f3ce53fdab9ca4d0fa9b589f02","impliedFormat":99},{"version":"edbeff52e73b0ff82898142aaf8ffb336910a8ccdfc31b79960ea4ad4c9f407b","impliedFormat":99},{"version":"b64a8c7a27133db3f181199d21c0c582e86f38ba57a031a126b77229526b4916","impliedFormat":99},{"version":"1b1c48c4d7cbe6f40616594c2a3f6f95bb1dcefd200a7e4167e47b67725b631a","impliedFormat":99},{"version":"97b02501eb45f487174d5a0ff89b6a95690d50e9eae242e2162118edd5f2705c","impliedFormat":99},{"version":"8eca47167dadd486582ecd4e41f7fba6ae66cc4a4c5202f1f7acf34129a0dadf","impliedFormat":99},{"version":"390dc7901776ab8f54c64100156ae561f4601a6913e86e7d1658715d7c414763","impliedFormat":99},{"version":"6841c30168fa7fe25409d83ae5e210c6340cd412e543e98625d277764d136994","impliedFormat":99},{"version":"1dc13534a1f9f442a683b92ae3200c611f19c2e8039c0b381e09076c85e90049","impliedFormat":99},{"version":"f68896096cba0f06ffbf39a67c2280f6f2e5b90c75db56a3f9ae5f7f3bb54460","impliedFormat":99},{"version":"ceed5b112e868b1c223f4f24e03d302e8043f6bd8f6cf8ede8e75f0471ede6d3","impliedFormat":99},{"version":"26cfaec143443411bc7d5363f274f885ced430b8f4bee25a81f7827248848d7b","impliedFormat":99},{"version":"f9a591e5fe0be6728cc84e70325aacafffcf203b051ddef37d65651b43c05056","impliedFormat":99},{"version":"293c0a3e323608f4e20667acc74d7bdba727db954b840ee1db03f2fd5807c761","impliedFormat":99},{"version":"de8b4c367880fe92a0a740b706f08a46d1cf9e3981d55c2701e82423e81ef0ef","impliedFormat":99},{"version":"8f1b151c1f2ab5f797666d1d53199ad5cec66ab6f4c46f4c02d51ac6d47998d3","impliedFormat":99},{"version":"3a3fd6f5ca85ceeb293f2a010125f9455404958122b6dd0ba0b34f7dab74feb5","impliedFormat":99},{"version":"5bd7f6f573ac89ec20aaf326e79394da8a89fbff8a297aa864de9137ca045678","impliedFormat":99},{"version":"01498e4cffc8badc7ba4bacb201e88d89e7ffa46d0a710f1d0510a11104b4e15","impliedFormat":99},{"version":"5916b6f272fe245dd8032c708487405eb9f5b8a83ded6630ec1ab02df36ed63d","impliedFormat":99},{"version":"9e003336714371c98108af3dc53342829039327f8b1db97d826ca81805746b7f","impliedFormat":99},{"version":"d8954254110123f6f5c9fda6280674f6b853d47df7fc41c2090e741dc8b6b627","impliedFormat":99},{"version":"1e257873c8332ca2066f2f9409269352839d6ef6cd5624ba6b777199e78f70af","impliedFormat":99},{"version":"409e0eb04698050bf40f5da901990a58f7119591fad21dc5f4d94ef20be7f457","impliedFormat":99},{"version":"0fa0e6941b1d3095f625c4bda62c0a37247ab8749cfdbc8b44f4b4518d5482f5","impliedFormat":99},{"version":"56c7641a2de5b6695f415a89826b724734aa8cdcc72a112c8e80c3d140b86f4b","impliedFormat":99},{"version":"e96bd939a55117abe6ccbc02839f2f4d9ce3893368fea528ca91c59ebddf496f","impliedFormat":99},{"version":"81f6bf27eedb1ed92466abfcee33795a6b2304691ae01f42e60f8c76894fade7","impliedFormat":99},{"version":"228127c94406a1583eb6e1314a611d9ee26418d4590b4466ed0468d5be0b7e41","impliedFormat":99},{"version":"26a0c2d883e1ed55ba00810d957dedcde5d16d637e33063686e2bc3f58a5c64a","impliedFormat":99},{"version":"68099697ac4e919f6f1832389f32eb67d3d94fae744967f33e0cbc049a222a3a","impliedFormat":99},{"version":"bfb900f7de2066a4be644c269285fda8ccca40b065476a27b082173014d00467","impliedFormat":99},{"version":"ca2f4468c5bcfc7a37aace0a1f20f92b226b097bebb834f29ecbce8ee399c6cf","impliedFormat":99},{"version":"b787dc6f2d3fa1d219038e6b360245b6c7d15c00a64ee31b24c56e823a0e71ea","impliedFormat":99},{"version":"ce757254610e6b3a37357a5892c46a86525d0d7f0a5e4a907f6707a3928b8a63","impliedFormat":99},{"version":"31a63b6b49338cc6ddb1a318beda72d3d8fd523e50f8dd5d5ff3accd39a490d7","impliedFormat":99},{"version":"8fc7615fb8fa095406f5a58b1b817b9a685c516058877a3d2c06d4545fdf5dbe","impliedFormat":99},{"version":"eeab2749ab639ddcd1b01f3c3acebe9616e0265021bf6aff910070015b03b92b","impliedFormat":99},{"version":"d5da26af31358a4883edb6112879018b14c7c1fbcc457aa36961b03ee17bedea","impliedFormat":99},{"version":"4e93fb2d2c59bbc1f1a5211b36c447efe4d0af568d682ef1e5eb5f84ca6ccc2e","impliedFormat":99},{"version":"b6cc07bc56c7418ab500421d2629c26acdb6ec2e9af85c5e2c5d7e8c9f92566d","impliedFormat":99},{"version":"3d13fe973e92e708ad3dbbf1b2385bb799f8e70c8da71a1ac72fcb5521c8a5e9","impliedFormat":99},{"version":"16f3f66b5182e57c554d0e374e29fdc0a899c1321b3f94fa997d19abf9faf931","impliedFormat":99},{"version":"df459c67b9eef71318851331b23926961f0476b4b9d1674addcb627eabe583b2","impliedFormat":99},{"version":"b93915733f1802a8d9093116a5e660385afda0f72a5bab9c9bd356549a61f1cd","impliedFormat":99},{"version":"1dfb1491b28cf3734f3c07745a56d7758a12d546f81a70fbfe8ee9faeb528c54","impliedFormat":99},{"version":"42b00a511331c7f79039ae3be83fd5941b212ce193654c3ac5d82157227b69ad","impliedFormat":99},{"version":"1a5914065c7c6e2b6e98437c4ba6059bfeda3441f0f55cb07189df1e78698922","impliedFormat":99},{"version":"66d3f42196f32c639d8240bbd520852abc024d673c713bc5ab26b4bdde750a74","impliedFormat":99},{"version":"18ce9175445b3edec11bbca1c682a8f3919e74fb3504abd883ac462ea8089a0d","impliedFormat":99},{"version":"aec96f94a27fc61d5f4ead202628e811199f887d48bb7614b7e1706b629cd1ba","impliedFormat":99},{"version":"2ab01a0368f65b3b891e25416ae785dca54808f70d8f6204b99589ed4f7f1d2f","impliedFormat":99},{"version":"efd87ca2190e2d0f905e30343443c8d2f0d32cb2b1c9e05b2cb97b0061abec08","impliedFormat":99},{"version":"3323edd649d2c85d3528912cdf6fb770258d59d75241575fcf25c7850837de79","impliedFormat":99},{"version":"e0c8deca5262879f11ee84fe6664dcd197a60f546930363bf2d78d37c3138c69","impliedFormat":99},{"version":"3b8ba0456ce7763676505d103eb336a6b97659d6fc8a7d7d186558ea0b8c7ea5","impliedFormat":99},{"version":"7bae4a3f50a844fcbdc504d717f5f13dd7178ca99f131b230305db6b55e1dbc3","impliedFormat":99},{"version":"f3a4668046e42e9f5ebfdc8b79238eb27c399443dd1dcfcd4c4c3652692ed031","impliedFormat":99},{"version":"07160ad59d49c6f2999f9703542918df3eb1ef93857bc560b4baa7c6775d22ce","impliedFormat":99},{"version":"cbb7705b157d0be735c4564681d749529d26ac77296757fdf4d861a76e279d4d","impliedFormat":99},{"version":"c23b9684ab48ea6956f0a510c3cf724277fa457efa7ff85d5907f4e4290ba0aa","impliedFormat":99},{"version":"3859635347ecc10d4ff5dd68bde66420f5a8539b7313dd62020aa025208d2222","impliedFormat":99},{"version":"f49e8feb6d7473579a5ceb5872598bbc1be3723da653993472720629c72fa0ba","impliedFormat":99},{"version":"14c727434cfe6a078b51a88d005033ad01a76bec36292d7b47369d82e48e1cb0","impliedFormat":99},{"version":"1c1ae4ec02de9778286f84e0d15a1b74cc610c13c5b6a13c1ada2e6770eeb4e1","signature":"6d6449b80881e70de3f27d314c1e8a6353071f30442df504dc00e429b4f2252f"},{"version":"0e354464ab326224591b02875550f37ae289785c1558a494f858e3d2b289851c","signature":"8123bb1692f9138dedb3997a3c3ca15cafd7bacbafc0f67f50c62d4c8774fccb"},{"version":"99e1ac75d2f131ce59c1b44ae1ca25d568d9822e8292b06bef1a0b994eaf38a8","signature":"6a9d493e0c5865db9fc7519b48fb79ba3eaf00535a697ff7ea1f0dabccf4d15d"},{"version":"de708061021467057ac23fc62822e8d0840a216e24dcc423d4658a95033fdb8d","signature":"0283eafdc2b9ec618b38542bb438d3e514d72ca37203be108f45f0f960019a0e"},{"version":"59ce31d87135ea5719f4451f6a288ac851746e6200088bcc1d3a7b1c0094c442","signature":"797b1b35838a594d3ba015115250d87d02d7e3ec59ac0ca62d4d32e0dd79bb50"},{"version":"52138496c4a4b63f3466d28c46e6b87a3982565dd6aa38a32c1f55e789e3bf4d","signature":"b5fd5dfc03aecb8ed1d8b60c341824e9ae1dbbd00b941fbc8c461120cd26f4f9"},{"version":"ecb846f6a7e33ab36bf06a172cf74a1eefd0d062c78d89fe4172ecb95a9d9224","signature":"a1371fa0685ee549cbb4dd2f6c4205b8d69cc7a695ba45b859d58575e12ca4a5"},{"version":"8dedf145bef222eb6a09d63a4a6d8f340cd315cbf61ede98ed459bb5b5ffcaeb","signature":"7a4fe07bffc8b6ec1785aec2b011f454fc93828d90b9269ccdda995af85bf073"},{"version":"9a4bf2ff8f2595182b497507fec721a7ba3b6a616aac9743ef2d1e2f2c2f5358","signature":"c7429d15c4b492628c3b307bb6e3cfe8eb2ee741469b1ca524f90b84a143fe8f"},{"version":"8ad83abba071cb20fe7166a8adae3bd77a79be8711426fd96f5be354d868efdb","signature":"ac02d8be5e6d2e71292fe738d73adebc09aaa60603a8e51f7230faec34c5378a"},{"version":"00c6a6bee7ec5494cde411095458ff463d27d6890e90bcb54432becf5e247a24","signature":"d092958065bbc70478d8049066581c325f46a724087ef328cf2d47fbdc282b9a"},{"version":"0872ece3daf3df853bb9a0ca45cdae713dbf616445fff7c792bad8484d5f97ea","signature":"a0948a68b9c152fab283c5f443f8ec9535c005d8bbe560b2b8ff87f54279b68a"},{"version":"3593227c7a844ef53b5d7c50cfe2cd61262f233a970081117634fba1f9613dd5","signature":"7fc4d84099fd385c7645d9d41f854d415baad44aad0b6e07d6d89a89ef7bfc49"},{"version":"ef1b801787af0d1c73a87574b74f49c79c2c89c85360e0faedf3b345d527ad5f","signature":"a501d75788b8433deb30e2113ccbad77c77fb3ce7426757194549f621804f562"},{"version":"c840e12da509f2c771dbc356a23750227a43d1864640c7e6404b8f9ec86b3871","impliedFormat":99},{"version":"6ae92eaaaef30fae975de604d3af31d5b00eca7f02d89fab589152df926685fd","impliedFormat":99},{"version":"e3b3780b68c70ff42894b68ee8f49186ef3335fc86a9106dd07e11580b460cc1","impliedFormat":99},{"version":"459fda119c27213d3defde220c051414020029abd52fb6fb9aea0beedc512c6b","impliedFormat":99},{"version":"968b0403af74a785c9408ca69a677235e49d0c80b2c27fb9858ad421a8778c7d","signature":"58a5ec371db12fd72d7b69a8c237fc87c5a131763b45d262a3d191c5d1356d6d"},{"version":"a18af5e38762561f2b762b6d25a0431a28261d56c8a2b5679dac0f85098286b1","signature":"74e379c34c5c743ac5aba4b22ba97a6c881157ae3a1684867ef5a6022e9364ef"},{"version":"72d2f9ba376af956f371a50e99ce9a2b14ec03e19ba841f2777237505a5757d7","signature":"53774aa9ee1a946a98d3b2659d6aa4d81b0468b05525256a44acbfb4105a8412"},"0a02a9c82bacf747bf9666ef1bd1ab826ee08c0dafd526035e9628f39229dd9d",{"version":"632103a9c889da19e213763a467a89159dcbbc650518b47210f200c4d74ea1d2","signature":"cf8b1979ffd2f536106875f0b58c79a8b401278739c3d70dac5d4e201cb3c32c"},{"version":"0177372f4103fce5ab4fbd8525d8c3dd93f4ea28528551d9a89b811291020d93","signature":"4b494a012ad3720275005cec75f84eb34f8bf5c41e635573fb1fef06f2f4a646"},{"version":"a3e4027bba3b04457fc5649fa0d8c3f152d297e4587a674482b8350d13fed9bd","signature":"c2c4afc8c03490924367c6e6a877dddec82fb37ef9f2554c5754c71c7188e3e9"},{"version":"50bd3793fb4aba7fbb986433937ac4f1ab861006818604acb53b9f9b3f220ad3","signature":"2597e455bbe9695f1933dc417072ee2ee3ef9a7520f88ff8376dc052c4937ad3"},{"version":"67499c68501e0e975423d982df06dd20a5b525ed796ccce021ec1ac6a7488c5c","signature":"19b0e6f016c179c8b32102a442f6bb02cb9c0a9b74f5ef716b37ba0465ccadc0"},{"version":"665265c5d2a05d8a27fc3bee9dd893934ba11419e110d3f256edc712f1f4c86e","signature":"8754fe347bd81594a37b5a19a333e4a8063a20f443fab1af850f7edf12bb5537"},{"version":"f07845a4f9772a545efa7c1086e83a81732c72026d3f365f0bb52bfae5b66752","signature":"b3b0332e154b1a2ccb655349b7e2471c65f61a5b523c06973d88cb50ce785d19"},{"version":"082062d5e676f7049e4a684dc6726c631fe153cb457e494cc240bbe3be5650a4","impliedFormat":99},{"version":"ab2e38bc6b61891361655b5d2e45c4cbc95c9db4920453fd5329cac7fd4e1385","impliedFormat":99},{"version":"9bb8a03e0015254999c1e96830242fa3764856fd14958d3b097149f4491b1fa6","impliedFormat":99},{"version":"21655de6cf9d8df920b2dd8aaa5d6b4f88630c5c6f4df66947f4a2c4e59f7c79","impliedFormat":99},{"version":"c98e4b259d28463c34c65cdbfba447d5ccd4fed0a138b7acf8c796309e61e2d6","signature":"d9ed1c6c07bd03524f35e2b7cf385c3278909b3ed2daafb4b74d460d8b6420ce"},{"version":"2b1fa7acb64cc815fe0f06e3a40e0b1b48abf97f2c2d6528a37c961dd02df095","signature":"633e87523348a4bf2e0999dfa6d93004738ecbd7186f7f2ae5f350e5d7781d2b"},{"version":"3508d7c66d3d63c355662c05597ba5a38e1fbf395e480a07c0b929caf0bcbb86","signature":"137673d794fa6adcae07fe30e38455116513f5894811194401033fe14bb56e38"},{"version":"a929d76da6aed09f88a3bb9b70f6cbb04328aaa19f1482ad650d24ac5af03dc3","signature":"6a2879106635e78675da8924862839ed3ab8806d3e08316152b00a697a4141aa"},{"version":"3e7064de07e84a24d10943b69a0278752f23f1999b396153feb0a63f355beae3","signature":"d6e9a3e9eddda48d8308210ee9ecc68f9425bcc378fb1f8bec08ebb7e0f1b6d3"},{"version":"cc0c992c4255de80ddb2de70f12007b3f33adad3021f31ce6bd683d4bdf92cb7","signature":"343542f6bbe309692eda70274e04acfbfe25aa0bfd9d2c9a711c5281bdb49cba"},{"version":"8ffdf73d62d015140d4c4edfe58757d2f21474d50da2f92d48e33c522b79dbc7","signature":"917fd3d6e4f13868f4a867924f3fbdd816fbad049d179cc81b17a45fd591cc86"},{"version":"4f5773ef65d8494efa60d203dffb7205cf0f662a64102331fc2921d2f3436eb3","signature":"5879818ce307b9ed0a24051ba091c110081cbe6a2ba56008132dbdf4181ab8be"},{"version":"6be9cc6d63419c8acb7c6b32fdd7fff8285842e69dd35588019d93f95a52571b","signature":"6cc449dc9995a239ca20bb0e067ba9e5008acbd036727e8cd97bc0001bdbb2b7"},{"version":"144073fb97265f2149a2122e95c0586f1818bf5d6ab0b050339a4e556bdca3de","signature":"19d54bf73a5a0216df1cf3bd0ff80167cf2bda8b0aa052d2cc7ff7caaccc4efe"},{"version":"28cb8c81a73ab8485fcf4bebcaa7264cd678224a222b85a491be882798d8f550","signature":"1a3c71cf6a6fbdd7591116f48d95ef7dedf3cba8345149fe195729409cd34fe2"},{"version":"89a3e8bdf17d2a9b2d3ce49292daf3c15f389bde130cdc42ba998f3b687b6252","signature":"fec7336827914a1816050bca31f2ee284f4d7deaf7211898cdd094a0deb2b513"},{"version":"a9cfe5372dc1e2c37fc8e554eb4cba17b69035ab033c0d4e0600a85b4e25915c","signature":"7c199173b55f57172fe53234f0fc95cc87e6565a13ce83e7b47918742bd47dfc"},{"version":"96d0274da06a039d38c7331653fed3aa056b4b2a2803ddea456e6715a9445393","signature":"001c2ad8eef03b07f14e41bee9a415db23dccadc02a78919faee940e545787d2"},{"version":"14ddfd8524dece18a84e2745bd609fb9dffd6339abe7c85af10f5cbb8cb67bfe","signature":"ee0527b1ff34f0ceffb2348f0095b1c1cddf4faa46085ea2a110cebaee50d347"},{"version":"2f5e49d5fac0bff2646d100b621df7471168da25022eca592f7af39e27402d31","signature":"b843fbec02d0cb54db1702adcfd063ad08120abeda2498a1787b64590684359c"},{"version":"9a9e04e07fe35d1874951bdc8de7359f75e671b9397557f7384ad6b2a315cf58","signature":"18a4751b41acc2856ed6f45b34fbe725cf9c7e4d90eba0ad2feb4e2d0990ec5e"},{"version":"f3c9b37783fcc62f8450b60893e12ee6d0475d64327315651bc344d89509d6a0","signature":"8aef51ae2a7868e062803dec9fbb656da273542c7c9f4621d5464b9605dfe009"},{"version":"a78eb0d122e55304d670c8a5e01b0ac0f37dbce5a53869669be076470a7f4d78","signature":"a7a3a87855b2d2cc8ae413e677b4899ffc58a5e4a20f055c07a404da99541520"},{"version":"fbcb5bbca46c9b6c2ce849723ef6d6c37d855e9999c06e5d48a0fc706c3b2f58","signature":"5283c1424f61516c54136798c3e7e256528a1a75581132e32e616d76add1160d"},{"version":"19e8160ad82839d8ece0f64fa0354373220e0b0192fb63601bd2bee81f2fd782","signature":"1592edebde83872e3c0cdd72f5eadddab86cf295a6d19f09620b84442fd7854e"},{"version":"3ba2d637c4bc0a43e18faa03d12509dfeff8eb4598001ce6148a8f3e530e567b","signature":"e5f9d5f6f37816cef8cfd651f6a81ff29222429b81fe76184722549e7904facf"},{"version":"586f0de1456ff1f22947e2aec82642f7ec102d0ad0b6f13edeb79dbaa8b9d11b","signature":"8c6eba7333e72b090341a04f45aab07e000ee74e78276b2c041119bf6dd60587"},{"version":"4e150e90bb4f5066740c6bf43a8e5061e998b884d37c7170caaae8dcd808b8ab","signature":"2445a341f73ffabebf7b9d8886a913be095356c2ba0673e3cc2e7fa68b500c36"},{"version":"6dc5f5d9c28c0aa23452a32416ce337ac09ce633ad893b988a1ce256fd7e72be","signature":"828afa634f40e99fc918fbfbacbc0148c5502118e44433a914acadf42cbcc802"},{"version":"052c188cf49779dda6dd016340f5b1158da01b9cc983108dc4037ec5c0575afa","signature":"2840fdae09764d8ef1660442dd476e00484643fff12b1039a7e44c6df5df5b53"},{"version":"8dcf898abdf1bfe773b873d5e1b329b8f4d061fdba45f2ad842a3fdb4db5ab07","signature":"b410611afb0627ebadfbb1f24feaba95b75f2d6eb44e9b4a78cdbca1b5f64aaf"},{"version":"55e5845f6f31bcb05e539336a48ced65fce64e02af796e6da40f4aee7bc78e91","signature":"0b8fd7aa2222d31c2de139a76ef2aa14dc86717c45b9ef30e2c733be1fa2707e"},"d1986184a09a52db8228cb2bb2a61a8c05c9354e5b93cec8e2628d8579c892d7",{"version":"1eeae8882ff74a3b5bd8b3c23aa703241c675cd8661d675c032197482835b2eb","affectsGlobalScope":true},{"version":"f714218368181b1c733138f4e4487d081ba896d37b61c8fbdf26ad4040a814cd","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881"},"d1986184a09a52db8228cb2bb2a61a8c05c9354e5b93cec8e2628d8579c892d7","033f14e95f1a339b960c0b421f2f33f0b97bbcd2e8ae9f13072da21c8bb8ced7"],"root":[[534,537],540,544,545,556,[572,579],[656,669],[674,684],[689,721]],"options":{"allowJs":true,"esModuleInterop":true,"jsx":4,"module":99,"skipLibCheck":true,"strict":true,"target":2},"referencedMap":[[720,1],[534,2],[721,3],[717,4],[718,2],[719,5],[579,6],[660,7],[663,8],[545,9],[536,10],[665,11],[667,12],[678,13],[677,14],[680,15],[682,16],[684,17],[691,18],[669,19],[693,20],[695,21],[577,22],[699,23],[697,24],[703,25],[701,26],[705,27],[709,28],[707,29],[711,30],[715,31],[713,32],[578,33],[683,34],[662,35],[664,36],[575,37],[690,38],[666,39],[694,40],[668,41],[659,42],[698,43],[696,44],[661,45],[676,46],[675,47],[679,48],[681,48],[692,49],[706,50],[708,51],[544,52],[710,50],[658,53],[700,54],[702,48],[704,55],[657,56],[574,57],[674,58],[556,59],[716,60],[656,61],[572,62],[573,60],[689,63],[714,49],[712,37],[576,64],[537,65],[540,66],[535,67],[552,68],[553,69],[632,70],[633,71],[565,72],[564,73],[563,74],[569,75],[568,76],[567,73],[561,73],[560,77],[566,78],[621,79],[602,80],[605,81],[601,82],[619,83],[585,84],[622,85],[606,84],[607,86],[623,84],[617,87],[608,84],[612,88],[613,84],[614,89],[611,90],[615,83],[624,91],[616,79],[625,92],[618,93],[620,94],[610,95],[558,96],[559,97],[570,98],[571,99],[549,100],[557,101],[603,2],[547,2],[548,102],[609,2],[551,103],[604,104],[562,105],[627,106],[628,107],[637,107],[636,108],[639,68],[638,68],[655,109],[654,110],[640,68],[641,68],[642,111],[643,112],[644,106],[645,108],[647,107],[646,68],[635,113],[630,114],[634,115],[629,116],[649,117],[648,118],[653,68],[650,119],[651,68],[631,120],[671,121],[670,68],[652,68],[688,122],[687,123],[685,124],[686,125],[550,126],[673,127],[672,104],[600,128],[595,129],[599,130],[597,2],[598,131],[626,132],[589,105],[592,133],[590,2],[593,134],[587,135],[588,136],[594,137],[591,138],[596,105],[581,139],[583,140],[584,141],[580,2],[582,2],[378,2],[142,142],[143,142],[144,143],[91,144],[145,145],[146,146],[147,147],[89,2],[148,148],[149,149],[150,150],[151,151],[152,152],[153,153],[154,153],[155,154],[156,155],[157,156],[158,157],[92,2],[90,2],[159,158],[160,159],[161,160],[162,161],[163,2],[164,162],[165,163],[166,164],[167,165],[168,166],[169,167],[170,168],[171,169],[172,170],[173,170],[174,171],[175,2],[176,172],[177,173],[179,174],[178,175],[180,176],[181,177],[182,178],[183,179],[184,180],[185,181],[186,182],[88,2],[195,183],[187,184],[188,185],[189,186],[190,187],[191,188],[192,189],[93,2],[94,190],[95,2],[96,2],[138,191],[139,192],[140,2],[141,176],[193,193],[194,194],[199,195],[463,105],[200,196],[198,197],[465,198],[464,199],[196,200],[461,2],[197,201],[79,2],[81,202],[460,105],[230,105],[555,203],[554,204],[538,2],[80,2],[546,105],[486,205],[491,206],[498,207],[481,208],[234,2],[242,209],[382,210],[385,211],[357,2],[370,212],[377,213],[259,2],[359,2],[240,2],[356,214],[402,215],[241,2],[232,216],[384,217],[386,218],[387,219],[458,220],[351,221],[304,222],[364,223],[365,224],[363,225],[362,2],[358,226],[383,227],[243,228],[428,2],[429,229],[270,230],[244,231],[271,230],[307,230],[210,230],[380,232],[379,2],[369,233],[476,2],[219,2],[497,234],[436,235],[437,236],[433,237],[515,2],[334,2],[438,52],[434,238],[520,239],[519,240],[514,2],[285,2],[337,241],[336,2],[513,242],[435,105],[290,243],[297,244],[299,245],[289,2],[294,246],[296,247],[298,248],[293,249],[291,2],[295,250],[516,2],[512,2],[518,251],[517,2],[288,252],[507,253],[510,254],[278,255],[277,256],[276,257],[523,105],[275,258],[264,2],[525,2],[542,259],[541,2],[526,105],[527,260],[202,2],[366,261],[367,262],[368,263],[206,2],[371,2],[226,264],[201,2],[450,105],[208,265],[449,266],[448,267],[439,2],[440,2],[447,2],[442,2],[445,268],[441,2],[443,269],[446,270],[444,269],[239,2],[236,2],[237,230],[391,2],[396,271],[397,272],[395,273],[393,274],[394,275],[389,2],[456,52],[231,52],[485,276],[492,277],[496,278],[325,279],[324,2],[319,2],[472,280],[480,281],[352,282],[353,283],[431,284],[341,2],[454,285],[329,105],[346,286],[457,287],[342,2],[345,288],[343,2],[455,289],[452,290],[451,2],[453,2],[349,2],[427,291],[214,292],[327,293],[331,294],[347,295],[350,296],[339,297],[332,298],[479,299],[405,300],[323,301],[211,302],[478,303],[207,304],[398,305],[390,2],[399,306],[416,307],[388,2],[415,308],[87,2],[410,309],[235,2],[430,310],[406,2],[220,2],[222,2],[361,2],[414,311],[238,2],[262,312],[348,313],[268,314],[328,2],[413,2],[392,2],[418,315],[419,316],[360,2],[421,317],[423,318],[422,319],[372,2],[412,302],[425,320],[322,321],[411,322],[417,323],[247,2],[251,2],[250,2],[249,2],[254,2],[248,2],[257,2],[256,2],[253,2],[252,2],[255,2],[258,324],[246,2],[314,325],[313,2],[318,326],[315,327],[317,328],[320,326],[316,327],[227,329],[306,330],[475,331],[473,2],[502,332],[504,333],[468,334],[503,335],[215,336],[212,336],[245,2],[229,337],[228,338],[224,339],[225,340],[233,341],[261,341],[272,341],[308,342],[273,342],[217,343],[216,2],[312,344],[311,345],[310,346],[309,347],[218,348],[459,349],[260,350],[467,351],[432,352],[462,353],[466,354],[355,355],[354,356],[335,357],[321,358],[303,359],[305,360],[302,361],[424,362],[326,2],[490,2],[223,363],[426,364],[474,365],[333,2],[263,366],[340,367],[338,368],[265,369],[400,370],[469,2],[266,371],[401,371],[488,2],[487,2],[489,2],[471,2],[470,2],[403,372],[330,2],[300,373],[221,374],[279,2],[205,375],[267,2],[494,105],[204,2],[506,376],[287,105],[500,52],[286,377],[483,378],[284,376],[209,2],[508,379],[282,105],[283,105],[274,2],[203,2],[281,380],[280,381],[269,382],[344,169],[404,169],[420,2],[408,383],[407,2],[292,252],[213,2],[301,105],[477,264],[484,384],[82,105],[85,385],[86,386],[83,105],[84,2],[381,190],[376,387],[375,2],[374,388],[373,2],[482,389],[493,390],[495,391],[499,392],[543,393],[501,394],[505,395],[533,396],[509,396],[532,397],[511,398],[521,399],[522,400],[524,401],[528,402],[531,264],[530,2],[529,403],[586,2],[409,404],[539,2],[77,2],[78,2],[13,2],[14,2],[16,2],[15,2],[2,2],[17,2],[18,2],[19,2],[20,2],[21,2],[22,2],[23,2],[24,2],[3,2],[25,2],[26,2],[4,2],[27,2],[31,2],[28,2],[29,2],[30,2],[32,2],[33,2],[34,2],[5,2],[35,2],[36,2],[37,2],[38,2],[6,2],[42,2],[39,2],[40,2],[41,2],[43,2],[7,2],[44,2],[49,2],[50,2],[45,2],[46,2],[47,2],[48,2],[8,2],[54,2],[51,2],[52,2],[53,2],[55,2],[9,2],[56,2],[57,2],[58,2],[60,2],[59,2],[61,2],[62,2],[10,2],[63,2],[64,2],[65,2],[11,2],[66,2],[67,2],[68,2],[69,2],[70,2],[1,2],[71,2],[72,2],[12,2],[75,2],[74,2],[73,2],[76,2],[114,405],[126,406],[112,407],[127,408],[136,409],[103,410],[104,411],[102,412],[135,403],[130,413],[134,414],[106,415],[123,416],[105,417],[133,418],[100,419],[101,413],[107,420],[108,2],[113,421],[111,420],[98,422],[137,423],[128,424],[117,425],[116,420],[118,426],[121,427],[115,428],[119,429],[131,403],[109,430],[110,431],[122,432],[99,408],[125,433],[124,420],[120,434],[129,2],[97,2],[132,435]],"affectedFilesPendingEmit":[721,719,579,660,663,545,536,665,667,678,677,680,682,684,691,669,693,695,577,699,697,703,701,705,709,707,711,715,713,578,683,662,664,575,690,666,694,668,659,698,696,661,676,675,679,681,692,706,708,544,710,658,700,702,704,657,574,674,556,716,656,572,573,689,714,712,576,537,540],"version":"5.7.3"} \ No newline at end of file diff --git a/handicap_engine.py b/handicap_engine.py index 74452a4..2b20230 100644 --- a/handicap_engine.py +++ b/handicap_engine.py @@ -24,7 +24,7 @@ from dataclasses import dataclass from datetime import date, timedelta from decimal import Decimal, ROUND_FLOOR from enum import Enum -from typing import Protocol, Sequence +from typing import Literal, Protocol, Sequence # --------------------------------------------------------------------------- @@ -585,3 +585,50 @@ class Player: def unit_playing_handicap(players: Sequence[Player], strategy: AllowanceStrategy) -> int: """Playing Handicap for én enhet (spiller eller lag) gitt en strategi.""" return strategy.playing_handicap([p.course_handicap_raw() for p in players]) + + +# --------------------------------------------------------------------------- +# Skins (ADR-039 Beslutning D) -- ikke et WHS/R&A-regulert format, ingen +# tilsvarende motorstøtte fantes fra før (ulikt match play over). +# --------------------------------------------------------------------------- + +def compute_skins( + scores_by_hole: Sequence[Sequence[tuple[str, int]]], + tie_handling: Literal["carry", "split"] = "carry", +) -> dict[str, float]: + """Skins vunnet per deltaker, gitt scorer hull for hull. + + `scores_by_hole[i]` er (deltaker_id, score)-par for hull i+1 -- KUN for + deltakere som faktisk har registrert en score på det hullet. Scoren skal + allerede være avgjort NETTO eller BRUTTO av kalleren FØR denne funksjonen + kalles (`round.skins_scoring`) -- motoren selv vet ikke, og bryr seg ikke + om, hvilket. + + - "carry": et uavgjort hull sitt "skinn" (og alt tidligere oppsamlet) + ruller videre til neste hull -- førstemann til en ENTYDIG laveste + score der tar HELE potten. + - "split": et uavgjort hull sitt skinn (og alt oppsamlet) deles LIKT + mellom de tied spillerne i stedet for å rulle videre -- kan gi + brøkdeler, derav float i returtypen. + + Et hull uten noen registrerte scorer hopper stille over (verken potten + eller noen vinnere endres) -- ikke en feiltilstand. + """ + winnings: dict[str, float] = {} + pot = 0.0 + for hole_scores in scores_by_hole: + if not hole_scores: + continue + pot += 1.0 + lowest = min(score for _, score in hole_scores) + winners = [pid for pid, score in hole_scores if score == lowest] + if len(winners) == 1: + winnings[winners[0]] = winnings.get(winners[0], 0.0) + pot + pot = 0.0 + elif tie_handling == "split": + share = pot / len(winners) + for pid in winners: + winnings[pid] = winnings.get(pid, 0.0) + share + pot = 0.0 + # "carry": potten står urørt og tas med videre til neste hull. + return winnings diff --git a/test_handicap_engine.py b/test_handicap_engine.py index 257607f..dc470a4 100644 --- a/test_handicap_engine.py +++ b/test_handicap_engine.py @@ -32,6 +32,7 @@ from handicap_engine import ( handicap_index_from_differentials, low_handicap_index, match_play_strokes, + compute_skins, max_hole_score_for_handicap, net_par, round_counts_for_handicap, @@ -502,6 +503,62 @@ def test_course_handicap_9_halves_index_rule_6_1b(): assert course_handicap_9(idx, slope9, rating9, par9) == round_half_up(expected) +# --------------------------------------------------------------------------- +# Skins (ADR-039 Beslutning D) +# --------------------------------------------------------------------------- + +def test_skins_outright_win_every_hole(): + scores = [[("a", 4), ("b", 5), ("c", 6)], [("a", 3), ("b", 3), ("c", 5)]] + result = compute_skins(scores, tie_handling="carry") + # Hull 1: a vinner (laveste 4) -> 1 skin. Hull 2: a/b uavgjort (3) -> carry. + assert result == {"a": 1.0}, result + + +def test_skins_carry_over_then_win(): + scores = [ + [("a", 4), ("b", 4), ("c", 5)], # uavgjort a/b -> carry (pott=1) + [("a", 5), ("b", 5), ("c", 4)], # c vinner alene -> tar pott (1+1=2) + ] + result = compute_skins(scores, tie_handling="carry") + assert result == {"c": 2.0}, result + + +def test_skins_three_way_tie_carries_whole_pot(): + scores = [ + [("a", 4), ("b", 4), ("c", 4)], # alle like -> carry (pott=1) + [("a", 5), ("b", 5), ("c", 3)], # c vinner alene -> tar hele pott (2) + ] + result = compute_skins(scores, tie_handling="carry") + assert result == {"c": 2.0}, result + + +def test_skins_split_tie_instead_of_carry(): + scores = [[("a", 4), ("b", 4), ("c", 5)]] + result = compute_skins(scores, tie_handling="split") + assert result == {"a": 0.5, "b": 0.5}, result + + +def test_skins_split_after_prior_carry_splits_whole_pot(): + scores = [ + [("a", 5), ("b", 4), ("c", 6)], # b vinner alene -> tar pott (1) + [("a", 4), ("b", 4), ("c", 5)], # a/b uavgjort -> splittes (pott=1 denne runden) + ] + result = compute_skins(scores, tie_handling="split") + assert result == {"b": 1.0 + 0.5, "a": 0.5}, result + + +def test_skins_empty_hole_skipped_not_an_error(): + scores = [[], [("a", 4), ("b", 5)]] + result = compute_skins(scores, tie_handling="carry") + assert result == {"a": 1.0}, result + + +def test_skins_no_winner_if_never_decided(): + scores = [[("a", 4), ("b", 4)], [("a", 5), ("b", 5)]] + result = compute_skins(scores, tie_handling="carry") + assert result == {}, result + + # --------------------------------------------------------------------------- # Enkel selvsjekk uten pytest # ---------------------------------------------------------------------------