---
# System prepended metadata

title: Roulette

---

# 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/
