最終更新 1 week ago

gistfile1.txt Raw
1 function buildRows(historyKey: TGKey): ResultRow[] {
2 const { slot, date } = TGKey.parse(historyKey);
3 let players: UserKey[] = Attendance.players(historyKey);
4
5 if (players.length === 0) {
6 const history = Store.read<{ scores: TGScore[] }>(TGKey.toHistoryPath(historyKey));
7 if (history?.scores) {
8 players = [...new Set(history.scores.map((s: TGScore) => s.playedBy ?? s.userKey))];
9 }
10 }
11
12 const weekKey = WRank.weekKey(new Date(date));
13 const history = Store.read<{ scores: TGScore[] }>(TGKey.toHistoryPath(historyKey));
14 const rows: ResultRow[] = [];
15
16 // Match each ATTENDEE (player) directly against the scores where
17 // (playedBy ?? userKey) === that player — this is the authoritative
18 // link, not "does this player own/share a character with a score".
19 for (const playerKey of players) {
20 const score = history?.scores.find((s: TGScore) => (s.playedBy ?? s.userKey) === playerKey);
21 if (!score) continue; // attendee hasn't submitted yet — handled elsewhere (placeholder row)
22
23 const foundChar = CharacterRegistry.find(score.characterName);
24 const classKey = (typeof score.class === "object" ? (score.class as any)?.key : score.class) as ClassKey;
25 const char: Character = foundChar ?? {
26 name: score.characterName,
27 class: CLASSES[classKey] ?? { key: classKey, name: classKey, shortName: classKey },
28 level: 0,
29 nation: score.nation,
30 ownerKey: score.userKey,
31 };
32
33 const wrEntry = WRank.entry(char.name, char.nation, weekKey);
34 const position = score.wRankAtSubmission
35 ? {
36 currentRank: score.wRankAtSubmission.rank,
37 previousRank: score.wRankAtSubmission.rank - score.wRankAtSubmission.delta,
38 }
39 : wrEntry
40 ? { currentRank: wrEntry.currentRank, previousRank: wrEntry.previousRank }
41 : undefined;
42
43 rows.push({
44 character: char,
45 score,
46 position,
47 leavesCount: Leaves.countForChar({ characterName: char.name }),
48 });
49 }
50
51 return rows;
52}