90 lines
2.6 KiB
TypeScript
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);
|
|
}
|