Ostatnio aktywny 1 month ago

nuno zrewidował ten Gist 1 month ago. Przejdź do rewizji

1 file changed, 121 insertions

format.ts(stworzono plik)

@@ -0,0 +1,121 @@
1 + import { ClassKey, Nation, WRankEntry } from "@src/types";
2 + import { getClassEmoji, getNationEmoji, getEmoji } from "@systems/emojis";
3 +
4 + // ─── Individual formatters ────────────────────────────────────────────────────
5 +
6 + export interface CharDisplayOptions {
7 + emoji?: boolean; // show class emoji (default: true)
8 + level?: boolean; // show level (default: true)
9 + }
10 +
11 + /**
12 + * Format a character for display in embeds and messages.
13 + * Output: <:class:> 79 «Flash»
14 + */
15 + function char(
16 + c: { class: ClassKey; level: number; name: string },
17 + options?: CharDisplayOptions
18 + ): string {
19 + const showEmoji = options?.emoji ?? true;
20 + const showLevel = options?.level ?? true;
21 + const classStr = showEmoji ? (getClassEmoji(c.class) || c.class) : c.class;
22 + const levelStr = showLevel ? `${c.level} ` : "";
23 + return `${classStr} ${levelStr}${c.name}`.trim();
24 + }
25 +
26 + /**
27 + * Format a nation name with its emoji.
28 + * Output: <:capella:> Capella
29 + */
30 + function nation(n: Nation): string {
31 + const emoji = getNationEmoji(n);
32 + return emoji ? `${emoji} ${n}` : n;
33 + }
34 +
35 + /**
36 + * Format a score line.
37 + * Output: <:score:> 3000 <:kd:> 32/18
38 + */
39 + function score(pts: number, k?: number, d?: number): string {
40 + const scoreEmoji = getEmoji("score") || "📊";
41 + const kdEmoji = getEmoji("kd") || "⚔️";
42 + const kdStr = k !== undefined && d !== undefined ? ` ${kdEmoji} ${k}/${d}` : "";
43 + return `${scoreEmoji} ${pts}${kdStr}`;
44 + }
45 +
46 + /**
47 + * Parse a Discord custom emoji string to an object for ButtonBuilder.setEmoji()
48 + * Input: "<:fb:1511020923510194428>"
49 + * Output: { name: "fb", id: "1511020923510194428" }
50 + */
51 + function emoji(emojiStr: string): { name: string; id: string } | string | null {
52 + if (!emojiStr) return null;
53 + const match = emojiStr.match(/^<:(\w+):(\d+)>$/);
54 + if (match) return { name: match[1], id: match[2] };
55 + return emojiStr;
56 + }
57 +
58 + // ─── W.Rank formatters ────────────────────────────────────────────────────────
59 +
60 + export interface WRankDisplayOptions {
61 + goal: number;
62 + brackets?: boolean; // wrap delta in parentheses (default: true)
63 + }
64 +
65 + /**
66 + * Format the rank indicator for a wrank entry.
67 + * Output: <:wrank_1_gold:> or <:wrank_1:> or bold/plain number fallback
68 + */
69 + function wrankRank(entry: WRankEntry, goal: number): string {
70 + const isDone = entry.tgCount >= goal;
71 + const rankKey = isDone ? `wrank_${entry.currentRank}_gold` : `wrank_${entry.currentRank}`;
72 + return getEmoji(rankKey) || (isDone ? `**${entry.currentRank}**` : `${entry.currentRank}`);
73 + }
74 +
75 + /**
76 + * Format the delta indicator for a wrank entry.
77 + * Output: <:wrank_up:><:wrank_up_2:> or ↑2, empty string if no change
78 + */
79 + function wrankDelta(entry: WRankEntry, options?: { brackets?: boolean }): string {
80 + const brackets = options?.brackets ?? true;
81 + const prev = entry.previousRank;
82 + const delta = prev !== undefined ? entry.currentRank - prev : 0;
83 +
84 + if (delta === 0 && prev === undefined) return "";
85 +
86 + let inner: string;
87 + if (delta < 0) {
88 + const abs = Math.abs(delta);
89 + const numEmoji = getEmoji(`wrank_up_${abs}`);
90 + inner = (getEmoji("wrank_up") || "↑") + (numEmoji || abs);
91 + } else if (delta > 0) {
92 + const numEmoji = getEmoji(`wrank_down_${delta}`);
93 + inner = (getEmoji("wrank_down") || "↓") + (numEmoji || delta);
94 + } else {
95 + inner = (getEmoji("wrank_neutral") || "·") + "0";
96 + }
97 +
98 + return brackets ? ` (${inner})` : ` ${inner}`;
99 + }
100 +
101 + /**
102 + * Format a full wrank display string: rank + delta.
103 + * Output: <:wrank_1_gold:> (<:wrank_up:><:wrank_up_2:>)
104 + */
105 + function wrankFull(entry: WRankEntry, options: WRankDisplayOptions): string {
106 + return wrankRank(entry, options.goal) + wrankDelta(entry, { brackets: options.brackets });
107 + }
108 +
109 + // ─── Namespace export ─────────────────────────────────────────────────────────
110 +
111 + export const format = {
112 + char,
113 + nation,
114 + score,
115 + emoji,
116 + wrank: {
117 + rank: wrankRank,
118 + delta: wrankDelta,
119 + full: wrankFull,
120 + },
121 + };
Nowsze Starsze