diff --git a/knockoutwhistweb/app/assets/stylesheets/main.less b/knockoutwhistweb/app/assets/stylesheets/main.less index 5179c42..b726d46 100644 --- a/knockoutwhistweb/app/assets/stylesheets/main.less +++ b/knockoutwhistweb/app/assets/stylesheets/main.less @@ -25,6 +25,8 @@ .game-field-background { background-image: @background-image; + background-repeat: no-repeat; + background-size: cover; max-width: 1400px; margin: 0 auto; min-height: 100vh; @@ -83,6 +85,10 @@ body { box-shadow: 0 1px 15px 0 #000000 } +.ingame-side-shadow { + box-shadow: 0 1px 15px 0 #000000 +} + #sessions { display: flex; flex-direction: column; @@ -117,45 +123,21 @@ body { font-size: 40px; font-family: Arial, serif; } -#playercards { - display: flex; - flex-direction: row; - justify-content: center; - height: 20%; - img { - animation: slideIn 0.5s ease-out forwards; - animation-fill-mode: backwards; - &:nth-child(1) { animation-delay: 0.5s; } - &:nth-child(2) { animation-delay: 1s; } - &:nth-child(3) { animation-delay: 1.5s; } - &:nth-child(4) { animation-delay: 2s; } - &:nth-child(5) { animation-delay: 2.5s; } - &:nth-child(6) { animation-delay: 3s; } - &:nth-child(7) { animation-delay: 3.5s; } - } -} -#card-slide { - div { - animation: slideIn 0.5s ease-out forwards; - animation-fill-mode: backwards; - &:nth-child(1) { animation-delay: 0.5s; } - &:nth-child(2) { animation-delay: 1s; } - &:nth-child(3) { animation-delay: 1.5s; } - &:nth-child(4) { animation-delay: 2s; } - &:nth-child(5) { animation-delay: 2.5s; } - &:nth-child(6) { animation-delay: 3s; } - &:nth-child(7) { animation-delay: 3.5s; } - } - +.ingame-cards-slide { + div { + animation: slideIn 0.5s ease-out forwards; + animation-fill-mode: backwards; + &:nth-child(1) { animation-delay: 0.5s; } + &:nth-child(2) { animation-delay: 1s; } + &:nth-child(3) { animation-delay: 1.5s; } + &:nth-child(4) { animation-delay: 2s; } + &:nth-child(5) { animation-delay: 2.5s; } + &:nth-child(6) { animation-delay: 3s; } + &:nth-child(7) { animation-delay: 3.5s; } + } } -#cardsplayed { - display: flex; - flex-direction: row; - height: 10%; - min-height: 10% -} #playedcardplayer { display: flex; flex-direction: column; diff --git a/knockoutwhistweb/app/controllers/IngameController.scala b/knockoutwhistweb/app/controllers/IngameController.scala index 6a5ece1..346bb83 100644 --- a/knockoutwhistweb/app/controllers/IngameController.scala +++ b/knockoutwhistweb/app/controllers/IngameController.scala @@ -1,32 +1,27 @@ package controllers import auth.{AuthAction, AuthenticatedRequest} -import de.knockoutwhist.cards.Hand import de.knockoutwhist.control.GameState.{InGame, Lobby, SelectTrump, TieBreak} -import exceptions.{CantPlayCardException, GameFullException, NotEnoughPlayersException, NotHostException, NotInThisGameException} +import exceptions.* import logic.PodManager -import logic.game.PollingEvents.CardPlayed -import logic.game.PollingEvents.GameStarted -import logic.game.{GameLobby, PollingEvents} -import model.sessions.{PlayerSession, UserSession} -import model.users.User +import logic.game.GameLobby +import model.sessions.UserSession import play.api.* -import play.api.libs.json.{JsArray, JsValue, Json} +import play.api.libs.json.{JsValue, Json} import play.api.mvc.* -import util.WebUIUtils import java.util.UUID import javax.inject.* -import scala.concurrent.Future -import scala.util.Try import scala.concurrent.ExecutionContext -@Singleton -class IngameController @Inject()( - val controllerComponents: ControllerComponents, - val authAction: AuthAction, - val podManager: PodManager - ) extends BaseController { +import scala.util.Try +@Singleton +class IngameController @Inject() ( + val cc: ControllerComponents, + val podManager: PodManager, + val authAction: AuthAction, + implicit val ec: ExecutionContext + ) extends AbstractController(cc) { def game(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => val game = podManager.getGame(gameId) game match { @@ -41,12 +36,12 @@ class IngameController @Inject()( case SelectTrump => Ok(views.html.ingame.selecttrump( g.getPlayerByUser(request.user), - g.logic + g )) case TieBreak => Ok(views.html.ingame.tie( g.getPlayerByUser(request.user), - g.logic + g )) case _ => InternalServerError(s"Invalid game state for in-game view. GameId: $gameId" + s" State: ${g.logic.getCurrentState}") @@ -54,7 +49,6 @@ class IngameController @Inject()( case None => NotFound("Game not found") } - //NotFound(s"Reached end of game method unexpectedly. GameId: $gameId") } def startGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => val game = podManager.getGame(gameId) @@ -67,30 +61,70 @@ class IngameController @Inject()( } } if (result.isSuccess) { - Redirect(routes.IngameController.game(gameId)) + Ok(Json.obj( + "status" -> "success", + "redirectUrl" -> routes.IngameController.game(gameId).url + )) } else { val throwable = result.failed.get throwable match { case _: NotInThisGameException => - BadRequest(throwable.getMessage) + BadRequest(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) case _: NotHostException => - Forbidden(throwable.getMessage) + Forbidden(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) case _: NotEnoughPlayersException => - BadRequest(throwable.getMessage) + BadRequest(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) case _ => - InternalServerError(throwable.getMessage) + InternalServerError(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) } } } - def kickPlayer(gameId: String, playerToKick: UUID): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => + def kickPlayer(gameId: String, playerToKick: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => val game = podManager.getGame(gameId) - game.get.leaveGame(playerToKick) - Redirect(routes.IngameController.game(gameId)) + val playerToKickUUID = UUID.fromString(playerToKick) + val result = Try { + game.get.leaveGame(playerToKickUUID) + } + if(result.isSuccess) { + Ok(Json.obj( + "status" -> "success", + "redirectUrl" -> routes.IngameController.game(gameId).url + )) + } else { + InternalServerError(Json.obj( + "status" -> "failure", + "errorMessage" -> "Something went wrong." + )) + } } def leaveGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => val game = podManager.getGame(gameId) - game.get.leaveGame(request.user.id) - Redirect(routes.MainMenuController.mainMenu()) + val result = Try { + game.get.leaveGame(request.user.id) + } + if (result.isSuccess) { + Ok(Json.obj( + "status" -> "success", + "redirectUrl" -> routes.MainMenuController.mainMenu().url + )) + } else { + InternalServerError(Json.obj( + "status" -> "failure", + "errorMessage" -> "Something went wrong." + )) + } } def joinGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => val game = podManager.getGame(gameId) @@ -122,7 +156,10 @@ class IngameController @Inject()( val game = podManager.getGame(gameId) game match { case Some(g) => - val cardIdOpt = request.body.asFormUrlEncoded.flatMap(_.get("cardId").flatMap(_.headOption)) + val jsonBody = request.body.asJson + val cardIdOpt: Option[String] = jsonBody.flatMap { jsValue => + (jsValue \ "cardID").asOpt[String] + } cardIdOpt match { case Some(cardId) => var optSession: Option[UserSession] = None @@ -134,27 +171,51 @@ class IngameController @Inject()( } optSession.foreach(_.lock.unlock()) if (result.isSuccess) { - NoContent + Ok(Json.obj( + "status" -> "success", + "redirectUrl" -> routes.IngameController.game(gameId).url + )) } else { val throwable = result.failed.get throwable match { case _: CantPlayCardException => - BadRequest(throwable.getMessage) + BadRequest(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) case _: NotInThisGameException => - BadRequest(throwable.getMessage) + BadRequest(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) case _: IllegalArgumentException => - BadRequest(throwable.getMessage) + BadRequest(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) case _: IllegalStateException => - BadRequest(throwable.getMessage) + BadRequest(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) case _ => - InternalServerError(throwable.getMessage) + InternalServerError(Json.obj( + "status" -> "failure", + "errorMessage" -> throwable.getMessage + )) } } case None => - BadRequest("cardId parameter is missing") + BadRequest(Json.obj( + "status" -> "failure", + "errorMessage" -> "cardId Parameter is missing" + )) } case None => - NotFound("Game not found") + NotFound(Json.obj( + "status" -> "failure", + "errorMessage" -> "Game not found" + )) } } } @@ -253,7 +314,7 @@ class IngameController @Inject()( val session = g.getUserSession(request.user.id) optSession = Some(session) session.lock.lock() - g.selectTie(g.getUserSession(request.user.id), tie.toInt - 1) + g.selectTie(g.getUserSession(request.user.id), tie.toInt) } optSession.foreach(_.lock.unlock()) if (result.isSuccess) { diff --git a/knockoutwhistweb/app/controllers/JavaScriptRoutingController.scala b/knockoutwhistweb/app/controllers/JavaScriptRoutingController.scala index 48c2f9f..eb7e82a 100644 --- a/knockoutwhistweb/app/controllers/JavaScriptRoutingController.scala +++ b/knockoutwhistweb/app/controllers/JavaScriptRoutingController.scala @@ -20,7 +20,7 @@ class JavaScriptRoutingController @Inject()( routes.javascript.IngameController.kickPlayer, routes.javascript.IngameController.leaveGame, routes.javascript.IngameController.playCard, - routes.javascript.IngameController.polling + routes.javascript.PollingController.polling ) ).as("text/javascript") } diff --git a/knockoutwhistweb/app/controllers/PollingController.scala b/knockoutwhistweb/app/controllers/PollingController.scala new file mode 100644 index 0000000..73d4b11 --- /dev/null +++ b/knockoutwhistweb/app/controllers/PollingController.scala @@ -0,0 +1,134 @@ +package controllers + +import auth.{AuthAction, AuthenticatedRequest} +import de.knockoutwhist.cards.Hand +import logic.PodManager +import logic.game.{GameLobby, PollingEvents} +import logic.game.PollingEvents.{CardPlayed, LobbyUpdate, NewRound, ReloadEvent} +import model.sessions.UserSession +import model.users.User +import play.api.libs.json.{JsArray, JsValue, Json} +import play.api.mvc.{AbstractController, Action, AnyContent, ControllerComponents, Result} +import util.WebUIUtils + +import javax.inject.{Inject, Singleton} +import scala.concurrent.{ExecutionContext, Future} + +@Singleton +class PollingController @Inject() ( + val cc: ControllerComponents, + val podManager: PodManager, + val authAction: AuthAction, + implicit val ec: ExecutionContext + ) extends AbstractController(cc) { + + private def buildCardPlayResponse(game: GameLobby, hand: Option[Hand], newRound: Boolean): JsValue = { + val currentRound = game.logic.getCurrentRound.get + val currentTrick = game.logic.getCurrentTrick.get + + val trickCardsJson = Json.toJson( + currentTrick.cards.map { case (card, player) => + Json.obj("cardId" -> WebUIUtils.cardtoString(card), "player" -> player.name) + } + ) + val scoreTableJson = Json.toJson( + game.getLogic.getPlayerQueue.get.toList.map { player => + Json.obj( + "name" -> player.name, + "tricks" -> currentRound.tricklist.count(_.winner.contains(player)) + ) + } + ) + + val stringHand = hand.map { h => + val cardStrings = h.cards.map(WebUIUtils.cardtoString) + Json.toJson(cardStrings).as[JsArray] + }.getOrElse(Json.arr()) + + val firstCardId = currentTrick.firstCard.map(WebUIUtils.cardtoString).getOrElse("BLANK") + val nextPlayer = game.getLogic.getPlayerQueue.get.duplicate().nextPlayer().name + Json.obj( + "status" -> "cardPlayed", + "animation" -> newRound, + "handData" -> stringHand, + "currentPlayerName" -> game.logic.getCurrentPlayer.get.name, + "trumpSuit" -> currentRound.trumpSuit.toString, + "trickCards" -> trickCardsJson, + "scoreTable" -> scoreTableJson, + "firstCardId" -> firstCardId, + "nextPlayer" -> nextPlayer + ) + } + + private def buildLobbyUsersResponse(game: GameLobby, userSession: UserSession): JsValue = { + Json.obj( + "status" -> "lobbyUpdate", + "host" -> userSession.host, + "users" -> game.getUsers.map(u => Json.obj( + "name" -> u.name, + "id" -> u.id, + "self" -> (u.id == userSession.id) + )) + ) + } + + + def handleEvent(event: PollingEvents, game: GameLobby, userSession: UserSession): Result = { + event match { + case NewRound => + val player = game.getPlayerByUser(userSession.user) + val hand = player.currentHand() + val jsonResponse = buildCardPlayResponse(game, hand, true) + Ok(jsonResponse) + case CardPlayed => + val player = game.getPlayerByUser(userSession.user) + val hand = player.currentHand() + val jsonResponse = buildCardPlayResponse(game, hand, false) + Ok(jsonResponse) + case LobbyUpdate => + Ok(buildLobbyUsersResponse(game, userSession)) + case ReloadEvent => + val jsonResponse = Json.obj( + "status" -> "reloadEvent", + "redirectUrl" -> routes.IngameController.game(game.id).url + ) + Ok(jsonResponse) + } + } + + // --- Main Polling Action --- + def polling(gameId: String): Action[AnyContent] = authAction.async { implicit request: AuthenticatedRequest[AnyContent] => + + val playerId = request.user.id + + // 1. Safely look up the game + podManager.getGame(gameId) match { + case Some(game) => + + // 2. Short-Poll Check (Check for missed events) + if (game.getPollingState.nonEmpty) { + val event = game.getPollingState.dequeue() + + Future.successful(handleEvent(event, game, game.getUserSession(playerId))) + } else { + + val eventPromise = game.registerWaiter(playerId) + + eventPromise.future.map { event => + game.removeWaiter(playerId) + handleEvent(event, game, game.getUserSession(playerId)) + }.recover { + case _: Throwable => + game.removeWaiter(playerId) + NoContent + } + } + + case None => + // Game not found + Future.successful(NotFound("Game not found.")) + } + } + + +} diff --git a/knockoutwhistweb/app/logic/game/GameLobby.scala b/knockoutwhistweb/app/logic/game/GameLobby.scala index cd28c35..1cf7dfa 100644 --- a/knockoutwhistweb/app/logic/game/GameLobby.scala +++ b/knockoutwhistweb/app/logic/game/GameLobby.scala @@ -5,20 +5,20 @@ import de.knockoutwhist.control.GameLogic import de.knockoutwhist.control.GameState.{InGame, Lobby, MainMenu} import de.knockoutwhist.control.controllerBaseImpl.sublogic.util.{MatchUtil, PlayerUtil} import de.knockoutwhist.events.global.{CardPlayedEvent, GameStateChangeEvent, SessionClosed} -import de.knockoutwhist.events.player.PlayerEvent +import de.knockoutwhist.events.player.{PlayerEvent, ReceivedHandEvent} import de.knockoutwhist.player.Playertype.HUMAN import de.knockoutwhist.player.{AbstractPlayer, PlayerFactory} import de.knockoutwhist.rounds.{Match, Round, Trick} import de.knockoutwhist.utils.events.{EventListener, SimpleEvent} import exceptions.* -import logic.game.PollingEvents.{CardPlayed, GameStarted} +import logic.game.PollingEvents.{CardPlayed, LobbyUpdate, NewRound, ReloadEvent} import model.sessions.{InteractionType, UserSession} import model.users.User import java.util.UUID import scala.collection.mutable import scala.collection.mutable.ListBuffer -import scala.concurrent.{Promise => ScalaPromise} +import scala.concurrent.Promise as ScalaPromise class GameLobby private( val logic: GameLogic, @@ -31,7 +31,7 @@ class GameLobby private( logic.createSession() private val users: mutable.Map[UUID, UserSession] = mutable.Map() - private var pollingState: mutable.Queue[PollingEvents] = mutable.Queue() + private val pollingState: mutable.Queue[PollingEvents] = mutable.Queue() private val waitingPromises: mutable.Map[UUID, ScalaPromise[PollingEvents]] = mutable.Map() def registerWaiter(playerId: UUID): ScalaPromise[PollingEvents] = { @@ -53,19 +53,17 @@ class GameLobby private( host = false ) users += (user.id -> userSession) + addToQueue(LobbyUpdate) userSession } override def listen(event: SimpleEvent): Unit = { event match { + case event: ReceivedHandEvent => + addToQueue(NewRound) + users.get(event.playerId).foreach(session => session.updatePlayer(event)) case event: CardPlayedEvent => - val newEvent = PollingEvents.CardPlayed - if (waitingPromises.nonEmpty) { - waitingPromises.values.foreach(_.success(newEvent)) - waitingPromises.clear() - } else { - pollingState.enqueue(newEvent) - } + addToQueue(CardPlayed) case event: PlayerEvent => users.get(event.playerId).foreach(session => session.updatePlayer(event)) case event: GameStateChangeEvent => @@ -73,13 +71,9 @@ class GameLobby private( return } if (event.oldState == Lobby && event.newState == InGame) { - val newEvent = PollingEvents.GameStarted - if (waitingPromises.nonEmpty) { - waitingPromises.values.foreach(_.success(newEvent)) - waitingPromises.clear() - } else { - pollingState.enqueue(newEvent) - } + addToQueue(ReloadEvent) + }else { + addToQueue(ReloadEvent) } users.values.foreach(session => session.updatePlayer(event)) case event: SessionClosed => @@ -89,6 +83,15 @@ class GameLobby private( } } + private def addToQueue(event: PollingEvents): Unit = { + if (waitingPromises.nonEmpty) { + waitingPromises.values.foreach(_.success(event)) + waitingPromises.clear() + } else { + pollingState.enqueue(event) + } + } + /** * Start the game if the user is the host. * @param user the user who wants to start the game. @@ -125,6 +128,7 @@ class GameLobby private( throw new NotInThisGameException("You are not in this game!") } users.remove(userId) + addToQueue(LobbyUpdate) } /** @@ -188,9 +192,6 @@ class GameLobby private( */ def selectTie(userSession: UserSession, tieNumber: Int): Unit = { val player = getPlayerInteractable(userSession, InteractionType.TieChoice) - val highestNumber = logic.playerTieLogic.highestAllowedNumber() - if (tieNumber < 0 || tieNumber > highestNumber) - throw new IllegalArgumentException(s"Selected number $tieNumber is out of allowed range (0 to $highestNumber)") userSession.resetCanInteract() logic.playerTieLogic.receivedTieBreakerCard(tieNumber) } @@ -269,7 +270,11 @@ class GameLobby private( } trickOpt.get } - + + def getUsers: Set[User] = { + users.values.map(d => d.user).toSet + } + } object GameLobby { diff --git a/knockoutwhistweb/app/logic/game/PollingEvents.scala b/knockoutwhistweb/app/logic/game/PollingEvents.scala index 933cf82..5e5bc8a 100644 --- a/knockoutwhistweb/app/logic/game/PollingEvents.scala +++ b/knockoutwhistweb/app/logic/game/PollingEvents.scala @@ -2,5 +2,7 @@ package logic.game enum PollingEvents { case CardPlayed - case GameStarted + case NewRound + case ReloadEvent + case LobbyUpdate } \ No newline at end of file diff --git a/knockoutwhistweb/app/model/sessions/UserSession.scala b/knockoutwhistweb/app/model/sessions/UserSession.scala index 94e56ff..8bdef2c 100644 --- a/knockoutwhistweb/app/model/sessions/UserSession.scala +++ b/knockoutwhistweb/app/model/sessions/UserSession.scala @@ -7,7 +7,7 @@ import model.users.User import java.util.UUID import java.util.concurrent.locks.{Lock, ReentrantLock} -class UserSession(user: User, val host: Boolean) extends PlayerSession { +class UserSession(val user: User, val host: Boolean) extends PlayerSession { var canInteract: Option[InteractionType] = None val lock: ReentrantLock = ReentrantLock() diff --git a/knockoutwhistweb/app/util/WebUIUtils.scala b/knockoutwhistweb/app/util/WebUIUtils.scala index b905462..f797985 100644 --- a/knockoutwhistweb/app/util/WebUIUtils.scala +++ b/knockoutwhistweb/app/util/WebUIUtils.scala @@ -8,6 +8,10 @@ import scalafx.scene.image.Image object WebUIUtils { def cardtoImage(card: Card): Html = { + views.html.render.card.apply(f"images/cards/${cardtoString(card)}.png")(card.toString) + } + + def cardtoString(card: Card) = { val s = card.suit match { case Spades => "S" case Hearts => "H" @@ -29,6 +33,7 @@ object WebUIUtils { case Three => "3" case Two => "2" } - views.html.render.card.apply(f"images/cards/$cv$s.png")(card.toString) + f"$cv$s" } + } diff --git a/knockoutwhistweb/app/views/ingame/ingame.scala.html b/knockoutwhistweb/app/views/ingame/ingame.scala.html index 50f45f6..4ab4f17 100644 --- a/knockoutwhistweb/app/views/ingame/ingame.scala.html +++ b/knockoutwhistweb/app/views/ingame/ingame.scala.html @@ -4,7 +4,7 @@ @main("Ingame") {
-
+
@@ -72,7 +72,7 @@
-
+
@for(i <- player.currentHand().get.cards.indices) {
diff --git a/knockoutwhistweb/app/views/ingame/selecttrump.scala.html b/knockoutwhistweb/app/views/ingame/selecttrump.scala.html index 82c58c2..f9969c0 100644 --- a/knockoutwhistweb/app/views/ingame/selecttrump.scala.html +++ b/knockoutwhistweb/app/views/ingame/selecttrump.scala.html @@ -1,4 +1,4 @@ -@(player: de.knockoutwhist.player.AbstractPlayer, logic: de.knockoutwhist.control.GameLogic, gameId: String) +@(player: de.knockoutwhist.player.AbstractPlayer, gamelobby: logic.game.GameLobby) @main("Selecting Trumpsuit...") {
@@ -11,14 +11,14 @@

Select Trump Suit

- @if(player.equals(logic.getCurrentMatch.get.roundlist.last.winner.get)) { + @if(player.equals(gamelobby.logic.getCurrentMatch.get.roundlist.last.winner.get)) {
-
+
-
+
-
+
-
+
-
+
@for(i <- player.currentHand().get.cards.indices) {
@util.WebUIUtils.cardtoImage(player.currentHand().get.cards(i)) width="120px" style="border-radius: 6px"/> @@ -59,7 +59,7 @@
} else { }
diff --git a/knockoutwhistweb/app/views/ingame/tie.scala.html b/knockoutwhistweb/app/views/ingame/tie.scala.html index 7aad171..134f234 100644 --- a/knockoutwhistweb/app/views/ingame/tie.scala.html +++ b/knockoutwhistweb/app/views/ingame/tie.scala.html @@ -1,4 +1,4 @@ -@(player: de.knockoutwhist.player.AbstractPlayer, logic: de.knockoutwhist.control.GameLogic, gameId: String) +@(player: de.knockoutwhist.player.AbstractPlayer, gamelobby: logic.game.GameLobby) @main("Tie") {
@@ -15,20 +15,20 @@

The last round was tied between: - @for(players <- logic.playerTieLogic.getTiedPlayers) { + @for(players <- gamelobby.logic.playerTieLogic.getTiedPlayers) { @players }

- @if(player.equals(logic.playerTieLogic.currentTiePlayer())) { - @defining(logic.playerTieLogic.highestAllowedNumber()) { maxNum => + @if(player.equals(gamelobby.logic.playerTieLogic.currentTiePlayer())) { + @defining(gamelobby.logic.playerTieLogic.highestAllowedNumber()) { maxNum => -
+
@@ -42,8 +42,8 @@
Currently Picked Cards
- @if(logic.playerTieLogic.getSelectedCard.nonEmpty) { - @for((player, card) <- logic.playerTieLogic.getSelectedCard) { + @if(gamelobby.logic.playerTieLogic.getSelectedCard.nonEmpty) { + @for((player, card) <- gamelobby.logic.playerTieLogic.getSelectedCard) {
@@ -67,14 +67,14 @@ } } else {
Currently Picked Cards
- @if(logic.playerTieLogic.getSelectedCard.nonEmpty) { - @for((player, card) <- logic.playerTieLogic.getSelectedCard) { + @if(gamelobby.logic.playerTieLogic.getSelectedCard.nonEmpty) { + @for((player, card) <- gamelobby.logic.playerTieLogic.getSelectedCard) {
diff --git a/knockoutwhistweb/app/views/lobby/lobby.scala.html b/knockoutwhistweb/app/views/lobby/lobby.scala.html index 1ac678f..b7c53ba 100644 --- a/knockoutwhistweb/app/views/lobby/lobby.scala.html +++ b/knockoutwhistweb/app/views/lobby/lobby.scala.html @@ -20,42 +20,43 @@
@if((gamelobby.getUserSession(user.get.id).host)) { - @for(playersession <- gamelobby.getPlayers.values) { -
-
- Profile -
+
+ @for(playersession <- gamelobby.getPlayers.values) { +
+
+ Profile +
@if(playersession.id == user.get.id) {
@playersession.name (You)
- @*

Your text could be here!

*@ Remove } else {
@playersession.name
- @*

Your text could be here!

*@
Remove
} +
-
- } + } +
Start Game
} else { - @for(playersession <- gamelobby.getPlayers.values) { -
- Profile -
+
+ @for(playersession <- gamelobby.getPlayers.values) { +
+ Profile +
@if(playersession.id == user.get.id) { -
@playersession.name (You)
+
@playersession.name (You)
} else { -
@playersession.name
+
@playersession.name
} +
-
- } - + } +

Waiting for the host to start the game...

diff --git a/knockoutwhistweb/app/views/mainmenu/navbar.scala.html b/knockoutwhistweb/app/views/mainmenu/navbar.scala.html index 57d8d41..7f46751 100644 --- a/knockoutwhistweb/app/views/mainmenu/navbar.scala.html +++ b/knockoutwhistweb/app/views/mainmenu/navbar.scala.html @@ -1,5 +1,5 @@ @(user: Option[model.users.User]) -