diff --git a/frontend/src/components/Arena.tsx b/frontend/src/components/Arena.tsx
index 7926ad1..91cc7ee 100644
--- a/frontend/src/components/Arena.tsx
+++ b/frontend/src/components/Arena.tsx
@@ -1,5 +1,5 @@
import { useEffect, useMemo, useState } from "react";
-import { outcomeLabel, pct, kickoffDisplay, winProb } from "@/lib/format";
+import { outcomeLabel, pctParts, kickoffDisplay, winProb } from "@/lib/format";
import { type Lang, dict, teamShort } from "@/lib/i18n";
import type {
Outcome,
@@ -542,15 +542,15 @@ export default function Arena({
Crowd Pick{" "}
{t.crowdSub}
- {/* 비율은 분포 합 기준(=total 과 동일해야 정상) — 구 데이터 불일치 시에도 100% 이내로 표시 */}
+ {/* 비율은 분포 합 기준 + 합이 항상 100% 되도록 보정(최대 잔여 방식) */}
{(() => {
- const sum = crowd.teamAWin + crowd.draw + crowd.teamBWin;
+ const [a, d, b] = pctParts([crowd.teamAWin, crowd.draw, crowd.teamBWin]);
return (
<>
-
-
-
+
+
+
>
);
})()}
diff --git a/frontend/src/lib/format.ts b/frontend/src/lib/format.ts
index 00911b8..0714526 100644
--- a/frontend/src/lib/format.ts
+++ b/frontend/src/lib/format.ts
@@ -55,6 +55,27 @@ export function pct(part: number, total: number): number {
return Math.round((part / total) * 100);
}
+// 여러 비율을 정수 %로 — 합이 항상 정확히 100 (최대 잔여 방식).
+// 각자 따로 반올림하면 99/101 이 나오는 문제를 방지.
+export function pctParts(parts: number[]): number[] {
+ const total = parts.reduce((s, p) => s + p, 0);
+ if (!total) return parts.map(() => 0);
+ const raw = parts.map((p) => (p / total) * 100);
+ const floor = raw.map(Math.floor);
+ let remainder = 100 - floor.reduce((s, v) => s + v, 0);
+ // 소수부가 큰 순서로 남은 %를 1씩 분배
+ const order = raw
+ .map((v, i) => ({ i, frac: v - Math.floor(v) }))
+ .sort((a, b) => b.frac - a.frac);
+ const out = [...floor];
+ for (const { i } of order) {
+ if (remainder <= 0) break;
+ out[i] += 1;
+ remainder -= 1;
+ }
+ return out;
+}
+
// "방금 전 / 3분 전 / 2시간 전 / 5일 전" — 댓글 상대시간
export function relativeTime(iso: string, lang: Lang = "ko"): string {
const then = new Date(iso).getTime();