function buildRows(historyKey: TGKey): ResultRow[] { const { slot, date } = TGKey.parse(historyKey); let players: UserKey[] = Attendance.players(historyKey); if (players.length === 0) { const history = Store.read<{ scores: TGScore[] }>(TGKey.toHistoryPath(historyKey)); if (history?.scores) { players = [...new Set(history.scores.map((s: TGScore) => s.playedBy ?? s.userKey))]; } } const weekKey = WRank.weekKey(new Date(date)); const history = Store.read<{ scores: TGScore[] }>(TGKey.toHistoryPath(historyKey)); const rows: ResultRow[] = []; // Match each ATTENDEE (player) directly against the scores where // (playedBy ?? userKey) === that player — this is the authoritative // link, not "does this player own/share a character with a score". for (const playerKey of players) { const score = history?.scores.find((s: TGScore) => (s.playedBy ?? s.userKey) === playerKey); if (!score) continue; // attendee hasn't submitted yet — handled elsewhere (placeholder row) const foundChar = CharacterRegistry.find(score.characterName); const classKey = (typeof score.class === "object" ? (score.class as any)?.key : score.class) as ClassKey; const char: Character = foundChar ?? { name: score.characterName, class: CLASSES[classKey] ?? { key: classKey, name: classKey, shortName: classKey }, level: 0, nation: score.nation, ownerKey: score.userKey, }; const wrEntry = WRank.entry(char.name, char.nation, weekKey); const position = score.wRankAtSubmission ? { currentRank: score.wRankAtSubmission.rank, previousRank: score.wRankAtSubmission.rank - score.wRankAtSubmission.delta, } : wrEntry ? { currentRank: wrEntry.currentRank, previousRank: wrEntry.previousRank } : undefined; rows.push({ character: char, score, position, leavesCount: Leaves.countForChar({ characterName: char.name }), }); } return rows; }