Add showdown status and card-reveal action to parsed hands#105
Merged
ggratte merged 3 commits intoItalyToast:masterfrom Apr 20, 2026
Merged
Add showdown status and card-reveal action to parsed hands#105ggratte merged 3 commits intoItalyToast:masterfrom
ggratte merged 3 commits intoItalyToast:masterfrom
Conversation
What ---- Two new properties, populated once per hand in a post-parse pass: - HandHistory.WentToShowdown (bool) — true iff the hand reached the showdown phase with at least two players still live. - Player.RevealAction (enum: NotShown / MuckedAtShowdown / ShownAtShowdown / ShownVoluntarily) — what the rest of the table saw this player do with their hole cards. Derivation lives in HandHistories.Parser.Analyzers.ShowdownAnalyzer and is invoked from HandHistoryParserFastImpl.ParseFullHandHistory right after FinalizeHandHistory, so every site parser gets it for free. Why --- Until now, Player.HoleCards was a single nullable slot that parsers overwrote regardless of how cards became known (dealt to hero, shown voluntarily, forced at showdown, or leaked via "mucked [cards]" in summary). Downstream consumers couldn't tell a hero's dealt cards from a villain's showdown reveal, and had no convenience flag for WTSD. The three facts are intentionally kept on orthogonal axes: * Does the parser have the cards? → Player.HoleCards != null * Is this player the hero? → HandHistory.Hero * What did the table see? → Player.RevealAction This way a hero who reaches showdown and turns over cleanly gets RevealAction.ShownAtShowdown (table-visibility) without losing the fact that HoleCards was set from the "Dealt to" line (parser-knowledge). Reveal values may be partial in Omaha/hi-lo (e.g. a player shows only some of 4/5/6 hole cards); this is documented on the enum and callers can detect it by comparing HoleCards.Count against the expected count for GameDescription.GameType. Tests ----- Five new unit tests in ShowdownAnalyzerTests cover each enum value, the WentToShowdown flag, and the mucked-but-leaked-in-summary case. Cross-platform test-infra fixes (required to run the suite on macOS) -------------------------------------------------------------------- - Retargeted both unit-test projects from netcoreapp3.1 to net8.0. .NET Core 3.1 is EOL (Dec 2022) and has no native arm64 build, so the previous target couldn't run on Apple Silicon without installing the x64 runtime under Rosetta 2. Production libraries remain on netstandard2.0 / netstandard2.1, so downstream consumers are unaffected. The rationale is inlined in both csproj files. - Replaced a hard-coded backslash path separator in SampleHandHistoryRepositoryFileBasedImpl with Path.Combine. The old code returned null on unix filesystems, causing ~700 cascading NullReferenceException failures in tests that split the result. After these fixes the suite goes from unrunnable → 994 passing / 27 failing on macOS. The remaining 27 failures are pre-existing cross-platform issues (Windows-1252 sample-file encoding read as UTF-8, and "\r\n"-only line splits on LF checkouts) and are unrelated to this change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Surfaces two new properties on every parsed hand, derived once in a post-parse pass so no site parser needs to change:
HandHistory.WentToShowdown(bool) — true iff the hand reached showdown with at least two players still live.Player.RevealAction(enum:NotShown/MuckedAtShowdown/ShownAtShowdown/ShownVoluntarily) — what the rest of the table saw this player do with their hole cards.Why
Until now,
Player.HoleCardswas a single nullable slot that parsers overwrote regardless of how the cards became known — dealt to hero, shown voluntarily, forced at showdown, or leaked viamucked [cards]in summary. Consumers couldn't distinguish a hero's dealt cards from a villain's showdown reveal, and had no convenience flag for WTSD.The three facts are kept on orthogonal axes by design:
Player.HoleCards != nullHandHistory.HeroPlayer.RevealAction(new)So a hero who reaches showdown and turns over cleanly gets
RevealAction.ShownAtShowdown(table-visibility) without losing the fact thatHoleCardswas set from the "Dealt to" line (parser-knowledge).Reveal values may be partial in Omaha / hi-lo split games (a player shows only some of 4/5/6 hole cards). This is documented on the enum; callers detect it by comparing
HoleCards.Countagainst the expected count forGameDescription.GameType.Implementation
HandHistories.Objects/Cards/RevealAction.cs— new enum with XML docs.HandHistories.Objects/Players/Player.cs— newRevealActionproperty (defaults toNotShown).HandHistories.Objects/Hand/HandHistory.cs— newWentToShowdownproperty (defaults tofalse).HandHistories.Parser/Analyzers/ShowdownAnalyzer.cs— single linear walk ofHandActionsto populate both.HandHistories.Parser/Parsers/FastParser/Base/HandHistoryParserFastImpl.cs— invokes the analyzer right afterFinalizeHandHistoryinParseFullHandHistory, so every site parser inherits the behaviour.Test-infra fixes bundled in (required to run the suite on macOS)
These are small but worth flagging so reviewers know why they're in this PR:
netcoreapp3.1tonet8.0. .NET Core 3.1 is EOL (Dec 2022) with no native arm64 build, so the previous target couldn't run on Apple Silicon without x64 + Rosetta 2. Production libraries stay onnetstandard2.0/netstandard2.1— downstream consumers unaffected. Rationale is inlined in both csproj files.\path separator inSampleHandHistoryRepositoryFileBasedImpl.GetSampleHandHistoryFolderwithPath.Combine. The old code returnednullon unix filesystems, cascading into ~700NullReferenceExceptions in tests that split the result.After these fixes the suite goes from unrunnable on macOS → 994 passing / 27 failing. The remaining 27 failures are pre-existing cross-platform issues (Windows-1252 sample-file encoding read as UTF-8, and
\r\n-only line splits on LF checkouts) and are unrelated to this change.Test plan
ShowdownAnalyzerTests(5 tests) covers every enum value, theWentToShowdownflag, and the mucked-but-leaked-in-summary case — all pass.🤖 Generated with Claude Code