feat(ui): Fixed polling, added JQuery Ajax

Fixed Race Condition problems with polling, added JQuery
This commit is contained in:
LQ63
2025-11-19 15:14:47 +01:00
parent e60fe7c98d
commit e2a5cb9614
6 changed files with 312 additions and 312 deletions

View File

@@ -11,7 +11,7 @@ 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, LobbyUpdate, NewRound, ReloadEvent}
import logic.game.PollingEvents.{CardPlayed, LobbyCreation, LobbyUpdate, NewRound, ReloadEvent}
import model.sessions.{InteractionType, UserSession}
import model.users.User
@@ -27,21 +27,39 @@ class GameLobby private(
val name: String,
val maxPlayers: Int
) extends EventListener {
logic.addListener(this)
logic.createSession()
private val users: mutable.Map[UUID, UserSession] = mutable.Map()
private val pollingState: mutable.Queue[PollingEvents] = mutable.Queue()
private val eventsPerPlayer: mutable.Map[UUID, mutable.Queue[PollingEvents]] = mutable.Map()
private val waitingPromises: mutable.Map[UUID, ScalaPromise[PollingEvents]] = mutable.Map()
private val lock = new Object
lock.synchronized {
logic.addListener(this)
logic.createSession()
}
def registerWaiter(playerId: UUID): ScalaPromise[PollingEvents] = {
val promise = ScalaPromise[PollingEvents]()
waitingPromises.put(playerId, promise)
promise
lock.synchronized {
val queue = eventsPerPlayer.getOrElseUpdate(playerId, mutable.Queue())
if (queue.nonEmpty) {
val evt = queue.dequeue()
promise.success(evt)
promise
} else {
waitingPromises.put(playerId, promise)
promise
}
}
}
def removeWaiter(playerId: UUID): Unit = {
waitingPromises.remove(playerId)
lock.synchronized {
waitingPromises.remove(playerId)
}
}
def addUser(user: User): UserSession = {
@@ -72,7 +90,8 @@ class GameLobby private(
}
if (event.oldState == Lobby && event.newState == InGame) {
addToQueue(ReloadEvent)
}else {
return
} else {
addToQueue(ReloadEvent)
}
users.values.foreach(session => session.updatePlayer(event))
@@ -84,11 +103,29 @@ class GameLobby private(
}
private def addToQueue(event: PollingEvents): Unit = {
if (waitingPromises.nonEmpty) {
waitingPromises.values.foreach(_.success(event))
waitingPromises.clear()
} else {
pollingState.enqueue(event)
lock.synchronized {
users.keys.foreach { playerId =>
val q = eventsPerPlayer.getOrElseUpdate(playerId, mutable.Queue())
q.enqueue(event)
}
val waiterIds = waitingPromises.keys.toList
waiterIds.foreach { playerId =>
val q = eventsPerPlayer.getOrElseUpdate(playerId, mutable.Queue())
if (q.nonEmpty) {
val evt = q.dequeue()
val p = waitingPromises.remove(playerId)
p.foreach(_.success(evt))
}
}
}
waitingPromises.keys.foreach { playerId =>
val queue = eventsPerPlayer(playerId)
if (queue.nonEmpty) {
val promise = waitingPromises(playerId)
promise.success(queue.dequeue())
waitingPromises.remove(playerId)
}
}
}
@@ -218,8 +255,8 @@ class GameLobby private(
def getLogic: GameLogic = {
logic
}
def getPollingState: mutable.Queue[PollingEvents] = {
pollingState
def getEventsOfPlayer(playerId: UUID): mutable.Queue[PollingEvents] = {
eventsPerPlayer.getOrElseUpdate(playerId, mutable.Queue())
}
private def getPlayerBySession(userSession: UserSession): AbstractPlayer = {
val playerOption = getMatch.totalplayers.find(_.id == userSession.id)

View File

@@ -5,4 +5,5 @@ enum PollingEvents {
case NewRound
case ReloadEvent
case LobbyUpdate
case LobbyCreation
}