Ultima attività 1 month ago

nuno ha revisionato questo gist 1 month ago. Vai alla revisione

1 file changed, 96 insertions

scores.ts(file creato)

@@ -0,0 +1,96 @@
1 + import { TGScore, Nation, ClassKey } from "../types";
2 + import { cfg } from "./config";
3 + import { upsertScore, todayString } from "./history";
4 + import { recordScore } from "./wrank";
5 +
6 + // Normalize a slot string to a 24h integer hour
7 + // Accepts: "20", "8", "8pm", "20:00", "midnight", "midday", "noon"
8 + export function normalizeSlot(input: string): number | null {
9 + const s = input.trim().toLowerCase();
10 + if (s === "midnight") return 0;
11 + if (s === "midday" || s === "noon") return 12;
12 +
13 + const pmMatch = s.match(/^(\d{1,2})pm$/);
14 + if (pmMatch) {
15 + const h = parseInt(pmMatch[1]);
16 + return h === 12 ? 12 : h + 12;
17 + }
18 +
19 + const amMatch = s.match(/^(\d{1,2})am$/);
20 + if (amMatch) {
21 + const h = parseInt(amMatch[1]);
22 + return h === 12 ? 0 : h;
23 + }
24 +
25 + const colonMatch = s.match(/^(\d{1,2}):\d{2}$/);
26 + if (colonMatch) return parseInt(colonMatch[1]);
27 +
28 + const numMatch = s.match(/^(\d{1,2})$/);
29 + if (numMatch) return parseInt(numMatch[1]);
30 +
31 + return null;
32 + }
33 +
34 + // Detect which slot a submission belongs to based on current time
35 + export function detectSlot(): number | null {
36 + const slots = cfg("slots").filter((s) => s.active);
37 + const windowMs = cfg("scoreWindowHours") * 60 * 60 * 1000;
38 + const durationMs = cfg("tgDurationMinutes") * 60 * 1000;
39 + const now = Date.now();
40 +
41 + for (const slot of slots) {
42 + const today = new Date();
43 + const tgTime = new Date(today);
44 + tgTime.setHours(slot.tgHour, 0, 0, 0);
45 + const closeTime = tgTime.getTime() + durationMs;
46 + const windowEnd = closeTime + windowMs;
47 +
48 + if (now >= closeTime && now <= windowEnd) {
49 + return slot.tgHour;
50 + }
51 + }
52 + return null;
53 + }
54 +
55 + export interface ScoreSubmission {
56 + userKey: string; // owner's key (score goes here)
57 + playedBy?: string; // borrower's key if different from owner
58 + characterName: string;
59 + cls: ClassKey;
60 + nation: Nation;
61 + pts: number;
62 + k?: number;
63 + d?: number;
64 + slot: number;
65 + date?: string;
66 + atk?: number;
67 + def?: number;
68 + heal?: number;
69 + submittedByOfficer: boolean;
70 + }
71 +
72 + export function submitScore(sub: ScoreSubmission): void {
73 + const date = sub.date ?? todayString();
74 + const historyKey = `${date}-${String(sub.slot).padStart(2, "0")}`;
75 +
76 + const score: TGScore = {
77 + userKey: sub.userKey,
78 + playedBy: sub.playedBy,
79 + characterName: sub.characterName,
80 + class: sub.cls,
81 + nation: sub.nation,
82 + pts: sub.pts,
83 + k: sub.k,
84 + d: sub.d,
85 + atk: sub.atk,
86 + def: sub.def,
87 + heal: sub.heal,
88 + submittedAt: new Date().toISOString(),
89 + slot: sub.slot,
90 + date,
91 + submittedByOfficer: sub.submittedByOfficer,
92 + };
93 +
94 + upsertScore(score);
95 + recordScore(sub.userKey, sub.characterName, sub.cls, sub.nation, sub.pts, historyKey);
96 + }
Più nuovi Più vecchi