diff --git a/knockoutwhist b/knockoutwhist index b9a7b0a..5aa1cef 160000 --- a/knockoutwhist +++ b/knockoutwhist @@ -1 +1 @@ -Subproject commit b9a7b0a2af7cef7225bf1a0388ebf58171a173f2 +Subproject commit 5aa1cef35689d2df8a89e2d8864fc5fcf9c30e33 diff --git a/knockoutwhistweb/app/assets/stylesheets/dark-mode.less b/knockoutwhistweb/app/assets/stylesheets/dark-mode.less index 02d2efa..c34aab1 100644 --- a/knockoutwhistweb/app/assets/stylesheets/dark-mode.less +++ b/knockoutwhistweb/app/assets/stylesheets/dark-mode.less @@ -3,7 +3,7 @@ --background-image: url('/assets/images/background.png') !important; --color: #f8f9fa !important; /* Light text on dark bg */ --highlightscolor: rgba(131, 131, 131, 0.75) !important; - + --background-color: #192734; /* Bootstrap variable overrides for dark mode */ --bs-body-color: var(--color); --bs-link-color: #66b2ff; diff --git a/knockoutwhistweb/app/assets/stylesheets/light-mode.less b/knockoutwhistweb/app/assets/stylesheets/light-mode.less index 5975dcc..3054bc2 100644 --- a/knockoutwhistweb/app/assets/stylesheets/light-mode.less +++ b/knockoutwhistweb/app/assets/stylesheets/light-mode.less @@ -2,4 +2,5 @@ --background-image: url('/assets/images/img.png'); --color: black; --highlightscolor: rgba(0, 0, 0, 0.75); + --background-color: rgba(228, 232, 237, 1); } diff --git a/knockoutwhistweb/app/assets/stylesheets/main.less b/knockoutwhistweb/app/assets/stylesheets/main.less index d41bf29..e1beaa4 100644 --- a/knockoutwhistweb/app/assets/stylesheets/main.less +++ b/knockoutwhistweb/app/assets/stylesheets/main.less @@ -14,7 +14,7 @@ --bs-border-color: rgba(0, 0, 0, 0.125) !important; --bs-heading-color: var(--color) !important; } - +@background-color: var(--background-color); @highlightcolor: var(--highlightscolor); @background-image: var(--background-image); @color: var(--color); @@ -29,6 +29,10 @@ background-repeat: no-repeat; background-attachment: fixed; } +.lobby-background { + background-color: @background-color; + +} .navbar-header{ text-align:center; @@ -71,6 +75,10 @@ body { overflow: auto; } +.navbar-drop-shadow { + box-shadow: 0 1px 15px 0 #000000 +} + #sessions { display: flex; flex-direction: column; @@ -205,4 +213,36 @@ body { color: @color; font-size: 1.5em; font-family: Arial, serif; -} \ No newline at end of file +} + +/* In-game centered stage and blurred sides overlay */ +.ingame-stage { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: 2rem 1rem; +} + +/* Wrapper that adds a backdrop blur to the background outside the centered card */ +.blur-sides { + position: relative; +} + +/* Create an overlay that blurs everything behind it, except the central content area */ +.blur-sides::before { + content: ""; + position: fixed; + inset: 0; + pointer-events: none; + /* fallback: subtle vignette if backdrop-filter unsupported */ + background: radial-gradient(ellipse at center, rgba(0,0,0,0) 30%, rgba(0,0,0,0.35) 100%); +} + +@supports ((-webkit-backdrop-filter: blur(8px)) or (backdrop-filter: blur(8px))) { + .blur-sides::before { + background: rgba(0,0,0,0.08); + -webkit-backdrop-filter: blur(10px) saturate(110%); + backdrop-filter: blur(10px) saturate(110%); + } +} diff --git a/knockoutwhistweb/app/controllers/IngameController.scala b/knockoutwhistweb/app/controllers/IngameController.scala index 373701d..0008ece 100644 --- a/knockoutwhistweb/app/controllers/IngameController.scala +++ b/knockoutwhistweb/app/controllers/IngameController.scala @@ -38,12 +38,14 @@ class IngameController @Inject()( case SelectTrump => Ok(views.html.ingame.selecttrump( g.getPlayerByUser(request.user), - g.logic + g.logic, + gameId )) case TieBreak => Ok(views.html.ingame.tie( g.getPlayerByUser(request.user), - g.logic + g.logic, + gameId )) case _ => InternalServerError(s"Invalid game state for in-game view. GameId: $gameId" + s" State: ${g.logic.getCurrentState}") @@ -250,7 +252,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) + g.selectTie(g.getUserSession(request.user.id), tie.toInt - 1) } optSession.foreach(_.lock.unlock()) if (result.isSuccess) { diff --git a/knockoutwhistweb/app/logic/game/GameLobby.scala b/knockoutwhistweb/app/logic/game/GameLobby.scala index 486bf4f..0e8ac9f 100644 --- a/knockoutwhistweb/app/logic/game/GameLobby.scala +++ b/knockoutwhistweb/app/logic/game/GameLobby.scala @@ -157,6 +157,9 @@ 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) } diff --git a/knockoutwhistweb/app/views/ingame/ingame.scala.html b/knockoutwhistweb/app/views/ingame/ingame.scala.html index db56c27..ba204cb 100644 --- a/knockoutwhistweb/app/views/ingame/ingame.scala.html +++ b/knockoutwhistweb/app/views/ingame/ingame.scala.html @@ -3,6 +3,7 @@ @(player: de.knockoutwhist.player.AbstractPlayer, gamelobby: logic.game.GameLobby) @main("Ingame") { +
@@ -67,4 +68,5 @@
+
} diff --git a/knockoutwhistweb/app/views/ingame/selecttrump.scala.html b/knockoutwhistweb/app/views/ingame/selecttrump.scala.html index 8aef1e3..82c58c2 100644 --- a/knockoutwhistweb/app/views/ingame/selecttrump.scala.html +++ b/knockoutwhistweb/app/views/ingame/selecttrump.scala.html @@ -1,27 +1,72 @@ -@(player: de.knockoutwhist.player.AbstractPlayer, logic: de.knockoutwhist.control.GameLogic) +@(player: de.knockoutwhist.player.AbstractPlayer, logic: de.knockoutwhist.control.GameLogic, gameId: String) @main("Selecting Trumpsuit...") {
- @if(player.equals(logic.getCurrentMatch.get.roundlist.last.winner.get)) { -

Knockout Whist

-

You (@player.toString) have won the last round! Select a trumpsuit for the next round!

-

Available trumpsuits are displayed below:

-
- @util.WebUIUtils.cardtoImage(de.knockoutwhist.cards.Card(de.knockoutwhist.cards.CardValue.Ace, de.knockoutwhist.cards.Suit.Spades)) - @util.WebUIUtils.cardtoImage(de.knockoutwhist.cards.Card(de.knockoutwhist.cards.CardValue.Ace, de.knockoutwhist.cards.Suit.Clubs)) - @util.WebUIUtils.cardtoImage(de.knockoutwhist.cards.Card(de.knockoutwhist.cards.CardValue.Ace, de.knockoutwhist.cards.Suit.Hearts)) - @util.WebUIUtils.cardtoImage(de.knockoutwhist.cards.Card(de.knockoutwhist.cards.CardValue.Ace, de.knockoutwhist.cards.Suit.Diamonds)) -
-

Your cards

+
+
+
+
+
+
+

Select Trump Suit

+
+
+ @if(player.equals(logic.getCurrentMatch.get.roundlist.last.winner.get)) { + -
- @for(card <- player.currentHand().get.cards) { - @util.WebUIUtils.cardtoImage(card) - } +
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ @for(i <- player.currentHand().get.cards.indices) { +
+ @util.WebUIUtils.cardtoImage(player.currentHand().get.cards(i)) width="120px" style="border-radius: 6px"/> +
+ } +
+ } else { + + } +
+
+
+
- } else { -

Knockout Whist

-

@player.toString is choosing a trumpsuit. Starting new round when @player.toString picked a trumpsuit...

- } +
} \ No newline at end of file diff --git a/knockoutwhistweb/app/views/ingame/tie.scala.html b/knockoutwhistweb/app/views/ingame/tie.scala.html index 505c68d..7aad171 100644 --- a/knockoutwhistweb/app/views/ingame/tie.scala.html +++ b/knockoutwhistweb/app/views/ingame/tie.scala.html @@ -1,27 +1,107 @@ -@(player: de.knockoutwhist.player.AbstractPlayer, logic: de.knockoutwhist.control.GameLogic) +@(player: de.knockoutwhist.player.AbstractPlayer, logic: de.knockoutwhist.control.GameLogic, gameId: String) @main("Tie") {
-

Knockout Whist

-

The last Round was tied between - @for(players <- logic.playerTieLogic.getTiedPlayers) { - @players - } -

- @if(player.equals(logic.playerTieLogic.currentTiePlayer())) { -

Pick a card between 1 and @logic.playerTieLogic.highestAllowedNumber()! The resulting card will be your card for the cut.

- } else { -

@logic.playerTieLogic.currentTiePlayer() is currently picking his number for the cut.

-

Currently picked Cards:

-
- @for((player, card) <- logic.playerTieLogic.getSelectedCard) { -
-

@player

- @util.WebUIUtils.cardtoImage(card) -
- } -
- } +
+
+
+
+
+
+

Tie Break

+
+
+
+

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

+
+ @if(player.equals(logic.playerTieLogic.currentTiePlayer())) { + @defining(logic.playerTieLogic.highestAllowedNumber()) { maxNum => + + +
+
+ +
+
+ +
+
+ +
+
+
Currently Picked Cards
+ +
+ @if(logic.playerTieLogic.getSelectedCard.nonEmpty) { + @for((player, card) <- logic.playerTieLogic.getSelectedCard) { +
+
+
+

@player

+
+ @util.WebUIUtils.cardtoImage(card) +
+
+
+
+ } + } else { +
+ +
+ } +
+ } + } else { + + +
Currently Picked Cards
+ +
+ @if(logic.playerTieLogic.getSelectedCard.nonEmpty) { + @for((player, card) <- logic.playerTieLogic.getSelectedCard) { +
+
+
+

@player

+
+ @util.WebUIUtils.cardtoImage(card) +
+
+
+
+ } + } else { +
+ +
+ } +
+ } + +
+
+
+
+
+
} \ No newline at end of file diff --git a/knockoutwhistweb/app/views/lobby/lobby.scala.html b/knockoutwhistweb/app/views/lobby/lobby.scala.html index 46eabb6..a8832e9 100644 --- a/knockoutwhistweb/app/views/lobby/lobby.scala.html +++ b/knockoutwhistweb/app/views/lobby/lobby.scala.html @@ -1,82 +1,73 @@ @(user: Option[model.users.User], gamelobby: logic.game.GameLobby) @main("Lobby") { -
-
-
-
-
- Lobby-Name: @gamelobby.name +
+
+
+
+
+
+ Lobby-Name: @gamelobby.name +
+
+ +
-
- -
-
-
-
-
Playeramount: @gamelobby.getPlayers.size / @gamelobby.maxPlayers
+
+
+
Playeramount: @gamelobby.getPlayers.size / @gamelobby.maxPlayers
+
-
-
- - @if((gamelobby.getUserSession(user.get.id).host)) { - @for(playersession <- gamelobby.getPlayers.values) { -
-
+
+ @if((gamelobby.getUserSession(user.get.id).host)) { + @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!

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

Your text could be here!

*@ - Remove +
@playersession.name (You)
} else { -
@playersession.name
-@*

Your text could be here!

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

Waiting for the host to start the game...

-
-
-
-
-
-
- Loading...
+ } + +
+

Waiting for the host to start the game...

+
+ Loading... +
-
- } + } +
-
+
} \ No newline at end of file diff --git a/knockoutwhistweb/app/views/main.scala.html b/knockoutwhistweb/app/views/main.scala.html index daccc3a..12d9c2c 100644 --- a/knockoutwhistweb/app/views/main.scala.html +++ b/knockoutwhistweb/app/views/main.scala.html @@ -18,15 +18,10 @@ - -
+ @* And here's where we render the `Html` object containing * the page content. *@ @content -
- -
-
diff --git a/knockoutwhistweb/app/views/mainmenu/creategame.scala.html b/knockoutwhistweb/app/views/mainmenu/creategame.scala.html index 1e5905c..f1de596 100644 --- a/knockoutwhistweb/app/views/mainmenu/creategame.scala.html +++ b/knockoutwhistweb/app/views/mainmenu/creategame.scala.html @@ -2,31 +2,33 @@ @main("Create Game") { @navbar(user) -
-
-
- - -
-
- - -
+
+ +
- - -
- 2 - 3 - 4 - 5 - 6 - 7 -
+ + +
+
+ + +
+
+ + +
+ 2 + 3 + 4 + 5 + 6 + 7 +
+
+
+
-
-
-
- + +
} \ No newline at end of file diff --git a/knockoutwhistweb/app/views/mainmenu/navbar.scala.html b/knockoutwhistweb/app/views/mainmenu/navbar.scala.html index 5d21070..57d8d41 100644 --- a/knockoutwhistweb/app/views/mainmenu/navbar.scala.html +++ b/knockoutwhistweb/app/views/mainmenu/navbar.scala.html @@ -1,6 +1,6 @@ @(user: Option[model.users.User])