import { LitElement, html, type PropertyValues, type TemplateResult, } from "lit"; import { customElement, property } from "lit/decorators.js"; import { assetUrl } from "../../../../core/AssetUrls"; import { renderNumber, translateText } from "../../../Utils"; import { PlayerInfo, RANK_TYPE_LABEL_KEYS, RankType } from "./GameInfoRanking"; const goldCoinIcon = assetUrl("images/GoldCoinIcon.svg"); @customElement("player-row") export class PlayerRow extends LitElement { @property({ type: Object }) player: PlayerInfo; @property({ type: String }) rankType: RankType; @property({ type: Number }) bestScore = 1; @property({ type: Number }) rank = 1; @property({ type: Number }) score = 0; @property({ type: Boolean }) currentPlayer = false; private failedFlag: string | null = null; createRenderRoot() { return this; } render() { if (!this.player) return html``; const { player } = this; return html`
  • ${player.winner ? html`
    ` : ""} ${this.renderRank()} ${this.renderIdentity()}
    ${this.renderPlayerInfo()}
  • `; } protected willUpdate(changed: PropertyValues): void { if (changed.has("player")) { const previous = changed.get("player") as PlayerInfo | undefined; if (previous?.flag !== this.player?.flag) this.failedFlag = null; } } private renderRank(): TemplateResult { const rankClass = { 1: "border-yellow-400/20 bg-yellow-400/10 text-yellow-300", 2: "border-slate-300/15 bg-slate-300/10 text-slate-300", 3: "border-amber-600/20 bg-amber-600/10 text-amber-500", }[this.rank] ?? "border-white/[0.06] bg-white/[0.035] text-white/35"; return html`
    ${this.rank}
    `; } private renderPlayerIcon() { return html`
    ${this.renderIcon()} ${this.player.winner ? this.renderCrownIcon() : this.player.killedAt !== undefined ? this.renderEliminatedIcon() : ""}
    `; } private renderCrownIcon() { return html` `; } private renderEliminatedIcon(): TemplateResult { return html` `; } private renderIdentity(): TemplateResult { return html`
    ${this.renderPlayerIcon()}
    ${this.player.clanTag ? html`
    ${this.player.clanTag}
    ` : ""}
    ${this.player.username}
    `; } private renderPlayerInfo() { switch (this.rankType) { case RankType.Lifetime: case RankType.ConquestHumans: case RankType.ConquestNations: case RankType.ConquestBots: return this.renderScoreAsBar(); case RankType.Atoms: case RankType.Hydros: case RankType.MIRV: return this.renderBombScore(); case RankType.TotalGold: case RankType.ConqueredGold: case RankType.StolenGold: return this.renderGoldScore(); case RankType.NavalTrade: case RankType.TrainTrade: return this.renderTradeScore(); default: return html``; } } private renderScoreAsBar() { const isLifetime = this.rankType === RankType.Lifetime; const formattedScore = `${Number(this.score).toFixed(0)}${ isLifetime ? "%" : "" }`; return html`
    ${this.renderScoreBar(formattedScore)}
    `; } private renderScoreBar(formattedScore: string) { const bestScore = Math.max(this.bestScore, 1); const currentScore = Math.max(this.score, 0); const accessibleMax = Math.max(bestScore, currentScore); const width = Math.min(Math.max((this.score / bestScore) * 100, 0), 100); return html`
    `; } private renderBombScore() { return this.renderValueScore(false); } private renderGoldScore() { return this.renderValueScore(true); } private renderTradeScore() { return this.renderValueScore(true); } private renderValueScore(showCoin: boolean) { const formattedScore = renderNumber(this.score); return html`
    ${showCoin ? this.renderCoinIcon() : ""}
    ${formattedScore}
    `; } private scoreLabel(): string { return `${this.player.username}: ${translateText( RANK_TYPE_LABEL_KEYS[this.rankType], )}`; } private renderIcon() { const flagUrl = this.getFlagUrl(); if (flagUrl) { return html` this.handleFlagError()} class="size-10 rounded-xl border border-white/10 bg-white/[0.055] object-contain p-1" />`; } return html` `; } private getFlagUrl(): string | null { if (!this.player.flag || this.failedFlag === this.player.flag) return null; try { return assetUrl(this.player.flag); } catch { return null; } } private handleFlagError(): void { this.failedFlag = this.player.flag ?? null; this.requestUpdate(); } private initials(): string { const normalized = this.player.username.trim(); return normalized.length > 0 ? normalized.slice(0, 2).toUpperCase() : "?"; } private renderCoinIcon(): TemplateResult { return html``; } }