Zuletzt aktiv 1 month ago

nuno hat die Gist bearbeitet 1 month ago. Zu Änderung gehen

1 file changed, 111 insertions

tg.ts(Datei erstellt)

@@ -0,0 +1,111 @@
1 + /**
2 + * TG — thin dispatcher for TG-related operations.
3 + * Orchestrates Score, Attendance, WRank, and Bringer.
4 + *
5 + * Usage:
6 + * import { TG } from "@systems/tg";
7 + *
8 + * TG.currentWeek()
9 + * TG.resetWeek()
10 + * TG.getAttendance({ historyKey })
11 + * TG.getScore({ character, slot })
12 + * TG.getWeeklySummary({ character })
13 + */
14 +
15 + import { Nation, Character, UserKey, SlotHour, TGScore } from "@types";
16 + import { WRank } from "@systems/wrank";
17 + import { Bringer } from "@systems/bringer";
18 + import { Score, WeeklySummary } from "@systems/score";
19 + import { Attendance } from "@systems/attendance";
20 + import { Config } from "@systems/config";
21 + import { TGKey } from "@systems/tg-key";
22 +
23 + export const TG = {
24 + // ── Week ──────────────────────────────────────────────────────────────────
25 +
26 + currentWeek() {
27 + return WRank.currentWeek();
28 + },
29 +
30 + /**
31 + * Reset to a new week — carry Bringer forward, clear ranks.
32 + * Called every Monday 00:00 by the Scheduler.
33 + */
34 + resetWeek(): void {
35 + const now = new Date();
36 + const newWeekKey = WRank.weekKey(now);
37 + const prevWeekKey = WRank.weekKey(new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000));
38 +
39 + // Access internal data via WRank
40 + const prevWeek = WRank.weekFromKey(prevWeekKey);
41 + const newWeek = WRank.currentWeek(); // ensures new week exists
42 +
43 + if (prevWeek) {
44 + const goal = Config.get({ section: "wrank", key: "goal" });
45 + for (const nation of [Nation.Capella, Nation.Procyon]) {
46 + const entries = prevWeek.entries[nation];
47 + const rank1 = entries.find((e) => e.currentRank === 1);
48 +
49 + // Rank 1 with >= goal TGs becomes Bringer — no exceptions
50 + // Officers use Bringer.override() for manual adjustments
51 + if (rank1 && rank1.tgCount >= goal) {
52 + newWeek.bringer[nation] = rank1.characterName;
53 + } else {
54 + newWeek.bringer[nation] = null;
55 + }
56 +
57 + // Overrides do NOT carry forward — each week starts clean
58 + delete (newWeek.bringer as any)[`${nation}Override`];
59 + }
60 + }
61 +
62 + WRank.save();
63 + console.log(`[TG] Week reset to ${newWeekKey}. Bringer:`, newWeek.bringer);
64 + },
65 +
66 + // ── Attendance ────────────────────────────────────────────────────────────
67 +
68 + getAttendance({ historyKey, nation }: {
69 + historyKey: TGKey;
70 + nation?: Nation;
71 + }): UserKey[] {
72 + const players = Attendance.players(historyKey);
73 + if (!nation) return players;
74 + // Filter by nation requires character lookup — caller handles if needed
75 + return players;
76 + },
77 +
78 + allSubmitted(historyKey: TGKey): boolean {
79 + return Attendance.allSubmitted(historyKey);
80 + },
81 +
82 + // ── Score ─────────────────────────────────────────────────────────────────
83 +
84 + getScore({ character, slot, date }: {
85 + character: Character;
86 + slot: SlotHour;
87 + date?: string;
88 + }): TGScore | null {
89 + return Score.get({ character, slot });
90 + },
91 +
92 + getWeeklySummary({ character }: { character: Character }): WeeklySummary {
93 + return Score.getWeeklySummary({ character });
94 + },
95 +
96 + submitScore(params: Parameters<typeof Score.submit>[0]): void {
97 + Score.submit(params);
98 + },
99 +
100 + // ── Bringer ───────────────────────────────────────────────────────────────
101 +
102 + getBringer({ nation }: { nation: Nation }): string | null {
103 + return Bringer.get({ nation });
104 + },
105 +
106 + // ── W.Rank ────────────────────────────────────────────────────────────────
107 +
108 + getEntry(character: Character) {
109 + return WRank.entry(character.name, character.nation);
110 + },
111 + };
Neuer Älter