Create test for complete game

create notifications for reply the players
implement notifications on GameEventPlayerNotificationListener
add priority to the eventbus.subscribe()
improve JWT creation
update libs koin + ktor
remove output of GameCommandStream
improve logs
create a function disableShuffleDeck to disable the shuffle of the deck (for tests)
This commit is contained in:
2025-03-08 01:07:45 +01:00
parent 99f0760d3c
commit 51d857513c
55 changed files with 659 additions and 235 deletions

View File

@@ -11,6 +11,8 @@ data class Deck(
constructor(players: Set<Player>) :
this(playersHands = PlayersHands(players))
fun shuffle(): Deck = copy(stack = stack.shuffle())
fun placeFirstCardOnDiscard(): Deck {
val takenCard = stack.first()
return copy(
@@ -21,16 +23,9 @@ data class Deck(
fun takeOneCardFromStackTo(player: Player): Deck =
takeOne().let { (deck, newPlayerCard) ->
val newHands =
deck.playersHands
.mapValues { (p, cards) ->
if (p == player) {
cards + newPlayerCard
} else {
cards
}
}.toPlayersHands()
deck.copy(playersHands = newHands)
deck.copy(
playersHands = deck.playersHands.addCard(player, newPlayerCard),
)
}
fun putOneCardFromHand(
@@ -40,7 +35,7 @@ data class Deck(
run {
// Validate parameters
val playerHand =
playersHands[player]
playersHands.getHand(player)
?: error("No player on this game")
if (playerHand.none { it == card }) {
error("No card exist on the player hand")
@@ -70,8 +65,7 @@ data class Deck(
(1..2).map { Card.PassCard(color) }
}.let {
it + (1..4).map { Card.Plus4Card() }
}.shuffled()
.toStack()
}.toStack()
.let { Deck(it) }
}
}
@@ -100,6 +94,8 @@ value class Stack(
operator fun plus(card: Card): Stack = cards.plus(card).toStack()
operator fun minus(card: Card): Stack = cards.minus(card).toStack()
fun shuffle(): Stack = shuffled().toStack()
}
fun List<Card>.toStack(): Stack = Stack(this.toSet())

View File

@@ -12,4 +12,6 @@ import java.util.UUID
@Serializable(with = GameIdSerializer::class)
value class GameId(
override val id: UUID = UUID.randomUUID(),
) : AggregateId
) : AggregateId {
override fun toString(): String = id.toString()
}

View File

@@ -18,6 +18,7 @@ data class Player(
PlayerId(UUID.fromString(id)),
)
@Serializable
@JvmInline
value class PlayerId(
@Serializable(with = UUIDSerializer::class)

View File

@@ -5,28 +5,38 @@ import kotlinx.serialization.Serializable
@Serializable
@JvmInline
value class PlayersHands(
private val map: Map<Player, List<Card>> = emptyMap(),
) : Map<Player, List<Card>> by map {
constructor(players: Set<Player>) : this(players.associateWith { emptyList<Card>() }.toPlayersHands())
private val map: Map<Player.PlayerId, List<Card>> = emptyMap(),
) : Map<Player.PlayerId, List<Card>> by map {
constructor(players: Set<Player>) :
this(players.map { it.id }.associateWith { emptyList<Card>() }.toPlayersHands())
fun getHand(player: Player): List<Card>? = this[player.id]
fun removeCard(
player: Player,
card: Card,
): PlayersHands =
mapValues { (p, cards) ->
if (p == player) {
mapValues { (playerId, cards) ->
if (playerId == player.id) {
if (!cards.contains(card)) error("The hand no contain the card")
cards - card
} else {
cards
}
}.toPlayersHands()
fun addCard(
player: Player,
newCard: Card,
): PlayersHands = addCards(player, listOf(newCard))
fun addCards(
player: Player,
newCards: List<Card>,
): PlayersHands =
mapValues { (p, cards) ->
if (p == player) {
if (p == player.id) {
if (cards.intersect(newCards).isNotEmpty()) error("The hand already contain the card")
cards + newCards
} else {
cards
@@ -34,4 +44,4 @@ value class PlayersHands(
}.toPlayersHands()
}
fun Map<Player, List<Card>>.toPlayersHands(): PlayersHands = PlayersHands(this)
fun Map<Player.PlayerId, List<Card>>.toPlayersHands(): PlayersHands = PlayersHands(this)