LiveUpdate

Type: object

Sent with QoS 0, not retained.

This is the lowest level of messages. It will be sent at any relevant state change.
A relevant state change is for example if the tracked cards have changed, but not if
the position of a card is updated.

NOTE: If you need a live stream of the card positions that updates quickly and
continuously, use the blackjack/card_positions topic.

NOTE: In the future we plan to expose an Idle state and a CardPrep state to give you
more information on the table state. We will do so once this functionality matures in
our own use cases. Feedback is always welcome.

BlackjackRound

Type: object

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.

BlackjackGamePhase

Type: enum (of string)

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.

Must be one of:

  • "DEALERS_TURN"
  • "DEALER_FINISHED"
  • "DEALER_MAYBE_FINISHED"
  • "FIRST_CARDS"
  • "PLAYERS_TURN"
  • "PRE_FIRST_CARDS"
  • "ROUND_CANCELED"
  • "ROUND_OVER"

Type: array
No Additional Items

Each item of this array must be:

PlayerAPI

Type: object

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.

Type: array

Must contain a minimum of 0 items

No Additional Items

Each item of this array must be:

CardStackAPI

Type: object

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.

Type: array

Must contain a minimum of 1 items

No Additional Items

Each item of this array must be:

CardAPI

Type: object

Describes a playing card.

Rectangle

Type: object

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).

Type: array

Must contain a minimum of 4 items

Must contain a maximum of 4 items

No Additional Items

Tuple Validation

Item at 1 must be:
Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:
Item at 2 must be:
Item at 2 must be:
Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:
Item at 2 must be:
Item at 3 must be:
Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:
Item at 2 must be:
Item at 4 must be:
Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:
Item at 2 must be:

EstimatedCard

Type: object

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.

CardLabel

Type: object

Value

Type: enum (of string)

Must be one of:

  • "10"
  • "2"
  • "3"
  • "4"
  • "5"
  • "6"
  • "7"
  • "8"
  • "9"
  • "A"
  • "J"
  • "K"
  • "Q"

Suit

Type: enum (of string)

Must be one of:

  • "C"
  • "D"
  • "H"
  • "S"

TrackedData

Type: object

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.

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

BBox

Type: object

lt stands for the left top corner and rb for the right bottom corner.

Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:
Item at 2 must be:

Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:
Item at 2 must be:

EstimatedChipStack

Type: object

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.

Default: null

Type: array
No Additional Items

Each item of this array must be:

ChipAPI

Type: object

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.

TrackedData

Type: object

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.

Same definition as tracked

Type: array of array
No Additional Items

Each item of this array must be:

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

Default: null

EarlySettlement

Type: enum (of string)

How 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.

Must be one of:

  • "EVEN_MONEY"
  • "SURRENDERED"

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

Type: array of array
No Additional Items

Each item of this array must be:

Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:
Item at 2 must be:
Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

DealerAPI

Type: object

This structure contains the dealer specific information.

stack is None while the dealer doesn't have any cards.


CardStackAPI

Type: object

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.

Same definition as CardStackAPI

Type: array of array
No Additional Items

Each item of this array must be:

Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:

SupportedLayoutSideBet

Type: enum (of string)

Must be one of:

  • "Bust"
  • "Insurance"
  • "Swiss Casino Jack"
Item at 2 must be:

LayoutSideBetAPI

Type: object

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

Type: array
No Additional Items

Each item of this array must be:

ChipStackAPI

Type: object

Describes a stack of chips (without counting, just stating its presence).

Same definition as ChipStackAPI

Type: integer

Type: array of array
No Additional Items

Each item of this array must be:

Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:

Timestamp

Type: object

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.

Item at 2 must be:

CardFarAwayDiagnostic

Type: object

A card was seen where it was not expected.

NOTE: This will include the duration for how long that was in the future.

Type: enum (of string)

Must be one of:

  • "CardFarAway"

DealerCardFarAwayDiagnostic

Type: object

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.

Type: enum (of string)

Must be one of:

  • "DealerCardFarAway"

DealerNotFinished

Type: object

Given the configured rules, the dealer should have drawn another card.

Type: enum (of string)

Must be one of:

  • "DealerNotFinished"

MaybeSurrender

Type: object

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.

Type: enum (of string)

Must be one of:

  • "MaybeSurrender"

DealerCardAfterFinish

Type: object

Given the configured rules, the dealer drew a card too many.

Type: enum (of string)

Must be one of:

  • "DealerCardAfterFinish"

PlayerCardsMissing

Type: object

A card for the players was missing.

Type: enum (of string)

Must be one of:

  • "PlayerCardsMissing"

Timestamp

Type: object

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.

Same definition as Timestamp

Type: array of array
No Additional Items

Each item of this array must be:

Type: array

Must contain a minimum of 2 items

Must contain a maximum of 2 items

No Additional Items

Tuple Validation

Item at 1 must be:

Timestamp

Type: object

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.

Same definition as Timestamp
Item at 2 must be:

BlackjackGamePhase

Type: enum (of string)

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.

Same definition as phase

Type: array
No Additional Items

Each item of this array must be:

BillAPI

Type: object

Describes a single bill of cash.

Rectangle

Type: object

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).

Same definition as last_detection

EstimatedBill

Type: object

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.

BillLabel

Type: object

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.

Type: number Default: 1.0

TrackedData

Type: object

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.

Same definition as tracked

Type: stringFormat: uuid