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:
Host can't play in this game mode, he just seats at the table.
Host have to seat at the table to start a tournament.
Host can't really leave the state. If he leaves/disconnects, new Host Away
status is set.
Task: VPSUP-23
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
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
join to the table, when it's expiredTask: VP-592
Task: VP-594
Task: VP-611
Task: VP-595
Task: VP-611
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.
do not allow him to return on table and play.
section in task).
tests connected with this logic, added new ones.
Task: VP-606
users/current/is-current-user-playing/ endpoint which return True if the user is playing at any table
Task: VP-594
Task: VP-596
Task: VP-574 (check comments section)
best_hand_folded_counter statistic on pre-flop.Task: VP-553
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
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
Added to events API spec:
telemetry_trace_id (nullable)
duration (nullable)
player_id (nullable)
player_name (nullable)
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
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
Replaced show_next_game_button bool field from game_state event to next_hand event
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
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
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)
```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.
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:
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).
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."
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.
refresh_state action.Task: VP-474
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)
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
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
Deleted players_timebank field from the game_state event
Deleted timebank_left field from the turn event
Task: VP-467
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
Added call_amount field to the turn event.
Task: VP-451
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:
Task: VP-398
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.
api/v1/tables/{short_table_token}/configuration/, now you can't change configuration during the tournament.
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
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
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
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:
/api/v1/reports/{short_table_token}/send-report/Task: VP-275
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
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
Added delay for displaying heads-up-showdown announcing pop-up.
New field in heads_up_showdown event -> announce_time
Task: VP-290
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
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
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
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
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
Reorganize calculation of cash_loss_amount metric, now it is calculated at
the end of the game.
Task: VP-311
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
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
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
All timers data(expirations, intervals, remaining times) now in floats
Task: VP-310
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
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
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
}
}
```
player_disconnected:````json
{
"event": "player_disconnected",
"timestamp": 1621848905.704886,
"payload": {
"channel": "T",
"order": 0,
"player": 56,
"table_token": "0111666b-837a-4672-ba46-2b645524ad83"
}
}
````
error_representation field to action_error event.Task: VP-238
Added permissions for next_hand and game_start in flow.
Added celery task which starts the moment the table expires
Task: VP-297
Continuation Bet in statisticA 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)
LIMP to statisticFor 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
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
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
}
}
```
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
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
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.
joinRequest:
```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_outRequest:
```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
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
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
added next_hand_expiration in next_hand event, so you can show next hand timer.
action_ante - new type of action_ackstart_tournament - just empty event, which is sent when tournament was startedincrease_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 fieldfields:
winners: {100: 4.00, 400: 6.00, 200: 10.00}
pause_next_hand - sent when tournament was pausedfields:
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 unpausedfields:
next_hand_expiration - new timestamp when next hand will be started.
blind_scheduler_expiration - timestamp in seconds when next blind level will be increased.
```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"
}
```
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"]
}
}
```
leave player behavior, so now when player is left he would geta 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.
left or was kicked on hismove - enforce user's move dynamically.
Task: VP-191
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
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:
/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)"
}
]
```
/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.
/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"
}
]
```
/users/current/game-stats/ - user's game specific statshttps://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
Fix kick/ban player behavior.
Add immediate user disconnect when player kicked by server.
Remove sending private_game_state and private_data for cases when
player becomes disconnected or kicked.
Player hasn't selected a seat! error, which happens when new gamestarted with disconnected player.
Task: VP-172
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
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
Add players_statuses field to GameStateInfo, options:
- DISCONNECTED - "D"
- CONNECTED - "C"
- KICKED - "K"
- LEFT - "L"
- SEATED - "S"
Task: VP-15
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
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
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
players_delayed_stack field to ETCD. So, now when player tries toadd 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.
delayed_table_stack field to ActionACK, so now when userperforms actions - he would have info about delayed table stack.
players_delayed_stack field to GameStateInfo, so now if playerrefreshes table, he would have info about the money he has in delayed stack.
Task: VP-167
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.
bank and table_stack to PlayerInfo action message. So now itwill be used by following events:
- player connected
- player disconnected
- player kicked
- player left
- player seated
players_bank, players_stack and players_timebank ETCDfields 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
Add raising action_error when player's turn time expired.
Task: VP-129
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
Winners messageAdded 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).
GameStateInfo messageAdded 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
Add calculation for min/max amount of raise/bet for Pot-Limit game.
Task: VP-152
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
/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",
}`
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.
```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
```
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)
ActionACK messageAdded new bank field, which shows how much money player currently has in bank.
Task: VP-135
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
Add time track service, functionality to use it from vp framework.
Task: VP-101
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.
{"action": "update_jitsi_id", "jitsi_id": "345", "timestamp": "2017-02-15T20:26:08.937881-06:00"}
{"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
The player will now occupy the seat through websocket protocol.
{"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
{"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"]}}
{"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
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
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
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
/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.
/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.
/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.
/tables/{table_token}/open/ add new permission so that you cannot open the table that has no configuration.{"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"}
{"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"}
{"action": "game_start", "game_type_id": "THD", "timestamp": "2017-02-15T20:26:08.937881-06:00"}
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
Add websocket jwt authentication.
Add new websocket events:
{
"event": "user_connected",
"payload": {
"user": user,
}
"timestamp": Timestamp with time zone
}
{
"event": "auth_error",
"payload": {
"code": error code (String),
"detail": erro detail (String),
}
"timestamp": Timestamp with time zone
}
Task: VP-62
Update: now endpoint for short-lived jwt token
accepts an empty request body
/api/v1/auth/token/short/ - get short access and refresh token (login)Task: VP-52
Add an endpoint to generate short jwt token for websocket connection:
/api/v1/auth/token/short/ - get short access and refresh token (login)Task: VP-52
Add a new endpoint:
/tables/{table_token}/start/Task: VP-77
Edited structure of table configuration json.
Removed the configuration field and all the
fields that it contained are now one level higher.
/tables/{table_token}/configuration/Task: VP-72
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
Add a new endpoint:
/tables/{table_token}/configuration/Task: VP-72
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
Add base Stripe payments implementation.
New API endpoints:
/api/v1/payments/prices/ - get existing products and prices to performpayment.
/api/v1/payments/prices/{id}/get-payment-intent/ - prepare paymentintent 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:
Create table - POST /api/v1/tables/
Get payment intent - POST /api/v1/payments/prices/{id}/get-payment-intent/
Perform payment on frontend side (added rent table page to do it for
testing for now - https://backend-dev.versuspoker.com/rent-table/)
table become paid.
Task: VP-86
Added game_state event for websockets debug page
Task: VP-85
Api for table players was changed to /players/ instead /player/
Now table creator can't kick yourself
Task: VP-71
Fix few API issues, now API:
kicked or leftthe 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
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
Now if the user tries to take the seat he has already taken the error is not returned
Task: VP-71
Add Debug Websockets https://backend-dev.versuspoker.com/debug/websockets/
Task: VP-85
Add new endpoints for player:
/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.
/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).
/player/{id}/leave/ - this method frees up player seatfixes the time and fills the 'left' field.
/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
Add new endpoints for table:
/tables/{table_token}/join/ - method is available for anyauthenticated user on paid and opened tables, if user is not a kicked
layer.
/tables/{table_token}/stats/ - method just returns table stats field.Task: VP-74
Add new endpoint for table:
/tables/{table_token}/open/ - method is available only for creator andfor already paid tables. It sets corresponding table status, open and
expire fields (open = NOW, expire = open + 24h).
Task: VP-73
Add base tables and lookups API endpoints:
/tables/ - method returns tables where current user is creator orplayer.
/tables/{table_token}/ - get details of some table available for user(the table is available if user either creator or player).
/tables/ - method to create new tables, allowed to any authenticateduser.
/tables/{table_token}/ - method to update tables, allowed toonly table creators until tables are not opened, only name and type
fields may be updated for now.
/tables/{table_token}/ - method to remove table - available forcreators 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
Actualize ERD, add new fields and removed redundant stuff, updated Django
Admin and etc.
Task: VP-70
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
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
/api/v1/users/current/ - get current authenticated user profilePostman collection: https://www.getpostman.com/collections/5c075a2c9bc83759e18e
Swagger spec: http://localhost:8000/swagger
Task: VP-52