Compare commits

...

14 Commits

13 changed files with 125 additions and 34 deletions

View File

@@ -292,3 +292,38 @@
### Features ### Features
* Add logging to Gateway for pod synchronization and startup events ([6ef7401](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/6ef74014430673e725245bf37e44c5b90b81abb3)) * Add logging to Gateway for pod synchronization and startup events ([6ef7401](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/6ef74014430673e725245bf37e44c5b90b81abb3))
## (2026-01-07)
### Features
* Add logging to Gateway for pod synchronization and startup events ([2615707](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/26157076d686a5dd3f8157ec2b2d1ae9d9e9eedf))
## (2026-01-07)
### Features
* Add Health and Login endpoints with updated Redis configuration ([4a5af36](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/4a5af36ae0dcb540e02b7a1cd042e54cc6342c78))
## (2026-01-07)
### Features
* Update Gateway to use ArrayList for game IDs and bound users ([2f89951](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/2f89951c25484d6bc412536a83019ee6d0b7f780))
## (2026-01-07)
### Features
* Update joinGame endpoint to accept gameId as a path parameter ([cf18549](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/cf1854976a51eb4931d50cf93640498ed18686fc))
## (2026-01-07)
### Features
* Enhance user state management with polling and WebSocket connection handling ([b4bf2ce](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/b4bf2ceb4dc76ac388124b9705a1aa9e577582af))
### Bug Fixes
* Update knockoutwhistfrontend hash for consistency ([0e555cd](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/0e555cdfeb114464c9438bfd5dc397201a073867))
## (2026-01-07)
### Features
* Implement PlayDogCard functionality in user session and update Vue component ([859dfce](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/859dfce521b193b9208d0c70fca88016f8fe08f4))
* Implement PlayDogCard functionality in user session and update Vue component ([61ae9b5](https://git.janis-eccarius.de/KnockOutWhist/KnockOutWhist-Web/commit/61ae9b5a5e7cd9fd82b77e9159814b0066874c2d))

View File

@@ -1,6 +1,6 @@
meta { meta {
name: Game name: Game
seq: 3 seq: 2
} }
auth { auth {

View File

@@ -0,0 +1,16 @@
meta {
name: Health
type: http
seq: 3
}
get {
url: {{host}}/health/simple
body: none
auth: inherit
}
settings {
encodeUrl: true
timeout: 0
}

View File

@@ -0,0 +1,3 @@
vars {
host: https://st.knockout.janis-eccarius.de/api
}

View File

@@ -0,0 +1,30 @@
package controllers
import auth.{AuthAction, AuthenticatedRequest}
import dto.subDTO.UserDTO
import logic.user.{SessionManager, UserManager}
import model.users.User
import play.api.*
import play.api.libs.json.Json
import play.api.mvc.*
import play.api.mvc.Cookie.SameSite.{Lax, None, Strict}
import javax.inject.*
/**
* This controller creates an `Action` to handle HTTP requests to the
* application's home page.
*/
@Singleton
class HealthController @Inject()(
val controllerComponents: ControllerComponents,
) extends BaseController {
def simple(): Action[AnyContent] = {
Action { implicit request =>
Ok("OK")
}
}
}

View File

@@ -55,32 +55,21 @@ class MainMenuController @Inject()(
} }
def joinGame(): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] => def joinGame(gameId: String): Action[AnyContent] = authAction { implicit request: AuthenticatedRequest[AnyContent] =>
val jsonBody = request.body.asJson val game = PodManager.getGame(gameId)
val gameId: Option[String] = jsonBody.flatMap { jsValue => game match {
(jsValue \ "gameId").asOpt[String] case Some(g) =>
} g.addUser(request.user)
if (gameId.isDefined) { Ok(Json.obj(
val game = PodManager.getGame(gameId.get) "status" -> "success",
game match { "redirectUrl" -> routes.IngameController.game(g.id).url,
case Some(g) => "content" -> IngameController.returnInnerHTML(g, g.logic.getCurrentState, request.user).toString
g.addUser(request.user) ))
Ok(Json.obj( case None =>
"status" -> "success", NotFound(Json.obj(
"redirectUrl" -> routes.IngameController.game(g.id).url, "status" -> "failure",
"content" -> IngameController.returnInnerHTML(g, g.logic.getCurrentState, request.user).toString "errorMessage" -> "No Game found"
)) ))
case None =>
NotFound(Json.obj(
"status" -> "failure",
"errorMessage" -> "No Game found"
))
}
} else {
BadRequest(Json.obj(
"status" -> "failure",
"errorMessage" -> "Invalid form submission"
))
} }
} }

View File

@@ -34,6 +34,7 @@ class StatusController @Inject()(
Json.obj( Json.obj(
"status" -> "authenticated", "status" -> "authenticated",
"username" -> user.name, "username" -> user.name,
"userId" -> user.id,
"inGame" -> false "inGame" -> false
) )
) )
@@ -43,6 +44,7 @@ class StatusController @Inject()(
Json.obj( Json.obj(
"status" -> "authenticated", "status" -> "authenticated",
"username" -> user.name, "username" -> user.name,
"userId" -> user.id,
"inGame" -> true, "inGame" -> true,
"gameId" -> game.id "gameId" -> game.id
) )

View File

@@ -7,6 +7,7 @@ import org.redisson.config.Config
import play.api.Logger import play.api.Logger
import play.api.inject.ApplicationLifecycle import play.api.inject.ApplicationLifecycle
import java.util
import java.util.UUID import java.util.UUID
import javax.inject.* import javax.inject.*
import scala.concurrent.ExecutionContext import scala.concurrent.ExecutionContext
@@ -22,7 +23,9 @@ class Gateway @Inject()(
val redis: RedisManager = { val redis: RedisManager = {
val config: Config = Config() val config: Config = Config()
config.useSingleServer.setAddress("valkey://" + sys.env.getOrElse("VALKEY_HOST", "localhost") + ":" + sys.env.getOrElse("VALKEY_PORT", "6379")) val url = "redis://" + sys.env.getOrElse("REDIS_HOST", "localhost") + ":" + sys.env.getOrElse("REDIS_PORT", "6379")
logger.info(s"Connecting to Redis at $url")
config.useSingleServer.setAddress(url)
RedisManager(config) RedisManager(config)
} }
@@ -43,8 +46,8 @@ class Gateway @Inject()(
PodManager.podName, PodManager.podName,
PodManager.podIp, PodManager.podIp,
9000, 9000,
PodManager.getAllGameIds().asJava, new util.ArrayList[String](PodManager.getAllGameIds().asJava),
PodManager.allBoundUsers().asJava new util.ArrayList[String](PodManager.allBoundUsers().asJava)
) )
} }

View File

@@ -54,6 +54,16 @@ class UserSession(val user: User, val host: Boolean, val gameLobby: GameLobby) e
case None => case None =>
println("Card Index not found or is not a number." + data) println("Card Index not found or is not a number." + data)
} }
case "PlayDogCard" =>
val maybeCardIndex: Option[Int] = (data \ "cardindex").asOpt[Int]
maybeCardIndex match {
case Some(index) =>
val session = gameLobby.getUserSession(user.id)
gameLobby.playDogCard(session, index)
case None =>
val session = gameLobby.getUserSession(user.id)
gameLobby.playDogCard(session, -1)
}
case "PickTrumpsuit" => case "PickTrumpsuit" =>
val maybeSuitIndex: Option[Int] = (data \ "suitIndex").asOpt[Int] val maybeSuitIndex: Option[Int] = (data \ "suitIndex").asOpt[Int]
maybeSuitIndex match { maybeSuitIndex match {

View File

@@ -15,7 +15,7 @@ GET /rules controllers.MainMenuController.rules()
GET /navSPA/:pType controllers.MainMenuController.navSPA(pType) GET /navSPA/:pType controllers.MainMenuController.navSPA(pType)
POST /createGame controllers.MainMenuController.createGame() POST /createGame controllers.MainMenuController.createGame()
POST /joinGame controllers.MainMenuController.joinGame() POST /joinGame/:gameId controllers.MainMenuController.joinGame(gameId: String)
# User authentication routes # User authentication routes
POST /login controllers.UserController.login_Post() POST /login controllers.UserController.login_Post()
@@ -30,4 +30,7 @@ GET /websocket controllers.WebsocketController.socket()
# Status # Status
GET /status controllers.StatusController.requestStatus() GET /status controllers.StatusController.requestStatus()
GET /status/:gameId controllers.StatusController.game(gameId: String) GET /status/:gameId controllers.StatusController.game(gameId: String)
# Health
GET /health/simple controllers.HealthController.simple()

View File

@@ -1,3 +1,3 @@
MAJOR=4 MAJOR=4
MINOR=21 MINOR=27
PATCH=0 PATCH=0