Add deterministic post-action coach
This commit is contained in:
@@ -10,6 +10,12 @@ class CashGameSessionTest {
|
||||
@Test
|
||||
fun `blank player name has an honest second-person fallback`() {
|
||||
assertEquals("You", cashGameConfig(" ").playerName)
|
||||
assertFalse("coach must be opt-in", cashGameConfig("Jay").coachEnabled)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `coach preference crosses the session boundary explicitly`() {
|
||||
assertTrue(cashGameConfig("Jay", coachEnabled = true).coachEnabled)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package com.jsjdesigns.poker
|
||||
|
||||
import com.jsjdesigns.poker.bot.CoachingReview
|
||||
import com.jsjdesigns.poker.bot.DecisionTrace
|
||||
import com.jsjdesigns.poker.game.Action
|
||||
import com.jsjdesigns.poker.game.ActionType
|
||||
import com.jsjdesigns.poker.game.Street
|
||||
import com.jsjdesigns.poker.game.TableSnapshot
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
|
||||
class CoachPresentationTest {
|
||||
|
||||
private fun review(
|
||||
handNumber: Int = 4,
|
||||
token: Long = 12,
|
||||
street: Street = Street.RIVER,
|
||||
aligned: Boolean = false,
|
||||
trace: DecisionTrace = postflopTrace(),
|
||||
) = CoachingReview(
|
||||
decisionToken = token,
|
||||
handNumber = handNumber,
|
||||
street = street,
|
||||
trace = trace,
|
||||
alignedWithBaseline = aligned,
|
||||
)
|
||||
|
||||
@Test
|
||||
fun `postflop presentation consumes audited equity and pot odds fields`() {
|
||||
val presentation = coachPresentation(review())
|
||||
|
||||
assertEquals("Worth reviewing", presentation.title)
|
||||
assertEquals(
|
||||
"Estimated 34% equity vs random hands; calling needs 25%. Baseline: Call 20.",
|
||||
presentation.detail,
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `preflop presentation never describes percentile as equity`() {
|
||||
val trace = DecisionTrace(
|
||||
estimatedEquity = null,
|
||||
handStrengthPercentile = 0.08,
|
||||
breakEvenEquity = null,
|
||||
decisionThreshold = null,
|
||||
preflopRangeThreshold = 0.22,
|
||||
potOdds = null,
|
||||
intended = Action(ActionType.RAISE, 6),
|
||||
chosen = Action(ActionType.RAISE, 8),
|
||||
mistakeApplied = false,
|
||||
adjustments = emptyList(),
|
||||
reason = "chart baseline",
|
||||
)
|
||||
|
||||
val presentation = coachPresentation(
|
||||
review(street = Street.PREFLOP, aligned = true, trace = trace),
|
||||
)
|
||||
|
||||
assertEquals("Baseline agrees", presentation.title)
|
||||
assertTrue("percentile" in presentation.detail)
|
||||
assertTrue("equity" !in presentation.detail)
|
||||
assertTrue("Raise to 6" in presentation.detail)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `review is visible only for opted-in exact latest decision and hand`() {
|
||||
val review = review()
|
||||
val matching = UiState(
|
||||
gameConfig = CashGameConfig("Jay", coachEnabled = true),
|
||||
snapshot = snapshot(handNumber = 4),
|
||||
coachReview = review,
|
||||
latestHeroDecisionToken = 12,
|
||||
)
|
||||
|
||||
assertEquals(review, matching.visibleCoachReview())
|
||||
assertNull(
|
||||
matching.copy(
|
||||
gameConfig = matching.gameConfig?.copy(coachEnabled = false),
|
||||
).visibleCoachReview(),
|
||||
)
|
||||
assertNull(matching.copy(latestHeroDecisionToken = 13).visibleCoachReview())
|
||||
assertNull(matching.copy(snapshot = snapshot(handNumber = 5)).visibleCoachReview())
|
||||
}
|
||||
|
||||
private fun postflopTrace() = DecisionTrace(
|
||||
estimatedEquity = 0.34,
|
||||
handStrengthPercentile = null,
|
||||
breakEvenEquity = 0.25,
|
||||
decisionThreshold = 0.25,
|
||||
preflopRangeThreshold = null,
|
||||
potOdds = "60:20",
|
||||
intended = Action(ActionType.CALL, 20),
|
||||
chosen = Action(ActionType.FOLD),
|
||||
mistakeApplied = false,
|
||||
adjustments = emptyList(),
|
||||
reason = "fundamentals baseline",
|
||||
)
|
||||
|
||||
private fun snapshot(handNumber: Int) = TableSnapshot(
|
||||
handNumber = handNumber,
|
||||
street = Street.RIVER,
|
||||
phase = TableSnapshot.Phase.BETTING,
|
||||
board = emptyList(),
|
||||
pot = 80,
|
||||
currentBet = 20,
|
||||
minRaiseSize = 20,
|
||||
button = 0,
|
||||
seats = emptyList(),
|
||||
toAct = null,
|
||||
toActToken = null,
|
||||
lastAction = null,
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user