feat: add LMC Rank column alongside LMC Points

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 09:38:04 -05:00
co-authored by Claude Sonnet 4.6
parent f33022fe92
commit d9741062dc
2 changed files with 21 additions and 3 deletions
+1
View File
@@ -74,6 +74,7 @@
<th class="cursor-pointer select-none" data-sort="name">Player</th>
<th class="text-right cursor-pointer select-none" data-sort="pts">ITC Points</th>
<th class="text-right hidden sm:table-cell cursor-pointer select-none" data-sort="lmc">LMC Points</th>
<th class="text-right hidden sm:table-cell cursor-pointer select-none" data-sort="lmcrank">LMC Rank</th>
<th class="text-right hidden sm:table-cell cursor-pointer select-none" data-sort="wlt">WLT</th>
<th class="text-right hidden sm:table-cell cursor-pointer select-none" data-sort="wpct">Win %</th>
<th class="text-right hidden sm:table-cell cursor-pointer select-none" data-sort="rank">ITC Rank</th>
+20 -3
View File
@@ -157,7 +157,8 @@ const sortCols = {
wlt: { key: r => (+r.wins||0) * 10000 - (+r.losses||0) * 100 - (+r.ties||0), defaultDir: 'desc' },
wpct: { key: r => { const g=(+r.wins||0)+(+r.losses||0)+(+r.ties||0); return g?(+r.wins||0)/g:-1; }, defaultDir: 'desc' },
rank: { key: r => +(r.placing || Infinity), defaultDir: 'asc' },
lmc: { key: r => { const uid = r.userId || r.user?.id; return uid && lmcPoints[uid] != null ? lmcPoints[uid] : -Infinity; }, defaultDir: 'desc' },
lmc: { key: r => { const uid = r.userId || r.user?.id; return uid && lmcPoints[uid] != null ? lmcPoints[uid] : -Infinity; }, defaultDir: 'desc' },
lmcrank: { key: r => { const uid = r.userId || r.user?.id; return uid && lmcRanks[uid] != null ? lmcRanks[uid] : Infinity; }, defaultDir: 'asc' },
elo: { key: r => { const e = findElo(fullName(r.user || {}), r.userId || r.user?.id); return e?.elo ?? -Infinity; }, defaultDir: 'desc' },
};
@@ -222,6 +223,7 @@ async function getMemberIds(force) {
/* ---- LMC Points data ---- */
const lmcPoints = {}; // userId → number
const lmcRanks = {}; // userId → number
let lmcLoaded = false;
async function loadLmcData(ids) {
@@ -230,7 +232,10 @@ async function loadLmcData(ids) {
for await (const page of streamPlacings(CONFIG.lmcLeagueId)) {
for (const rec of page) {
const uid = rec.userId || rec.user?.id;
if (uid && ids.has(uid)) lmcPoints[uid] = +(rec.ITCPoints || 0);
if (uid && ids.has(uid)) {
lmcPoints[uid] = +(rec.ITCPoints || 0);
if (rec.placing != null) lmcRanks[uid] = rec.placing;
}
}
}
} catch (e) {
@@ -348,15 +353,25 @@ function render(state) {
: `<span class="block text-xs opacity-40">${fmtWpct(d.w, d.l, d.t)} career</span>`;
const mobilePct = `<span class="block text-xs opacity-40 sm:hidden">${fmtWpct(r.wins, r.losses, r.ties)} win rate</span>`;
const mobileElo = eloMatch ? `<span class="block text-xs opacity-40 sm:hidden">ELO ${Math.round(eloMatch.elo)}</span>` : '';
const mobileLmc = (uid && lmcLoaded && lmcPoints[uid] != null) ? `<span class="block text-xs opacity-40 sm:hidden">LMC ${fmtPts(lmcPoints[uid])}</span>` : '';
const mobileLmc = (() => {
if (!uid || !lmcLoaded || lmcPoints[uid] == null) return '';
const rankStr = lmcRanks[uid] != null ? ` · LMC #${lmcRanks[uid]}` : '';
return `<span class="block text-xs opacity-40 sm:hidden">LMC ${fmtPts(lmcPoints[uid])}${rankStr}</span>`;
})();
const lmcCell = (() => {
if (!lmcLoaded) return `<td class="text-right font-mono hidden sm:table-cell"><span class="opacity-20">…</span></td>`;
const pts = uid ? lmcPoints[uid] : undefined;
return `<td class="text-right font-mono hidden sm:table-cell">${pts != null ? fmtPts(pts) : '<span class="text-base-content/40">—</span>'}</td>`;
})();
const lmcRankCell = (() => {
if (!lmcLoaded) return `<td class="text-right font-mono text-base-content/40 hidden sm:table-cell"><span class="opacity-20">…</span></td>`;
const rank = uid ? lmcRanks[uid] : undefined;
return `<td class="text-right font-mono text-base-content/40 hidden sm:table-cell">${rank != null ? '#' + rank : '—'}</td>`;
})();
return `<td class="text-right font-mono font-bold">${fmtPts(r.ITCPoints)}` +
mobilePct + mobileLmc + mobileElo + `</td>` +
lmcCell +
lmcRankCell +
`<td class="text-right font-mono hidden sm:table-cell">` +
`<span class="text-success">${r.wins || 0}</span><span class="text-error">${r.losses || 0}</span>${r.ties || 0}` +
careerSub + `</td>` +
@@ -408,6 +423,7 @@ async function load(force) {
// Reset and kick off LMC fetch non-blocking
Object.keys(lmcPoints).forEach(k => delete lmcPoints[k]);
Object.keys(lmcRanks).forEach(k => delete lmcRanks[k]);
loadLmcData(ids);
for await (const page of streamPlacings(CONFIG.leagueId, CONFIG.regionId)) {
@@ -438,6 +454,7 @@ function showSkeleton() {
`<td><div class="skeleton h-4 w-3/5"></div><div class="skeleton h-3 w-2/5 mt-1 sm:hidden"></div></td>` +
`<td><div class="skeleton h-4 w-12 ml-auto"></div><div class="skeleton h-3 w-10 mt-1 ml-auto sm:hidden"></div></td>` +
`<td class="hidden sm:table-cell"><div class="skeleton h-4 w-12 ml-auto"></div></td>` +
`<td class="hidden sm:table-cell"><div class="skeleton h-4 w-10 ml-auto"></div></td>` +
`<td class="hidden sm:table-cell"><div class="skeleton h-4 w-14 ml-auto"></div></td>` +
`<td class="hidden sm:table-cell"><div class="skeleton h-4 w-12 ml-auto"></div></td>` +
`<td class="hidden sm:table-cell"><div class="skeleton h-4 w-10 ml-auto"></div></td>` +