# Roulette This is a single player (user vs system dealer) implementation of the famous [Roulette][roulette_wiki] game. ## Code name `roulette`. ## Scope This docs discuss about: - Game rule - Tech design Considered, but currently out of scope: - Game skin - Advance rules - Advance promotion configuration ## Rule Check #51 for a good overview and online sample to play with. Keep in mind #51 just shown the basic rule of the game. Wikipedia article has more advance rules which can change the advantage of the house. This docs layout the technical design to support just the basic rules. In future, we might support advance rules in form of game config or just add new roulette games, if the different is too much for the config table. ## Tech design First, notice that this game is pretty similar to `dice_3`: A game record contains multiple bet, each can be either `UserWin`, `UserLose` (there's no draw result for this game). Hence, our tech design will be pretty similar. Please make sure to read and understand how `dice_3` is implemented first. ### Constants There's only a finite (hundreds) type of bet user can place for this Roulette game. For consistent with our other games, we call they "game type" and we're using string instead of int, trade the storage space and processing time (string is always slower than int) to make them human-readable (in DB, during debugging and in HTTP request). Below value are not just enough for the docs. Implementer should check the game table and online references to fully understand it and add complete list (brute force scanning is acceptable, don't try to be clever and introduce bugs). ```go // file internal/consts/cards_roulette_game_type.go type RouletteGameType string const ( // Inside: place chip inside the nunber area //------------------------------------------------------------------------ // Straight bet: place chip on a single number. RouletteGameTypeStraight0 RouletteGameType = "STRAIGHT_0" RouletteGameTypeStraight1 RouletteGameType = "STRAIGHT_1" ... RouletteGameTypeStraight36 RouletteGameType = "STRAIGHT_36" // Split: place a chip in the line between 2 numbers. // // Note that it's acceptable to use underscore for those constants // that represent the split. The smaller numebr should always come first. RouletteGameTypeSplit_0_1 RouletteGameType = "SPLIT_0_1" RouletteGameTypeSplit_0_2 RouletteGameType = "SPLIT_0_2" RouletteGameTypeSplit_0_3 RouletteGameType = "SPLIT_0_3" ... RouletteGameTypeSplit_34_35 RouletteGameType = "SPLIT_34_35" RouletteGameTypeSplit_35_36 RouletteGameType = "SPLIT_35_36" // Street: ... // Trio: place chip in the corner created by 0 and 1, 2, 3. RouletteGameTypeTrio_0_1_2 RouletteGameType = "TRIO_0_1_2" RouletteGameTypeTrio_0_2_3 RouletteGameType = "TRIO_0_2_3" // Square: place chip in the corner created by 4 numbers. // There corners is listed in order: smaller first. RouletteGameTypeSquare_1_2_4_5 RouletteGameType = "SQUARE_1_2_4_5" RouletteGameTypeSquare_2_3_5_6 RouletteGameType = "SQUARE_2_3_5_6" ... RouletteGameTypeSquare_32_33_35_36 RouletteGameType = "SQUARE_32_33_35_36" // Six: A bet on two adjacent lines. ... // // Outside: place chip outside the nunber area //------------------------------------------------------------------------ RouletteGameTypeRed RouletteGameType = "RED" RouletteGameTypeBlack RouletteGameType = "BLACK" ... ) ``` ### DB - `roulette_game_record`: read-only from Staff and Partner perspective, can only be created via `rpc/game/roulette`. This should come with Audit and Comment. - `id`, `ctime` - `user_id`: user who place the bet - `partner_id`: Partner who will pay the `reward_amount`. This can be derived from `user_id`, but we add it here for denormalization, to speed up the report generation. - `total_bet_amount`: total money user had placed bet for this record - `num`: the generated number (0 to 36) that server generated when user submit bet - `total_reward_amount`: total money that user win from this record - `roulette_bet_record`: read-only resource APIs, can be created only via `rpc/game/roulette` - `id`, `ctime` - `roulette_game_record_id`: ref to the parent record - `bet_amount`: the money user placed for this particular bet - `bet_type`: type of the bet (see #51, or the next sections) - `result_type`: either `UserWin` or `UserLose` - `reward`: 0 if this web win nothing, or positive value, as per the number on parent game record ### Resources API For the admin page, we will implement: - Read-only API for `roulette_bet_record` - Read-only API for `roulette_game_record` ### RPC API #### User to place bet ``` POST /api/game/roulette ``` Request: ```json { "bets": [ { "bet_amount": 10, "game_type": "RED" }, { "bet_amount": 20, "game_type": "SQUARE_32_33_35_36" } ] } ``` Response: ```json { "numm": 1, "total_reward_amount": 170, "total_bet_amount": 30, "winning_game_types": ["RED", "STRAIGHT_1", ...], "bets": [ { "game_result": 1, "bet_amount": 10, "reward_amount": 170, "game_type": "RED" }, { "game_result": 0, "bet_amount": 20, "reward_amount": 0, "game_type": "SQUARE_32_33_35_36" } ] } ``` Note that above values are made up, and don't reflect actual game logic. Reason and explantions for some response fields: - `num`: secure random generated number, 0 to 36, FE will do some fabulous animation to show this number. - `winning_game_types`: to highlight the winning place that user should have placed their bets. If user has some positive `total_reward_amount`, their rewarded bet game types must exist in this array. - `bets`: bets from user, with the calculated result. #### User to view bet history Add 2 new RPCs: - `/api/me/roulette_game_record/get` - `/api/me/roulette_bet_record/get` Implementation should be easy. Check `rpc/me/dice_1_game_record` for references. > TODO (jl): `winning_game_types` can be be pretty big array of strings, check > with FE again to see if they really need it. And if that array affect our > performance, we might need to encode them using strings, or bitset. ## References - #51 - [Wiki][roulette_wiki] - [How to play roulette](roulette_site) <!-- ref --> [roulette_wiki]: https://en.wikipedia.org/wiki/Roulette [roulette_site]: https://www.roulettesites.org/rules/