Sent with QoS 1, not retained.
We send this exactly once for a final round. It is sent when the dealer has removed all
cards from the table, not when the dealer is finished drawing cards.
This is the full data structure describing the live state of the table: the cards and
where they are, the chips, the cash and the phase the round is in.
It says nothing about how the round ended. Hand values, who won or lost and what each bet
paid are worked out from the game's rules and published on their own topic.
players
The length of this list is fixed and determined with the calibration procedure.
NOTE: Don't rely on this being constant for a single configuration, even though it
is currently. Also, the system can be recalibrated at any time, changing the length
of this list.
dealer
All the information about the dealer.
layout_side_bets
If side bets are configured, the stacks assigned to them are listed here.
lifetime
The number of frames since the round was initialized
diagnostics
This contains warnings about procedure issues
initialized_ts
The timestamp when this round was initialized. It can be initialized by the detection
of game objects like cards and chip stacks.
phase_timestamps
The timestamps for when each phase change.
If a phase is not present in the dict, it means it has not started.
A phase can also be present multiple times if a card is not seen anymore
and we decide that it is better to go to a previous phase.
cash
A flat list of the bills we estimate are on the table right now. It is a snapshot taken
when this message was published, not part of the round state: cash neither starts nor
ends a round.
NOTE: in the future we want to add structure to it and identify cash transactions.
id
UUID v4. It is generated each new round. A round starts as soon as anything relevant
is detected. Currently 'anything relevant' means cards or chips.
The latter is only considered if that model is deployed and configured.
Not every UUID should be treated as a full round, it might be canceled and never reach
RoundOver but only RoundCanceled.
Example: A chip stack is recognized and then disappears.
This describes the current game phase.
Note: It doesn't always move forward. Sometimes the system will correct itself
due to cards being occluded or intentionally moved.
The round starts as EMPTY.
When the first chip is placed on the table we enter PRE_FIRST_CARDS.
Once a card is detected and assigned to a player or dealer, we enter FIRST_CARDS.
When the dealer has a card, and all players have 2 cards we go to PLAYERS_TURN.
In this state the players do all their actions.
DEALERS_TURN is the dealers turn.
When the round is over we go to DEALER_DONE.
In some situations we cannot determine if the round is over without more context
so we go to DEALER_MAYBE_DONE. For example: All players have busted,
but the dealer has to finish playing the hand anyways because of a side bet.
At the end we will go into ROUND_OVER if the round is supposed to be stored, and into
ROUND_CANCELED if we classify it as sensor noise.
This state will only be reached once, you should not miss this event.
We use this to mark what rounds we store in the database or show on the screen.
Even rounds with wrong dealer procedure will reach ROUND_OVER, they are marked
as such in the anomalies / diagnostics fields.
This structure contains all player specific information.
stacks
This refers to the card stack, and the chips associated to this stack of cards.
A player can have 0 stacks, which means that it is inactive.
A player can have >1 stack, when they split their cards.
initial_bets
When the round starts and players place their bets, the chip stacks are tracked
as initial bets here.
The initial bets for the next round are also tracked here.
payout_stacks
After the dealer is done, stacks can be identified as being a payout and they will
be tracked in this field.
NOTE: We are not yet tracking payouts on a per bet level, but a per player level.
side_bets
This will track the chip stacks for each configured player side bet.
Must contain a minimum of 0 items
The word stack refers to card stack and the associated chip stacks.
A stack is usually part of a player data structure or a dealer data structure.
There is no distinction between a dealer stack and a player stack as of now on
the data modeling level.
cards
Here we track the cards belonging to this stack. This list is never empty.
NOTE: The cards might be deleted from here in the same round. This is supposed to
happen when a dealer drops a card, it got assigned to a stack, and then quickly moves
the card somewhere else.
is_doubled
We take multiple indicators to decide if a stack was doubled including:
- card rotation
- card placement
- chip stacks
main_bet_stacks
These are the chip stacks that we think are the main bet for this card stack.
There are multiple chip stacks here if a player doubled, or is about to split.
In case of a split: The main bet stacks are then split up to each stack.
back_bet_stacks
In Europe it is common to allow other people to bet on your hand with a bet position
called back bet. The semantics are similar to the main_bet_stacks.
settled_early
The hand left the table before the dealer's second card, and how it was settled:
folded (SURRENDERED) or a blackjack taken at 1:1 against a dealer ace (EVEN_MONEY).
We read this off the hand being collected, so it can flip back to None if the cards
reappear. None for databases recorded before the field existed.
Must contain a minimum of 1 items
Describes a playing card.
The keypoints are the corners of the rectangle. This is actually a parallelogram as
of today, but don't rely on it.
rotation is measured as the angle in degrees between the longer axis with the
y-axis (the second coordinate).
Must contain a minimum of 4 items
Must contain a maximum of 4 items
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Certainty runs from 0 to 1 and says how sure the system is of the label. It is not a
probability: readings a few frames apart are near-duplicates, so it saturates far faster
than independent evidence would.
It defaults so that recordings made before it replaced evidence still decode.
This data is tracked over time. Don't rely too much on it, e.g. hit_counter_max might
change during the lifetime of a tracked object.
The fields start and stop are useful to understand when in a round this object
was seen. They are given in the number of frames since initialization.
Note: In the future these might be fully timestamped.
Describes a stack of chips (without counting, just stating its presence).
lt stands for the left top corner and rb for the right bottom corner.
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Certainty runs from 0 to 1 and says how sure the system is of the label. It is not a
probability: readings a few frames apart are near-duplicates, so it saturates far faster
than independent evidence would.
It defaults so that recordings made before it replaced evidence still decode.
chips is what the stack is made of, bottom to top -- None on a table with no chip
model deployed, which is every table until one is. It is a list rather than a count per
denomination because a stack can be mixed, and the order is what lets a chip added on
top keep the reading the chips below it already earned.
One chip in a stack, as the currency it belongs to and what it is worth.
denomination is in whole currency units, so a twenty-five euro chip is 25. Which
denominations exist is a property of the deployed chip model, the same way a bill's is,
so there is no global list of them here.
This data is tracked over time. Don't rely too much on it, e.g. hit_counter_max might
change during the lifetime of a tracked object.
The fields start and stop are useful to understand when in a round this object
was seen. They are given in the number of frames since initialization.
Note: In the future these might be fully timestamped.
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Describes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIHow a hand was settled before the dealer completed their own hand.
Both are read the same way -- the hand leaves the table before the dealer's second
card -- and are told apart by the cards it was holding.
Describes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIDescribes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIMust contain a minimum of 2 items
Must contain a maximum of 2 items
Describes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIDescribes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIThis structure contains the dealer specific information.
stack is None while the dealer doesn't have any cards.
The word stack refers to card stack and the associated chip stacks.
A stack is usually part of a player data structure or a dealer data structure.
There is no distinction between a dealer stack and a player stack as of now on
the data modeling level.
cards
Here we track the cards belonging to this stack. This list is never empty.
NOTE: The cards might be deleted from here in the same round. This is supposed to
happen when a dealer drops a card, it got assigned to a stack, and then quickly moves
the card somewhere else.
is_doubled
We take multiple indicators to decide if a stack was doubled including:
- card rotation
- card placement
- chip stacks
main_bet_stacks
These are the chip stacks that we think are the main bet for this card stack.
There are multiple chip stacks here if a player doubled, or is about to split.
In case of a split: The main bet stacks are then split up to each stack.
back_bet_stacks
In Europe it is common to allow other people to bet on your hand with a bet position
called back bet. The semantics are similar to the main_bet_stacks.
settled_early
The hand left the table before the dealer's second card, and how it was settled:
folded (SURRENDERED) or a blackjack taken at 1:1 against a dealer ace (EVEN_MONEY).
We read this off the hand being collected, so it can flip back to None if the cards
reappear. None for databases recorded before the field existed.
Must contain a minimum of 2 items
Must contain a maximum of 2 items
Describes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIDescribes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIDescribes a stack of chips (without counting, just stating its presence).
Same definition as ChipStackAPIMust contain a minimum of 2 items
Must contain a maximum of 2 items
A timestamp includes the date_time and the frame number since round initialization.
It is in the configured local timezone.
Don't assume that the timezone is correct, it might not have been configured,
it will fall back to UTC.
A card was seen where it was not expected.
NOTE: This will include the duration for how long that was in the future.
A card was seen where it was not expected while it was the dealers turn.
NOTE: This will include the duration for how long that was in the future.
Given the configured rules, the dealer should have drawn another card.
Legacy, decode only. The tracker no longer emits this: a surrender is now a per-stack
surrendered flag and the round reaches DEALERMAYBEFINISHED like any other. Kept so
databases recorded between v2.6.2 and that change still load.
Given the configured rules, the dealer drew a card too many.
A card for the players was missing.
A timestamp includes the date_time and the frame number since round initialization.
It is in the configured local timezone.
Don't assume that the timezone is correct, it might not have been configured,
it will fall back to UTC.
Must contain a minimum of 2 items
Must contain a maximum of 2 items
A timestamp includes the date_time and the frame number since round initialization.
It is in the configured local timezone.
Don't assume that the timezone is correct, it might not have been configured,
it will fall back to UTC.
This describes the current game phase.
Note: It doesn't always move forward. Sometimes the system will correct itself
due to cards being occluded or intentionally moved.
The round starts as EMPTY.
When the first chip is placed on the table we enter PRE_FIRST_CARDS.
Once a card is detected and assigned to a player or dealer, we enter FIRST_CARDS.
When the dealer has a card, and all players have 2 cards we go to PLAYERS_TURN.
In this state the players do all their actions.
DEALERS_TURN is the dealers turn.
When the round is over we go to DEALER_DONE.
In some situations we cannot determine if the round is over without more context
so we go to DEALER_MAYBE_DONE. For example: All players have busted,
but the dealer has to finish playing the hand anyways because of a side bet.
At the end we will go into ROUND_OVER if the round is supposed to be stored, and into
ROUND_CANCELED if we classify it as sensor noise.
This state will only be reached once, you should not miss this event.
We use this to mark what rounds we store in the database or show on the screen.
Even rounds with wrong dealer procedure will reach ROUND_OVER, they are marked
as such in the anomalies / diagnostics fields.
Describes a single bill of cash.
The keypoints are the corners of the rectangle. This is actually a parallelogram as
of today, but don't rely on it.
rotation is measured as the angle in degrees between the longer axis with the
y-axis (the second coordinate).
Certainty runs from 0 to 1 and says how sure the system is of the label. It is not a
probability: readings a few frames apart are near-duplicates, so it saturates far faster
than independent evidence would.
It defaults so that recordings made before it replaced evidence still decode.
A banknote, as the currency it belongs to and what it is worth.
Which bills exist is a property of the model that detected them: the class map travels
with the model artifact and is resolved into these labels before a detection leaves the
detection element. So there is no global list of bills here and no ordinal -- a class id
only means something next to the model that produced it.
This data is tracked over time. Don't rely too much on it, e.g. hit_counter_max might
change during the lifetime of a tracked object.
The fields start and stop are useful to understand when in a round this object
was seen. They are given in the number of frames since initialization.
Note: In the future these might be fully timestamped.