Última atividade 1 month ago

nuno revisou este gist 1 month ago. Ir para a revisão

1 file changed, 306 insertions

types.ts(arquivo criado)

@@ -0,0 +1,306 @@
1 +
2 + // ─── Branded primitive types ─────────────────────────────────────────────────
3 + export type UserKey = string;
4 + export type DiscordId = string;
5 + export type CharName = string;
6 + export type SlotHour = number;
7 + export type VoteType = "yes" | "no";
8 + export type ConfirmType = "yes" | "no";
9 +
10 +
11 + // ─── Nation ───────────────────────────────────────────────────────────────────
12 + export enum Nation {
13 + Capella = "Capella",
14 + Procyon = "Procyon",
15 + }
16 +
17 + // ─── Class ────────────────────────────────────────────────────────────────────
18 + export type ClassKey =
19 + | "BL" // Blader
20 + | "FB" // Force Blader
21 + | "FS" // Force Shielder
22 + | "FA" // Force Archer
23 + | "FG" // Force Gunner
24 + | "GL" // Gladiator
25 + | "DM" // Dark Mage
26 + | "WI" // Wizard
27 + | "WA"; // Warrior
28 +
29 + export interface CharacterClass {
30 + key: ClassKey;
31 + name: string; // "Force Blader"
32 + shortName: string; // "FB"
33 + }
34 +
35 + export const CLASSES: Record<ClassKey, CharacterClass> = {
36 + FB: { key: "FB", name: "Force Blader", shortName: "FB" },
37 + WI: { key: "WI", name: "Wizard", shortName: "WI" },
38 + BL: { key: "BL", name: "Blader", shortName: "BL" },
39 + FS: { key: "FS", name: "Force Shielder", shortName: "FS" },
40 + FA: { key: "FA", name: "Force Archer", shortName: "FA" },
41 + FG: { key: "FG", name: "Force Gunner", shortName: "FG" },
42 + GL: { key: "GL", name: "Gladiator", shortName: "GL" },
43 + DM: { key: "DM", name: "Dark Mage", shortName: "DM" },
44 + WA: { key: "WA", name: "Warrior", shortName: "WA" },
45 + };
46 +
47 + export const CLASS_NAMES: Record<ClassKey, string> = {
48 + BL: "Blader",
49 + FB: "Force Blader",
50 + FS: "Force Shielder",
51 + FA: "Force Archer",
52 + FG: "Force Gunner",
53 + GL: "Gladiator",
54 + DM: "Dark Mage",
55 + WI: "Wizard",
56 + WA: "Warrior",
57 + };
58 +
59 + // ─── Character ───────────────────────────────────────────────────────────────
60 +
61 + export interface CharacterStats {
62 + str?: number;
63 + int?: number;
64 + dex?: number;
65 + honorRank?: number;
66 + honorPoints?: number;
67 + custom?: Record<string, number>;
68 + }
69 +
70 + export interface Character {
71 + name: string;
72 + class: CharacterClass;
73 + level: number;
74 + nation: Nation;
75 + active?: boolean;
76 + ownerKey: UserKey;
77 + stats?: CharacterStats;
78 + sharedWith?: string[]; // usermap keys with permanent access
79 + }
80 +
81 + export interface BorrowRequest {
82 + requesterKey: string; // who wants to borrow
83 + ownerKey: string; // who owns the character
84 + charName: string; // which character
85 + requestedAt: number; // timestamp for expiry
86 + }
87 +
88 + // ─── Account ─────────────────────────────────────────────────────────────────
89 +
90 + export interface AccountData {
91 + collection?: Record<string, number>;
92 + animaMastery?: Record<string, number>;
93 + custom?: Record<string, number>;
94 + }
95 +
96 + export interface AccountMap {
97 + [userKey: string]: AccountData;
98 + }
99 +
100 + // interface UserIdentity {
101 + // discordId: DiscordId; // never changes — primary key
102 + // discordUsername: string; // current username — may change
103 + // userKey: UserKey | null; // system key
104 + // lookupId: string; // discordId if ID-mapped, discordUsername if legacy
105 + // displayName: string;
106 + // serverNickname: string | null;
107 + // globalNickname: string | null;
108 + // aliases: string[];
109 + // activeCharacter: Character | null;
110 + // }
111 +
112 + // ─── Usermap ─────────────────────────────────────────────────────────────────
113 +
114 + export interface UsermapEntry {
115 + file: string;
116 + aliases: string[];
117 + }
118 +
119 + export interface Usermap {
120 + [discordUsername: string]: UsermapEntry | string; // string = legacy format
121 + }
122 +
123 + // ─── TG Slots ────────────────────────────────────────────────────────────────
124 +
125 + export interface TGSlot {
126 + tgHour: number; // 20
127 + pollOpens: string; // "10:00"
128 + closesAfter: number; // minutes after tgHour (default 35)
129 + active: boolean;
130 + }
131 +
132 + // ─── Poll ────────────────────────────────────────────────────────────────────
133 +
134 + // export interface VoteEntry {
135 + // userKey: string;
136 + // displayName: string; // server nickname → global nickname → username
137 + // characterName?: string; // active character name at time of vote
138 + // characterClass?: ClassKey; // snapshotted
139 + // characterLevel?: number; // snapshotted
140 + // characterNation?: Nation; // snapshotted at vote time
141 + // votedAt: string; // HH:MM formatted
142 + // previousYesAt?: string;
143 + // previousNoAt?: string;
144 + // publicMessage?: string; // resolved from message system or officer override
145 + // publicMessageOverride?: string;// set by officer via /tg poll set-message
146 + // ephemeralOverride?: string; // set by officer via /tg poll set-ephemeral
147 + // borrowedFrom?: string // Borrowed character from who
148 + // discordId?: string; // real Discord ID of the voter (for notifications)
149 + // }
150 +
151 + export interface VoteEntry {
152 + userKey?: UserKey;
153 + displayName?: string;
154 + characterName?: CharName;
155 + characterClass?: ClassKey;
156 + characterLevel?: number;
157 + characterNation?: Nation;
158 + borrowedFrom?: UserKey;
159 + discordId?: DiscordId;
160 + votedAt?: string;
161 + publicMessage?: string;
162 + previousYesAt?: string;
163 + previousNoAt?: string;
164 + }
165 +
166 + export interface PollState {
167 + slot: SlotHour;
168 + messageId?: string | null;
169 + locked: boolean;
170 + confirmed?: "yes" | "no" | null;
171 + yes: Map<string, VoteEntry>;
172 + no: Map<string, VoteEntry>;
173 + lockedYesKeys?: Set<UserKey>;
174 + lockMessage?: string;
175 + confirmMessage?: string;
176 + called?: boolean;
177 + calledAt?: string;
178 + }
179 +
180 + // ─── Scores ──────────────────────────────────────────────────────────────────
181 +
182 + export interface TGScore {
183 + userKey: UserKey;
184 + playedBy?: UserKey; // if borrowed
185 + characterName: string;
186 + class: string;
187 + nation: Nation;
188 + pts: number;
189 + k?: number;
190 + d?: number;
191 + stats?: TGStats;
192 + submittedAt: string;
193 + slot: SlotHour;
194 + date: string;
195 + submittedByOfficer: boolean;
196 + wRankAtSubmission?: {
197 + rank: number;
198 + delta: number;
199 + };
200 + }
201 +
202 + export interface TGStats {
203 + atk?: number;
204 + def?: number;
205 + heal?: number;
206 + }
207 +
208 + // ─── TG Result ───────────────────────────────────────────────────────────────
209 +
210 + export interface NationKD {
211 + k: number;
212 + d: number;
213 + }
214 +
215 + export interface TGResult {
216 + slot: number;
217 + date: string; // YYYY-MM-DD
218 + closedAt?: string; // ISO timestamp
219 + confirmed: boolean;
220 + nationKD: {
221 + source: Nation; // which nation is source of truth
222 + capella: NationKD;
223 + procyon: NationKD;
224 + };
225 + scores: TGScore[];
226 + }
227 +
228 + // ─── W.Rank ──────────────────────────────────────────────────────────────────
229 +
230 + // export interface WRankEntry {
231 + // character: Character;
232 + // weeklyPoints: number;
233 + // tgCount: number;
234 + // currentRank: number;
235 + // previousRank?: number;
236 + // }
237 +
238 +
239 + // interface UserIdentity {
240 + // discordId: DiscordId; // never changes — primary key
241 + // discordUsername: string; // current username — may change
242 + // userKey: UserKey | null; // system key
243 + // lookupId: string; // discordId if ID-mapped, discordUsername if legacy
244 + // displayName: string;
245 + // serverNickname: string | null;
246 + // globalNickname: string | null;
247 + // aliases: string[];
248 + // activeCharacter: Character | null;
249 + // }
250 +
251 + export interface WRankPosition {
252 + currentRank: number;
253 + previousRank?: number;
254 + }
255 +
256 + // ─── Bringer ─────────────────────────────────────────────────────────────────
257 +
258 + export interface BringerState {
259 + currentWeek: string; // "2026-W22"
260 + capella: string | null; // userKey
261 + procyon: string | null;
262 + capellaOverride?: string;
263 + procyonOverride?: string;
264 + }
265 +
266 + // ─── Messages ────────────────────────────────────────────────────────────────
267 +
268 + export interface MessageEntry {
269 + clicks: number;
270 + message?: string; // single message (legacy)
271 + messages?: string[]; // array of messages
272 + random?: boolean;
273 + days?: Record<string, { messages: string[]; random?: boolean }>;
274 + dates?: Record<string, { messages: string[]; random?: boolean }>;
275 + }
276 +
277 + export interface MessageBlock {
278 + yes: MessageEntry[];
279 + no: MessageEntry[];
280 + users?: Record<string, { yes: MessageEntry[]; no: MessageEntry[] }>;
281 + }
282 +
283 + export interface MessagesFile {
284 + public: MessageBlock;
285 + ephemeral: MessageBlock;
286 + }
287 +
288 + // ─── Emojis ──────────────────────────────────────────────────────────────────
289 +
290 + export interface EmojiMap {
291 + [key: string]: string; // e.g. "capella" → "<:Capella:1477082112560726238>"
292 + }
293 +
294 + // ─── Interaction context ─────────────────────────────────────────────────────
295 +
296 + export interface ResolvedUser {
297 + userId: string;
298 + discordUsername: string; // interaction.user.username
299 + userKey: string | null; // resolved from usermap
300 + lookupUsername: string | null;
301 + displayName: string; // server nickname → global nickname → username
302 + serverNickname: string | null;
303 + globalNickname: string | null;
304 + aliases: string[];
305 + activeCharacter: Character | null;
306 + }
Próximo Anterior