extract action command
This commit is contained in:
@@ -2,14 +2,12 @@ package eventDemo.app.command
|
|||||||
|
|
||||||
import eventDemo.app.GameState
|
import eventDemo.app.GameState
|
||||||
import eventDemo.app.command.command.GameCommand
|
import eventDemo.app.command.command.GameCommand
|
||||||
|
import eventDemo.app.command.command.IWantToPlayCardCommand
|
||||||
import eventDemo.app.command.command.IamReadyToPlayCommand
|
import eventDemo.app.command.command.IamReadyToPlayCommand
|
||||||
import eventDemo.app.command.command.IwantToPlayCardCommand
|
|
||||||
import eventDemo.app.entity.Player
|
import eventDemo.app.entity.Player
|
||||||
import eventDemo.app.event.GameEventStream
|
import eventDemo.app.event.GameEventStream
|
||||||
import eventDemo.app.event.buildStateFromEventStream
|
import eventDemo.app.event.buildStateFromEventStream
|
||||||
import eventDemo.app.event.event.CardIsPlayedEvent
|
|
||||||
import eventDemo.app.event.event.GameEvent
|
import eventDemo.app.event.event.GameEvent
|
||||||
import eventDemo.app.event.event.PlayerReadyEvent
|
|
||||||
import io.ktor.websocket.Frame
|
import io.ktor.websocket.Frame
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -29,7 +27,7 @@ class GameCommandHandler(
|
|||||||
outgoing: SendChannel<Frame>,
|
outgoing: SendChannel<Frame>,
|
||||||
) {
|
) {
|
||||||
private val commandStream = GameCommandStream(incoming, outgoing)
|
private val commandStream = GameCommandStream(incoming, outgoing)
|
||||||
private val playerNotifier = outgoing
|
private val playerNotifier: (String) -> Unit = { runBlocking { outgoing.send(Frame.Text(it)) } }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init the handler
|
* Init the handler
|
||||||
@@ -41,48 +39,20 @@ class GameCommandHandler(
|
|||||||
nack()
|
nack()
|
||||||
}
|
}
|
||||||
|
|
||||||
val state = command.buildState()
|
val gameState = command.buildGameState()
|
||||||
|
|
||||||
when (command) {
|
when (command) {
|
||||||
is IwantToPlayCardCommand -> {
|
is IWantToPlayCardCommand -> {
|
||||||
// Check the command can be executed
|
command.run(gameState, playerNotifier, eventStream)
|
||||||
if (state.commandCardCanBeExecuted(command)) {
|
|
||||||
eventStream.publish(
|
|
||||||
CardIsPlayedEvent(
|
|
||||||
command.payload.gameId,
|
|
||||||
command.payload.card,
|
|
||||||
command.payload.player,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
runBlocking {
|
|
||||||
playerNotifier.send(Frame.Text("Command cannot be executed"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
is IamReadyToPlayCommand -> {
|
is IamReadyToPlayCommand -> {
|
||||||
if (state.playerIsAlreadyReady(command.payload.player)) {
|
command.run(gameState, playerNotifier, eventStream)
|
||||||
nack()
|
|
||||||
} else {
|
|
||||||
PlayerReadyEvent(
|
|
||||||
command.payload.gameId,
|
|
||||||
command.payload.player,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun GameState.playerIsAlreadyReady(player: Player): Boolean = readyPlayers.contains(player)
|
private fun GameCommand.buildGameState(): GameState = payload.gameId.buildStateFromEventStream(eventStream)
|
||||||
|
|
||||||
private fun GameState.commandCardCanBeExecuted(command: IwantToPlayCardCommand): Boolean =
|
|
||||||
canBePlayThisCard(
|
|
||||||
command.payload.player,
|
|
||||||
command.payload.card,
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun GameCommand.buildState(): GameState = payload.gameId.buildStateFromEventStream(eventStream)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
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.event.CardIsPlayedEvent
|
||||||
|
import eventDemo.libs.command.CommandId
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A command to perform an action to play a new card
|
||||||
|
*/
|
||||||
|
@Serializable
|
||||||
|
@SerialName("PlayCard")
|
||||||
|
data class IWantToPlayCardCommand(
|
||||||
|
override val payload: Payload,
|
||||||
|
) : GameCommand {
|
||||||
|
override val name: String = "PlayCard"
|
||||||
|
override val id: CommandId = CommandId()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class Payload(
|
||||||
|
override val gameId: GameId,
|
||||||
|
override val player: Player,
|
||||||
|
val card: Card,
|
||||||
|
) : GameCommand.Payload
|
||||||
|
|
||||||
|
fun run(
|
||||||
|
state: GameState,
|
||||||
|
playerNotifier: (String) -> Unit,
|
||||||
|
eventStream: GameEventStream,
|
||||||
|
) {
|
||||||
|
val commandCardCanBeExecuted: Boolean =
|
||||||
|
state.canBePlayThisCard(
|
||||||
|
payload.player,
|
||||||
|
payload.card,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (commandCardCanBeExecuted) {
|
||||||
|
eventStream.publish(
|
||||||
|
CardIsPlayedEvent(
|
||||||
|
payload.gameId,
|
||||||
|
payload.card,
|
||||||
|
payload.player,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
playerNotifier("Command cannot be executed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package eventDemo.app.command.command
|
package eventDemo.app.command.command
|
||||||
|
|
||||||
|
import eventDemo.app.GameState
|
||||||
import eventDemo.app.entity.GameId
|
import eventDemo.app.entity.GameId
|
||||||
import eventDemo.app.entity.Player
|
import eventDemo.app.entity.Player
|
||||||
|
import eventDemo.app.event.GameEventStream
|
||||||
|
import eventDemo.app.event.event.PlayerReadyEvent
|
||||||
import eventDemo.libs.command.CommandId
|
import eventDemo.libs.command.CommandId
|
||||||
import kotlinx.serialization.SerialName
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
@@ -22,4 +25,23 @@ data class IamReadyToPlayCommand(
|
|||||||
override val gameId: GameId,
|
override val gameId: GameId,
|
||||||
override val player: Player,
|
override val player: Player,
|
||||||
) : GameCommand.Payload
|
) : GameCommand.Payload
|
||||||
|
|
||||||
|
fun run(
|
||||||
|
state: GameState,
|
||||||
|
playerNotifier: (String) -> Unit,
|
||||||
|
eventStream: GameEventStream,
|
||||||
|
) {
|
||||||
|
val playerIsAlreadyReady: Boolean = state.readyPlayers.contains(payload.player)
|
||||||
|
|
||||||
|
if (playerIsAlreadyReady) {
|
||||||
|
playerNotifier("You are already ready")
|
||||||
|
} else {
|
||||||
|
eventStream.publish(
|
||||||
|
PlayerReadyEvent(
|
||||||
|
payload.gameId,
|
||||||
|
payload.player,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
package eventDemo.app.command.command
|
|
||||||
|
|
||||||
import eventDemo.app.entity.Card
|
|
||||||
import eventDemo.app.entity.GameId
|
|
||||||
import eventDemo.app.entity.Player
|
|
||||||
import eventDemo.libs.command.CommandId
|
|
||||||
import kotlinx.serialization.SerialName
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A command to perform an action to play a new card
|
|
||||||
*/
|
|
||||||
@Serializable
|
|
||||||
@SerialName("PlayCard")
|
|
||||||
data class IwantToPlayCardCommand(
|
|
||||||
override val payload: Payload,
|
|
||||||
) : GameCommand {
|
|
||||||
override val name: String = "PlayCard"
|
|
||||||
override val id: CommandId = CommandId()
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
data class Payload(
|
|
||||||
override val gameId: GameId,
|
|
||||||
override val player: Player,
|
|
||||||
val card: Card,
|
|
||||||
) : GameCommand.Payload
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user