diff --git a/app/components/__tests__/QualifyingPointsStandings.test.tsx b/app/components/__tests__/QualifyingPointsStandings.test.tsx index d66718b..536b561 100644 --- a/app/components/__tests__/QualifyingPointsStandings.test.tsx +++ b/app/components/__tests__/QualifyingPointsStandings.test.tsx @@ -14,7 +14,7 @@ const scoringRules = { }; describe("QualifyingPointsStandings", () => { - it("renders fractional QP to hundredths", () => { + it("renders fractional QP to at most hundredths with trailing zeros trimmed", () => { render( { ); expect(screen.getByText("14.67 QP")).toBeInTheDocument(); - expect(screen.getByText("0.50 QP")).toBeInTheDocument(); + // 0.50 trims its trailing zero to 0.5; 14.67 and 0.43 are unaffected. + expect(screen.getByText("0.5 QP")).toBeInTheDocument(); expect(screen.getByText("0.43 QP")).toBeInTheDocument(); }); }); diff --git a/app/components/scoring/QualifyingPointsStandings.tsx b/app/components/scoring/QualifyingPointsStandings.tsx index 21ecfc0..835426e 100644 --- a/app/components/scoring/QualifyingPointsStandings.tsx +++ b/app/components/scoring/QualifyingPointsStandings.tsx @@ -55,7 +55,9 @@ interface QualifyingPointsStandingsProps { function formatQP(raw: string): string { const n = parseFloat(raw); if (isNaN(n)) return "—"; - return n % 1 === 0 ? n.toString() : n.toFixed(2); + // At most 2 decimals, trailing zeros trimmed (1.50→1.5). Mirrors the Discord + // embed's formatQPValue (app/services/discord.ts) so the site and Discord agree. + return parseFloat(n.toFixed(2)).toString(); } export function QualifyingPointsStandings({ diff --git a/app/services/__tests__/discord.test.ts b/app/services/__tests__/discord.test.ts index c009174..96ad65d 100644 --- a/app/services/__tests__/discord.test.ts +++ b/app/services/__tests__/discord.test.ts @@ -857,11 +857,13 @@ describe("sendQualifyingPointsUpdateNotification", () => { }); const desc = getDescription(); - // Mirrors the web UI's formatQP: fractional QP renders with 2 decimals ("1.50"), - // never rounded to an integer. The Points Awarded line no longer carries a "+". - expect(desc).toContain("• **Novak Djokovic (snarkymcgee)** — 1.50 QP"); + // Mirrors the web UI's formatQP: fractional QP renders with up to 2 decimals and + // trailing zeros trimmed ("1.5"), never rounded to an integer. The Points Awarded + // line no longer carries a "+". + expect(desc).toContain("• **Novak Djokovic (snarkymcgee)** — 1.5 QP"); expect(desc).not.toContain("+"); expect(desc).not.toContain("2 QP"); + expect(desc).not.toContain("1.50"); }); it("excludes participants ranked outside the top 8 from the Drafted Participants section", async () => { diff --git a/app/services/discord.ts b/app/services/discord.ts index 8541820..7db95d4 100644 --- a/app/services/discord.ts +++ b/app/services/discord.ts @@ -66,11 +66,12 @@ function escapeMarkdown(text: string): string { /** * Format a QP value for display. QP is genuinely fractional (e.g. a tennis R16 loser * earns 1.5 QP from the 9–16 split), so we must NOT round: show whole numbers plainly - * and fractional values to 2 decimals. Mirrors the web UI's formatQP - * (app/components/scoring/QualifyingPointsStandings.tsx) so Discord and the site agree. + * and fractional values to at most 2 decimals with trailing zeros trimmed (1.50→1.5). + * Mirrors the web UI's formatQP (app/components/scoring/QualifyingPointsStandings.tsx) + * so Discord and the site agree. */ function formatQPValue(n: number): string { - return n % 1 === 0 ? n.toString() : n.toFixed(2); + return parseFloat(n.toFixed(2)).toString(); } export interface StandingEntry {