Última actividad 1 week ago

gistfile1.txt Sin formato
1import { Config } from "@systems/config";
2import { submitScore, detectSlot, normalizeSlot } from "@systems/scores";
3import { getEffectiveCharacter } from "@systems/borrow";
4import { format } from "@format";
5import { getEmoji } from "@systems/emojis";
6
7// ─── Types ────────────────────────────────────────────────────────────────────
8
9export 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
21export type ScoreSubmitResult =
22 | { ok: true; message: string }
23 | { ok: false; message: string };
24
25// ─── Core ─────────────────────────────────────────────────────────────────────
26
27export 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}