fix Bringer showing incorrectly from previous weeks on result post
This commit is contained in:
parent
772477e6e8
commit
7d68530826
4 changed files with 76 additions and 94 deletions
|
|
@ -18,19 +18,10 @@
|
|||
import { format } from "@format";
|
||||
import { Logger } from "@systems/logger";
|
||||
import { DiscordClient } from "@discord/client";
|
||||
import { ResultUI, ResultRow as UIResultRow } from "@ui/result";
|
||||
import { ResultUI, ResultRow as UIResultRow, ResultRow } from "@ui/result";
|
||||
|
||||
const log = Logger.for("result");
|
||||
|
||||
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||
|
||||
interface ResultRow {
|
||||
character: Character;
|
||||
score?: TGScore;
|
||||
position?: { currentRank: number; previousRank?: number };
|
||||
leavesCount: number;
|
||||
}
|
||||
|
||||
// ─── Data ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
function buildRows(historyKey: TGKey): ResultRow[] {
|
||||
|
|
@ -80,6 +71,7 @@
|
|||
score,
|
||||
position,
|
||||
leavesCount: Leaves.countForChar({ characterName: char.name }),
|
||||
historyKey
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -103,7 +95,10 @@
|
|||
return;
|
||||
}
|
||||
|
||||
const embed = ResultUI.buildEmbed(historyKey, rows as any);
|
||||
const { date } = TGKey.parse(historyKey);
|
||||
const weekKey = WRank.weekKey(new Date(date));
|
||||
const week = WRank.weekFromKey(weekKey);
|
||||
const embed = ResultUI.buildEmbed(historyKey, rows, week);
|
||||
|
||||
await PersistentMessage.post({
|
||||
store: "results",
|
||||
|
|
|
|||
13
src/types.ts
13
src/types.ts
|
|
@ -177,19 +177,6 @@ export interface PollState {
|
|||
calledAt?: string;
|
||||
}
|
||||
|
||||
|
||||
// export interface PollState {
|
||||
// messageId: string | null;
|
||||
// slot: number;
|
||||
// yes: Map<string, VoteEntry>; // userId → VoteEntry
|
||||
// no: Map<string, VoteEntry>;
|
||||
// locked: boolean;
|
||||
// confirmed: "yes" | "no" | null;
|
||||
// lockMessage?: string;
|
||||
// confirmMessage?: string;
|
||||
// lockedYesKeys?: Set<string>; // snapshot of userKeys in yes at lock time
|
||||
// }
|
||||
|
||||
// ─── Scores ──────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface TGScore {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@
|
|||
import { Config } from "@systems/config";
|
||||
import { Logger } from "@systems/logger";
|
||||
import { Runtime } from "@systems/runtime";
|
||||
import { TGStats } from "@root/src/types";
|
||||
import { Character, TGScore, TGStats } from "@root/src/types";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import { WRankWeek } from "@root/src/systems/wrank";
|
||||
|
||||
const log = Logger.for("result-ui");
|
||||
|
||||
|
|
@ -19,20 +20,8 @@
|
|||
// ─── Types ────────────────────────────────────────────────────────────────────
|
||||
|
||||
export interface ResultRow {
|
||||
character: {
|
||||
name: string;
|
||||
class: any;
|
||||
level: number;
|
||||
nation: any;
|
||||
ownerKey: string;
|
||||
};
|
||||
score?: {
|
||||
pts: number;
|
||||
k?: number;
|
||||
d?: number;
|
||||
stats?: TGStats;
|
||||
wRankAtSubmission?: { rank: number; delta: number };
|
||||
};
|
||||
character: Character;
|
||||
score?: TGScore;
|
||||
position?: { currentRank: number; previousRank?: number };
|
||||
leavesCount: number;
|
||||
historyKey: TGKey;
|
||||
|
|
@ -41,7 +30,7 @@
|
|||
export interface ResultLayout {
|
||||
name: string;
|
||||
description: string;
|
||||
buildEmbed(historyKey: TGKey, rows: ResultRow[]): EmbedBuilder;
|
||||
buildEmbed(historyKey: TGKey, rows: ResultRow[], week?: WRankWeek|null): EmbedBuilder;
|
||||
formatRow(row: ResultRow, context: any): string;
|
||||
}
|
||||
|
||||
|
|
@ -107,8 +96,8 @@
|
|||
// ─── Dispatcher ───────────────────────────────────────────────────────────────
|
||||
|
||||
export const ResultUI = {
|
||||
buildEmbed(historyKey: TGKey, rows: ResultRow[]): EmbedBuilder {
|
||||
return activeLayout().buildEmbed(historyKey, rows);
|
||||
buildEmbed(historyKey: TGKey, rows: ResultRow[], week?: WRankWeek|null): EmbedBuilder {
|
||||
return activeLayout().buildEmbed(historyKey, rows, week);
|
||||
},
|
||||
|
||||
formatRow(row: ResultRow, context: any): string {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
import { EmbedHelpers } from "@ui/embed-helpers";
|
||||
import { TextAlign } from "@ui/text-align";
|
||||
import { ResultLayout, ResultRow } from "../index";
|
||||
import { WRankWeek } from "@root/src/systems/wrank";
|
||||
|
||||
const TEMPLATE = "{wrank} {class} {name}{indicators} {score} {kd}";
|
||||
|
||||
|
|
@ -26,12 +27,13 @@
|
|||
function formatRow(
|
||||
row: ResultRow,
|
||||
context: NationContext,
|
||||
allNames: string[],
|
||||
allNameBlocks: string[],
|
||||
allScores: string[],
|
||||
allKds: string[],
|
||||
allAtks: string[],
|
||||
allDefs: string[]
|
||||
): string {
|
||||
allDefs: string[],
|
||||
week: WRankWeek | null
|
||||
): string {
|
||||
const char = row.character;
|
||||
const goal = Config.get({ section: "wrank", key: "goal" });
|
||||
const wrEntry = Layout.wrankEntry(char as any, row.position, row.score?.pts, 1);
|
||||
|
|
@ -44,19 +46,22 @@
|
|||
const scoreColumn = [...allScores, ...allAtks];
|
||||
const kdColumn = [...allKds, ...allDefs];
|
||||
|
||||
const bringerTag = Layout.bringer(char as any, week ?? undefined);
|
||||
const nameBlock = bringerTag ? `${char.name}${TextAlign.gap(1)}${bringerTag}` : char.name;
|
||||
const paddedBlock = TextAlign.padToMax(nameBlock, allNameBlocks);
|
||||
const cockroach = Layout.cockroach(char as any, row.historyKey);
|
||||
|
||||
const tokens: Record<string, string> = {
|
||||
wrank: Layout.wrank(wrEntry, goal, context),
|
||||
class: Emoji.class(classKey) || classKey || "?",
|
||||
name: TextAlign.padToMax(char.name, allNames),
|
||||
indicators: Layout.indicators(char as any, { historyKey: row.historyKey }),
|
||||
name: paddedBlock,
|
||||
indicators: cockroach,
|
||||
score: `${scoreEmoji} ${TextAlign.padToMax(scoreText, scoreColumn)}`,
|
||||
kd: TextAlign.gap(KD_GAP) + TextAlign.padToMax(kdText, kdColumn),
|
||||
};
|
||||
|
||||
const mainLine = Layout.formatRow(TEMPLATE, tokens);
|
||||
|
||||
// Read stats from the NESTED shape (row.score.stats), matching TGScore's
|
||||
// actual canonical structure.
|
||||
const stats = row.score?.stats;
|
||||
const hasStats = !!stats && !!(stats.atk || stats.def || stats.heal);
|
||||
if (!hasStats) return mainLine;
|
||||
|
|
@ -70,9 +75,9 @@
|
|||
const statsLine = `${prefixGap} ${TextAlign.gap(SCORE_GAP)}${TextAlign.padToMax(atkText, scoreColumn)} ${TextAlign.gap(DEF_GAP)}${TextAlign.padToMax(defText, kdColumn)} ${TextAlign.gap(HEAL_GAP)}${healText}`;
|
||||
|
||||
return `${mainLine}\n${statsLine}`;
|
||||
}
|
||||
}
|
||||
|
||||
function buildEmbed(historyKey: TGKey, rows: ResultRow[]): EmbedBuilder {
|
||||
function buildEmbed(historyKey: TGKey, rows: ResultRow[], week: WRankWeek|null): EmbedBuilder {
|
||||
const { date, slot } = TGKey.parse(historyKey);
|
||||
|
||||
const capellaRows = rows.filter((r) => r.character.nation === Nation.Capella);
|
||||
|
|
@ -86,8 +91,14 @@
|
|||
const sortedCapella = [...capellaRows].sort(sortByScore);
|
||||
const sortedProcyon = [...procyonRows].sort(sortByScore);
|
||||
|
||||
const capellaNames = sortedCapella.map((r) => r.character.name);
|
||||
const procyonNames = sortedProcyon.map((r) => r.character.name);
|
||||
const capellaNameBlocks = sortedCapella.map((r) => {
|
||||
const tag = Layout.bringer(r.character as any, week ?? undefined);
|
||||
return tag ? `${r.character.name}${TextAlign.gap(1)}${tag}` : r.character.name;
|
||||
});
|
||||
const procyonNameBlocks = sortedProcyon.map((r) => {
|
||||
const tag = Layout.bringer(r.character as any, week ?? undefined);
|
||||
return tag ? `${r.character.name}${TextAlign.gap(1)}${tag}` : r.character.name;
|
||||
});
|
||||
const capellaScores = sortedCapella.map((r) => r.score ? format.scoreBold(r.score.pts) : "—");
|
||||
const procyonScores = sortedProcyon.map((r) => r.score ? format.scoreBold(r.score.pts) : "—");
|
||||
const capellaKds = sortedCapella.map((r) => r.score && (r.score.k || r.score.d) ? format.kd(r.score.k ?? 0, r.score.d ?? 0) : "—");
|
||||
|
|
@ -108,8 +119,8 @@
|
|||
const capellaEmoji = Emoji.get("capella");
|
||||
const procyonEmoji = Emoji.get("procyon");
|
||||
|
||||
const capellaFormatted = sortedCapella.map((r) => formatRow(r, capContext, capellaNames, capellaScores, capellaKds, capellaAtks, capellaDefs));
|
||||
const procyonFormatted = sortedProcyon.map((r) => formatRow(r, proContext, procyonNames, procyonScores, procyonKds, procyonAtks, procyonDefs));
|
||||
const capellaFormatted = sortedCapella.map((r) => formatRow(r, capContext, capellaNameBlocks, capellaScores, capellaKds, capellaAtks, capellaDefs, week));
|
||||
const procyonFormatted = sortedProcyon.map((r) => formatRow(r, proContext, procyonNameBlocks, procyonScores, procyonKds, procyonAtks, procyonDefs, week));
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`⚔️ TG Result — ${format.date(new Date(date), "dd/MM/YYYY")} · ${slot}:00`)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue