最後活躍 1 week ago

nuno 已修改 1 week ago. 還原成這個修訂版本

1 file changed, 97 insertions

gistfile1.txt(檔案已創建)

@@ -0,0 +1,97 @@
1 + import { Config } from "@systems/config";
2 + import { submitScore, detectSlot, normalizeSlot } from "@systems/scores";
3 + import { getEffectiveCharacter } from "@systems/borrow";
4 + import { format } from "@format";
5 + import { getEmoji } from "@systems/emojis";
6 +
7 + // ─── Types ────────────────────────────────────────────────────────────────────
8 +
9 + export interface ScoreSubmitInput {
10 + userKey: string;
11 + pts: number;
12 + slot?: number | string | null; // number = already resolved, string = needs normalizing, null/undefined = auto-detect
13 + k?: number;
14 + d?: number;
15 + atk?: number;
16 + def?: number;
17 + heal?: number;
18 + submittedByOfficer?: boolean;
19 + }
20 +
21 + export type ScoreSubmitResult =
22 + | { ok: true; message: string }
23 + | { ok: false; message: string };
24 +
25 + // ─── Core ─────────────────────────────────────────────────────────────────────
26 +
27 + export namespace score {
28 + /**
29 + * Resolve, validate and persist a score submission for a given userKey.
30 + * Used by both the slash command handler and the modal submit handler.
31 + */
32 + export async function submitForUser(input: ScoreSubmitInput): Promise<ScoreSubmitResult> {
33 + const { userKey, pts, k, d, atk, def, heal, submittedByOfficer = false } = input;
34 +
35 + const { char, borrowedFrom } = getEffectiveCharacter(userKey);
36 + if (!char) {
37 + return { ok: false, message: "❌ No active character found. Use `/tg char set-active` first." };
38 + }
39 +
40 + // Resolve slot
41 + let slot: number | null = null;
42 + if (typeof input.slot === "number") {
43 + slot = input.slot;
44 + } else if (typeof input.slot === "string") {
45 + slot = normalizeSlot(input.slot);
46 + if (slot === null) {
47 + return { ok: false, message: `❌ Could not parse slot "${input.slot}".` };
48 + }
49 + } else {
50 + slot = detectSlot() ?? Config.get({ section: "poll", key: "slots" }).find((s) => s.active)?.tgHour ?? 20;
51 + }
52 +
53 + await submitScore({
54 + userKey: borrowedFrom ?? userKey,
55 + playedBy: borrowedFrom ? userKey : undefined,
56 + characterName: char.name,
57 + cls: char.class,
58 + nation: char.nation,
59 + pts,
60 + k,
61 + d,
62 + slot,
63 + atk,
64 + def,
65 + heal,
66 + submittedByOfficer,
67 + });
68 +
69 + const scoreEmoji = getEmoji("score") || "📊";
70 + const kdEmoji = getEmoji("kd") || "⚔️";
71 + const kdNote = k !== undefined && d !== undefined ? `\n${kdEmoji} ${k}/${d}` : "";
72 + const statsNote = [
73 + atk !== undefined ? `ATK: ${atk}` : null,
74 + def !== undefined ? `DEF: ${def}` : null,
75 + heal !== undefined ? `HEAL: ${heal}` : null,
76 + ].filter(Boolean).join(" · ");
77 +
78 + const charDisplay = format.char(char);
79 + const borrowNote = borrowedFrom ? ` *(borrowed from ${borrowedFrom})*` : "";
80 +
81 + const line = format.scoreSubmitLine({
82 + slot,
83 + char,
84 + pts,
85 + k,
86 + d,
87 + atk,
88 + def,
89 + heal,
90 + });
91 +
92 + return {
93 + ok: true,
94 + message: `✅ ${line}${borrowNote}`,
95 + };
96 + }
97 + }
上一頁 下一頁