tg-bot-ts/src/systems/scores.ts
Nuno Duque Nunes 1446cd10fc initial commit
2026-06-01 13:36:51 +01:00

90 lines
2.6 KiB
TypeScript

import { TGScore, Nation, ClassKey } from "../types";
import { cfg } from "./config";
import { upsertScore, todayString } from "./history";
import { recordScore } from "./wrank";
// Normalize a slot string to a 24h integer hour
// Accepts: "20", "8", "8pm", "20:00", "midnight", "midday", "noon"
export function normalizeSlot(input: string): number | null {
const s = input.trim().toLowerCase();
if (s === "midnight") return 0;
if (s === "midday" || s === "noon") return 12;
const pmMatch = s.match(/^(\d{1,2})pm$/);
if (pmMatch) {
const h = parseInt(pmMatch[1]);
return h === 12 ? 12 : h + 12;
}
const amMatch = s.match(/^(\d{1,2})am$/);
if (amMatch) {
const h = parseInt(amMatch[1]);
return h === 12 ? 0 : h;
}
const colonMatch = s.match(/^(\d{1,2}):\d{2}$/);
if (colonMatch) return parseInt(colonMatch[1]);
const numMatch = s.match(/^(\d{1,2})$/);
if (numMatch) return parseInt(numMatch[1]);
return null;
}
// Detect which slot a submission belongs to based on current time
export function detectSlot(): number | null {
const slots = cfg("slots").filter((s) => s.active);
const windowMs = cfg("scoreWindowHours") * 60 * 60 * 1000;
const durationMs = cfg("tgDurationMinutes") * 60 * 1000;
const now = Date.now();
for (const slot of slots) {
const today = new Date();
const tgTime = new Date(today);
tgTime.setHours(slot.tgHour, 0, 0, 0);
const closeTime = tgTime.getTime() + durationMs;
const windowEnd = closeTime + windowMs;
if (now >= closeTime && now <= windowEnd) {
return slot.tgHour;
}
}
return null;
}
export interface ScoreSubmission {
usermapKey: string;
characterName: string;
cls: ClassKey;
nation: Nation;
pts: number;
slot: number;
date?: string;
atk?: number;
def?: number;
heal?: number;
submittedByOfficer: boolean;
}
export function submitScore(sub: ScoreSubmission): void {
const date = sub.date ?? todayString();
const historyKey = `${date}-${String(sub.slot).padStart(2, "0")}`;
const score: TGScore = {
usermapKey: sub.usermapKey,
characterName: sub.characterName,
class: sub.cls,
nation: sub.nation,
pts: sub.pts,
atk: sub.atk,
def: sub.def,
heal: sub.heal,
submittedAt: new Date().toISOString(),
slot: sub.slot,
date,
submittedByOfficer: sub.submittedByOfficer,
};
upsertScore(score);
recordScore(sub.usermapKey, sub.characterName, sub.cls, sub.nation, sub.pts, historyKey);
}