1.0.104

Implement new feature: Tournament Director game mode.

To set this game mode you need to POST request

/api/v1/tables/{short_table_token}/choose_game_mode/ with game_mode=TD

Feature details:

  1. Host can't play in this game mode, he just seats at the table.

  2. Host have to seat at the table to start a tournament.

  3. Host can't really leave the state. If he leaves/disconnects, new Host Away

status is set.

  1. Other logic is like in regular tournament.

Task: VPSUP-23

1.0.103

  • Fix private_data message:

Changed "heads_up_showdown" in payload to "timed_event_scenario", because now

there could be 2 scenarios: heads-up showdown and all-in scenario. In

private_data will be sent info about current timed event scenario to restore

it for reconnected player.

Task: VPSUP-9

1.0.102

  • Implement new feature: all-in scenario.

For cases when game was finished on any round before the

river when all players (>= 3) went all-in.

payload:

    event: "all_in_scenario"



    channel: Table (Public) or Private (Player only) delivery.



    players: list with ids of active players in the game.



    announce_time: amount of seconds for event announcement (always 0 for

        this event).



    card_reveal_time: amount of seconds for reveal each card.



    best_hands: contain str representation of best hands for each player

        for each round (flop, turn, river).



    final_community_cards: list with cards were already open on

        the table plus remaining cards (heads-up-showdown reveal cards)

        which will be opened one by one with animation.



    finish_time_expiration: time when all cards

        should be revealed and when next hand timer will be started.



    timestamp : timestamp of the action.

Task: VPSUP-9

1.0.101

  • Fix permission for join to the table, when it's expired

Task: VP-592

1.0.100

  • Add permission for game_stats which check that user in game or not.

Task: VP-594

1.0.99

  • Fix config apply, so settings are now applied between tournament games

Task: VP-611

1.0.98

  • Fix an issue with pydantic validation for amount value.

Task: VP-595

1.0.97

  • Fix an issue where table settings were not saved when tournament in progress.

Task: VP-611

1.0.96

  • Refactored player leave logic in tournament. Now we have 2 cases:

  • Player DISCONNECT from tournament. In this case we should allow him to

reconnect and play further, and system will play for him while he's missing.

  1. Player LEAVE tournament. Here we should kick him on next hand and

do not allow him to return on table and play.

  • Removed restriction to kick players from tournament (see comments

section in task).

  • Removed redundant auto-actions tests for tournament, fixed old

tests connected with this logic, added new ones.

Task: VP-606

1.0.95

  • Add users/current/is-current-user-playing/ endpoint which return True

if the user is playing at any table

Task: VP-594

1.0.94

  • Added message on updating table settings while playing.

Task: VP-596

1.0.93

  • Added opportunity for hand winner to call rabbit hunt.

Task: VP-574 (check comments section)

1.0.92

  • Fixed calculation best_hand_folded_counter statistic on pre-flop.

Task: VP-553

1.0.91

Fixed checking the relevance of the data when getting statistics from InfluxDB,

now we see that the number of started hands coincides with the number of

completed hands of the player, if this is not the case, then we wait until

the statistics have time to be saved and try to get the data again.

Task: VP-547

1.0.90

  • Adjust logic when host leaves after 10 minutes:

  • The game will end after 10 minutes if the host leaves or disconnects.

  • Now this logic only works for cash games, not tournaments.

  • After the host exits, a separate message host_left is sent.

Task: VP-590

1.0.89

Added to events API spec:

  • telemetry_trace_id (nullable)

  • duration (nullable)

  • player_id (nullable)

  • player_name (nullable)

1.0.88

Added end_after_current_game bool field to winners_award_timer

and unpause_winners_award_timer events,

which will be true if the host pushed end_current_game button.

Task: VP-474

1.0.87

Renamed next events:

next_hand event to winners_award_timer

pause_next_hand event to pause_winners_award_timer

unpause_next_hand event to unpause_winners_award_timer

In pause_winners_award_timer event (previous pause_next_hand) were renamed next fields:

next_hand_timer_remaining_time -> winners_award_timer_remaining_time

next_hand_timer_remaining_time_with_extra_time -> winners_award_timer_remaining_time_with_extra_time

In winners_award_timer event (previous next_hand) was renamed next_hand_timer_expiration field to winners_award_timer_expiration

Replaced is_winners_award_timer_paused bool flag from private_data to winners_award_timer and unpause_winners_award_timer events.

Added new string field post_event to winners_award_timer and unpause_winners_award_timer events, which could be game_start or finalize_current_game

Task: VP-474

1.0.86

Replaced show_next_game_button bool field from game_state event to next_hand event

1.0.85

Deleted show_start_game_button_expiration because it's no longer actual.

Added functionality for specifying event name for errors.

By default all errors-events are called as 'action_error'

but we can specify an event name to distinguish this error,

to make it possible to be handled by the frontend side.

Added new error event unable_to_start_game when the game wasn't actually started:

```json

{

"event": "unable_to_start_game",

"timestamp": 1629285226.00576,

"payload": {

"order": 0,

"error": "Unable to start the game with less than 2 players with enough money.",

"error_representation": "Unable to start the game with less than 2 players with enough money.",

"table_token": "6dd7fb75-4190-4be4-939f-97a238227b7e",

"channel": "T",

"amount": null,

"player": null,

"action": "game_start"

}

}

```

Added new field to game_state event: show_next_game_button (bool):

True, if the game wasn't started by the server for some reasons.

It needed to display next-game button for

the host if them refreshed the page, to start the hand manually.

Task: VP-489

1.0.84

Added end_after_current_game bool field to game_state event,

which will be true if the host pushed end_current_game button.

Task: VP-474

1.0.83

Added new endpoint - POST api/v1/tables/{short_table_token}/choose_game_mode/

with payload:

```json

{"game_mode": "C"}

```

or

```json

{"game_mode": "T"}

```

After that all players will get next new websocket event:

```json

{

"event": "game_mode_chosen",

"timestamp": 1628596529.157647,

"payload": {

"player": null,

"channel": "T",

"game_mode": "C",

"table_token": "036945cf-87d2-4bdd-9915-34e57a90de63",

"order": 0

}

}

```

Also the postman collection was updated:

https://www.getpostman.com/collections/f6ee097f7e0ca29e8927

When the Host opens the Table and goes to the Pre-Lobby(Lets use this new term), they will be

presented with two buttons at the table: "Play a Cash Game"

and "Play a Sit-n-Go Tournament". (use .../choose_game_mode/ endpoint for it)

At this moment the table has the new game_mode , which you can get by the config:

```json

{"game_mode": "UNDEFINED"}

```

Depending on which button is pressed will THEN determine what type of

game will be played and will pull from the the options that have been

set in Table Settings. Once the game type is selected, the Game Type

buttons are replaced with a single "Start Cash Game" or

"Start Tournament"(this is a regular lobby which has already ) - When this button is selected, the game will

actually start or validation will take place

that won't let the game start.

Added End Current Game Functionality.

New end_current_game action:

Request:

```json

{

"action": "end_current_game",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

Response:

```json

{

"event": "end_current_game",

"timestamp": 1628596919.571513,

"payload": {

"channel": "T",

"table_token": "036945cf-87d2-4bdd-9915-34e57a90de63",

"order": 0,

"player": 701

}

}

```

End Current Game Functionality:

  1. Add a button to the table management screen that says, "End Current Game" which ends the game and triggers all current existing logic (stats + end game reporting).

  2. Add Confirmation Pop Ups based on the game type.

If a cash game is in progress show:

“You have opted to end the Cash Game underway at the current table after the completion of the current hand. Doing so will cash out all current players and end-of-game reports will be generated for the current cash game. All statistics will be updated in each players’ account and all players will be moved to the lobby where you may begin another game.”

If a tournament is in progress show:

"“You have opted to end the Tournament before its completion after the completion of the current hand. Doing so will end the Tournament prematurely and end-of-game reports will be generated showing the current leaders based upon their table stack amounts. All statistics will be updated in each players’ account and all players will be moved to the lobby where you can begin another game."

  1. Once a game is ended by the host, all users should be taken back to the pre-lobby where they may begin another game. They will see the pre-lobby screen.

Added current_game_ended event.

Event to indicate that the current hand was ended, game report was sent,

and also this is a trigger for switching layout to pre-lobby.

Deleted refresh_state action.

Task: VP-474

1.0.82

Added feed messages for the end_game event.

Example:

```json

[

{

"message_template": "{{1}} wins with {{2}}",

"body": {

  "1": {

    "type": "PLAYER",

    "player_id": 300

  },

  "2": {

    "type": "HAND",

    "hand_combination": "Pair of 3's + 8 10 J"

  }

}

},

{

"message_template": "{{1}} wins with {{2}}",

"body": {

  "1": {

    "type": "PLAYER",

    "player_id": 200

  },

  "2": {

    "type": "HAND",

    "hand_combination": "Ace High + 10 8 7 6"

  }

}

},

{

"message_template": "{{1}} wins with {{2}}",

"body": {

  "1": {

    "type": "PLAYER",

    "player_id": 100

  },

  "2": {

    "type": "HAND",

    "hand_combination": "Ace High + 1л0 8 7 6"

  }

}

}

]

```

According to requirements, we shouldn't separate winners by amount of side-pots or something else,

which is why if the player has won any side-pot, he will be considered as a winner.

Therefore it's ok that there are cases when all player could be winners.(like in the example above)

1.0.81

Added next_hand_timer_remaining_time_with_extra_time field to pause_next_hand event

to technical and debugging purposes.

Added show_pause_button to unpause_next_hand event which indicate

whether show pause button or not, in cases when the remaining time

less then extra time for the timer.

Task: VP-482

1.0.80

Updated feed message templates for action_ack, deleted ACTION formatter, now

the template has only two formatters:

  • PLAYER

  • MONEY

Edited feed message template for blind_level_data event:

  • message template: New Blinds Level: {{1}}

  • body: {"type": "BLIND_LEVEL", "blind_level": 5}

Deleted feed message for the bankroll event

Task: VP-398

1.0.79

Deleted players_timebank field from the game_state event

Deleted timebank_left field from the turn event

Task: VP-467

1.0.78

Fixed the bug: when some player has already performed FOLD and left after that, the system perform FOLD again.

Now the system doesn't perform second redundant FOLD for this player

Feed message for player_seated event was changed to "{{1}} took seat {{2}}."

Also, if somebody left the seat (seat=null) the template message is "{{1}} left the seat."

Added game_mode field to MONEY formatter, example:

{"type": "MONEY", "amount": 5, "game_mode": "T"}

Task: VP-398

1.0.77

Added call_amount field to the turn event.

Task: VP-451

1.0.76

Added the feed.

All events now have a feed_message field, some of them with null,

is means feed message for this particular event is not implemented.

Added to game_state event feed_messages field, it is a list with all stored messages for the current hand.

btw: feed_messages field clean at the hand start, but you shouldn't clean it manually by yourself,

let's save all history from the previous hand, but if somebody

reload the browser page, he will see feed messages only for the current hand.

Changing in events:

action_ack :

Added action_repr_name and action_repr_value fields for UI representation of action on the avatar,

so we no longer needed to do some business logic on the frontend side to display it.

Added feed_message field with message template: "{{1}} makes {{2}} {{3}}" or

"{{1}} makes {{3}}"(for cases without amount) with body:

body = {

            1: {"type": "PLAYER", "player_id": 234}

            2: {"type": "MONEY", "amount": 5},  (this is `action_repr_value`)

            3: {"type": "ACTION", "action": "Raise"},  (this is `action_repr_name`)

        }

Also added many feed messages to the different events, please see:

Commit link

Task: VP-398

1.0.75

  • Added actual state config to private_data.

  • After update configuration via

api/v1/tables/{short_table_token}/configuration/

state config in state_config_updated will send to all players.

Also state_config_updated will be sent before game_start event. It was added to private_data as well.

  • Added the permission for api/v1/tables/{short_table_token}/configuration/, now you can't change

configuration during the tournament.

  • After the start of the game, if the config was switched to a new one,

it will send state_config_updated

state_config_updated event example:

```json

{

"event": "state_config_updated",

"timestamp": 1625481785.625936,

"payload": {

"order": 0,

"config": {

  "name": "name",

  "allowed_games": [

    "THD"

  ],

  "THD": {

    "format": "blinds",

    "limit": "NL"

  },

  "game_mode": "C",

  "big_blind": 2.0,

  "small_blind": 1.0,

  "ante": 5.0,

  "min_limit_size": 5.0,

  "max_limit_size": 10.0,

  "max_buy_in": 500.0,

  "min_buy_in": 1.0,

  "turn_time_limit": 30,

  "timebank_limit": 60,

  "time_between_hands": 10,

  "default_bank_value": 40,

  "rabbit_hunting": "true",

  "straddles": "true",

  "stats_bluffing": "false",

  "video_showdown": "true",

  "tournament_settings": {

    "entry_fee": 10,

    "payout_table": {

      "1": 50,

      "2": 30,

      "3": 20,

      "4": 0,

      "5": 0

    },

    "starting_chips": 1500,

    "level_duration": 900,

    "blind_schedule": {

      "1": {

        "ante": 0,

        "small_blind": 10,

        "big_blind": 20

      },

      ...

      "30": {

        "ante": 280,

        "small_blind": 300,

        "big_blind": 600

      }

    },

    "pausing": "true"

  }

},

"table_token": "ee277637-204e-4aad-b4eb-94397bea9b7b",

"channel": "T",

"player": null

}

}

```

Task: VP-390

1.0.74

Some changes in next_hand and unpause_next_hand events:

  • next_hand_expiration field was renamed to next_hand_timer_expiration

  • added new field show_start_game_button_expiration timestamp in seconds

when UI-pause button should be changed to game-start button.

It needed for example when, as a result of the last hand, there are

not enough players with money on the table to start the next game,

or for any other reason why the game could not start by the timer,

we must allow the player to start the game manually,

for this we must draw the game-start button.

next_hand_remaining_time field in pause_next_hand event was renamed to next_hand_timer_remaining_time

Task: VP-389

1.0.73

Deleted logic for immediately finalize tournament if all players have left, except one.

Keep in mind, there is only one case when the tournament is considered

as finished -> when there is only one player with money.

But if all players have left except one, the tournament should continue

until all the money is in the hands of one player, and the system

will force all left players to play all tournament hands and place

blinds and antes, and also fold for them. But they still have

the opportunity to return and continue the tournament.

Task: VP-380

1.0.72

  • Added SendgridEmailClient which allow sending email to players.

  • Added BaseTableReport which collect stats for the players and send.

  • Added HostReportCacheGame, HostReportTournament,

PlayerReportCacheGame, PlayerReportTournament for sending end game

reports to players.

  • Added new API endpoint which send end game report to the host of the table:

    • POST /api/v1/reports/{short_table_token}/send-report/

Task: VP-275

1.0.71

  • Removed C-BET and LIMP from table statistics

  • Added C-BET and LIMP to user page statistics

  • Added VPIP%, PFR%, Average Pot Winnings, and Biggest Pot Won to

table statistics

Task: VP-326

1.0.70

For the tournament games, the system should not throw out anyone

regardless of what, all participants in the tournament must reach the

end, if for some reason they left/disconnected from the game,

the system must make a move for them, this logic was implemented.

In previous realization we throw-up the left-player only at starting the next hand.

Edited logic for leave, now it's called after the hand(right after game_end event), same as kick logic.

Also, if the hand not in progress, the player will be left immediately.

Task: VP-355

1.0.69

Added delay for displaying heads-up-showdown announcing pop-up.

New field in heads_up_showdown event -> announce_time

Task: VP-290

1.0.68

Changed event name increase_blind_level to blind_level_data

Added this event after tournament_winners, to clean-up data about blinds levels, and blind scheduler timer

Task: VP-364

1.0.67

Added validation for fields with a limited number of digits after the decimal point.

  • Common fields: big_blind, small_blind, min_buy_in, max_buy_in, timebank_limit, turn_time_limit, default_bank_value, time_between_hands

  • Tournament fields: big_blind, small_blind, entry_fee, level_duration, starting_chips

Task: VP-361

1.0.66

Added player_join_status_updated event.

Payload example:

{"event": "player_join_status_updated", "timestamp": 1623301513.589255, "payload": {"join_status": "ALLOWED_TO_PLAY", "channel": "T", "table_token": "18e7d0c7-f3d3-4bfa-a97c-b2f2738c9019", "order": 1, "player": 5}}

Task: VP-334

1.0.65

Added short_table_token to table model - unique short four-place alphanumeric code

so users can join the table using it, instead of long UUID.

Added filter by this field for tables and table_players.

Also changed request-body for endpoint/api/v1/payments/prices/{{price}}/get-payment-intent/ :

object_id takes now short_table_token instead of table_token

Task: VP-322

1.0.64

Deleted fields from the game_state event:

allowed_to_play, current_sit_out_players, wishing_to_play_immediately, wishing_to_play_on_bb_position


Added players_join_statuses field to the game_state event with variety enums:

  • ALLOWED_TO_PLAY - means the player is allowed to join to next hand.

  • SIT_OUT - means the player is sit-out player who put a tick sit-out

    in previous hands(not current).
    
    And who has not yet expressed a desire to play.
    
  • SIT_OUT_READY_TO_PLAY - same as SIT_OUT, but who already

    has expressed a desire to play.
    
  • SIT_OUT_PARTICIPANT - means the player is sit-out player who put a tick

    `sit-out` in current hand.
    
  • NEW_PLAYER - means the player considered as a new player.

    And who has not yet expressed a desire to play.
    
  • NEW_PLAYER_READY_TO_PLAY - same as NEW_PLAYER, but who already has expressed a

    desire to play.
    
  • NEW_PLAYER_PARTICIPANT - means the player considered as a new player,

    but he is a participant of the current game. For example in cases when
    
    some player left the game and join again immediately.
    
    And who has not yet expressed a desire to play.
    
  • NEW_PLAYER_PARTICIPANT_READY_TO_PLAY - same as NEW_PLAYER_PARTICIPANT,

    but who already has expressed a desire to play.
    

Task: VP-334

1.0.63

Reorganize calculation of cash_loss_amount metric, now it is calculated at

the end of the game.

Task: VP-311

1.0.62

Reorganized showdown win/loss metric gathering, now it is collected only

between players who went till showdown_round.

More info about gathering:

showdown win/loss ("10/0", "0/10"): PLAYER value - COMPETITOR value

Both values are calculated as relative amount of player vs competitor wins. It

means that metric is calculated only among players who played till showdown

(actively participated in river or stayed as all-in till river). For players

who won showdown round the vs_showdown_win_counter metric value is

incremented relatively to that players who were in showdown round too, but

lost. So in the result value there are compared only showdown winners and

showdown loosers.

vs_showdown_win_counter calculated at the end of the river round - for all

winners it is incremented against the players who lost the last round.

Task: VP-327

1.0.61

Update preflop_raises_counter metric gathering, now it is collected only

once during the round. So if player performs 2 raises on preflop this metric

would be incremented only once.

Task: VP-324

1.0.60

Add pots_participants field to BaseGameState to remember how much money

each player had in a pot for further metrics processing.

Reorganize VS chips win/loss metric - amount of chips which player has

from competitor (when he won competitor's money).

So at the end of the game vs_win_amount metric is calculated for that

between all game winners, so during the game we remember how much money each

player had in a pot and at the end of the game we just split each pot

participant (player whose money are in the pot) amount of money between

winners.

Task: VP-328

1.0.59

All timers data(expirations, intervals, remaining times) now in floats

Task: VP-310

1.0.58

Card revealing was reworked.

Depending on where in the hand two players have gone all-in, the card reveals as follows:

If Video Showdown occurs pre-flop

1) The five community cards are all dealt FACE DOWN on the table.

2) A countdown timer appears underneath the middle (3rd) card and begins the countdown.

3) When the time reaches zero, the first THREE cards (i.e. the flop) are all turned over.

4) The timer resets, and when to zero the Turn (4th) card is revealed.

5) The timer resets, and when to zero the River (5th) card is revealed.

6) Winners are determined.

If Video Showdown occurs post-flop

1) The remaining community cards appear on the table face down

2) A countdown timer appears underneath the middle (3rd) card and begins the countdown.

3) The remaining community card(s) are turned over after the counter expires for each remaining card.

4) Winners are determined

Task: VP-290

1.0.57

Added best_hands field to heads_up_showdown event:

```json

{

"best_hands": {

"100": {

  "flop": "Pair of Aces + 6 7 8",

  "turn": "Pair of Aces + 7 8 10",

  "river": "Flush (10 High)"

},

"200": {

  "flop": "Ace High + 8 7 6 2",

  "turn": "Ace High + 10 8 7 6",

  "river": "Flush (10 High)"

}

}

}

```

Task: VP-303

1.0.56

Added delayed kick.

After player was kicked, he still can continue current hand, and in the

end of the hand he will be automatically kicked

by the server and will be thrown out of seat.

Kicked player could continue current hand, will be left by the server,

but he can easily rejoin again but in this case he will be considered as

a new player, so he must go through the join/re-join

procedure (decide whether he wants to play next hand immediately or

on a BB position).

kick_player_after_game

Request:

```json

{

"action": "kick_player_after_game",

"payload": {

"player": 69

},

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

After last hand, kicked_after_game player will be kicked by the server with next responses:

Response for left player:

```json

{

"event": "force_disconnect_user",

"payload": {

"reason": "You were kicked by table creator"

}

}

```

Response for other players:

```json

{

"event": "player_kicked",

"timestamp": 1621595247.265341,

"payload": {

"order": 0,

"player": 10,

"table_token": "0738daf7-eb6e-46d0-af13-b89d21f206b2",

"channel": "T"

}

}

```

leave_player

Request:

```json

{

"action": "leave_player",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

Response for left player:

```json

{

"event": "force_disconnect_user",

"payload": {

"reason": "You left the table"

}

}

```

Response for other players:

```json

{

"event": "player_left",

"timestamp": 1621595616.693867,

"payload": {

"order": 0,

"channel": "T",

"table_token": "58b76a7a-4d88-4f22-a61f-3840447ca0df",

"player": 11

}

}

```

Changed payload for player_disconnected:

````json

{

"event": "player_disconnected",

"timestamp": 1621848905.704886,

"payload": {

"channel": "T",

"order": 0,

"player": 56,

"table_token": "0111666b-837a-4672-ba46-2b645524ad83"

}

}

````

1.0.55

  • Added error_representation field to action_error event.

Task: VP-238

1.0.54

  • Added permissions for next_hand and game_start in flow.

  • Added celery task which starts the moment the table expires

Task: VP-297

1.0.53

  • Added Continuation Bet in statistic

A continuation bet is when you were the last to raise preflop,

and hence the aggressor, and you continued that aggression on the flop by being

the first to bet.

The formula for calculating CBET is:

Continuation bet % = (times made a continuation bet on the flop) * 100

/ (number of opportunities to make a continuation bet on the flop)

  • Added LIMP to statistic

For example, in hold’em before the flop, a player who calls the big blind

(rather than raises) is described as "limping in."

Task: VP-283

1.0.52

Added permissions and checks for WS and API so that the player cannot have

two connections to the table at the same time.

Task: VP-230

1.0.51

Deleted multiple winners event for side-pot cases.

Now we have only one game_end (it's also added in debug tool) event with next fields:

    event: "game_end"

    payload:{

        channel: Table (Public) or Private (Player only) delivery

        side_pot_evaluation_time: time for evaluating one side-pot

        side_pots_evaluation_expiration: datetime when

            next-hand-timer will be started after all side-pots have

            been evaluated one by one. It's might be `None`,

            because in heads-up-showdown cases it's not

            needed to show side-pots evaluation.

        best_hands: dict where key is a player id,

            value is a player current best hand

        best_hands_combinations: dict where key is a player id,

            value is a name of best poker combination

        pocket_cards: dict where key is a player id,

            value is a list of pocket cards

        can_show_cards: list of players ids who can show cards

        can_call_rabbit_hunt: list of players

            ids who can call rabbit-hunt

    }

    timestamp: timestamp of the action

Example:

```json

{

"event": "game_end",

"timestamp": 1619775048.288722,

"payload": {

"best_hands_combinations": {

  "129": "Straight, 7-J",

  "130": "Flush (Ace High)"

},

"side_pot_evaluation_time": 7,

"best_hands": {

  "129": ["7S", "9D", "8S", "JS", "10D"],

  "130": ["7S", "8S", "JS", "4S", "AS"]

},

"pocket_cards": {

  "129": ["2C", "10D"],

  "130": ["5H", "AS"]

},

"can_show_cards": [],

"can_call_rabbit_hunt": [],

"channel": "T",

"side_pots_evaluation_expiration": 1619775055.271853,

"table_token": "380d2dde-9a05-494e-a3c6-c64085cee936",

"winners": [

  {

    "pot_id": 0,

    "pot_size": "4.0",

    "pot_chunks": ["4.0"],

    "winners": [130],

    "reason": ["Flush (Ace High)"]

  }

],

"player": null,

"order": 3

    }

}

```

1.0.50

Now players cannot start the game again or perform any actions with the table

if the table has expired and more than 2 minutes have passed since the last game.

After the table has expired, and the game is over, players are given two

minutes to say goodbye, during which time they can enter and leave the table

and perform any actions other than starting a new game.

Task: VP-220

1.0.49

Added new event heads_up_showdown (it's also added in debug tool)

For cases when game was finished on any round before the

river when only 2 players left in the game (others folded),

one of them went all-in and the second one called or also went all-in.

payload:

    event: "heads_up_showdown"



    channel: Table (Public) or Private (Player only) delivery.



    players: list with ids of active players in the game.



    card_reveal_time: amount of seconds for reveal each card.



    final_community_cards: list with cards were already open on

        the table plus remaining cards (heads-up-showdown reveal cards)

        which will be opened one by one with animation.



    finish_time_expiration: time when all cards

        should be revealed and when next hand timer will be started.



    timestamp : timestamp of the action.

Task: VP-223

1.0.48

Updated debug-events

Added allowed_to_play field to game_state event, it's array with ids of player who are allowed to play.

If this is the very first game, then all players are allowed into

the game. If not, then only players who played in the previous game.

But if someone played the previous game but then was kicked or left,

then he is removed from the allowed_to_play and if he wants to play

he must go through the standard 'join procedure'

as for all new players.

Added new actions:

join

Request:

```json

{

"action": "join",

"immediately": "true",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

Response:

```json

{

"event": "join",

"timestamp": 1618558616.944414,

"payload": {

"player": 69,

"table_token": "a1ce4c4c-f713-499c-875b-557c0c9c007f",

"channel": "T", "order": 0

}

}

```

sit_out

Request:

```json

{

"action": "sit_out",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

Response:

```json

{

"event": "sit_out",

"timestamp": 1618558650.017811,

"payload": {

"player": 69,

"table_token": "a1ce4c4c-f713-499c-875b-557c0c9c007f",

"channel": "T", "order": 0

}

}

```

Task: VP-195

Task: VP-196

1.0.47

Added next fields to private_data event:

increase_blind_level,

pause_next_hand,

tournament_winners,

next_hand,

is_next_hand_timer_paused

Task: VP-159

1.0.46

Now Total number of hands played, # of Cash Games Played and

# of Tournament Played are calculated at the end of the game when winners are

calculated.

Also updated Current bankroll amount not it shows actual table player bank

instead of stack.

Task: VP-233

1.0.45

Add tournament games

added next_hand_expiration in next_hand event, so you can show next hand timer.

Added events:

  • action_ante - new type of action_ack

  • start_tournament - just empty event, which is sent when tournament was started

  • increase_blind_level - sent when blind-scheduler updates amount of blinds/ante.

  • fields:

    blinds_level - Current level of blind schedule.

    next_blinds_level - level of blind schedule for the next tournament hand.

    blind_scheduler_expiration - timestamp in seconds when next blind level will be increased.

  • tournament_winners - contain tournament winners in winners field

  • fields:

    winners: {100: 4.00, 400: 6.00, 200: 10.00}

  • pause_next_hand - sent when tournament was paused

  • fields:

    next_hand_remaining_time - Time in seconds before next hand will be started.

    blind_scheduler_remaining_time - Time in seconds before next service_timers blind schedule level will be increased.

  • unpause_next_hand - sent when tournament was unpaused

  • fields:

    next_hand_expiration - new timestamp when next hand will be started.

    blind_scheduler_expiration - timestamp in seconds when next blind level will be increased.

Added actions:

```json

{

"action": "pause_next_hand",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

```json

{

"action": "unpause_next_hand",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

1.0.37

Add action: open_rabbit_hunt_cards

Request:

```json

{

"action": "open_rabbit_hunt_cards",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

Response:

```json

{

"event": "open_rabbit_hunt_cards",

"timestamp": 1613913319.664718,

"payload": {

"player": 55,

"community_cards": ["4C", "7H", "5D", "AS", "9H"],

"table_token": "e3de4697-5fbc-4882-b165-a68f5961b329",

"order": 0,

"channel": "T",

"rabbit_hunt_cards": ["AS", "9H"]

}

}

```

1.0.44

  1. Fix leave player behavior, so now when player is left he would get

a following message:

```json

{

"type": "force_disconnect_user",

"reason": "You were kicked by table creator",

"channel_id": "specific.92611f4752624f4394c8aaa5259da94c!05e63a0bea034fcc997b0be9599369fd"

}

```

The rest table players would get standard player_left message.

  1. Add fix for making move for user when user left or was kicked on his

move - enforce user's move dynamically.

Task: VP-191

1.0.43

Fix kick/ban player behavior, so now when player is kicked he would get

a following message:

```json

{

"type": "force_disconnect_user",

"reason": "You were kicked by table creator",

"channel_id": "specific.92611f4752624f4394c8aaa5259da94c!05e63a0bea034fcc997b0be9599369fd"

}

```

The rest table players would get standard player_kicked message.

Task: VP-172

1.0.42

Add all statistics collecting during the game play, storing it in InfluxDB and

utils methods to gather statics from InfluxDB.

Also add functionality for following endpoints:

  1. GET /players/{id}/stats/ - current player's own stats

https://projects.invisionapp.com/d/#/console/20262624/441361482/preview

Returns (data is always returned in this format with different values):

```json

[

{

    "label": "Total number of hands played",

    "value": "0"

},

{

    "label": "Total time played at table",

    "value": "00:00:00"

},

{

    "label": "Net chips amount",

    "value": "$0"

},

{

    "label": "Current bankroll amount",

    "value": "$0"

},

{

    "label": "Pots won %",

    "value": "0% (0 of 0)"

},

{

    "label": "Flops seen %",

    "value": "0% (0 of 0)"

}

]

```

  1. GET /players/{id}/versus-stats/ - compared stats for users

(id is id of a player with whom current user compares)

https://projects.invisionapp.com/d/#/console/20262624/426412785/preview

https://projects.invisionapp.com/d/#/console/20262624/426412786/preview

Returns (data is always returned in this format with different values):

```json

{

"table": [

    {

        "label": "Total hands played",

        "value": "0"

    },

    {

        "label": "Flops seen %",

        "value": "0%"

    },

    {

        "label": "Pots won %",

        "value": "0%"

    },

    {

        "label": "Total pots won",

        "value": "0"

    }

],

"vs": [

    {

        "label": "Win/loss of chips",

        "value": "$0"

    },

    {

        "label": "Showdown win/loss",

        "value": "0"

    }

]

}

```

Note that table section contains absolute info for another player and

vs contains compared info between current user and another player. To call

this method current user should be also a player from the same table with

another player.

  1. GET /users/current/stats/ - total stats of a current user (career overview)

https://projects.invisionapp.com/d/#/console/20262624/426442485/preview

Returns (data is always returned in this format with different values):

```json

[

{

    "label": "Joined in",

    "value": "March 2021"

},

{

    "label": "# of Cash Games Played",

    "value": "0"

},

{

    "label": "# of Tournament Played",

    "value": "0"

}

]

```

  1. GET /users/current/game-stats/ - user's game specific stats

https://projects.invisionapp.com/d/#/console/20262624/426442485/preview

Returns (data is always returned in this format with different values):

```json

[

{

    "label": "Folded best hand %",

    "value": "0%"

},

{

    "label": "$ Lost when folded best hand",

    "value": "$0"

},

{

    "label": "% of pots won without best hand",

    "value": "0%"

},

{

    "label": "Flops seen %",

    "value": "0%"

},

{

    "label": "Pots won %",

    "value": "0%"

},

{

    "label": "Total pots won",

    "value": "0"

},

{

    "label": "VPIP%",

    "value": "0%"

},

{

    "label": "PFR%",

    "value": "0%"

},

{

    "label": "Aggression factor",

    "value": "0"

},

{

    "label": "Total hands played",

    "value": "0"

},

{

    "label": "Average Pot Winnings",

    "value": "$0"

},

{

    "label": "Biggest pot won",

    "value": "$0"

},

{

    "label": "# Times screwed on the river",

    "value": "0"

}

]

```

Note that game_type is a required query param, that should belong to

available game types.

Task: VP-155

1.0.41

Fix kick/ban player behavior.

  1. Add immediate user disconnect when player kicked by server.

  2. Remove sending private_game_state and private_data for cases when

player becomes disconnected or kicked.

  1. Fix Player hasn't selected a seat! error, which happens when new game

started with disconnected player.

Task: VP-172

1.0.40

Moved the private_data from the game_state to a separate event.

```json

{

"event": "private_data",

"timestamp": 1615367234.782203,

"payload": {

"player": null,

"pocket_cards": ["4S", "KS"],

"channel": "P",

"table_token": "d9fd2aad-3e8f-4215-bf98-10ec7db2bdc8",

"turn": {

  "order": 0,

  "table_token": "d9fd2aad-3e8f-4215-bf98-10ec7db2bdc8",

  "event": "turn",

  "player": 58,

  "channel": "T",

  "available_actions": ["action_fold",

    "action_raise", "action_call"],

  "seat": 1,

  "bet": "1.0",

  "min_amount": "3.0",

  "max_amount": "39.0",

  "interval": 30,

  "timestamp": 1615367234.781867,

  "timestamp_turn_expiration": 1615367240.839949,

  "timestamp_total_expiration": 1615367250.839949,

  "timebank_left": 10

},

"order": 2,

"show_pocket_cards": null,

"winners": null}

}

```

Task: VP-181

1.0.39

Improve buy-in action validation. Now when player makes buy-in for a very

first time - he should be forced to make buy-in on amount no less then

min-buy-in from game config. Otherwise, if it is not the first buy-in

operation it is allowed to put any amount to table stack with buy-in action.

Add new players_initial_buy_in field to GameState (it has ids of players

who already did initial buy-in), add bool has_initial_buy_in field for

following events (cause all of them return actual player info):

- player connected

- player disconnected

- player kicked

- player left

- player seated



- action_bet

- action_call

- action_check

- action_fold

- action_raise

- big_blind

- small_blind

Task: VP-135

1.0.38

Add players_statuses field to GameStateInfo, options:

- DISCONNECTED - "D"

- CONNECTED - "C"

- KICKED - "K"

- LEFT - "L"

- SEATED - "S"

Task: VP-15

1.0.37

Add action: open_rabbit_hunt_cards

Request:

```json

{

"action": "open_rabbit_hunt_cards",

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

Response:

```json

{

"event": "open_rabbit_hunt_cards",

"timestamp": 1613913319.664718,

"payload": {

"player": 55,

"community_cards": ["4C", "7H", "5D", "AS", "9H"],

"table_token": "e3de4697-5fbc-4882-b165-a68f5961b329",

"order": 0,

"channel": "T",

"rabbit_hunt_cards": ["AS", "9H"]

}

}

```

Keep in mind that after receiving the open_rabbit_hunt_cards event, you must clear the can_call_rabbit_hunt

array so as not to show them the Rabbit-Hunt button anymore, on the backend side this array is cleared out after the first click of the

Rabbit-Hunt button, so no one can ever press this button a second time.

Perhaps it makes sense to add "can_call_rabbit_hunt" to the response to nullify it, but it will always be an empty array,

so it's probably better to just do it manually at the frontend side as described above

Add fields to game_state event:

rabbit_hunt_cards - list of opened rabbit-hunt cards of the table

folded_players - list of players ids who fold during the game

Add fields to winners event:

can_call_rabbit_hunt - list of players

        ids who can call rabbit-hunt(if anyone clicks Rabbit-Hunt button it clears)

Task: VP-153

1.0.36

  1. Add new players_delayed_stack field to ETCD. So, now when player tries to

add money to his table stack during the game (does buy-in) - his added

money would be remembered in players_delayed_stack and on a new game start

player's delayed stack would be added to players_stack.

The logic of buy-in when game is not started stays the same - money would be

immediately added to players_stack in such a case.

  1. Add new delayed_table_stack field to ActionACK, so now when user

performs actions - he would have info about delayed table stack.

  1. Add new players_delayed_stack field to GameStateInfo, so now if player

refreshes table, he would have info about the money he has in delayed stack.

Task: VP-167

1.0.35

  1. Removed automatic setting of players_stack, now when new player sits -

he will always have a 0 stack. For players_bank and players_timebank

fields there are no changes - their values are set when player firstly sits

to the table from table configuration.

  1. Add bank and table_stack to PlayerInfo action message. So now it

will be used by following events:

- player connected

- player disconnected

- player kicked

- player left

- player seated
  1. Reorganized players_bank, players_stack and players_timebank ETCD

fields structure to provide possibility of storing values for kicked/left or

sat out player.

Before:

```

players_stack: [Decimal('0'), Decimal('15.5'), Decimal('5.25'), Decimal('0'), Decimal('29.0'), Decimal('0'), Decimal('0'), Decimal('0'), Decimal('0')]

players_bank: [Decimal('0'), Decimal('30'), Decimal('40'), Decimal('0'), Decimal('30'), Decimal('0'), Decimal('0'), Decimal('0'), Decimal('0')]

players_timebank: [Decimal('0'), Decimal('90'), Decimal('90'), Decimal('0'), Decimal('89.3'), Decimal('0'), Decimal('0'), Decimal('0'), Decimal('0')]

```

Now:

```

players_stack: {

'dmitry': Decimal(15.5),

'paul': Decimal(5.25),

'jack': Decimal(29.0),

# jim is a player who doesn't play now, but he played on this table before

'jim': Decimal(28.1)

}

players_bank: {

'dmitry': Decimal(30),

'paul': Decimal(40),

'jack': Decimal(30),

# jim is a player who doesn't play now, but he played on this table before

'jim': Decimal(10)

}

players_timebank: {

'dmitry': Decimal(90),

'paul': Decimal(90),

'jack': Decimal(89.33),

# jim is a player who doesn't play now, but he played on this table before

'jim': Decimal(55)

}

```

Task: VP-135

1.0.34

Add raising action_error when player's turn time expired.

Task: VP-129

1.0.33

Add action: show_pocket_cards

Request:

```json

{

"action": "show_pocket_cards",

"data": {"cards": ["8D"]},

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

Response:

```json

{

"event": "show_pocket_cards",

"timestamp": 1612752880.697588,

"payload": {

"player": 21,

"seat": 2,

"visible_cards": ["JS", null],

"best_hand": ["JS", "JD", "3S", "2C", "2D"],

"best_hand_combination": "two_pair",

"table_token": "4506aef5-2956-4dfa-baf2-a237d526ef53",

"order": 0,

"channel": "T"

}

}

```

It raises errors if:

- player called this action when hand is not completed yet



- if player is not the one from folded players or is the only one who left

not folded



- if not existing player's cards were sent in request

Update Winners message

Added new can_show_cards field, which returns players ids, who is allowed to

call show_pocket_cards action (folded players or the player who is left one

not folded).

Also removed players, who has possibility to hide their cards from winners

pocket_cards, best_hand and best_hand_combination. So no info

would exist about such players cards.

Now in pocket_cards, best_hand and best_hand_combination returned

only always available players cards (when there were few competing for the pot

players).

Update GameStateInfo message

Added new fields to private_data dict of GameStateInfo:

- ``winners`` - list of generated `winners` messages (is not None only if

the game was finished). The amount of `winners` messages is equal to amount

of side pots.



- ``show_pocket_cards`` - list of generated `show_pocket_cards` messages

(is not None only if the game was finished). The amount of

`show_pocket_cards` messages is equal to amount of players, who shown

their cards.

So now frontend should always show returned in winners message

pocket_cards, best_hand and best_hand_combination (cause such ones

would be always visible) and fill the rest pocket cards according to

show_pocket_cards event.

Task: VP-144

1.0.32

Add calculation for min/max amount of raise/bet for Pot-Limit game.

Task: VP-152

1.0.31

Add action for chat messaging:

request: {"action": "send_chat_message", "payload": {"message": "Hello World!!!"}, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

response: {"event": "chat_message", "timestamp": 1612752880.697588, "payload": {"player": null, "message": "Hello World!!!", "username": "user_1", "table_token": "4506aef5-2956-4dfa-baf2-a237d526ef53", "order": 0, "channel": "T"}}

Field game_type_id in start game action was renamed to game_type:

{"action": "game_start", "game_type": "THD", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

Task: VP-148

1.0.30

  • PATCH /tables/{table_token}/configuration/

Edited table configuration structure, check swagger spec.

Now configuration looks like:

`{

"name": "name",

"allowed_games": ["THD", "OMH", "SCS"],

"THD": {

    "format": "blinds",

    "limit": "NL"

},

"big_blind": 2.00,

"small_blind": 1.00,

"ante": 5.00,

"min_limit_size": 5.00,

"max_limit_size": 10.00,

"max_buy_in": 500.00,

"min_buy_in": 1.00,

"turn_time_limit": 30,

"timebank_limit": 600,

"time_between_hands": 10,

"default_bank_value": 40,

"rabbit_hunting": "true",

"straddles": "true",

"stats_bluffing": "false",

"video_showdown": "true",

}`

1.0.29

Remove bank and extra_time_bank fields from TablePlayer. So now this data

is stayed in ETCD state, so when left or kicked player comes back - his

data would exist in state. At the beginning these values would be set on

sit_player action with default values from table configuration.

Add action: update_bankroll

```json

{

"action": "update_bankroll",

"payload": [{"player": 1, "amount": 20}, {"player": 2, "amount": -20}],

"timestamp": "2017-02-15T20:26:08.937881-06:00"

}

```

As a result of this action call there would be returned few messages

(according to amount of players, whose data should be updated), for example:

```text

  • 0 order=0 table_token='FEZEKNUKBL' event='action_ack' player=100 channel=TABLE action='update_bankroll' action_time=Decimal('0') amount=Decimal('50') table_stack=Decimal('0') bank=Decimal('100') bet=Decimal('0') seat=1 username=None executed_by=USER timestamp=datetime.datetime(2021, 2, 9, 9, 59, 11, 642305)

```

It raises errors if:

- player, who called the action is not the table creator



- if any of `players` in `payload` doesn't seat on the table -> new amounts

wouldn't be applied at all (for all players from payload)



- if any of `players` would have negative `bank` because of such

operation -> new amounts wouldn't be applied at all (for all players from

payload)

Update ActionACK message

Added new bank field, which shows how much money player currently has in bank.

Task: VP-135

1.0.28

Update turn websocket action format:

- added ``timestamp_turn_expiration`` field, which shows when turn

`decision time` would be expired



- renamed ``timestamp_expiration`` -> ``timestamp_total_expiration``

Task: VP-129

1.0.27

Add time track service, functionality to use it from vp framework.

Task: VP-101

1.0.26

Remove jitsi_id field from TablePlayer instance and possibility to PATCH

jitsi_id with API and move this logic to websockets.

Also there is added a new field players_jitsi_id to the GameState, from which

actual players jitsi ids may be taken.

Add action:

{"action": "update_jitsi_id", "jitsi_id": "345", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

Update action:

{"action": "sit_player", "seat": 1, "jitsi_id": "123", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

Add jitsi_id field to sit_player signal, so when the sit_player signal

was called for a first time sit_player there would be updated corresponding

players_jitsi_id field

in game state.

Note: when user updates the seat to the same current seat with a new

jitsi_id or when user just changes his seat from one to another -

new jitsi_id won't be set. To perform such operation you need to call

update_jitsi_id action.

Task: VP-112

1.0.25

The player will now occupy the seat through websocket protocol.

Add new action:

{"action": "sit_player", "seat": 1, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

Deleted update_channel_id action.

Due to the fact that now the user sits on the web socket, now, simultaneously with this action, we record the player's channel_id.

Therefore, the update_channel_id method is no longer needed.

Deleted table_stack, seat fields from table api. Make sure you are not trying to get or patch this fields through http.

Task: VP-115

1.0.24

Add new actions:

initialize_state

{"action": "initialize_state", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

Calls a chain of events(game_state, turn, pocket_cards) so that the frontend client can get

up-to-date information about the game at any time, for example, when the page is refreshed.

Response example:

{"event": "game_state", "timestamp": 1609846139.138019, "payload": {"bets": [[null, "0.25", null, null, null, null, null, null, "0.5"]], "community_cards": [], "players_stack": ["0", "49.75", "0", "0", "0", "0", "0", "0", "49.5"], "table_token": "f426b488-9666-41e4-90b3-e846d80bbce0", "pots_winners": [[]], "sequence": 0, "players_timebank": ["0", "600", "0", "0", "0", "0", "0", "0", "600"], "order": 0, "dealer_seat": 1, "game_id": "307cf8b7-c318-48b0-8949-072f7863d9e7", "turn_player_seat": 1, "pots_players": [[]], "pots": ["0"], "seats": [null, 80, null, null, null, null, null, null, 81], "players": [null, 80, null, null, null, null, null, null, 81], "players_bank": ["0", "0.00", "0", "0", "0", "0", "0", "0", "0.00"], "channel": "T", "betting_round": 0}}

{"event": "turn", "timestamp": 1609846139.138859, "payload": {"seat": 1, "available_actions": ["fold", "raise", "call"], "table_token": "f426b488-9666-41e4-90b3-e846d80bbce0", "player": 80, "timebank_left": 600, "channel": "T", "order": 1, "timestamp_expiration": 1609846799.138826}}

{"event": "pocket_cards", "timestamp": 1609846139.139143, "payload": {"seat": 1, "player": 80, "table_token": "f426b488-9666-41e4-90b3-e846d80bbce0", "channel": "P", "order": 2, "pocket_cards": ["AC", "6D"]}}

refresh_state

{"action": "refresh_state", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

Refresh game state for a current table.

So that everything works correctly after a refresh, don't forget patch seat to null and sit down again

Delete actions:

game_state

Updates:

Edit enums for actions, now it looks like:

available_actions": ["fold", "raise", "call"]

Now table create with default table configuration:

`TABLE_SETTINGS_DEFAULT = {

"name": "name",

"allowed_games": ["THD"],

"THD": {

    "format": "blinds",

    "limit": "NL"

},

"chip_values": {

    "big_blind": 0.50,

    "small_blind": 0.25,

    "ante": 0.25,

    "max_buy_in": 50.00,

    "min_buy_in": 1.00

},

"timing": {

    "decision_time": 30,

    "time_bank_amount": 600,

    "time_between_hands": 10

},

"default_bank_value": 50,

"rabbit_hunting": "true",

"straddles": "true",

"stats_bluffing": "false",

"video_showdown": "true"

}`

Task: VP-62

1.0.23

add new action that allows you to get the game state

{"action": "game_state", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

Task: VP-62

1.0.22

Updates:

  • POST /tables/ now the table is created by default with null configuration (was previously created with an empty object {})

  • POST /tables/{table_token}/start/ this endpoint was removed, now the game started using the websocket protocol, and only the dealer can start the game

permissions:

  • PUT, PATCH /player/{id}/ - method to update player details. Now available only when there is no game in

progress on the table or before the table was open.

  • POST /tables/{table_token}/join/ now player available to join in status table - 'paid'

(in the previous implementation was 'open').

Also added a new permission so that you cannot join to a table that has no configuration.

  • PATCH /tables/{table_token}/configuration/ now you can patch the configuration only when there is no game in

progress on the table or before the table was open, because at that moment the state of the game does not exist yet.

Also a new websocket event has been added that sends a message to the websocket channel for all users when the table

configuration has been changed, so that the front-end always has an up-to-date table configuration.

  • POST /tables/{table_token}/open/ add new permission so that you cannot open the table that has no configuration.

Websocket examples:

valid actions:

{"action": "buy_in","amount": 20.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "action_call","amount": 10.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "action_bet","amount": 10.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "action_raise","amount": 10.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "action_fold", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "action_check", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "update_channel_id", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

invalid actions:

{"action": "buy_in","amount": 1000.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "action_call","amount": 10.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "invalid_action","amount": 1000.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

{"action": "small_blind","amount": 10.0, "timestamp": "2017-02-15T20:26:08.937881-06:00"}

game_start action example:

{"action": "game_start", "game_type_id": "THD", "timestamp": "2017-02-15T20:26:08.937881-06:00"}

game state example:

state = {

"channel": "T",

"pots": ["20.0"],

"betting_round": 4,

"seats": [null, 22, null, null, null, 23, null, null, null],

"order": 1,

"pots_players": [[22, 23]],

"players_timebank": ["0", "600", "0", "0", "0", "600", "0", "0", "0"],

"players_statuses": ["0", "S", "0", "0", "0", "S", "0", "0", "0"],

"players": [null, 22, null, null, null, 23, null, null, null],

"players_bank": ["0", "0.00", "0", "0", "0", "0.00", "0", "0", "0"],

"table_token": "259f1433-58b2-4f80-8ca5-d9f0d80e20a1",

"bets": [

        [null, "10.0", null, null, null, "10.0", null, null, null],

        [null, null, null, null, null, null, null, null, null],

        [null, null, null, null, null, null, null, null, null],

        [null, null, null, null, null, null, null, null, null],

        [null, null, null, null, null, null, null, null, null]

         ],

"turn_player_seat": 5,

"pots_winners": [[23]],

"game_id": "096577d2-07b1-479d-b364-d025244ba038",

"players_stack": ["0", "30.0", "0", "0", "0", "50.0", "0", "0", "0"],

"sequence": 0,

"dealer_seat": 1,

"community_cards": ["QS", "5C", "KS", "9S", "2H"]

}

Task: VP-62

1.0.21

Add websocket jwt authentication.

Add new websocket events:

user_connected

{

"event": "user_connected",

"payload": {

       "user": user,

    }

"timestamp": Timestamp with time zone

}

auth_error

{

"event": "auth_error",

"payload": {

       "code": error code (String),

       "detail": erro detail (String),

    }

"timestamp": Timestamp with time zone

}

Task: VP-62

1.0.20

Update: now endpoint for short-lived jwt token

accepts an empty request body

  • POST /api/v1/auth/token/short/ - get short access and refresh token (login)

Task: VP-52

1.0.19

Add an endpoint to generate short jwt token for websocket connection:

  • POST /api/v1/auth/token/short/ - get short access and refresh token (login)

Task: VP-52

1.0.18

Add a new endpoint:

  • POST /tables/{table_token}/start/

Task: VP-77

1.0.17

Edited structure of table configuration json.

Removed the configuration field and all the

fields that it contained are now one level higher.

  • PATCH /tables/{table_token}/configuration/

Task: VP-72

1.0.16

Add a new websocket events:

jitsi_id_changed - send if table player jitsi_id was changed(also added it to websocket debug page)

user_seated- send if table player seat was changed

Task: VP-89

1.0.15

Add a new endpoint:

  • PATCH /tables/{table_token}/configuration/

Task: VP-72

1.0.14

Add celery tasks to:

  • to expire tables, which expired time came (every minute)

  • to clean unpaid tables, which were created > 24h ago (once a day)

Task: VP-86

1.0.13

Add base Stripe payments implementation.

New API endpoints:

  • GET /api/v1/payments/prices/ - get existing products and prices to perform

payment.

  • POST /api/v1/payments/prices/{id}/get-payment-intent/ - prepare payment

intent for payment confirmation and etc (start payment process).

Replace cc_token field to payment_method in User entity and update API

to return user's card data in /users/current/

So to pay for the table user should:

  1. Create table - POST /api/v1/tables/

  2. Get payment intent - POST /api/v1/payments/prices/{id}/get-payment-intent/

  3. Perform payment on frontend side (added rent table page to do it for

testing for now - https://backend-dev.versuspoker.com/rent-table/)

  1. After that Stripe will send webhook to backend, it would be processed and

table become paid.

Task: VP-86

1.0.12

Added game_state event for websockets debug page

Task: VP-85

1.0.11

Api for table players was changed to /players/ instead /player/

Now table creator can't kick yourself

Task: VP-71

1.0.10

Fix few API issues, now API:

  • not returns any tables or table players if user was kicked or left

the game

So only active table players and creators can get table info and its

table players, update it and perform other different operations.

Task: VP-87

1.0.9

Available for S3 direct upload destinations are:

  • player_avatars

  • table_custom_backgrounds

  • table_custom_background_musics

Also note if you have a Content-Disposition error on S3 direct upload to AWS,

you need to change request attributes ordering, so Content-Disposition would

go before file.

Task: VP-52

1.0.8

Now if the user tries to take the seat he has already taken the error is not returned

Task: VP-71

1.0.7

Add Debug Websockets https://backend-dev.versuspoker.com/debug/websockets/

Task: VP-85

1.0.6

Add new endpoints for player:

  • GET /player/ - get list of players. Returns only players at the same

tables as the user, or players at the tables where the user is creator.

  • GET /player/{id}/ - get player details. Find only players at the same

tables as the user, or players at the tables where the user is creator.

  • GET /player/{id}/stats/ - return player stats

  • POST /player/{id}/kick/ - this method frees up player seat, fixes the

time and fills the 'kick' field (only table creator can do this).

  • POST /player/{id}/leave/ - this method frees up player seat

fixes the time and fills the 'left' field.

  • PUT, PATCH /player/{id}/ - method to update player details.

If invalid user is trying to call this method - return 403 HTTP code.

Only player authenticated by JWT token can call this method for its own ID

If player is not found by ID - returns 404

Task: VP-71

1.0.5

Add new endpoints for table:

  • POST /tables/{table_token}/join/ - method is available for any

authenticated user on paid and opened tables, if user is not a kicked

layer.

  • GET /tables/{table_token}/stats/ - method just returns table stats field.

Task: VP-74

1.0.4

Add new endpoint for table:

  • POST /tables/{table_token}/open/ - method is available only for creator and

for already paid tables. It sets corresponding table status, open and

expire fields (open = NOW, expire = open + 24h).

Task: VP-73

1.0.3

Add base tables and lookups API endpoints:

  • GET /tables/ - method returns tables where current user is creator or

player.

  • GET /tables/{table_token}/ - get details of some table available for user

(the table is available if user either creator or player).

  • POST /tables/ - method to create new tables, allowed to any authenticated

user.

  • PUT, PATCH /tables/{table_token}/ - method to update tables, allowed to

only table creators until tables are not opened, only name and type

fields may be updated for now.

  • DELETE /tables/{table_token}/ - method to remove table - available for

creators only and for tables, which are not paid yet.

  • GET /lookups/table-statuses/ - get list of existing table statuses.

  • GET /lookups/table-statuses/{id}/ - get details of table status.

  • GET /lookups/table-types/ - get list of existing table types.

  • GET /lookups/table-types/{id}/ - get details of table type.

Task: VP-61

1.0.2

Actualize ERD, add new fields and removed redundant stuff, updated Django

Admin and etc.

Task: VP-70

1.0.1

Reorganize password reset, now it will lead to frontend (instead of custom

Django View) by the url from constance - PASSWORD_RESET_REDIRECT_LINK.

Task: VP-52

1.0.0

Add auth API:

  • POST /api/v1/auth/registration/ - to register a new user

  • POST /api/v1/auth/confirm-email/ - confirm email for user

  • POST /api/v1/auth/token/ - get access and refresh token (login)

  • POST /api/v1/auth/token/refresh/ - refresh access token

  • POST /api/v1/auth/token/verify/ - check whether login is valid

  • POST /api/v1/auth/password/change/ - change current user's password

  • POST /api/v1/auth/password/reset/ - reset current user's password

  • POST /api/v1/auth/password/reset/confirm/ - reset old password from

reset e-mail to a new password

  • GET /api/v1/users/current/ - get current authenticated user profile

Postman collection: https://www.getpostman.com/collections/5c075a2c9bc83759e18e

Swagger spec: http://localhost:8000/swagger

Task: VP-52