From 19bf71e02439826de21534d306bc10b0a4d29726 Mon Sep 17 00:00:00 2001 From: Erwan Huon <67637529+ERHash@users.noreply.github.com> Date: Mon, 2 Jun 2025 20:20:48 +0200 Subject: [PATCH] Add dynamic sorting to leaderboard by tiles, gold, and troops (#961) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description: This PR adds dynamic sorting to the in-game leaderboard. Players can now sort the leaderboard by tiles owned (default), gold, or troops by clicking the respective column headers. The currently selected sort is indicated with a downward arrow (⬇️). This improves usability and makes it easier to compare player stats mid-game. ### Please complete the following: [✅] I have added screenshots for all UI updates https://github.com/user-attachments/assets/d0238698-a187-4fc7-9407-04d11cccbc32 [✅] I process any text displayed to the user through translateText() and I've added it to the en.json file [❌] I have added relevant tests to the test directory [✅] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced [✅] I understand that submitting code with bugs that could have been caught through manual testing blocks releases and new features for all contributors Closes #923 --------- Co-authored-by: evanpelle Co-authored-by: evanpelle --- src/client/graphics/layers/Leaderboard.ts | 65 ++++++++++++++++++++--- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/src/client/graphics/layers/Leaderboard.ts b/src/client/graphics/layers/Leaderboard.ts index 2bcca0e8d..0749a90aa 100644 --- a/src/client/graphics/layers/Leaderboard.ts +++ b/src/client/graphics/layers/Leaderboard.ts @@ -44,6 +44,12 @@ export class Leaderboard extends LitElement implements Layer { private _shownOnInit = false; private showTopFive = true; + @state() + private _sortKey: "tiles" | "gold" | "troops" = "tiles"; + + @state() + private _sortOrder: "asc" | "desc" = "desc"; + init() {} tick() { @@ -62,13 +68,37 @@ export class Leaderboard extends LitElement implements Layer { } } + private setSort(key: "tiles" | "gold" | "troops") { + if (this._sortKey === key) { + this._sortOrder = this._sortOrder === "asc" ? "desc" : "asc"; + } else { + this._sortKey = key; + this._sortOrder = "desc"; + } + this.updateLeaderboard(); + } + private updateLeaderboard() { if (this.game === null) throw new Error("Not initialized"); const myPlayer = this.game.myPlayer(); - const sorted = this.game - .playerViews() - .sort((a, b) => b.numTilesOwned() - a.numTilesOwned()); + let sorted = this.game.playerViews(); + + const compare = (a: number, b: number) => + this._sortOrder === "asc" ? a - b : b - a; + + switch (this._sortKey) { + case "gold": + sorted = sorted.sort((a, b) => compare(a.gold(), b.gold())); + break; + case "troops": + sorted = sorted.sort((a, b) => compare(a.troops(), b.troops())); + break; + default: + sorted = sorted.sort((a, b) => + compare(a.numTilesOwned(), b.numTilesOwned()), + ); + } const numTilesWithoutFallout = this.game.numLandTiles() - this.game.numTilesWithFallout(); @@ -174,6 +204,8 @@ export class Leaderboard extends LitElement implements Layer { th { background-color: rgb(31 41 55 / 0.5); color: white; + cursor: pointer; + user-select: none; } .myPlayer { font-weight: bold; @@ -275,9 +307,30 @@ export class Leaderboard extends LitElement implements Layer { ${translateText("leaderboard.rank")} ${translateText("leaderboard.player")} - ${translateText("leaderboard.owned")} - ${translateText("leaderboard.gold")} - ${translateText("leaderboard.troops")} + this.setSort("tiles")}> + ${translateText("leaderboard.owned")} + ${this._sortKey === "tiles" + ? this._sortOrder === "asc" + ? "⬆️" + : "⬇️" + : ""} + + this.setSort("gold")}> + ${translateText("leaderboard.gold")} + ${this._sortKey === "gold" + ? this._sortOrder === "asc" + ? "⬆️" + : "⬇️" + : ""} + + this.setSort("troops")}> + ${translateText("leaderboard.troops")} + ${this._sortKey === "troops" + ? this._sortOrder === "asc" + ? "⬆️" + : "⬇️" + : ""} +