From 32472018d4b8540597d061969d762618dfa023cd Mon Sep 17 00:00:00 2001 From: Fabrice Lecomte Date: Wed, 5 Mar 2025 01:48:19 +0100 Subject: [PATCH] players hands and deck is modify on PlayerHavePassEvent & CardIsPlayedEvent events --- src/main/kotlin/eventDemo/app/entity/Deck.kt | 44 ++++++++++++++++--- .../kotlin/eventDemo/app/entity/PlayerHand.kt | 17 ++++--- .../eventDemo/app/event/GameStateBuilder.kt | 4 +- 3 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/eventDemo/app/entity/Deck.kt b/src/main/kotlin/eventDemo/app/entity/Deck.kt index c5601d0..55ae55d 100644 --- a/src/main/kotlin/eventDemo/app/entity/Deck.kt +++ b/src/main/kotlin/eventDemo/app/entity/Deck.kt @@ -6,9 +6,9 @@ import kotlinx.serialization.Serializable data class Deck( val stack: Set = emptySet(), val discard: Set = emptySet(), - val playersHands: List = emptyList(), + val playersHands: PlayerHands = emptyMap(), ) { - constructor(players: List) : this(playersHands = players.map { PlayerHand(it) }) + constructor(players: List) : this(playersHands = players.associateWith { emptyList() }) fun putOneCardOnDiscard(): Deck { val takenCard = stack.first() @@ -16,20 +16,54 @@ data class Deck( return copy(stack = newStack) } - fun take(n: Int): Pair> { + private fun take(n: Int): Pair> { val takenCards = stack.take(n) val newStack = stack.filterNot { takenCards.contains(it) }.toSet() return Pair(copy(stack = newStack), takenCards) } + private fun takeOne(): Pair = take(1).let { (deck, cards) -> Pair(deck, cards.first()) } + + fun takeOneCardTo(player: Player): Deck = + takeOne().let { (deck, newPlayerCard) -> + val newHands = + deck.playersHands.mapValues { (p, cards) -> + if (p == player) { + cards + newPlayerCard + } else { + cards + } + } + deck.copy(playersHands = newHands) + } + + fun putOneCardFromHand( + player: Player, + card: Card, + ): Deck = + run { + // Validate parameters + val playerHand = + playersHands[player] + ?: error("No player on this game") + if (playerHand.none { it == card }) { + error("No card exist on the player hand") + } + }.let { + copy( + discard = discard + card, + playersHands = playersHands.addCard(player, card), + ) + } + companion object { fun initHands( players: Set, handSize: Int = 7, ): Deck { val deck = new() - val playersHands = players.map { PlayerHand(it, deck.stack.take(handSize)) } - val allTakenCards = playersHands.flatMap { it.cards } + val playersHands = players.associateWith { deck.stack.take(handSize) } + val allTakenCards = playersHands.flatMap { it.value } val newStack = deck.stack.filterNot { allTakenCards.contains(it) }.toSet() return deck.copy( stack = newStack, diff --git a/src/main/kotlin/eventDemo/app/entity/PlayerHand.kt b/src/main/kotlin/eventDemo/app/entity/PlayerHand.kt index 4fea5cc..1b89bca 100644 --- a/src/main/kotlin/eventDemo/app/entity/PlayerHand.kt +++ b/src/main/kotlin/eventDemo/app/entity/PlayerHand.kt @@ -1,11 +1,14 @@ package eventDemo.app.entity -import kotlinx.serialization.Serializable +typealias PlayerHands = Map> -@Serializable -data class PlayerHand( - val player: Player, - val cards: List = emptyList(), -) { - val count = lazy { cards.count() } +fun PlayerHands.addCard( + player: Player, + card: Card, +) = mapValues { (p, cards) -> + if (p == player) { + cards - card + } else { + cards + } } diff --git a/src/main/kotlin/eventDemo/app/event/GameStateBuilder.kt b/src/main/kotlin/eventDemo/app/event/GameStateBuilder.kt index d616bda..2f0cdbe 100644 --- a/src/main/kotlin/eventDemo/app/event/GameStateBuilder.kt +++ b/src/main/kotlin/eventDemo/app/event/GameStateBuilder.kt @@ -37,6 +37,7 @@ private fun GameId.buildStateFromEvents(events: List): GameState = lastPlayer = event.player, direction = direction, lastColor = color, + deck = state.deck.putOneCardFromHand(event.player, event.card), ) } @@ -57,6 +58,7 @@ private fun GameId.buildStateFromEvents(events: List): GameState = is PlayerHavePassEvent -> { state.copy( lastPlayer = event.player, + deck = state.deck.takeOneCardTo(event.player), ) } @@ -69,7 +71,7 @@ private fun GameId.buildStateFromEvents(events: List): GameState = is GameStartedEvent -> { state.copy( lastColor = (event.deck.discard.first() as? Card.ColorCard)?.color, - lastCard = eventDemo.app.GameState.LastCard(event.deck.discard.first(), event.firstPlayer), + lastCard = GameState.LastCard(event.deck.discard.first(), event.firstPlayer), lastPlayer = event.firstPlayer, deck = event.deck, isStarted = true,