···749749 return err
750750 }
751751752752- // Get all active player IDs
753753- var playerIDs []int
754754- rows, err := DB.Query("SELECT id FROM submissions WHERE is_active = 1 AND status = 'completed'")
752752+ // Snapshot all player ratings BEFORE any updates (critical for proper rating period)
753753+ initialRatings := make(map[int]Glicko2Player)
754754+ rows, err := DB.Query("SELECT id, glicko_rating, glicko_rd, glicko_volatility FROM submissions WHERE is_active = 1 AND status = 'completed'")
755755 if err != nil {
756756 return err
757757 }
758758 for rows.Next() {
759759 var id int
760760- if err := rows.Scan(&id); err != nil {
760760+ var rating, rd, volatility float64
761761+ if err := rows.Scan(&id, &rating, &rd, &volatility); err != nil {
761762 return err
762763 }
763763- playerIDs = append(playerIDs, id)
764764+ initialRatings[id] = Glicko2Player{Rating: rating, RD: rd, Volatility: volatility}
764765 }
765766 rows.Close()
766767767768 // For each player, collect ALL their match results and update once (proper rating period)
768768- for _, playerID := range playerIDs {
769769- // Get player's current rating
770770- var rating, rd, volatility float64
771771- err := DB.QueryRow(
772772- "SELECT glicko_rating, glicko_rd, glicko_volatility FROM submissions WHERE id = ?",
773773- playerID,
774774- ).Scan(&rating, &rd, &volatility)
775775- if err != nil {
776776- continue
777777- }
778778-769769+ for playerID, player := range initialRatings {
779770 // Collect ALL match results for this player in this rating period
780771 var results []Glicko2Result
781772···799790 continue
800791 }
801792802802- // Get opponent's rating at the START of this rating period (not current)
803803- var oppRating, oppRD float64
804804- err := DB.QueryRow(
805805- "SELECT glicko_rating, glicko_rd FROM submissions WHERE id = ?",
806806- opponentID,
807807- ).Scan(&oppRating, &oppRD)
808808- if err != nil {
793793+ // Get opponent's rating from initial snapshot (not from DB which may be updated)
794794+ opponent, ok := initialRatings[opponentID]
795795+ if !ok {
809796 continue
810797 }
811798···813800 score := float64(myWins) / float64(totalGames)
814801815802 results = append(results, Glicko2Result{
816816- OpponentRating: oppRating,
817817- OpponentRD: oppRD,
803803+ OpponentRating: opponent.Rating,
804804+ OpponentRD: opponent.RD,
818805 Score: score,
819806 })
820807 }
···822809823810 // Update this player's rating based on ALL results at once (proper rating period)
824811 if len(results) > 0 {
825825- player := Glicko2Player{Rating: rating, RD: rd, Volatility: volatility}
826812 newPlayer := updateGlicko2(player, results)
827813828814 DB.Exec(