diff --git a/index.html b/index.html
index 6a4f757..4078bf7 100644
--- a/index.html
+++ b/index.html
@@ -73,6 +73,7 @@
# |
Player |
ITC Points |
+ LMC Points |
W–L–T |
Win % |
ITC Rank |
diff --git a/src/main.js b/src/main.js
index 15824fd..510cf90 100644
--- a/src/main.js
+++ b/src/main.js
@@ -40,9 +40,10 @@ loadHTML('/footer.html', 'footer');
CONFIG — the only block you edit
============================================================ */
const CONFIG = {
- teamId: "2iGDVMgX0a",
- leagueId: "BYaaUfKum7z0",
- regionId: "VgQKgqmTPU",
+ teamId: "2iGDVMgX0a",
+ leagueId: "BYaaUfKum7z0",
+ regionId: "VgQKgqmTPU",
+ lmcLeagueId: "cY0LeCAPfyiG",
// Fallback roster if the team endpoint requires auth.
memberIds: [],
@@ -156,6 +157,7 @@ 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' },
elo: { key: r => { const e = findElo(fullName(r.user || {}), r.userId || r.user?.id); return e?.elo ?? -Infinity; }, defaultDir: 'desc' },
};
@@ -218,10 +220,31 @@ async function getMemberIds(force) {
}
}
+/* ---- LMC Points data ---- */
+const lmcPoints = {}; // userId → number
+let lmcLoaded = false;
+
+async function loadLmcData(ids) {
+ lmcLoaded = false;
+ try {
+ 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);
+ }
+ }
+ } catch (e) {
+ console.warn('LMC data load failed:', e);
+ } finally {
+ lmcLoaded = true;
+ if (lastState) render(lastState);
+ }
+}
+
/* ---- Standings (cursor-paginated, circular-cursor safe) ---- */
-async function* streamPlacings() {
- const base = `${API}/placings?placingsType=player&leagueId=${CONFIG.leagueId}` +
- `®ionId=${CONFIG.regionId}&sortAscending=false&limit=1000`;
+async function* streamPlacings(leagueId, regionId) {
+ let base = `${API}/placings?placingsType=player&leagueId=${leagueId}&sortAscending=false&limit=1000`;
+ if (regionId) base += `®ionId=${regionId}`;
let nextKey = null;
let prevNextKey = undefined;
@@ -325,8 +348,15 @@ function render(state) {
: `${fmtWpct(d.w, d.l, d.t)} career`;
const mobilePct = `${fmtWpct(r.wins, r.losses, r.ties)} win rate`;
const mobileElo = eloMatch ? `ELO ${Math.round(eloMatch.elo)}` : '';
+ const mobileLmc = (uid && lmcLoaded && lmcPoints[uid] != null) ? `LMC ${fmtPts(lmcPoints[uid])}` : '';
+ const lmcCell = (() => {
+ if (!lmcLoaded) return `… | `;
+ const pts = uid ? lmcPoints[uid] : undefined;
+ return `${pts != null ? fmtPts(pts) : '—'} | `;
+ })();
return `${fmtPts(r.ITCPoints)}` +
- mobilePct + mobileElo + ` | ` +
+ mobilePct + mobileLmc + mobileElo + `` +
+ lmcCell +
`` +
`${r.wins || 0}–${r.losses || 0}–${r.ties || 0}` +
careerSub + ` | ` +
@@ -376,7 +406,11 @@ async function load(force) {
const { ids, live } = await getMemberIds(force);
const allRows = [];
- for await (const page of streamPlacings()) {
+ // Reset and kick off LMC fetch non-blocking
+ Object.keys(lmcPoints).forEach(k => delete lmcPoints[k]);
+ loadLmcData(ids);
+
+ for await (const page of streamPlacings(CONFIG.leagueId, CONFIG.regionId)) {
allRows.push(...page);
// Render incrementally so results appear as pages arrive
const kept = build(allRows, ids);
@@ -403,6 +437,7 @@ function showSkeleton() {
` | ` +
` | ` +
` | ` +
+ ` | ` +
` | ` +
` | ` +
` | ` +