import { LitElement, html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { EventBus } from "../../../core/EventBus"; import { GameMode, Team } from "../../../core/game/Game"; import { GameView, PlayerView } from "../../../core/game/GameView"; import { renderNumber, translateText } from "../../Utils"; import { Layer } from "./Layer"; type TeamEntry = { teamName: string; totalScoreStr: string; totalGold: string; totalTroops: string; totalScoreSort: number; players: PlayerView[]; }; @customElement("team-stats") export class TeamStats extends LitElement implements Layer { public game: GameView; public eventBus: EventBus; @property({ type: Boolean }) visible = false; teams: TeamEntry[] = []; private _shownOnInit = false; createRenderRoot() { return this; // use light DOM for Tailwind } init() {} tick() { if (this.game.config().gameConfig().gameMode !== GameMode.Team) return; if (!this._shownOnInit && !this.game.inSpawnPhase()) { this._shownOnInit = true; this.updateTeamStats(); } if (!this.visible) return; if (this.game.ticks() % 10 === 0) { this.updateTeamStats(); } } private updateTeamStats() { const players = this.game.playerViews(); const grouped: Record = {}; for (const player of players) { const team = player.team(); if (team === null) continue; grouped[team] ??= []; grouped[team].push(player); } this.teams = Object.entries(grouped) .map(([teamStr, teamPlayers]) => { let totalGold = 0n; let totalTroops = 0; let totalScoreSort = 0; for (const p of teamPlayers) { if (p.isAlive()) { totalTroops += p.troops(); totalGold += p.gold(); totalScoreSort += p.numTilesOwned(); } } const totalScorePercent = totalScoreSort / this.game.numLandTiles(); return { teamName: teamStr, totalScoreStr: formatPercentage(totalScorePercent), totalScoreSort, totalGold: renderNumber(totalGold), totalTroops: renderNumber(totalTroops / 10), players: teamPlayers, }; }) .sort((a, b) => b.totalScoreSort - a.totalScoreSort); this.requestUpdate(); } renderLayer(context: CanvasRenderingContext2D) {} shouldTransform(): boolean { return false; } render() { if (!this.visible) { return html``; } return html`
e.preventDefault()} >
${translateText("leaderboard.team")}
${translateText("leaderboard.owned")}
${translateText("leaderboard.gold")}
${translateText("leaderboard.troops")}
${this.teams.map( (team) => html`
${team.teamName}
${team.totalScoreStr}
${team.totalGold}
${team.totalTroops}
`, )}
`; } } function formatPercentage(value: number): string { const perc = value * 100; if (Number.isNaN(perc)) return "0%"; return perc.toPrecision(2) + "%"; }