The app is for the code challenge
- Ruby version 2.7.1
- Ruby on Rails 6.1
- Redis
- Make sure the required Ruby version is installed.
- Make sure Redis server is installed and running.
- Run
bundle install
to install gems. - Run
rspec
The app's API has three endpoints:
GET /
- returns the game statusPOST /start
- starts a new gamePOST /deliveries
- adds a delivery to the current frame. The endpoint receives pins number inpins
parameter.
The app stores game data in json object. Default storage is Redis, but it is possible to configure any kind of storage and pass it to game as dependency. Example:
{
"frames": [[5,5],[0,10],[10,0],...],
"active": true,
"bonus": [],
"current_frame": 5
}
frames
- stores array of frames with deliveriesactive
- shows if game is startedbonus
- stores bonus deliveries in case of last frame is a spare or a strikecurrent_frame
- current frame index
- When a game is started a new game data object is created and persisted in storage.
- While new deliveries are being added the app distributes deliveries between frames.
If it is the last frame and not a spare or a strike the game is finished and
active
property bocomesfalse
. If the last frame is a spare or a strike the app puts pins intobonus
property. - When the game status is requested scores for each frames are calculated and included
into game representation. If a frame score is not possible to calculate (for example there
are not next deliveries for a strike frame), then the score for the frame is
null
{
"status": "success",
"data": {
"frames": [[0, 10], [5, 5], [1, 1], [2, 2], [8, 2], [0, 0], [5, 2], [4, 0], [6, 1], [10, 0]],
"active": false,
"bonus": [10, 5],
"score": [15, 26, 28, 32, 42, 42, 49, 53, 60, 85]
}
}
Having data for each frame and scores allows to display a game details on a frontend.
- Modular structure.
- Isolated logic layer with various service objects within game context:
Commands::BuildGameSchema
- build default game schema on startCommands::CalculateScore
- calculates game scores according to framesCommands::CreateDelivery
- add delivery to the curren game, distributes deliveriesRepositories::GameRepository
- communicates with storage objectPresenters::GamePresenter
- decorates game status before sending in response.
- Exchangeable storage to store game data is passed to repository as dependency.
- Custom exception objects with configurable messages.
- Self-explanatory code and test coverage with integration and unit tests.