Create GameStateRepository
Use GameState.apply() to build Projection Create GameEventHandler Add PlayerWinEvent
This commit is contained in:
@@ -1,15 +1,14 @@
|
||||
package eventDemo.app.command
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.command.command.GameCommand
|
||||
import eventDemo.app.command.command.ICantPlayCommand
|
||||
import eventDemo.app.command.command.IWantToJoinTheGameCommand
|
||||
import eventDemo.app.command.command.IWantToPlayCardCommand
|
||||
import eventDemo.app.command.command.IamReadyToPlayCommand
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.buildStateFromEventStream
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.event.GameEvent
|
||||
import eventDemo.app.event.projection.GameStateRepository
|
||||
import eventDemo.app.notification.ErrorNotification
|
||||
import eventDemo.shared.toFrame
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
@@ -24,7 +23,8 @@ import kotlinx.coroutines.channels.trySendBlocking
|
||||
* This action can be executing an action and produce a new [GameEvent] after verification.
|
||||
*/
|
||||
class GameCommandHandler(
|
||||
private val eventStream: GameEventStream,
|
||||
private val eventHandler: GameEventHandler,
|
||||
private val gameStateRepository: GameStateRepository,
|
||||
) {
|
||||
private val logger = KotlinLogging.logger { }
|
||||
|
||||
@@ -58,16 +58,14 @@ class GameCommandHandler(
|
||||
nack()
|
||||
}
|
||||
|
||||
val gameState = command.buildGameState()
|
||||
val gameState = gameStateRepository.get(command.payload.gameId)
|
||||
|
||||
when (command) {
|
||||
is IWantToPlayCardCommand -> command.run(gameState, playerErrorNotifier, eventStream)
|
||||
is IamReadyToPlayCommand -> command.run(gameState, playerErrorNotifier, eventStream)
|
||||
is IWantToJoinTheGameCommand -> command.run(gameState, playerErrorNotifier, eventStream)
|
||||
is ICantPlayCommand -> command.run(gameState, playerErrorNotifier, eventStream)
|
||||
is IWantToPlayCardCommand -> command.run(gameState, playerErrorNotifier, eventHandler)
|
||||
is IamReadyToPlayCommand -> command.run(gameState, playerErrorNotifier, eventHandler)
|
||||
is IWantToJoinTheGameCommand -> command.run(gameState, playerErrorNotifier, eventHandler)
|
||||
is ICantPlayCommand -> command.run(gameState, playerErrorNotifier, eventHandler)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun GameCommand.buildGameState(): GameState = payload.gameId.buildStateFromEventStream(eventStream)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package eventDemo.app.command.command
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.event.PlayerHavePassEvent
|
||||
import eventDemo.app.event.projection.GameState
|
||||
import eventDemo.libs.command.CommandId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@@ -26,13 +26,13 @@ data class ICantPlayCommand(
|
||||
fun run(
|
||||
state: GameState,
|
||||
playerErrorNotifier: (String) -> Unit,
|
||||
eventStream: GameEventStream,
|
||||
eventHandler: GameEventHandler,
|
||||
) {
|
||||
val playableCards = state.playableCards(payload.player)
|
||||
if (playableCards.isEmpty()) {
|
||||
val takenCard = state.deck.stack.first()
|
||||
|
||||
eventStream.publish(
|
||||
eventHandler.handle(
|
||||
PlayerHavePassEvent(
|
||||
gameId = payload.gameId,
|
||||
player = payload.player,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package eventDemo.app.command.command
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.event.NewPlayerEvent
|
||||
import eventDemo.app.event.projection.GameState
|
||||
import eventDemo.libs.command.CommandId
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -27,11 +27,11 @@ data class IWantToJoinTheGameCommand(
|
||||
fun run(
|
||||
state: GameState,
|
||||
playerErrorNotifier: (String) -> Unit,
|
||||
eventStream: GameEventStream,
|
||||
eventHandler: GameEventHandler,
|
||||
) {
|
||||
val logger = KotlinLogging.logger {}
|
||||
if (!state.isStarted) {
|
||||
eventStream.publish(
|
||||
eventHandler.handle(
|
||||
NewPlayerEvent(
|
||||
payload.gameId,
|
||||
payload.player,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package eventDemo.app.command.command
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.entity.Card
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.event.CardIsPlayedEvent
|
||||
import eventDemo.app.event.projection.GameState
|
||||
import eventDemo.libs.command.CommandId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@@ -28,7 +28,7 @@ data class IWantToPlayCardCommand(
|
||||
fun run(
|
||||
state: GameState,
|
||||
playerErrorNotifier: (String) -> Unit,
|
||||
eventStream: GameEventStream,
|
||||
eventHandler: GameEventHandler,
|
||||
) {
|
||||
if (!state.isStarted) {
|
||||
playerErrorNotifier("The game is Not started")
|
||||
@@ -36,7 +36,7 @@ data class IWantToPlayCardCommand(
|
||||
}
|
||||
|
||||
if (state.canBePlayThisCard(payload.player, payload.card)) {
|
||||
eventStream.publish(
|
||||
eventHandler.handle(
|
||||
CardIsPlayedEvent(
|
||||
payload.gameId,
|
||||
payload.card,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package eventDemo.app.command.command
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.event.PlayerReadyEvent
|
||||
import eventDemo.app.event.projection.GameState
|
||||
import eventDemo.libs.command.CommandId
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@@ -26,7 +26,7 @@ data class IamReadyToPlayCommand(
|
||||
fun run(
|
||||
state: GameState,
|
||||
playerErrorNotifier: (String) -> Unit,
|
||||
eventStream: GameEventStream,
|
||||
eventHandler: GameEventHandler,
|
||||
) {
|
||||
val playerExist: Boolean = state.players.contains(payload.player)
|
||||
val playerIsAlreadyReady: Boolean = state.readyPlayers.contains(payload.player)
|
||||
@@ -36,7 +36,7 @@ data class IamReadyToPlayCommand(
|
||||
} else if (playerIsAlreadyReady) {
|
||||
playerErrorNotifier("You are already ready")
|
||||
} else {
|
||||
eventStream.publish(
|
||||
eventHandler.handle(
|
||||
PlayerReadyEvent(
|
||||
payload.gameId,
|
||||
payload.player,
|
||||
|
||||
@@ -47,6 +47,11 @@ data class Deck(
|
||||
)
|
||||
}
|
||||
|
||||
fun playerHasNoCardLeft(): List<Player.PlayerId> =
|
||||
playersHands
|
||||
.filter { (playerId, hand) -> hand.isEmpty() }
|
||||
.map { (playerId, hand) -> playerId }
|
||||
|
||||
private fun take(n: Int): Pair<Deck, List<Card>> {
|
||||
val takenCards = stack.take(n)
|
||||
val newStack = stack.filterNot { takenCards.contains(it) }.toStack()
|
||||
|
||||
27
src/main/kotlin/eventDemo/app/event/GameEventHandler.kt
Normal file
27
src/main/kotlin/eventDemo/app/event/GameEventHandler.kt
Normal file
@@ -0,0 +1,27 @@
|
||||
package eventDemo.app.event
|
||||
|
||||
import eventDemo.app.event.event.GameEvent
|
||||
|
||||
/**
|
||||
* A stream to publish and read the played card event.
|
||||
*/
|
||||
class GameEventHandler(
|
||||
private val eventBus: GameEventBus,
|
||||
private val eventStream: GameEventStream,
|
||||
) {
|
||||
private val projectionsBuilders: MutableList<(GameEvent) -> Unit> = mutableListOf()
|
||||
|
||||
fun registerProjectionBuilder(builder: GameProjectionBuilder) {
|
||||
projectionsBuilders.add(builder)
|
||||
}
|
||||
|
||||
fun handle(vararg events: GameEvent) {
|
||||
events.forEach { event ->
|
||||
eventStream.publish(event)
|
||||
projectionsBuilders.forEach { it(event) }
|
||||
eventBus.publish(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typealias GameProjectionBuilder = (GameEvent) -> Unit
|
||||
@@ -8,11 +8,9 @@ import eventDemo.libs.event.EventStream
|
||||
* A stream to publish and read the played card event.
|
||||
*/
|
||||
class GameEventStream(
|
||||
private val eventBus: GameEventBus,
|
||||
private val eventStream: EventStream<GameEvent, GameId>,
|
||||
) : EventStream<GameEvent, GameId> by eventStream {
|
||||
override fun publish(event: GameEvent) {
|
||||
eventStream.publish(event)
|
||||
eventBus.publish(event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,14 +17,15 @@ data class GameStartedEvent(
|
||||
fun new(
|
||||
id: GameId,
|
||||
players: Set<Player>,
|
||||
shuffleIsDisabled: Boolean = isDisabled,
|
||||
): GameStartedEvent =
|
||||
GameStartedEvent(
|
||||
gameId = id,
|
||||
firstPlayer = if (isDisabled) players.first() else players.random(),
|
||||
firstPlayer = if (shuffleIsDisabled) players.first() else players.random(),
|
||||
deck =
|
||||
Deck
|
||||
.newWithoutPlayers()
|
||||
.let { if (isDisabled) it else it.shuffle() }
|
||||
.let { if (shuffleIsDisabled) it else it.shuffle() }
|
||||
.initHands(players)
|
||||
.placeFirstCardOnDiscard(),
|
||||
)
|
||||
|
||||
12
src/main/kotlin/eventDemo/app/event/event/PlayerWinEvent.kt
Normal file
12
src/main/kotlin/eventDemo/app/event/event/PlayerWinEvent.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
package eventDemo.app.event.event
|
||||
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.entity.Player
|
||||
|
||||
/**
|
||||
* This [GameEvent] is sent when a player is ready.
|
||||
*/
|
||||
data class PlayerWinEvent(
|
||||
override val gameId: GameId,
|
||||
val player: Player,
|
||||
) : GameEvent
|
||||
@@ -1,4 +1,4 @@
|
||||
package eventDemo.app
|
||||
package eventDemo.app.event.projection
|
||||
|
||||
import eventDemo.app.entity.Card
|
||||
import eventDemo.app.entity.Deck
|
||||
@@ -17,6 +17,7 @@ data class GameState(
|
||||
val readyPlayers: Set<Player> = emptySet(),
|
||||
val deck: Deck = Deck(players),
|
||||
val isStarted: Boolean = false,
|
||||
val playerWins: Set<Player> = emptySet(),
|
||||
) {
|
||||
@Serializable
|
||||
data class LastCard(
|
||||
@@ -92,6 +93,11 @@ data class GameState(
|
||||
?.filter { canBePlayThisCard(player, it) }
|
||||
?: emptyList()
|
||||
|
||||
fun playerHasNoCardLeft(): List<Player> =
|
||||
deck.playerHasNoCardLeft().map { playerId ->
|
||||
players.find { it.id == playerId } ?: error("inconsistency detected between players")
|
||||
}
|
||||
|
||||
fun canBePlayThisCard(
|
||||
player: Player,
|
||||
card: Card,
|
||||
@@ -1,8 +1,8 @@
|
||||
package eventDemo.app.event
|
||||
package eventDemo.app.event.projection
|
||||
|
||||
import eventDemo.app.GameState
|
||||
import eventDemo.app.entity.Card
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.event.CardIsPlayedEvent
|
||||
import eventDemo.app.event.event.GameEvent
|
||||
import eventDemo.app.event.event.GameStartedEvent
|
||||
@@ -10,19 +10,33 @@ import eventDemo.app.event.event.NewPlayerEvent
|
||||
import eventDemo.app.event.event.PlayerChoseColorEvent
|
||||
import eventDemo.app.event.event.PlayerHavePassEvent
|
||||
import eventDemo.app.event.event.PlayerReadyEvent
|
||||
import eventDemo.app.event.event.PlayerWinEvent
|
||||
|
||||
fun GameId.buildStateFromEventStream(eventStream: GameEventStream): GameState =
|
||||
buildStateFromEvents(
|
||||
eventStream.readAll(this),
|
||||
)
|
||||
|
||||
/**
|
||||
* Build the state to the specific event
|
||||
*/
|
||||
fun GameEvent.buildStateFromEventStreamTo(eventStream: GameEventStream): GameState =
|
||||
gameId.buildStateFromEvents(
|
||||
eventStream.readAll(gameId).takeWhile { it != this } + this,
|
||||
)
|
||||
|
||||
private fun GameId.buildStateFromEvents(events: List<GameEvent>): GameState =
|
||||
events.fold(GameState(this)) { state: GameState, event: GameEvent ->
|
||||
events.fold(GameState(this)) { state, event ->
|
||||
state.apply(event)
|
||||
}
|
||||
|
||||
fun List<GameEvent>.buildStateFromEvents(): GameState =
|
||||
fold(GameState(this.first().gameId)) { state, event ->
|
||||
state.apply(event)
|
||||
}
|
||||
|
||||
fun GameState.apply(event: GameEvent): GameState =
|
||||
let { state ->
|
||||
when (event) {
|
||||
is CardIsPlayedEvent -> {
|
||||
val direction =
|
||||
@@ -83,5 +97,11 @@ private fun GameId.buildStateFromEvents(events: List<GameEvent>): GameState =
|
||||
isStarted = true,
|
||||
)
|
||||
}
|
||||
|
||||
is PlayerWinEvent -> {
|
||||
copy(
|
||||
playerWins = playerWins + event.player,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package eventDemo.app.event.projection
|
||||
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class GameStateRepository(
|
||||
private val eventStream: GameEventStream,
|
||||
eventHandler: GameEventHandler,
|
||||
) {
|
||||
private val projections: ConcurrentHashMap<GameId, GameState> = ConcurrentHashMap()
|
||||
|
||||
init {
|
||||
eventHandler.registerProjectionBuilder { event ->
|
||||
val projection = projections[event.gameId]
|
||||
if (projection == null) {
|
||||
event.gameId
|
||||
.buildStateFromEventStream(eventStream)
|
||||
.update()
|
||||
} else {
|
||||
projection
|
||||
.apply(event)
|
||||
.let { projections.put(it.gameId, it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun get(gameId: GameId): GameState = gameId.buildStateFromEventStream(eventStream)
|
||||
|
||||
private fun GameState.update() {
|
||||
projections[gameId] = this
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package eventDemo.app.eventListener
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.app.event.GameEventBus
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.buildStateFromEventStreamTo
|
||||
import eventDemo.app.event.event.CardIsPlayedEvent
|
||||
import eventDemo.app.event.event.GameEvent
|
||||
import eventDemo.app.event.event.GameStartedEvent
|
||||
@@ -11,11 +10,14 @@ import eventDemo.app.event.event.NewPlayerEvent
|
||||
import eventDemo.app.event.event.PlayerChoseColorEvent
|
||||
import eventDemo.app.event.event.PlayerHavePassEvent
|
||||
import eventDemo.app.event.event.PlayerReadyEvent
|
||||
import eventDemo.app.event.event.PlayerWinEvent
|
||||
import eventDemo.app.event.projection.buildStateFromEventStreamTo
|
||||
import eventDemo.app.notification.PlayerAsJoinTheGameNotification
|
||||
import eventDemo.app.notification.PlayerAsPlayACardNotification
|
||||
import eventDemo.app.notification.PlayerHavePassNotification
|
||||
import eventDemo.app.notification.PlayerWasChoseTheCardColorNotification
|
||||
import eventDemo.app.notification.PlayerWasReadyNotification
|
||||
import eventDemo.app.notification.PlayerWinNotification
|
||||
import eventDemo.app.notification.TheGameWasStartedNotification
|
||||
import eventDemo.app.notification.WelcomeToTheGameNotification
|
||||
import eventDemo.app.notification.YourNewCardNotification
|
||||
@@ -102,7 +104,14 @@ class GameEventPlayerNotificationListener(
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
is PlayerWinEvent -> {
|
||||
PlayerWinNotification(
|
||||
player = event.player,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (notification == null) {
|
||||
logger.atInfo {
|
||||
message = "Notification Ignore: $event"
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
package eventDemo.app.eventListener
|
||||
|
||||
import eventDemo.app.event.GameEventBus
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.buildStateFromEventStreamTo
|
||||
import eventDemo.app.event.event.GameEvent
|
||||
import eventDemo.app.event.event.GameStartedEvent
|
||||
import eventDemo.app.event.event.PlayerWinEvent
|
||||
import eventDemo.app.event.projection.GameState
|
||||
import eventDemo.app.event.projection.buildStateFromEventStreamTo
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
|
||||
class GameEventReactionListener(
|
||||
private val eventBus: GameEventBus,
|
||||
private val eventHandler: GameEventHandler,
|
||||
private val eventStream: GameEventStream,
|
||||
private val priority: Int = DEFAULT_PRIORITY,
|
||||
) {
|
||||
@@ -21,22 +25,53 @@ class GameEventReactionListener(
|
||||
fun init() {
|
||||
eventBus.subscribe(priority) { event: GameEvent ->
|
||||
val state = event.buildStateFromEventStreamTo(eventStream)
|
||||
if (state.isReady && !state.isStarted) {
|
||||
val reactionEvent =
|
||||
GameStartedEvent.new(
|
||||
state.gameId,
|
||||
state.players,
|
||||
sendStartGameEvent(state, event)
|
||||
sendWinnerEvent(state, event)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendStartGameEvent(
|
||||
state: GameState,
|
||||
event: GameEvent,
|
||||
) {
|
||||
if (state.isReady && !state.isStarted) {
|
||||
val reactionEvent =
|
||||
GameStartedEvent.new(
|
||||
state.gameId,
|
||||
state.players,
|
||||
)
|
||||
logger.atInfo {
|
||||
message = "Event Send on reaction of: $event"
|
||||
payload =
|
||||
mapOf(
|
||||
"event" to event,
|
||||
"reactionEvent" to reactionEvent,
|
||||
)
|
||||
logger.atInfo {
|
||||
message = "Event Send on reaction of: $event"
|
||||
payload =
|
||||
mapOf(
|
||||
"event" to event,
|
||||
"reactionEvent" to reactionEvent,
|
||||
)
|
||||
}
|
||||
eventStream.publish(reactionEvent)
|
||||
}
|
||||
eventHandler.handle(reactionEvent)
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendWinnerEvent(
|
||||
state: GameState,
|
||||
event: GameEvent,
|
||||
) {
|
||||
val winner = state.playerHasNoCardLeft().firstOrNull()
|
||||
if (winner != null) {
|
||||
val reactionEvent =
|
||||
PlayerWinEvent(
|
||||
state.gameId,
|
||||
winner,
|
||||
)
|
||||
logger.atInfo {
|
||||
message = "Event Send on reaction of: $event"
|
||||
payload =
|
||||
mapOf(
|
||||
"event" to event,
|
||||
"reactionEvent" to reactionEvent,
|
||||
)
|
||||
}
|
||||
eventStream.publish(reactionEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
package eventDemo.app.notification
|
||||
|
||||
import eventDemo.app.entity.Player
|
||||
import eventDemo.shared.UUIDSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.util.UUID
|
||||
|
||||
@Serializable
|
||||
data class PlayerWinNotification(
|
||||
@Serializable(with = UUIDSerializer::class)
|
||||
override val id: UUID = UUID.randomUUID(),
|
||||
val player: Player,
|
||||
) : Notification
|
||||
@@ -1,10 +1,7 @@
|
||||
package eventDemo.app.query
|
||||
|
||||
import eventDemo.app.entity.GameId
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.buildStateFromEventStream
|
||||
import eventDemo.app.event.event.CardIsPlayedEvent
|
||||
import eventDemo.libs.event.readLastOf
|
||||
import eventDemo.app.event.projection.GameStateRepository
|
||||
import eventDemo.shared.GameIdSerializer
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.resources.Resource
|
||||
@@ -37,19 +34,21 @@ class Game(
|
||||
/**
|
||||
* API routes to read the game state.
|
||||
*/
|
||||
fun Route.readTheGameState(eventStream: GameEventStream) {
|
||||
fun Route.readTheGameState(gameStateRepository: GameStateRepository) {
|
||||
authenticate {
|
||||
// Read the last played card on the game.
|
||||
get<Game.Card> { body ->
|
||||
eventStream
|
||||
.readLastOf<CardIsPlayedEvent, _, _>(body.game.id)
|
||||
?.let { call.respond(it.card) }
|
||||
gameStateRepository
|
||||
.get(body.game.id)
|
||||
.lastCard
|
||||
?.card
|
||||
?.let { call.respond(it) }
|
||||
?: call.response.status(HttpStatusCode.BadRequest)
|
||||
}
|
||||
|
||||
// Read the last played card on the game.
|
||||
get<Game.State> { body ->
|
||||
val state = body.game.id.buildStateFromEventStream(eventStream)
|
||||
val state = gameStateRepository.get(body.game.id)
|
||||
call.respond(state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package eventDemo.configuration
|
||||
|
||||
import eventDemo.app.command.GameCommandHandler
|
||||
import eventDemo.app.event.GameEventBus
|
||||
import eventDemo.app.event.GameEventHandler
|
||||
import eventDemo.app.event.GameEventStream
|
||||
import eventDemo.app.event.projection.GameStateRepository
|
||||
import eventDemo.app.eventListener.GameEventPlayerNotificationListener
|
||||
import eventDemo.libs.event.EventBusInMemory
|
||||
import eventDemo.libs.event.EventStreamInMemory
|
||||
@@ -26,10 +28,16 @@ val appKoinModule =
|
||||
GameEventBus(EventBusInMemory())
|
||||
}
|
||||
single {
|
||||
GameEventStream(get(), EventStreamInMemory())
|
||||
GameEventStream(EventStreamInMemory())
|
||||
}
|
||||
single {
|
||||
GameCommandHandler(get())
|
||||
GameStateRepository(get(), get())
|
||||
}
|
||||
single {
|
||||
GameEventHandler(get(), get())
|
||||
}
|
||||
single {
|
||||
GameCommandHandler(get(), get())
|
||||
}
|
||||
|
||||
singleOf(::GameEventPlayerNotificationListener)
|
||||
|
||||
@@ -5,6 +5,6 @@ import io.ktor.server.application.Application
|
||||
import org.koin.ktor.ext.get
|
||||
|
||||
fun Application.configureGameListener() {
|
||||
GameEventReactionListener(get(), get())
|
||||
GameEventReactionListener(get(), get(), get())
|
||||
.init()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user