From d57e6efa985ca07c32f9f54595fe7393dbdf4d8a Mon Sep 17 00:00:00 2001 From: lq64 Date: Wed, 3 Dec 2025 09:18:11 +0100 Subject: [PATCH] feat(ui): FRO-7 Endscreen (#97) Added a nice look to the endscreen. Implemented a ranking method inside GameLobby to get an order. Co-authored-by: LQ63 Reviewed-on: https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/pulls/97 Reviewed-by: Janis Co-authored-by: lq64 Co-committed-by: lq64 --- .../app/logic/game/GameLobby.scala | 32 +++++ .../app/views/ingame/finishedMatch.scala.html | 119 +++++++++++++++--- knockoutwhistweb/app/views/main.scala.html | 2 +- 3 files changed, 133 insertions(+), 20 deletions(-) diff --git a/knockoutwhistweb/app/logic/game/GameLobby.scala b/knockoutwhistweb/app/logic/game/GameLobby.scala index 0da9376..23b7aa6 100644 --- a/knockoutwhistweb/app/logic/game/GameLobby.scala +++ b/knockoutwhistweb/app/logic/game/GameLobby.scala @@ -20,6 +20,7 @@ import play.api.libs.json.{JsObject, Json} import java.util.{Timer, TimerTask, UUID} import scala.collection.mutable import scala.collection.mutable.ListBuffer +import scala.util.Try class GameLobby private( val logic: GameLogic, @@ -277,6 +278,37 @@ class GameLobby private( def getUsers: Set[User] = { users.values.map(d => d.user).toSet } + def getFinalRanking: List[(String, (Int, Int))] = { + Try { + val match1 = getMatch + if (!match1.isOver) { + List.empty + } else { + val winnerName = logic.getWinner.get.name + + val allPlayerNames = match1.totalplayers.map(_.name) + val roundlist = match1.roundlist + + val playerMetrics: Map[String, (Int, Int)] = allPlayerNames.map { name => + val roundsWon = roundlist.count { round => + round.winner.exists(_.name == name) + } + val totalTricksWon = roundlist.flatMap(_.tricklist).count { trick => + trick.winner.exists(_.name == name) + } + name -> (roundsWon, totalTricksWon) + }.toMap + + val winnerMetrics = playerMetrics(winnerName) + val remainingPlayersMetrics = playerMetrics.view.filterKeys(_ != winnerName).toList + + val sortedRemainingPlayers = remainingPlayersMetrics.sortBy { case (_, (rounds, tricks)) => + (-rounds, -tricks) + } + (winnerName, winnerMetrics) :: sortedRemainingPlayers + } + }.getOrElse(List()) + } private def transmitToAll(event: JsObject): Unit = { users.values.foreach(session => { diff --git a/knockoutwhistweb/app/views/ingame/finishedMatch.scala.html b/knockoutwhistweb/app/views/ingame/finishedMatch.scala.html index b172c52..8cf76b9 100644 --- a/knockoutwhistweb/app/views/ingame/finishedMatch.scala.html +++ b/knockoutwhistweb/app/views/ingame/finishedMatch.scala.html @@ -1,27 +1,108 @@ @(user: Option[model.users.User], gamelobby: logic.game.GameLobby) -
-
-
-
-
Winner: @gamelobby.getLogic.getWinner
-
-
-
- @if((gamelobby.getUserSession(user.get.id).host)) { -
-
Return to lobby
-
- } else { -
-
- Loading... +
+
+
+
+
+
+

Match Over!

+

Congratulations to the winner:

+

+ @gamelobby.getLogic.getWinner.get.name +

+
+ +
+
+ Final Standings +
+
+
+ Player +
+
+ Rounds won + Tricks won +
+
+
+ @gamelobby.getFinalRanking.zipWithIndex.map { case ((playerName, (wonRounds, tricksWon)), index) => + @defining(index + 1) { rank => +
+
+ #@rank + @playerName +
+
+ @wonRounds + @tricksWon +
+
+ } + } +
+ @if(gamelobby.getFinalRanking.isEmpty) { +
No final scores available.
+ } +
+ + + @if(user.isDefined && gamelobby.getUserSession(user.get.id).host) { +
+
+ Return to Lobby +
+
+ } else { +
+
+
+ Loading... +
+

+ Waiting for the Host to continue... +

+
+
+ }
- }
-
+ \ No newline at end of file diff --git a/knockoutwhistweb/app/views/main.scala.html b/knockoutwhistweb/app/views/main.scala.html index d53c6b6..a24d416 100644 --- a/knockoutwhistweb/app/views/main.scala.html +++ b/knockoutwhistweb/app/views/main.scala.html @@ -17,7 +17,7 @@ - +