nuno revisou este gist 1 week ago. Ir para a revisão
1 file changed, 100 insertions
gistfile1.txt(arquivo criado)
| @@ -0,0 +1,100 @@ | |||
| 1 | + | function formatRow( | |
| 2 | + | row: ResultRow, | |
| 3 | + | context: NationContext, | |
| 4 | + | allNames: string[], | |
| 5 | + | allScores: string[], | |
| 6 | + | allKds: string[], | |
| 7 | + | allAtks: string[], | |
| 8 | + | allDefs: string[] | |
| 9 | + | ): string { | |
| 10 | + | const char = row.character; | |
| 11 | + | const goal = Config.get({ section: "wrank", key: "goal" }); | |
| 12 | + | const wrEntry = Layout.wrankEntry(char as any, row.position, row.score?.pts, 1); | |
| 13 | + | const classKey = (typeof char.class === "object" ? char.class?.key : char.class) as ClassKey; | |
| 14 | + | ||
| 15 | + | const scoreEmoji = Emoji.get("score") || "📊"; | |
| 16 | + | const scoreText = row.score ? format.scoreBold(row.score.pts) : "—"; | |
| 17 | + | const kdText = row.score && (row.score.k || row.score.d) ? format.kd(row.score.k ?? 0, row.score.d ?? 0) : "—"; | |
| 18 | + | ||
| 19 | + | // Column targets combine primary + secondary stat widths, so the main | |
| 20 | + | // row makes room for the stats line beneath it. | |
| 21 | + | const scoreColumn = [...allScores, ...allAtks]; | |
| 22 | + | const kdColumn = [...allKds, ...allDefs]; | |
| 23 | + | ||
| 24 | + | const tokens: Record<string, string> = { | |
| 25 | + | wrank: Layout.wrank(wrEntry, goal, context), | |
| 26 | + | class: Emoji.class(classKey) || classKey || "?", | |
| 27 | + | name: TextAlign.padToMax(char.name, allNames), | |
| 28 | + | indicators: Layout.indicators(char as any, { historyKey: row.historyKey }), | |
| 29 | + | score: `${scoreEmoji} ${TextAlign.padToMax(scoreText, scoreColumn)}`, | |
| 30 | + | kd: TextAlign.gap(KD_GAP) + TextAlign.padToMax(kdText, kdColumn), | |
| 31 | + | }; | |
| 32 | + | ||
| 33 | + | const mainLine = Layout.formatRow(TEMPLATE, tokens); | |
| 34 | + | ||
| 35 | + | const hasStats = row.score && (row.score.atk || row.score.def || row.score.heal); | |
| 36 | + | log.debug(`formatRow stats check: char=${char.name} score=${JSON.stringify(row.score)} hasStats=${hasStats}`); | |
| 37 | + | if (!hasStats) return mainLine; | |
| 38 | + | ||
| 39 | + | const prefixText = `${tokens.wrank} ${tokens.class} ${tokens.name}${tokens.indicators}`; | |
| 40 | + | const prefixGap = TextAlign.padLeft("", TextAlign.estimateWidth(prefixText)); | |
| 41 | + | const atkText = format.statText("anima_atk", row.score!.atk, "⚔️"); | |
| 42 | + | const defText = format.statText("anima_def", row.score!.def, "🛡️"); | |
| 43 | + | const healText = format.statText("circle_massheal_purple", row.score!.heal, "💚"); | |
| 44 | + | ||
| 45 | + | const statsLine = `${prefixGap} ${TextAlign.gap(SCORE_GAP)}${TextAlign.padToMax(atkText, scoreColumn)} ${TextAlign.gap(DEF_GAP)}${TextAlign.padToMaxOffset(defText, kdColumn, DEF_WIDTH_OFFSET)} ${TextAlign.gap(HEAL_GAP)}${healText}`; | |
| 46 | + | ||
| 47 | + | return `${mainLine}\n${statsLine}`; | |
| 48 | + | } | |
| 49 | + | ||
| 50 | + | function buildEmbed(historyKey: TGKey, rows: ResultRow[]): EmbedBuilder { | |
| 51 | + | const { date, slot } = TGKey.parse(historyKey); | |
| 52 | + | ||
| 53 | + | const capellaRows = rows.filter((r) => r.character.nation === Nation.Capella); | |
| 54 | + | const procyonRows = rows.filter((r) => r.character.nation === Nation.Procyon); | |
| 55 | + | ||
| 56 | + | const capContext = Layout.nationContext(capellaRows); | |
| 57 | + | const proContext = Layout.nationContext(procyonRows); | |
| 58 | + | ||
| 59 | + | const sortByScore = (a: ResultRow, b: ResultRow) => (b.score?.pts ?? 0) - (a.score?.pts ?? 0); | |
| 60 | + | ||
| 61 | + | const sortedCapella = [...capellaRows].sort(sortByScore); | |
| 62 | + | const sortedProcyon = [...procyonRows].sort(sortByScore); | |
| 63 | + | ||
| 64 | + | const capellaNames = sortedCapella.map((r) => r.character.name); | |
| 65 | + | const procyonNames = sortedProcyon.map((r) => r.character.name); | |
| 66 | + | const capellaScores = sortedCapella.map((r) => r.score ? format.scoreBold(r.score.pts) : "—"); | |
| 67 | + | const procyonScores = sortedProcyon.map((r) => r.score ? format.scoreBold(r.score.pts) : "—"); | |
| 68 | + | const capellaKds = sortedCapella.map((r) => r.score && (r.score.k || r.score.d) ? format.kd(r.score.k ?? 0, r.score.d ?? 0) : "—"); | |
| 69 | + | const procyonKds = sortedProcyon.map((r) => r.score && (r.score.k || r.score.d) ? format.kd(r.score.k ?? 0, r.score.d ?? 0) : "—"); | |
| 70 | + | ||
| 71 | + | const atkEmoji = Emoji.get("atk") || "⚔️"; | |
| 72 | + | const defEmoji = Emoji.get("def") || "🛡️"; | |
| 73 | + | const capellaAtks = sortedCapella.map((r) => r.score?.atk ? `${atkEmoji} ${format.number.abbrev(r.score.atk)}` : ""); | |
| 74 | + | const procyonAtks = sortedProcyon.map((r) => r.score?.atk ? `${atkEmoji} ${format.number.abbrev(r.score.atk)}` : ""); | |
| 75 | + | const capellaDefs = sortedCapella.map((r) => r.score?.def ? `${defEmoji} ${format.number.abbrev(r.score.def)}` : ""); | |
| 76 | + | const procyonDefs = sortedProcyon.map((r) => r.score?.def ? `${defEmoji} ${format.number.abbrev(r.score.def)}` : ""); | |
| 77 | + | ||
| 78 | + | const capK = capellaRows.reduce((s, r) => s + (r.score?.k ?? 0), 0); | |
| 79 | + | const capD = capellaRows.reduce((s, r) => s + (r.score?.d ?? 0), 0); | |
| 80 | + | const proK = procyonRows.reduce((s, r) => s + (r.score?.k ?? 0), 0); | |
| 81 | + | const proD = procyonRows.reduce((s, r) => s + (r.score?.d ?? 0), 0); | |
| 82 | + | ||
| 83 | + | const capellaEmoji = Emoji.get("capella"); | |
| 84 | + | const procyonEmoji = Emoji.get("procyon"); | |
| 85 | + | ||
| 86 | + | const capellaFormatted = sortedCapella.map((r) => formatRow(r, capContext, capellaNames, capellaScores, capellaKds, capellaAtks, capellaDefs)); | |
| 87 | + | const procyonFormatted = sortedProcyon.map((r) => formatRow(r, proContext, procyonNames, procyonScores, procyonKds, procyonAtks, procyonDefs)); | |
| 88 | + | ||
| 89 | + | const embed = new EmbedBuilder() | |
| 90 | + | .setTitle(`⚔️ TG Result — ${format.date(new Date(date), "dd/MM/YYYY")} · ${slot}:00`) | |
| 91 | + | .setColor(0xe8a317) | |
| 92 | + | .setFooter({ text: `TG Result · ${TGKey.toDisplay(historyKey)}` }) | |
| 93 | + | .setTimestamp(); | |
| 94 | + | ||
| 95 | + | EmbedHelpers.addPerPlayerColumn(embed, `${capellaEmoji} Capella${(capK || capD) ? ` — ${format.kd(capK, capD)}` : ""}`, capellaFormatted); | |
| 96 | + | embed.addFields({ name: "\u200b", value: "\u200b", inline: false }); | |
| 97 | + | EmbedHelpers.addPerPlayerColumn(embed, `${procyonEmoji} Procyon${(proK || proD) ? ` — ${format.kd(proK, proD)}` : ""}`, procyonFormatted); | |
| 98 | + | ||
| 99 | + | return embed; | |
| 100 | + | } | |
Próximo
Anterior