Skip to content

Commit

Permalink
removing executor
Browse files Browse the repository at this point in the history
  • Loading branch information
robertfmurdock committed Jul 19, 2023
1 parent 900168d commit 6651217
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import com.zegreatrob.coupling.model.pairassignmentdocument.TimeResultValue
import com.zegreatrob.coupling.model.pairassignmentdocument.calculateTimeSinceLastPartnership
import com.zegreatrob.coupling.model.pairassignmentdocument.pairOf
import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.testmints.action.SimpleExecutableAction
import com.zegreatrob.testmints.action.async.SimpleSuspendAction

data class CreatePairCandidateReportAction(
val player: Player,
val history: List<PairAssignmentDocument>,
val allPlayers: List<Player>,
) : SimpleExecutableAction<CreatePairCandidateReportAction.Dispatcher, PairCandidateReport> {
) : SimpleSuspendAction<CreatePairCandidateReportAction.Dispatcher, PairCandidateReport> {
override val performFunc = link(Dispatcher::perform)

interface Dispatcher {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,28 @@ package com.zegreatrob.coupling.server.action.pairassignmentdocument
import com.zegreatrob.coupling.model.map
import com.zegreatrob.coupling.model.party.PairingRule
import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.testmints.action.ExecutableActionExecutor
import com.zegreatrob.coupling.server.action.CannonProvider
import com.zegreatrob.testmints.action.annotation.ActionMint
import kotools.types.collection.NotEmptyList

@ActionMint
data class CreatePairCandidateReportListAction(val game: GameSpin) {

interface Dispatcher<out D> : PlayerCandidatesFinder where D : CreatePairCandidateReportAction.Dispatcher {

val execute: ExecutableActionExecutor<CreatePairCandidateReportAction.Dispatcher>
interface Dispatcher<out D> : CannonProvider<D>, PlayerCandidatesFinder
where D : CreatePairCandidateReportAction.Dispatcher {

suspend fun perform(action: CreatePairCandidateReportListAction) = action.createReports()

private fun CreatePairCandidateReportListAction.createReportsUsingLongestRule() =
private suspend fun CreatePairCandidateReportListAction.createReportsUsingLongestRule() =
game.createReports(PairingRule.LongestTime)

private fun CreatePairCandidateReportListAction.createReports(): NotEmptyList<PairCandidateReport> =
private suspend fun CreatePairCandidateReportListAction.createReports(): NotEmptyList<PairCandidateReport> =
game.createReports(game.rule)

private fun GameSpin.createReports(rule: PairingRule) =
private suspend fun GameSpin.createReports(rule: PairingRule) =
remainingPlayers.map { player -> pairCandidateReport(rule, player) }

private fun GameSpin.pairCandidateReport(rule: PairingRule, player: Player): PairCandidateReport {
private suspend fun GameSpin.pairCandidateReport(rule: PairingRule, player: Player): PairCandidateReport {
val candidates = findCandidates(remainingPlayers, rule, player)
return if (candidates.isNotEmpty()) {
createReport(player, candidates)
Expand All @@ -34,7 +33,7 @@ data class CreatePairCandidateReportListAction(val game: GameSpin) {
}
}

private fun GameSpin.createReport(player: Player, candidates: List<Player>) = execute(
private suspend fun GameSpin.createReport(player: Player, candidates: List<Player>) = cannon.fire(
CreatePairCandidateReportAction(player, history, candidates),
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
package com.zegreatrob.coupling.server.action.pairassignmentdocument

import com.zegreatrob.coupling.model.forEach
import com.zegreatrob.coupling.model.map
import com.zegreatrob.coupling.model.pairassignmentdocument.NeverPaired
import com.zegreatrob.coupling.model.pairassignmentdocument.PairAssignmentDocument
import com.zegreatrob.coupling.model.pairassignmentdocument.TimeResultValue
import com.zegreatrob.coupling.model.party.PairingRule
import com.zegreatrob.coupling.model.player.Player
import com.zegreatrob.coupling.server.action.StubActionExecutor
import com.zegreatrob.coupling.server.action.stubActionExecutor
import com.zegreatrob.coupling.testaction.StubCannon
import com.zegreatrob.minassert.assertIsEqualTo
import com.zegreatrob.testmints.async.ScopeMint
import com.zegreatrob.testmints.async.asyncSetup
import kotlinx.coroutines.channels.produce
import kotools.types.collection.NotEmptyList
import kotools.types.collection.notEmptyListOf
import kotlin.test.Test

class CreatePairCandidateReportsActionTest {

class WhenThePartyPrefersPairingWithDifferentBadges :
CreatePairCandidateReportListAction.Dispatcher<CreatePairCandidateReportAction.Dispatcher> {
override val execute = stubActionExecutor(CreatePairCandidateReportAction::class)
interface CreatePairCandidateReportsActionTestDispatcher :
CreatePairCandidateReportListAction.Dispatcher<CreatePairCandidateReportsActionTestDispatcher>,
CreatePairCandidateReportAction.Dispatcher

class WhenThePartyPrefersPairingWithDifferentBadges {

@Test
fun willReturnAllReportsForPlayersWithTheSameBadge() = asyncSetup(object {
fun willReturnAllReportsForPlayersWithTheSameBadge() = asyncSetup(object :
ScopeMint(),
CreatePairCandidateReportsActionTestDispatcher {
val bill = Player(id = "Bill", badge = 1, avatarType = null)
val ted = Player(id = "Ted", badge = 1, avatarType = null)
val amadeus = Player(id = "Mozart", badge = 1, avatarType = null)
Expand All @@ -36,18 +43,25 @@ class CreatePairCandidateReportsActionTest {

val history = emptyList<PairAssignmentDocument>()
val gameSpin = GameSpin(players, history, PairingRule.PreferDifferentBadge)
}) {
expectedReports.toList().forEach { report ->
execute.givenPlayerReturnReport(report, players.without(report.player), history)
}
} exercise {
val receivedActions = mutableListOf<Any?>()
override val cannon = StubCannon<CreatePairCandidateReportsActionTestDispatcher>(
receivedActions,
exerciseScope.produce { expectedReports.forEach { report -> send(report) } },
)
}) exercise {
perform(CreatePairCandidateReportListAction(gameSpin))
} verify { result ->
result.assertIsEqualTo(expectedReports)
receivedActions.assertIsEqualTo(
expectedReports.map { CreatePairCandidateReportAction(it.player, history, players.without(it.player)) }
.toList(),
)
}

@Test
fun willReturnFilterCandidatesByUnlikeBadge() = asyncSetup(object {
fun willReturnFilterCandidatesByUnlikeBadge() = asyncSetup(object :
ScopeMint(),
CreatePairCandidateReportsActionTestDispatcher {
val history = emptyList<PairAssignmentDocument>()
val bill = Player(id = "Bill", badge = 1, avatarType = null)
val ted = Player(id = "Ted", badge = 1, avatarType = null)
Expand All @@ -62,39 +76,53 @@ class CreatePairCandidateReportsActionTest {
val expectedReports = notEmptyListOf(billReport, tedReport, amadeusReport, shortyReport)

val gameSpin = GameSpin(players, history, PairingRule.PreferDifferentBadge)
}) {
execute.run {
givenPlayerReturnReport(billReport, listOf(altAmadeus, altShorty), history)
givenPlayerReturnReport(tedReport, listOf(altAmadeus, altShorty), history)
givenPlayerReturnReport(amadeusReport, listOf(bill, ted), history)
givenPlayerReturnReport(shortyReport, listOf(bill, ted), history)
}
} exercise {
val receivedActions = mutableListOf<Any?>()
override val cannon = StubCannon<CreatePairCandidateReportsActionTestDispatcher>(
receivedActions,
exerciseScope.produce {
expectedReports.forEach { report -> send(report) }
},
)
}) exercise {
perform(CreatePairCandidateReportListAction(gameSpin))
} verify { result ->
result.assertIsEqualTo(expectedReports)
receivedActions.assertIsEqualTo(
listOf(
CreatePairCandidateReportAction(bill, history, listOf(altAmadeus, altShorty)),
CreatePairCandidateReportAction(ted, history, listOf(altAmadeus, altShorty)),
CreatePairCandidateReportAction(altAmadeus, history, listOf(bill, ted)),
CreatePairCandidateReportAction(altShorty, history, listOf(bill, ted)),
),
)
}

@Test
fun willReturnReportForOnePlayer() = asyncSetup(object {
fun willReturnReportForOnePlayer() = asyncSetup(object :
ScopeMint(),
CreatePairCandidateReportsActionTestDispatcher {
val history = emptyList<PairAssignmentDocument>()
val bill = Player(id = "Bill", badge = 1, avatarType = null)
val players = notEmptyListOf(bill)
val billReport = PairCandidateReport(bill, emptyList(), TimeResultValue(1))
val gameSpin = GameSpin(players, history, PairingRule.PreferDifferentBadge)
}) {
execute.givenPlayerReturnReport(billReport, emptyList(), history)
} exercise {
val receivedActions = mutableListOf<Any?>()
override val cannon = StubCannon<CreatePairCandidateReportsActionTestDispatcher>(
receivedActions,
exerciseScope.produce { send(billReport) },
)
}) exercise {
perform(CreatePairCandidateReportListAction(gameSpin))
} verify {
it.assertIsEqualTo(notEmptyListOf(billReport))
receivedActions.assertIsEqualTo(listOf(CreatePairCandidateReportAction(bill, history, emptyList())))
}
}

@Test
fun whenThePartyPrefersPairingByLongestTime() = asyncSetup(object :
CreatePairCandidateReportListAction.Dispatcher<CreatePairCandidateReportAction.Dispatcher> {
override val execute = stubActionExecutor(CreatePairCandidateReportAction::class)
ScopeMint(),
CreatePairCandidateReportsActionTestDispatcher {
val history = listOf<PairAssignmentDocument>()
val bill = Player(id = "Bill", badge = 1, avatarType = null)
val ted = Player(id = "Ted", badge = 1, avatarType = null)
Expand All @@ -107,34 +135,26 @@ class CreatePairCandidateReportsActionTest {
val amadeusReport = PairCandidateReport(altAmadeus, emptyList(), NeverPaired)
val shortyReport = PairCandidateReport(altShorty, emptyList(), NeverPaired)
val expectedReports = notEmptyListOf(billReport, tedReport, amadeusReport, shortyReport)
}) {
execute.run {
givenPlayerReturnReport(billReport, players.without(bill), history)
givenPlayerReturnReport(tedReport, players.without(ted), history)
givenPlayerReturnReport(amadeusReport, players.without(altAmadeus), history)
givenPlayerReturnReport(shortyReport, players.without(altShorty), history)
}
} exercise {
val receivedActions = mutableListOf<Any?>()
override val cannon = StubCannon<CreatePairCandidateReportsActionTestDispatcher>(
receivedActions,
exerciseScope.produce { expectedReports.forEach { report -> send(report) } },
)
}) exercise {
perform(CreatePairCandidateReportListAction(GameSpin(players, history, PairingRule.LongestTime)))
} verify {
it.assertIsEqualTo(expectedReports)
receivedActions.assertIsEqualTo(
listOf(
CreatePairCandidateReportAction(bill, history, players.without(bill)),
CreatePairCandidateReportAction(ted, history, players.without(ted)),
CreatePairCandidateReportAction(altAmadeus, history, players.without(altAmadeus)),
CreatePairCandidateReportAction(altShorty, history, players.without(altShorty)),
),
)
}

companion object {

private fun StubActionExecutor<
CreatePairCandidateReportAction.Dispatcher,
CreatePairCandidateReportAction,
PairCandidateReport,
>.givenPlayerReturnReport(
pairCandidateReport: PairCandidateReport,
players: List<Player>,
history: List<PairAssignmentDocument>,
) = whenever(
receive = CreatePairCandidateReportAction(pairCandidateReport.player, history, players),
returnValue = pairCandidateReport,
)

private fun NotEmptyList<Player>.without(player: Player) = toList().filterNot { it == player }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ import com.zegreatrob.coupling.server.secret.JwtSecretGenerator
import com.zegreatrob.coupling.server.secret.ServerDeleteSecretCommandDispatcher
import com.zegreatrob.coupling.server.slack.FetchSlackRepository
import com.zegreatrob.testmints.action.ActionCannon
import com.zegreatrob.testmints.action.ExecutableActionExecutor
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
Expand Down Expand Up @@ -141,7 +140,6 @@ class CurrentPartyDispatcher(
ServerSavePinCommandDispatcher,
CannonProvider<CurrentPartyDispatcher> {
override val userId: String get() = commandDispatcher.userId
override val execute: ExecutableActionExecutor<PairAssignmentDispatcher<CurrentPartyDispatcher>> = this
override val cannon: ActionCannon<CurrentPartyDispatcher> = ActionCannon(this, LoggingActionPipe(traceId))
suspend fun isAuthorized() = currentPartyId.validateAuthorized() != null
override val actionDispatcher = this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import com.zegreatrob.coupling.server.action.pairassignmentdocument.FindNewPairs
import com.zegreatrob.coupling.server.action.pairassignmentdocument.NextPlayerAction
import com.zegreatrob.coupling.server.action.pairassignmentdocument.ShufflePairsAction
import com.zegreatrob.coupling.server.action.pairassignmentdocument.Wheel
import com.zegreatrob.testmints.action.ExecutableActionExecutor

interface PairAssignmentDispatcher<D> :
ShufflePairsAction.Dispatcher<D>,
Expand All @@ -20,6 +19,5 @@ interface PairAssignmentDispatcher<D> :
D : NextPlayerAction.Dispatcher<D>,
D : AssignPinsAction.Dispatcher,
D : FindNewPairsAction.Dispatcher<D> {
override val execute: ExecutableActionExecutor<PairAssignmentDispatcher<D>>
override val wheel: Wheel get() = this
}

0 comments on commit 6651217

Please sign in to comment.