chore: hide paused elo and mvp UI

Hide paused MVP/Elo UI from the public historical page and remove server 3 from the frontend selector while preserving backend code and data.
This commit is contained in:
devRaGonSa
2026-05-19 09:57:09 +02:00
committed by GitHub
parent 032aaa9ad5
commit bf3ba630fc
3 changed files with 224 additions and 309 deletions

View File

@@ -0,0 +1,224 @@
---
id: TASK-111
title: Hide paused Elo and MVP ranking UI
status: pending
type: frontend
team: Frontend Senior
supporting_teams: [PM]
roadmap_item: historical-ui
priority: high
---
# TASK-111 - Hide paused Elo and MVP ranking UI
## Goal
Hide paused or experimental Elo/MMR and advanced MVP ranking blocks from the public historical page while preserving stable historical content.
## Context
HLL Vietnam now uses this operational backend policy:
- live data source: RCON
- historical data source: RCON
- public-scoreboard fallback only when RCON historical data fails
- Comunidad Hispana #03 removed from default targets
- Elo/MMR paused and decoupled from backend startup
Manual visual review of `http://localhost:8080/historico.html` shows that the public historical page still displays paused or experimental ranking blocks:
- MVP mensual V1
- MVP mensual V2
- Comparativa V1 vs V2
- Elo/MMR mensual / persistent rating
This contradicts the current product decision. This task is only a public UI/product-scope change. Preserve backend endpoints, historical ingestion, Elo/MMR implementation code, persisted data, snapshots, migrations and schemas.
Use branch:
- `chore/hide-paused-elo-mvp-ui`
## Steps
1. Inspect the listed files first.
2. Hide or remove from the public historical page the paused/experimental UI blocks:
- MVP mensual V1
- MVP mensual V2
- Comparativa V1 vs V2
- Elo/MMR mensual / persistent rating
3. Stop calling the related frontend fetch/render flows for those hidden sections in `historico.js`.
4. Keep normal historical content visible:
- summary/resumen
- weekly/monthly basic historical rankings
- recent matches
- any other non-Elo, non-MVP experimental historical content already considered stable
5. Remove `comunidad-hispana-03` from the frontend historical server selector and JavaScript server list if still present.
6. Preserve backend endpoints and code. Do not delete backend Elo/MMR code, historical ingestion code, endpoints, persisted data, snapshots, migrations or schemas.
7. Prefer a minimal feature-flag-like constant in frontend JavaScript if useful, for example:
`const SHOW_PAUSED_ADVANCED_RANKINGS = false;`
Do not leave visible empty panels.
8. Update text/docs only if necessary to clarify that advanced MVP/Elo ranking UI is paused.
9. Do not add new frameworks or dependencies.
10. Validate the result.
11. Move this task file to `ai/tasks/done/` after validation is complete.
12. Commit and push the completed work to origin. Do not leave completed work only in local.
## Files to Read First
- `frontend/historico.html`
- `frontend/assets/js/historico.js`
- `frontend/assets/css/historico.css`
- `backend/app/payloads.py`
- `README.md`
- `docs/decisions.md`
- `ai/repo-context.md`
- `ai/architecture-index.md`
Rules:
- Read these files before implementation.
- Keep the implementation scoped to public historical UI behavior.
- Do not change backend historical policy.
## Expected Files to Modify
- `frontend/historico.html`
- `frontend/assets/js/historico.js`
- possibly `frontend/assets/css/historico.css`
- possibly `docs/decisions.md`
- possibly `ai/repo-context.md`
- possibly `ai/architecture-index.md`
- `ai/tasks/done/TASK-111-hide-paused-elo-mvp-ui.md`
Rules:
- Prefer modifying only these files.
- If additional files become necessary, explain why in the task outcome and commit message.
- The task file should be moved from `ai/tasks/pending/` to `ai/tasks/done/` only after validation is complete.
## Expected Files Not to Modify
- database migrations
- persisted data
- backend Elo/MMR implementation files
- historical ingestion implementation files
- Docker/Compose configuration
- local `.env`
- unrelated frontend pages
## Constraints
- Keep the change minimal and verifiable.
- Preserve HLL Vietnam project identity: military, Vietnam, tactical, sober.
- Do not implement backend functionality.
- Do not delete backend Elo/MMR code.
- Do not delete historical ingestion code.
- Do not delete endpoints.
- Do not delete persisted data, snapshots, migrations or schemas.
- Do not change backend historical policy.
- Do not reintroduce Comunidad Hispana #03.
- Do not remove normal historical sections such as summary, basic rankings and recent matches.
- Do not introduce unnecessary frameworks or dependencies.
- Do not overwrite repository-specific context with generic platform template text.
- Confirm `backend/runtime/` is not created or committed.
## Validation
Before completing the task:
1. Run `git status`.
2. Run `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`.
3. Run `docker compose down`.
4. Run `docker compose up -d --build`.
5. Run `docker compose ps`.
6. Run `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content`.
7. Run `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode`.
8. Manually verify `http://localhost:8080/historico.html`:
- no visible MVP mensual V1 block
- no visible MVP mensual V2 block
- no visible Comparativa V1 vs V2 block
- no visible Elo/MMR mensual block
- no visible Comunidad Hispana #03 selector
- summary/basic rankings/recent matches still render
9. Confirm no backend Elo/MMR code was deleted.
10. Confirm no migrations or persisted data changed.
11. Confirm `backend/runtime/` is not created or committed.
12. Review `git diff --name-only` and confirm changed files match the expected scope.
## Commit And Push Requirements
1. Run validation before committing.
2. Run `git status`.
3. Stage only intended files.
4. Commit with a clear message, for example:
`chore: hide paused elo and mvp UI`
5. Push the branch to origin.
6. Do not leave completed work only in local.
## Outcome
Completed.
Validation performed:
- Ran `git status`.
- Ran `node --check frontend/assets/js/historico.js`.
- Ran `powershell -ExecutionPolicy Bypass -File scripts/run-integration-tests.ps1`.
- Result: platform validation passed; no product integration tests are configured for this platform-only scope.
- Ran `docker compose down`.
- Ran `docker compose up -d --build`.
- Ran `docker compose ps`.
- Result: `backend` and `frontend` are running.
- Ran `Invoke-WebRequest http://localhost:8000/health | Select-Object -ExpandProperty Content`.
- Result: backend returned `status: ok`, `live_data_source: rcon`, and `historical_data_source: rcon`.
- Ran `Invoke-WebRequest http://localhost:8080 | Select-Object -ExpandProperty StatusCode`.
- Result: `200`.
- Verified served `http://localhost:8080/historico.html` content:
- no visible MVP mensual V1 block
- no visible MVP mensual V2 block
- no visible Comparativa V1 vs V2 block
- no visible Elo/MMR mensual block
- no visible Comunidad Hispana #03 selector
- summary, basic rankings and recent matches markup remains present
- Verified served `frontend/assets/js/historico.js` no longer includes the monthly MVP V1, monthly MVP V2 or Elo/MMR frontend fetch wrappers/endpoints.
- Confirmed no backend Elo/MMR code was deleted.
- Confirmed no migrations or persisted data changed.
- Confirmed `backend/runtime/` was not created or committed.
- Reviewed `git diff --name-only`; changed files are limited to public historical frontend files plus this task file move.
Browser validation note:
- The Browser plugin is available, but its required Node REPL execution tool was not exposed in this session after tool discovery.
- `npx playwright --version` could not be used as a fallback because npm failed with `UNABLE_TO_VERIFY_LEAF_SIGNATURE`.
- The manual visual checklist was therefore validated through the running Docker frontend using served HTML and JavaScript HTTP assertions.
Notable decisions:
- Removed the paused/experimental public UI panels instead of hiding empty shells.
- Disabled the related frontend fetch/render flows by removing their active cache/fetch wiring from `historico.js`.
- Preserved backend endpoints, Elo/MMR implementation code, migrations, persisted data and historical ingestion code.
- Removed `comunidad-hispana-03` from the public historical selector and JavaScript historical server list.
Follow-up:
- No follow-up task is required for this scoped UI pause.
Commit and push:
- Pending at task move time; final commit hash and push result will be reported by the worker after commit/push.
The final worker report must explicitly state:
- which paused/experimental UI blocks were hidden
- whether any related frontend fetch/render flows were disabled
- whether `comunidad-hispana-03` was present and removed from the public historical selector/list
- that normal historical content still renders
- that backend Elo/MMR code, endpoints, migrations and persisted data were preserved
- that `backend/runtime/` was not created or committed
- the commit hash and push result
## Change Budget
- Prefer fewer than 5 modified files.
- Prefer changes under 200 lines when feasible.
- Split the work into follow-up tasks if limits are exceeded.

View File

@@ -7,10 +7,6 @@ const HISTORICAL_SERVERS = Object.freeze([
slug: "comunidad-hispana-02",
label: "Comunidad Hispana #02",
},
{
slug: "comunidad-hispana-03",
label: "Comunidad Hispana #03",
},
{
slug: "all-servers",
label: "Todos",
@@ -93,27 +89,6 @@ document.addEventListener("DOMContentLoaded", () => {
const weeklyStateNode = document.getElementById("weekly-leaderboard-state");
const weeklyTableNode = document.getElementById("weekly-leaderboard-table");
const weeklyBodyNode = document.getElementById("weekly-leaderboard-body");
const monthlyMvpTitleNode = document.getElementById("monthly-mvp-title");
const monthlyMvpStateNode = document.getElementById("monthly-mvp-state");
const monthlyMvpListNode = document.getElementById("monthly-mvp-list");
const monthlyMvpNoteNode = document.getElementById("monthly-mvp-note");
const monthlyMvpSnapshotMetaNode = document.getElementById(
"monthly-mvp-snapshot-meta",
);
const monthlyMvpV2TitleNode = document.getElementById("monthly-mvp-v2-title");
const monthlyMvpV2StateNode = document.getElementById("monthly-mvp-v2-state");
const monthlyMvpV2ListNode = document.getElementById("monthly-mvp-v2-list");
const monthlyMvpV2NoteNode = document.getElementById("monthly-mvp-v2-note");
const monthlyMvpV2SnapshotMetaNode = document.getElementById(
"monthly-mvp-v2-snapshot-meta",
);
const comparisonStateNode = document.getElementById("mvp-comparison-state");
const comparisonListNode = document.getElementById("mvp-comparison-list");
const comparisonNoteNode = document.getElementById("mvp-comparison-note");
const eloMmrStateNode = document.getElementById("elo-mmr-state");
const eloMmrListNode = document.getElementById("elo-mmr-list");
const eloMmrNoteNode = document.getElementById("elo-mmr-note");
const eloMmrMetaNode = document.getElementById("elo-mmr-meta");
const weeklyValueHeadingNode = document.getElementById("weekly-leaderboard-value-heading");
const weeklyWindowNoteNode = document.getElementById("weekly-window-note");
const weeklySnapshotMetaNode = document.getElementById(
@@ -136,12 +111,7 @@ document.addEventListener("DOMContentLoaded", () => {
const summaryCache = new Map();
const recentMatchesCache = new Map();
const leaderboardCache = new Map();
const monthlyMvpCache = new Map();
const monthlyMvpV2Cache = new Map();
const eloMmrCache = new Map();
const pendingRequestCache = new Map();
let latestMonthlyMvpResult = null;
let latestMonthlyMvpV2Result = null;
const getSummarySnapshot = (serverSlug) =>
getCachedJson(
@@ -167,30 +137,6 @@ document.addEventListener("DOMContentLoaded", () => {
`${backendBaseUrl}/api/historical/snapshots/leaderboard?server=${encodeURIComponent(serverSlug)}&timeframe=${encodeURIComponent(timeframeKey)}&metric=${encodeURIComponent(metricKey)}&limit=10`,
);
const getMonthlyMvpSnapshot = (serverSlug) =>
getCachedJson(
monthlyMvpCache,
pendingRequestCache,
buildMonthlyMvpSnapshotKey(serverSlug),
`${backendBaseUrl}/api/historical/snapshots/monthly-mvp?server=${encodeURIComponent(serverSlug)}&limit=3`,
);
const getMonthlyMvpV2Snapshot = (serverSlug) =>
getCachedJson(
monthlyMvpV2Cache,
pendingRequestCache,
buildMonthlyMvpV2SnapshotKey(serverSlug),
`${backendBaseUrl}/api/historical/snapshots/monthly-mvp-v2?server=${encodeURIComponent(serverSlug)}&limit=3`,
);
const getEloMmrLeaderboard = (serverSlug) =>
getCachedJson(
eloMmrCache,
pendingRequestCache,
buildEloMmrSnapshotKey(serverSlug),
`${backendBaseUrl}/api/historical/elo-mmr/leaderboard?server=${encodeURIComponent(serverSlug)}&limit=5`,
);
const refreshServerContent = async () => {
const requestId = activeServerRequestId + 1;
const leaderboardRequestId = activeLeaderboardRequestId + 1;
@@ -218,32 +164,6 @@ document.addEventListener("DOMContentLoaded", () => {
summaryNoteNode.textContent = `La vista esta leyendo snapshots precalculados del historico local para ${activeServerLabel}.`;
setSnapshotMeta(summarySnapshotMetaNode, "Cargando snapshot de resumen...");
renderSummaryLoading(summaryNode);
monthlyMvpTitleNode.textContent = `Top 3 MVP mensual V1 - ${activeServerLabel}`;
monthlyMvpNoteNode.textContent = "Cargando periodo del MVP mensual V1...";
setState(monthlyMvpStateNode, "Cargando Top 3 MVP mensual V1...");
monthlyMvpListNode.innerHTML = "";
setSnapshotMeta(
monthlyMvpSnapshotMetaNode,
"Cargando snapshot del MVP mensual V1...",
);
monthlyMvpV2TitleNode.textContent = `Top 3 MVP mensual V2 - ${activeServerLabel}`;
monthlyMvpV2NoteNode.textContent = "Cargando lectura avanzada del MVP mensual V2...";
setState(monthlyMvpV2StateNode, "Cargando Top 3 MVP mensual V2...");
monthlyMvpV2ListNode.innerHTML = "";
setSnapshotMeta(
monthlyMvpV2SnapshotMetaNode,
"Cargando snapshot del MVP mensual V2...",
);
latestMonthlyMvpResult = null;
latestMonthlyMvpV2Result = null;
comparisonListNode.innerHTML = "";
comparisonNoteNode.textContent =
"Cargando comparativa entre los rankings mensuales V1 y V2...";
setState(comparisonStateNode, "Preparando comparativa V1 vs V2...");
eloMmrListNode.innerHTML = "";
eloMmrNoteNode.textContent = "Cargando lectura del rating persistente y score mensual...";
setState(eloMmrStateNode, "Cargando leaderboard Elo/MMR...");
setSnapshotMeta(eloMmrMetaNode, "Cargando metadata de Elo/MMR...");
weeklyWindowNoteNode.textContent = "Cargando snapshot del ranking activo...";
setSnapshotMeta(
weeklySnapshotMetaNode,
@@ -268,66 +188,6 @@ document.addEventListener("DOMContentLoaded", () => {
);
}
const cachedMonthlyMvpPayload = readCachedPayload(
monthlyMvpCache,
buildMonthlyMvpSnapshotKey(activeServerSlug),
);
if (cachedMonthlyMvpPayload) {
latestMonthlyMvpResult = { status: "fulfilled", value: cachedMonthlyMvpPayload };
hydrateMonthlyMvp(
{ status: "fulfilled", value: cachedMonthlyMvpPayload },
monthlyMvpStateNode,
monthlyMvpListNode,
monthlyMvpTitleNode,
monthlyMvpNoteNode,
monthlyMvpSnapshotMetaNode,
);
hydrateMvpComparison(
latestMonthlyMvpResult,
latestMonthlyMvpV2Result,
comparisonStateNode,
comparisonListNode,
comparisonNoteNode,
);
}
const cachedMonthlyMvpV2Payload = readCachedPayload(
monthlyMvpV2Cache,
buildMonthlyMvpV2SnapshotKey(activeServerSlug),
);
if (cachedMonthlyMvpV2Payload) {
latestMonthlyMvpV2Result = { status: "fulfilled", value: cachedMonthlyMvpV2Payload };
hydrateMonthlyMvpV2(
{ status: "fulfilled", value: cachedMonthlyMvpV2Payload },
monthlyMvpV2StateNode,
monthlyMvpV2ListNode,
monthlyMvpV2TitleNode,
monthlyMvpV2NoteNode,
monthlyMvpV2SnapshotMetaNode,
);
hydrateMvpComparison(
latestMonthlyMvpResult,
latestMonthlyMvpV2Result,
comparisonStateNode,
comparisonListNode,
comparisonNoteNode,
);
}
const cachedEloMmrPayload = readCachedPayload(
eloMmrCache,
buildEloMmrSnapshotKey(activeServerSlug),
);
if (cachedEloMmrPayload) {
hydrateEloMmr(
{ status: "fulfilled", value: cachedEloMmrPayload },
eloMmrStateNode,
eloMmrListNode,
eloMmrNoteNode,
eloMmrMetaNode,
);
}
const cachedLeaderboardPayload = readCachedPayload(
leaderboardCache,
buildLeaderboardSnapshotKey(
@@ -443,86 +303,6 @@ document.addEventListener("DOMContentLoaded", () => {
);
});
void settlePromise(getMonthlyMvpSnapshot(targetServerSlug)).then((monthlyMvpResult) => {
if (
!isActiveServerRequest(
requestId,
targetServerSlug,
targetTimeframe,
targetMetric,
)
) {
return;
}
latestMonthlyMvpResult = monthlyMvpResult;
hydrateMonthlyMvp(
monthlyMvpResult,
monthlyMvpStateNode,
monthlyMvpListNode,
monthlyMvpTitleNode,
monthlyMvpNoteNode,
monthlyMvpSnapshotMetaNode,
);
hydrateMvpComparison(
latestMonthlyMvpResult,
latestMonthlyMvpV2Result,
comparisonStateNode,
comparisonListNode,
comparisonNoteNode,
);
});
void settlePromise(getMonthlyMvpV2Snapshot(targetServerSlug)).then((monthlyMvpV2Result) => {
if (
!isActiveServerRequest(
requestId,
targetServerSlug,
targetTimeframe,
targetMetric,
)
) {
return;
}
latestMonthlyMvpV2Result = monthlyMvpV2Result;
hydrateMonthlyMvpV2(
monthlyMvpV2Result,
monthlyMvpV2StateNode,
monthlyMvpV2ListNode,
monthlyMvpV2TitleNode,
monthlyMvpV2NoteNode,
monthlyMvpV2SnapshotMetaNode,
);
hydrateMvpComparison(
latestMonthlyMvpResult,
latestMonthlyMvpV2Result,
comparisonStateNode,
comparisonListNode,
comparisonNoteNode,
);
});
void settlePromise(getEloMmrLeaderboard(targetServerSlug)).then((eloMmrResult) => {
if (
!isActiveServerRequest(
requestId,
targetServerSlug,
targetTimeframe,
targetMetric,
)
) {
return;
}
hydrateEloMmr(
eloMmrResult,
eloMmrStateNode,
eloMmrListNode,
eloMmrNoteNode,
eloMmrMetaNode,
);
});
};
const refreshLeaderboardContent = async () => {

View File

@@ -66,14 +66,6 @@
>
Comunidad Hispana #02
</button>
<button
class="historical-selector__button"
type="button"
data-server-slug="comunidad-hispana-03"
>
Comunidad Hispana #03
</button>
</div>
</div>
</div>
@@ -107,87 +99,6 @@
</div>
</section>
<section class="panel historical-panel" aria-labelledby="monthly-mvp-title">
<div class="panel__shell">
<div class="panel__header historical-panel__header">
<div>
<p class="eyebrow eyebrow--section">MVP mensual V1</p>
<h2 id="monthly-mvp-title">Top 3 V1 del alcance activo</h2>
<p class="historical-panel__note" id="monthly-mvp-note">
Cargando baseline del MVP mensual V1...
</p>
<p class="historical-snapshot-meta" id="monthly-mvp-snapshot-meta">
Cargando snapshot del MVP mensual V1...
</p>
</div>
</div>
<p class="historical-state" id="monthly-mvp-state" aria-live="polite">
Cargando Top 3 MVP mensual V1...
</p>
<div class="historical-mvp-grid" id="monthly-mvp-list"></div>
</div>
</section>
<section class="panel historical-panel" aria-labelledby="monthly-mvp-v2-title">
<div class="panel__shell">
<div class="panel__header historical-panel__header">
<div>
<p class="eyebrow eyebrow--section">MVP mensual V2</p>
<h2 id="monthly-mvp-v2-title">Top 3 V2 del alcance activo</h2>
<p class="historical-panel__note" id="monthly-mvp-v2-note">
Cargando lectura avanzada del MVP mensual V2...
</p>
<p class="historical-snapshot-meta" id="monthly-mvp-v2-snapshot-meta">
Cargando snapshot del MVP mensual V2...
</p>
</div>
</div>
<p class="historical-state" id="monthly-mvp-v2-state" aria-live="polite">
Cargando Top 3 MVP mensual V2...
</p>
<div class="historical-mvp-grid" id="monthly-mvp-v2-list"></div>
</div>
</section>
<section class="panel historical-panel" aria-labelledby="mvp-comparison-title">
<div class="panel__shell">
<div class="panel__header historical-panel__header">
<div>
<p class="eyebrow eyebrow--section">Comparativa V1 vs V2</p>
<h2 id="mvp-comparison-title">Lectura de validacion del alcance activo</h2>
<p class="historical-panel__note" id="mvp-comparison-note">
Cargando comparativa entre los rankings mensuales V1 y V2...
</p>
</div>
</div>
<p class="historical-state" id="mvp-comparison-state" aria-live="polite">
Preparando comparativa V1 vs V2...
</p>
<div class="historical-comparison-grid" id="mvp-comparison-list"></div>
</div>
</section>
<section class="panel historical-panel" aria-labelledby="elo-mmr-title">
<div class="panel__shell">
<div class="panel__header historical-panel__header">
<div>
<p class="eyebrow eyebrow--section">Elo/MMR mensual</p>
<h2 id="elo-mmr-title">Rating persistente y ranking mensual del alcance activo</h2>
<p class="historical-panel__note" id="elo-mmr-note">
Cargando sistema mensual de rating...
</p>
<p class="historical-snapshot-meta" id="elo-mmr-meta">
Cargando metadata de Elo/MMR...
</p>
</div>
</div>
<p class="historical-state" id="elo-mmr-state" aria-live="polite">
Cargando leaderboard Elo/MMR...
</p>
<div class="historical-elo-grid" id="elo-mmr-list"></div>
</div>
</section>
<section class="panel historical-panel" aria-labelledby="weekly-ranking-title">
<div class="panel__shell">
<div class="panel__header historical-panel__header">