tg-bot-ts/src/systems/attendance.ts

80 lines
No EOL
2 KiB
TypeScript

/**
* Attendance — tracks who was in each TG.
*
* Usage:
* import { Attendance } from "@systems/attendance";
*
* Attendance.snapshot(slot)
* Attendance.players(slot)
* Attendance.allSubmitted(slot, date)
*/
import fs from "fs";
import { Paths } from "@paths";
import { UserKey, HistoryKey } from "@types";
import { Store } from "@systems/store";
interface AttendanceData {
[historyKey: HistoryKey]: UserKey[];
}
let _data: AttendanceData = {};
function load(): void {
_data = Store.readOrDefault<AttendanceData>(Paths.data("attendance.json"), {});
}
function save(): void {
Store.write(Paths.data("attendance.json"), _data);
}
load();
export const Attendance = {
/**
* Snapshot attendance from poll state at lock time.
*/
snapshot(slot: number, lockedYesKeys: Set<UserKey>): void {
const date = new Date().toISOString().slice(0, 10);
const historyKey = `${date}-${slot}` as HistoryKey;
_data[historyKey] = [...lockedYesKeys];
save();
},
/**
* Get players who attended a specific TG.
*/
players(historyKey: HistoryKey): UserKey[] {
return _data[historyKey] ?? [];
},
/**
* Check if a specific player attended.
*/
includes(historyKey: HistoryKey, userKey: UserKey): boolean {
return (_data[historyKey] ?? []).includes(userKey);
},
/**
* Check if all attendees have submitted scores.
*/
allSubmitted(historyKey: HistoryKey): boolean {
const players = _data[historyKey] ?? [];
if (players.length === 0) return false;
try {
const result = JSON.parse(
fs.readFileSync(Paths.data("tg-history", `${historyKey}.json`), "utf8")
);
const submitted = new Set(result.scores?.map((s: any) => s.userKey) ?? []);
return players.every((p) => submitted.has(p));
} catch {
return false;
}
},
/**
* Get all history keys (for listing past TGs).
*/
all(): HistoryKey[] {
return Object.keys(_data) as HistoryKey[];
},
};