fix: invalidera predicted rating när PDGA-uträkningscykeln rullat över #29
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Beskrivning
Det lagrade
predicted_ratingräknas inte om/invalideras automatiskt när PDGA:s uträkningscykel passerat (andra tisdagen i månaden). Vi visar då en inaktuell prediktion som beräknades mot förra cykelns fönster.calculatePredictedRating()filtrerar rundor motgetNextPDGAUpdateDate()(r.date < nextUpdateDate,src/services/rating-calculator.js:98). När cykeln rullar över ändrasnextUpdateDate→ hela fönstret (12-mån-cutoff, recent-weighting) ska beräknas mot ett nytt datum. Men cachat värde i DB uppdateras bara närpredicted_ratingärnull/0(src/services/player-service.js:45) eller vid manuell round-history-refresh (src/routes/players.js:401). Det finns ingen kolumn som spårar när/mot vilken cykel prediktionen beräknades, så vi kan inte avgöra om den är inaktuell.Vi har idag
last_round_update(src/db.js:18), men den går inte att återanvända för detta:src/routes/players.js:382), inte i den lazy omräkningen igetPredictedRatingFromDB(src/services/player-service.js:152-154).src/routes/players.js:334) — att överlasta den skulle korrumpera rate-limitingen.Förväntat beteende
När
getPreviousPDGAUpdateDate()(senaste passerade andra-tisdagen) är senare än när prediktionen beräknades, ska det cachade värdet betraktas som inaktuellt och inte visas — UI visar—tills nästa manuella refresh producerar ett nytt värde.Vi räknar medvetet inte om automatiskt vid läsning: cachad
round_historykan vara lika gammal, så en omräkning direkt efter en officiell uträkning kan ge en missvisande siffra.—är en ärligare signal om att en refresh behövs.Teknisk orsak
src/db.js(players-schema, ~rad 11-78): saknar tidsstämpel för när predicted beräknades.src/models/player.js:190-201(savePredictedRatingToDB): skriver ingen tidsstämpel.src/services/player-service.js:35-85(getPlayerDataFromDB): recompute-gren triggas pånull/0(rad 45) utan staleness-koll.src/services/rating-calculator.js:40-71(getNextPDGAUpdateDate): finns för nästa uträkning, men ingen motsvarighet för föregående.Constraint: Appen har ingen scheduler/cron — invalidering måste ske lazy (vid läsning), inte som tidsstyrt jobb.
Förslag till lösning
predicted_calculated_at DATETIMEiplayers(migration isrc/db.jsenligt befintligtALTER TABLE-mönster).predicted_calculated_at = CURRENT_TIMESTAMPisavePredictedRatingToDB(src/models/player.js:190) — choke point som täcker både refresh-vägen (players.js:403) och lazy-vägen (player-service.js:154).getPreviousPDGAUpdateDate()isrc/services/rating-calculator.js(senaste passerade andra-tisdagen). Delas med issue 2.getPlayerDataFromDB(src/services/player-service.js:35-85): ompredicted_calculated_at < getPreviousPDGAUpdateDate()→ returnerapredictedRating(+std_dev/cutoff_rating/excluded_rounds_count) somnull. Räkna inte om, skriv inte till DB. Staleness-checken ligger före den befintliga recompute-grenen (rad 45) så den inte väcks. Recompute behålls bara för genuint aldrig-beräknade spelare.Scope
savePredictedRatingToDB,getPreviousPDGAUpdateDate()-helper, staleness-check i läsväg som nollar i svaret.