Fix historical leaderboard labels, stats ranking table uniformity and publish Steam icon
This commit is contained in:
@@ -0,0 +1,113 @@
|
|||||||
|
# TASK-250 - Fix historical ranking labels, table uniformity and Steam icon
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
This task fixes public labels that were still misleading in historical leaderboards, aligns the visible column order and wording between Stats and Ranking, and audits the Steam brand icon path used by external profiles.
|
||||||
|
|
||||||
|
## Files Read First
|
||||||
|
|
||||||
|
- `frontend/historico.html`
|
||||||
|
- `frontend/assets/js/historico.js`
|
||||||
|
- `frontend/ranking.html`
|
||||||
|
- `frontend/assets/js/ranking.js`
|
||||||
|
- `frontend/assets/js/stats.js`
|
||||||
|
- `frontend/assets/js/historico-partida.js`
|
||||||
|
|
||||||
|
## Historical Leaderboards
|
||||||
|
|
||||||
|
The weekly/monthly leaderboard table now adapts its ratio column to the active metric:
|
||||||
|
|
||||||
|
- `kills` -> `Kills/partida`
|
||||||
|
- `deaths` -> `Muertes/partida`
|
||||||
|
- `support` -> `Soporte/partida`
|
||||||
|
- `matches_over_100_kills` -> ratio column hidden
|
||||||
|
|
||||||
|
This removes the incorrect `Kills/partida` label from:
|
||||||
|
|
||||||
|
- Top muertes
|
||||||
|
- Top soporte
|
||||||
|
- Partidas 100+ kills
|
||||||
|
|
||||||
|
No aggregated real KPM was added in this task.
|
||||||
|
|
||||||
|
## Stats / Ranking Uniformity
|
||||||
|
|
||||||
|
Visible labels were normalized to Spanish or accepted abbreviations:
|
||||||
|
|
||||||
|
- `Deaths` -> `Muertes`
|
||||||
|
- `Teamkills` -> `TK`
|
||||||
|
- `matches_considered` -> `Partidas`
|
||||||
|
- `kd_ratio` -> `KD`
|
||||||
|
- `kills_per_match` -> `Kills/partida`
|
||||||
|
|
||||||
|
Shared player ranking column order now stays consistent:
|
||||||
|
|
||||||
|
- `Pos.`
|
||||||
|
- `Jugador`
|
||||||
|
- `Partidas`
|
||||||
|
- `Kills`
|
||||||
|
- `Muertes`
|
||||||
|
- `TK`
|
||||||
|
- `KD`
|
||||||
|
- `Kills/partida`
|
||||||
|
|
||||||
|
`ranking.html` keeps its extra `Valor activo` column before the shared block because that table is metric-driven.
|
||||||
|
|
||||||
|
## Steam Icon Audit
|
||||||
|
|
||||||
|
The code path in `historico-partida.js` is already correct:
|
||||||
|
|
||||||
|
- `./assets/img/brands/steam.png`
|
||||||
|
|
||||||
|
The local file also exists:
|
||||||
|
|
||||||
|
- `frontend/assets/img/brands/steam.png`
|
||||||
|
|
||||||
|
It is currently untracked in git:
|
||||||
|
|
||||||
|
- `git status --short --untracked-files=all -- frontend/assets/img/brands`
|
||||||
|
- `?? frontend/assets/img/brands/steam.png`
|
||||||
|
|
||||||
|
Production currently returns:
|
||||||
|
|
||||||
|
- `https://comunidadhll.devzamode.es/assets/img/brands/steam.png` -> `404`
|
||||||
|
|
||||||
|
So the remaining issue is deployment scope, not the frontend path.
|
||||||
|
|
||||||
|
The defensive `onerror` behavior remains in place.
|
||||||
|
|
||||||
|
Because this exact local asset exists and is the only Steam brand asset detected in:
|
||||||
|
|
||||||
|
- `frontend/assets/img/brands/`
|
||||||
|
- `frontend/assets/img/`
|
||||||
|
- `frontend/assets/`
|
||||||
|
|
||||||
|
it is the one asset that should be included with the TASK-250 frontend commit if the goal is to make the icon visible in production.
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
Executed:
|
||||||
|
|
||||||
|
- `node --check frontend/assets/js/historico.js`
|
||||||
|
- `node --check frontend/assets/js/stats.js`
|
||||||
|
- `node --check frontend/assets/js/ranking.js`
|
||||||
|
|
||||||
|
Static validation performed:
|
||||||
|
|
||||||
|
- no visible `Deaths` label remains in Stats / Ranking tables or selects
|
||||||
|
- no visible `Teamkills` label remains in Stats / Ranking tables or selects
|
||||||
|
- `Kills/partida` no longer appears for Top muertes, Top soporte or Partidas 100+ kills
|
||||||
|
- Top muertes now uses `Muertes/partida`
|
||||||
|
- Stats and Ranking keep the same relative order for shared columns
|
||||||
|
|
||||||
|
Operational validation performed:
|
||||||
|
|
||||||
|
- production Steam icon URL returns `404`
|
||||||
|
- local `frontend/assets/img/brands/steam.png` exists but is not tracked
|
||||||
|
- no alternate local Steam asset name or extension was detected
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- No backend changes were required.
|
||||||
|
- No map, weapon or clan asset was modified.
|
||||||
|
- To fully fix the Steam icon in production, the existing local `steam.png` must be included in a later isolated commit.
|
||||||
BIN
frontend/assets/img/brands/steam.png
Normal file
BIN
frontend/assets/img/brands/steam.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 284 KiB |
@@ -45,24 +45,32 @@ const LEADERBOARD_METRICS = Object.freeze([
|
|||||||
key: "kills",
|
key: "kills",
|
||||||
title: "Top kills",
|
title: "Top kills",
|
||||||
valueHeading: "Kills",
|
valueHeading: "Kills",
|
||||||
|
ratioHeading: "Kills/partida",
|
||||||
|
ratioMode: "kills",
|
||||||
emptyMessage: "Sin datos historicos suficientes para mostrar este ranking de kills.",
|
emptyMessage: "Sin datos historicos suficientes para mostrar este ranking de kills.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "deaths",
|
key: "deaths",
|
||||||
title: "Top muertes",
|
title: "Top muertes",
|
||||||
valueHeading: "Muertes",
|
valueHeading: "Muertes",
|
||||||
|
ratioHeading: "Muertes/partida",
|
||||||
|
ratioMode: "deaths",
|
||||||
emptyMessage: "Sin datos historicos suficientes para mostrar este ranking de muertes.",
|
emptyMessage: "Sin datos historicos suficientes para mostrar este ranking de muertes.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "matches_over_100_kills",
|
key: "matches_over_100_kills",
|
||||||
title: "Top partidas con 100+ kills",
|
title: "Top partidas con 100+ kills",
|
||||||
valueHeading: "Partidas 100+",
|
valueHeading: "Partidas 100+",
|
||||||
|
ratioHeading: null,
|
||||||
|
ratioMode: null,
|
||||||
emptyMessage: "Ningun jugador ha registrado partidas de 100+ kills en esta ventana.",
|
emptyMessage: "Ningun jugador ha registrado partidas de 100+ kills en esta ventana.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "support",
|
key: "support",
|
||||||
title: "Top puntos de soporte",
|
title: "Top puntos de soporte",
|
||||||
valueHeading: "Soporte",
|
valueHeading: "Soporte",
|
||||||
|
ratioHeading: "Soporte/partida",
|
||||||
|
ratioMode: "support",
|
||||||
emptyMessage: "Sin datos historicos suficientes para mostrar este ranking de soporte.",
|
emptyMessage: "Sin datos historicos suficientes para mostrar este ranking de soporte.",
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@@ -94,6 +102,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
const weeklyTableNode = document.getElementById("weekly-leaderboard-table");
|
const weeklyTableNode = document.getElementById("weekly-leaderboard-table");
|
||||||
const weeklyBodyNode = document.getElementById("weekly-leaderboard-body");
|
const weeklyBodyNode = document.getElementById("weekly-leaderboard-body");
|
||||||
const weeklyValueHeadingNode = document.getElementById("weekly-leaderboard-value-heading");
|
const weeklyValueHeadingNode = document.getElementById("weekly-leaderboard-value-heading");
|
||||||
|
const weeklyRatioHeadingNode = document.getElementById("weekly-leaderboard-ratio-heading");
|
||||||
const weeklyWindowNoteNode = document.getElementById("weekly-window-note");
|
const weeklyWindowNoteNode = document.getElementById("weekly-window-note");
|
||||||
const weeklySnapshotMetaNode = document.getElementById(
|
const weeklySnapshotMetaNode = document.getElementById(
|
||||||
"weekly-leaderboard-snapshot-meta",
|
"weekly-leaderboard-snapshot-meta",
|
||||||
@@ -210,6 +219,7 @@ document.addEventListener("DOMContentLoaded", () => {
|
|||||||
weeklyBodyNode,
|
weeklyBodyNode,
|
||||||
weeklyTitleNode,
|
weeklyTitleNode,
|
||||||
weeklyValueHeadingNode,
|
weeklyValueHeadingNode,
|
||||||
|
weeklyRatioHeadingNode,
|
||||||
weeklyWindowNoteNode,
|
weeklyWindowNoteNode,
|
||||||
weeklySnapshotMetaNode,
|
weeklySnapshotMetaNode,
|
||||||
activeMetricConfig,
|
activeMetricConfig,
|
||||||
@@ -547,6 +557,7 @@ function hydrateWeeklyLeaderboard(
|
|||||||
bodyNode,
|
bodyNode,
|
||||||
titleNode,
|
titleNode,
|
||||||
valueHeadingNode,
|
valueHeadingNode,
|
||||||
|
ratioHeadingNode,
|
||||||
noteNode,
|
noteNode,
|
||||||
snapshotMetaNode,
|
snapshotMetaNode,
|
||||||
metricConfig,
|
metricConfig,
|
||||||
@@ -555,6 +566,7 @@ function hydrateWeeklyLeaderboard(
|
|||||||
const targetServerSlug = result.value?.data?.server_slug || activeServerSlug;
|
const targetServerSlug = result.value?.data?.server_slug || activeServerSlug;
|
||||||
const resolvedTimeframeKey = result.value?.data?.timeframe || timeframeKey;
|
const resolvedTimeframeKey = result.value?.data?.timeframe || timeframeKey;
|
||||||
valueHeadingNode.textContent = metricConfig.valueHeading;
|
valueHeadingNode.textContent = metricConfig.valueHeading;
|
||||||
|
syncLeaderboardRatioColumn(tableNode, ratioHeadingNode, bodyNode, metricConfig);
|
||||||
if (result.status !== "fulfilled") {
|
if (result.status !== "fulfilled") {
|
||||||
titleNode.textContent = buildLeaderboardTitle(
|
titleNode.textContent = buildLeaderboardTitle(
|
||||||
metricConfig,
|
metricConfig,
|
||||||
@@ -614,13 +626,11 @@ function hydrateWeeklyLeaderboard(
|
|||||||
bodyNode.innerHTML = items
|
bodyNode.innerHTML = items
|
||||||
.map(
|
.map(
|
||||||
(item) => {
|
(item) => {
|
||||||
const kills = resolveHistoricalKills(item, metricConfig);
|
|
||||||
const matches = Number(item.matches_considered);
|
const matches = Number(item.matches_considered);
|
||||||
const killsPerMatch = formatHistoricalKillsPerMatch(
|
const ratioValue = formatHistoricalRatio(item, metricConfig, matches);
|
||||||
item?.kills_per_match,
|
const ratioCell = metricConfig.ratioMode
|
||||||
kills,
|
? `<td>${escapeHtml(ratioValue)}</td>`
|
||||||
matches,
|
: "";
|
||||||
);
|
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<tr>
|
<tr>
|
||||||
@@ -628,13 +638,14 @@ function hydrateWeeklyLeaderboard(
|
|||||||
<td>${escapeHtml(item.player?.name || "Jugador no identificado")}</td>
|
<td>${escapeHtml(item.player?.name || "Jugador no identificado")}</td>
|
||||||
<td>${escapeHtml(formatNumber(item.metric_value))}</td>
|
<td>${escapeHtml(formatNumber(item.metric_value))}</td>
|
||||||
<td>${escapeHtml(formatNumber(item.matches_considered))}</td>
|
<td>${escapeHtml(formatNumber(item.matches_considered))}</td>
|
||||||
<td>${escapeHtml(killsPerMatch)}</td>
|
${ratioCell}
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.join("");
|
.join("");
|
||||||
stateNode.hidden = true;
|
stateNode.hidden = true;
|
||||||
|
syncLeaderboardRatioColumn(tableNode, ratioHeadingNode, bodyNode, metricConfig);
|
||||||
tableNode.hidden = false;
|
tableNode.hidden = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1724,13 +1735,43 @@ function resolveHistoricalKills(item, metricConfig) {
|
|||||||
return Number.NaN;
|
return Number.NaN;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatHistoricalKillsPerMatch(rawKillsPerMatch, rawKills, rawMatches) {
|
function syncLeaderboardRatioColumn(tableNode, ratioHeadingNode, bodyNode, metricConfig) {
|
||||||
const directValue = Number(rawKillsPerMatch);
|
if (!tableNode || !ratioHeadingNode || !bodyNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const showRatio = Boolean(metricConfig?.ratioMode);
|
||||||
|
ratioHeadingNode.hidden = !showRatio;
|
||||||
|
ratioHeadingNode.textContent = metricConfig?.ratioHeading || "";
|
||||||
|
const ratioColumnIndex = ratioHeadingNode.cellIndex;
|
||||||
|
bodyNode.querySelectorAll("tr").forEach((row) => {
|
||||||
|
const ratioCell = row.children[ratioColumnIndex];
|
||||||
|
if (ratioCell) {
|
||||||
|
ratioCell.hidden = !showRatio;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatHistoricalRatio(item, metricConfig, matches) {
|
||||||
|
if (!metricConfig?.ratioMode) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (metricConfig.ratioMode === "kills") {
|
||||||
|
const kills = resolveHistoricalKills(item, metricConfig);
|
||||||
|
return formatHistoricalPerMatch(item?.kills_per_match, kills, matches);
|
||||||
|
}
|
||||||
|
if (metricConfig.ratioMode === "deaths" || metricConfig.ratioMode === "support") {
|
||||||
|
return formatHistoricalPerMatch(null, Number(item?.metric_value), matches);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatHistoricalPerMatch(rawDirectValue, rawTotalValue, rawMatches) {
|
||||||
|
const directValue = Number(rawDirectValue);
|
||||||
if (Number.isFinite(directValue)) {
|
if (Number.isFinite(directValue)) {
|
||||||
return formatDecimal(directValue, 2);
|
return formatDecimal(directValue, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
const kills = Number(rawKills);
|
const kills = Number(rawTotalValue);
|
||||||
const matches = Number(rawMatches);
|
const matches = Number(rawMatches);
|
||||||
if (!Number.isFinite(kills) || !Number.isFinite(matches) || matches <= 0) {
|
if (!Number.isFinite(kills) || !Number.isFinite(matches) || matches <= 0) {
|
||||||
return "-";
|
return "-";
|
||||||
|
|||||||
@@ -271,7 +271,7 @@
|
|||||||
if (statusCode === 400 && normalizedMessage.includes("metric")) {
|
if (statusCode === 400 && normalizedMessage.includes("metric")) {
|
||||||
setRankingState("warning", "La m\u00e9trica solicitada no est\u00e1 soportada.");
|
setRankingState("warning", "La m\u00e9trica solicitada no est\u00e1 soportada.");
|
||||||
renderEmptyState(
|
renderEmptyState(
|
||||||
"Usa kills, deaths, teamkills, partidas jugadas, K/D o Kills/partida.",
|
"Usa Kills, Muertes, TK, Partidas, KD o Kills/partida.",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -397,10 +397,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="ranking-table__metric">${formatMetricValue(item.metric_value, metric)}</td>
|
<td class="ranking-table__metric">${formatMetricValue(item.metric_value, metric)}</td>
|
||||||
|
<td>${safeInt(item.matches_considered, 0)}</td>
|
||||||
<td>${safeInt(item.kills, 0)}</td>
|
<td>${safeInt(item.kills, 0)}</td>
|
||||||
<td>${safeInt(item.deaths, 0)}</td>
|
<td>${safeInt(item.deaths, 0)}</td>
|
||||||
<td>${safeInt(item.teamkills, 0)}</td>
|
<td>${safeInt(item.teamkills, 0)}</td>
|
||||||
<td>${safeInt(item.matches_considered, 0)}</td>
|
|
||||||
<td>${safeDecimal(item.kd_ratio, 2, "0.00")}</td>
|
<td>${safeDecimal(item.kd_ratio, 2, "0.00")}</td>
|
||||||
${hideKppColumn ? "" : `<td>${killsPerMatch}</td>`}
|
${hideKppColumn ? "" : `<td>${killsPerMatch}</td>`}
|
||||||
</tr>
|
</tr>
|
||||||
@@ -454,10 +454,10 @@
|
|||||||
function labelForMetric(metric) {
|
function labelForMetric(metric) {
|
||||||
const labels = {
|
const labels = {
|
||||||
kills: "Kills",
|
kills: "Kills",
|
||||||
deaths: "Deaths",
|
deaths: "Muertes",
|
||||||
teamkills: "Teamkills",
|
teamkills: "TK",
|
||||||
matches_considered: "Partidas jugadas",
|
matches_considered: "Partidas",
|
||||||
kd_ratio: "K/D",
|
kd_ratio: "KD",
|
||||||
kills_per_match: "Kills/partida",
|
kills_per_match: "Kills/partida",
|
||||||
};
|
};
|
||||||
return labels[metric] || "Kills";
|
return labels[metric] || "Kills";
|
||||||
|
|||||||
@@ -359,8 +359,8 @@
|
|||||||
.map((item) => {
|
.map((item) => {
|
||||||
const rank = safeInt(item.ranking_position, 0);
|
const rank = safeInt(item.ranking_position, 0);
|
||||||
const playerName = escapeHtml(String(item.player_name || "Jugador sin nombre"));
|
const playerName = escapeHtml(String(item.player_name || "Jugador sin nombre"));
|
||||||
const kills = safeInt(firstFiniteValue(item.kills, item.metric_value), 0);
|
|
||||||
const matches = safeInt(item.matches_considered, 0);
|
const matches = safeInt(item.matches_considered, 0);
|
||||||
|
const kills = safeInt(firstFiniteValue(item.kills, item.metric_value), 0);
|
||||||
const killsPerMatch = formatKillsPerMatch(
|
const killsPerMatch = formatKillsPerMatch(
|
||||||
item.kills_per_match,
|
item.kills_per_match,
|
||||||
kills,
|
kills,
|
||||||
@@ -378,12 +378,12 @@
|
|||||||
<strong>${playerName}</strong>
|
<strong>${playerName}</strong>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="stats-annual-metric">${kills}</td>
|
|
||||||
<td>${matches}</td>
|
<td>${matches}</td>
|
||||||
<td>${killsPerMatch}</td>
|
<td class="stats-annual-metric">${kills}</td>
|
||||||
<td>${deaths}</td>
|
<td>${deaths}</td>
|
||||||
<td>${teamkills}</td>
|
<td>${teamkills}</td>
|
||||||
<td>${kd}</td>
|
<td>${kd}</td>
|
||||||
|
<td>${killsPerMatch}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`;
|
||||||
})
|
})
|
||||||
@@ -396,12 +396,12 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<th>Posici\u00f3n</th>
|
<th>Posici\u00f3n</th>
|
||||||
<th>Jugador</th>
|
<th>Jugador</th>
|
||||||
<th>Kills</th>
|
|
||||||
<th>Partidas</th>
|
<th>Partidas</th>
|
||||||
<th>Kills/partida</th>
|
<th>Kills</th>
|
||||||
<th>Muertes</th>
|
<th>Muertes</th>
|
||||||
<th>Teamkills</th>
|
<th>TK</th>
|
||||||
<th>K/D</th>
|
<th>KD</th>
|
||||||
|
<th>Kills/partida</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>${rowsMarkup}</tbody>
|
<tbody>${rowsMarkup}</tbody>
|
||||||
@@ -574,8 +574,8 @@
|
|||||||
<article class="stats-summary-card">
|
<article class="stats-summary-card">
|
||||||
<p class="stats-summary-title">Ventana semanal</p>
|
<p class="stats-summary-title">Ventana semanal</p>
|
||||||
<p><strong>Kills:</strong> ${safeInt(weeklyData?.kills, 0)}</p>
|
<p><strong>Kills:</strong> ${safeInt(weeklyData?.kills, 0)}</p>
|
||||||
<p><strong>Deaths:</strong> ${safeInt(weeklyData?.deaths, 0)}</p>
|
<p><strong>Muertes:</strong> ${safeInt(weeklyData?.deaths, 0)}</p>
|
||||||
<p><strong>Teamkills:</strong> ${safeInt(weeklyData?.teamkills, 0)}</p>
|
<p><strong>TK:</strong> ${safeInt(weeklyData?.teamkills, 0)}</p>
|
||||||
</article>
|
</article>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -590,8 +590,8 @@
|
|||||||
<article class="stats-summary-card">
|
<article class="stats-summary-card">
|
||||||
<p class="stats-summary-title">Ventana mensual</p>
|
<p class="stats-summary-title">Ventana mensual</p>
|
||||||
<p><strong>Kills:</strong> ${safeInt(monthlyData?.kills, 0)}</p>
|
<p><strong>Kills:</strong> ${safeInt(monthlyData?.kills, 0)}</p>
|
||||||
<p><strong>Deaths:</strong> ${safeInt(monthlyData?.deaths, 0)}</p>
|
<p><strong>Muertes:</strong> ${safeInt(monthlyData?.deaths, 0)}</p>
|
||||||
<p><strong>Teamkills:</strong> ${safeInt(monthlyData?.teamkills, 0)}</p>
|
<p><strong>TK:</strong> ${safeInt(monthlyData?.teamkills, 0)}</p>
|
||||||
</article>
|
</article>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -697,16 +697,16 @@
|
|||||||
<span class="stats-comparison-card__metric-value">${kills}</span>
|
<span class="stats-comparison-card__metric-value">${kills}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="stats-comparison-card__metric">
|
<div class="stats-comparison-card__metric">
|
||||||
<span class="stats-comparison-card__metric-label">Deaths</span>
|
<span class="stats-comparison-card__metric-label">Muertes</span>
|
||||||
<span class="stats-comparison-card__metric-value">${deaths}</span>
|
<span class="stats-comparison-card__metric-value">${deaths}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="stats-comparison-card__metric">
|
<div class="stats-comparison-card__metric">
|
||||||
<span class="stats-comparison-card__metric-label">K/D</span>
|
<span class="stats-comparison-card__metric-label">KD</span>
|
||||||
<span class="stats-comparison-card__metric-value">${kdRatio}</span>
|
<span class="stats-comparison-card__metric-value">${kdRatio}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="stats-comparison-card__detail">
|
<p class="stats-comparison-card__detail">
|
||||||
<strong>Kills por partida:</strong> ${killsPerMatch}
|
<strong>Kills/partida:</strong> ${killsPerMatch}
|
||||||
</p>
|
</p>
|
||||||
<p class="stats-comparison-card__note">${escapeHtml(rankingState.detail)}</p>
|
<p class="stats-comparison-card__note">${escapeHtml(rankingState.detail)}</p>
|
||||||
</article>
|
</article>
|
||||||
@@ -739,11 +739,11 @@
|
|||||||
<span class="stats-comparison-card__metric-value">${safeDecimal(monthlyKillsPerMatch, 2, "0.00")}</span>
|
<span class="stats-comparison-card__metric-value">${safeDecimal(monthlyKillsPerMatch, 2, "0.00")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="stats-comparison-card__metric">
|
<div class="stats-comparison-card__metric">
|
||||||
<span class="stats-comparison-card__metric-label">K/D semanal</span>
|
<span class="stats-comparison-card__metric-label">KD semanal</span>
|
||||||
<span class="stats-comparison-card__metric-value">${safeDecimal(weeklyKd, 2, "0.00")}</span>
|
<span class="stats-comparison-card__metric-value">${safeDecimal(weeklyKd, 2, "0.00")}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="stats-comparison-card__metric">
|
<div class="stats-comparison-card__metric">
|
||||||
<span class="stats-comparison-card__metric-label">K/D mensual</span>
|
<span class="stats-comparison-card__metric-label">KD mensual</span>
|
||||||
<span class="stats-comparison-card__metric-value">${safeDecimal(monthlyKd, 2, "0.00")}</span>
|
<span class="stats-comparison-card__metric-value">${safeDecimal(monthlyKd, 2, "0.00")}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -775,7 +775,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const rank = safeInt(ranking.ranking_position, 0);
|
const rank = safeInt(ranking.ranking_position, 0);
|
||||||
const metric = escapeHtml(String(ranking.metric || annualMetric));
|
const metric = escapeHtml(labelForStatsMetric(ranking.metric || annualMetric));
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<p><strong>Posici\u00f3n:</strong> ${rank}</p>
|
<p><strong>Posici\u00f3n:</strong> ${rank}</p>
|
||||||
@@ -863,6 +863,18 @@
|
|||||||
return `Ventana: ${windowStart} - ${windowEnd}`;
|
return `Ventana: ${windowStart} - ${windowEnd}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function labelForStatsMetric(metric) {
|
||||||
|
const labels = {
|
||||||
|
kills: "Kills",
|
||||||
|
deaths: "Muertes",
|
||||||
|
teamkills: "TK",
|
||||||
|
matches_considered: "Partidas",
|
||||||
|
kd_ratio: "KD",
|
||||||
|
kills_per_match: "Kills/partida",
|
||||||
|
};
|
||||||
|
return labels[String(metric || "").trim()] || "Kills";
|
||||||
|
}
|
||||||
|
|
||||||
function safeInt(value, fallback = 0) {
|
function safeInt(value, fallback = 0) {
|
||||||
const parsed = Number(value);
|
const parsed = Number(value);
|
||||||
if (!Number.isFinite(parsed)) {
|
if (!Number.isFinite(parsed)) {
|
||||||
|
|||||||
@@ -199,7 +199,7 @@
|
|||||||
<th>Jugador</th>
|
<th>Jugador</th>
|
||||||
<th id="weekly-leaderboard-value-heading">Kills</th>
|
<th id="weekly-leaderboard-value-heading">Kills</th>
|
||||||
<th>Partidas</th>
|
<th>Partidas</th>
|
||||||
<th>Kills/partida</th>
|
<th id="weekly-leaderboard-ratio-heading">Kills/partida</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody id="weekly-leaderboard-body"></tbody>
|
<tbody id="weekly-leaderboard-body"></tbody>
|
||||||
|
|||||||
@@ -87,11 +87,11 @@
|
|||||||
<label class="stats-search-form__label" for="ranking-metric">
|
<label class="stats-search-form__label" for="ranking-metric">
|
||||||
Métrica
|
Métrica
|
||||||
<select class="ranking-select" id="ranking-metric" name="metric">
|
<select class="ranking-select" id="ranking-metric" name="metric">
|
||||||
<option value="kills">Kills totales</option>
|
<option value="kills">Kills</option>
|
||||||
<option value="deaths">Deaths</option>
|
<option value="deaths">Muertes</option>
|
||||||
<option value="teamkills">Teamkills</option>
|
<option value="teamkills">TK</option>
|
||||||
<option value="matches_considered">Partidas jugadas</option>
|
<option value="matches_considered">Partidas</option>
|
||||||
<option value="kd_ratio">K/D</option>
|
<option value="kd_ratio">KD</option>
|
||||||
<option value="kills_per_match">Kills/partida</option>
|
<option value="kills_per_match">Kills/partida</option>
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
@@ -120,11 +120,11 @@
|
|||||||
<th>Pos.</th>
|
<th>Pos.</th>
|
||||||
<th>Jugador</th>
|
<th>Jugador</th>
|
||||||
<th id="ranking-metric-heading">Valor activo</th>
|
<th id="ranking-metric-heading">Valor activo</th>
|
||||||
<th>Kills</th>
|
|
||||||
<th>Deaths</th>
|
|
||||||
<th>Teamkills</th>
|
|
||||||
<th>Partidas</th>
|
<th>Partidas</th>
|
||||||
<th>K/D</th>
|
<th>Kills</th>
|
||||||
|
<th>Muertes</th>
|
||||||
|
<th>TK</th>
|
||||||
|
<th>KD</th>
|
||||||
<th id="ranking-kpp-heading">Kills/partida</th>
|
<th id="ranking-kpp-heading">Kills/partida</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|||||||
Reference in New Issue
Block a user