W3911 Sudoku Server
From Coder Merlin
Revision as of 13:02, 20 October 2021 by David-ben-yaakov (talk | contribs) (→Server-side Returning "No Content")
Within these castle walls be forged Mavens of Computer Science ...
— Merlin, The Coder
Background[edit]
A Sudoku board is made up of nine boxes. Boxes (container for nine cells) are listed from top-to-bottom, left-to-right indexed from zero. Cells are listed from top-to-bottom, left-to-right, indexed from zero. All valid payloads and responses must use well-formed JSON. “cells” is returned as follows: “cells”: [[<nine values from top-left>], [<nine values from top-middle>], …]
End Points[edit]
POST /games?difficulty=<difficulty>
Creates a new game and associated board
Parameters:
difficulty: easy | medium | hard | hell
Body: none
Status code: 201 Created
Response: ID (integer) of newly created game {"id":<id>}
{"id": 728134}
Errors:
400 Bad Request (difficulty specified doesn't match requirements)
GET /games/<id>/cells?filter=<filter>
Returns the current cells for the specified game
Parameters:
filter: all | repeated | incorrect
Body: none
Status code: 200 OK
Response: {"board": [{"cells":[{"position":{"boxIndex":<boxIndex>,"cellIndex":<cellIndex>},"value":<value>}...
{"board": [{"cells":[{"position":{"boxIndex":0,"cellIndex":0},"value":0},{"position":{"boxIndex":0,"cellIndex":1},"value":1}, {"position":{"boxIndex":0,"cellIndex":2},"value":2},{"position":{"boxIndex":0,"cellIndex":3},"value":3}, {"position":{"boxIndex":0,"cellIndex":4},"value":4},{"position":{"boxIndex":0,"cellIndex":5},"value":5}, {"position":{"boxIndex":0,"cellIndex":6},"value":6},{"position":{"boxIndex":0,"cellIndex":7},"value":7}, {"position":{"boxIndex":0,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]}, {"cells":[{"position":{"boxIndex":1,"cellIndex":0},"value":0},{"position":{"boxIndex":1,"cellIndex":1},"value":1}, {"position":{"boxIndex":1,"cellIndex":2},"value":2},{"position":{"boxIndex":1,"cellIndex":3},"value":3}, {"position":{"boxIndex":1,"cellIndex":4},"value":4},{"position":{"boxIndex":1,"cellIndex":5},"value":5}, {"position":{"boxIndex":1,"cellIndex":6},"value":6},{"position":{"boxIndex":1,"cellIndex":7},"value":7}, {"position":{"boxIndex":1,"cellIndex":8},"value":8}]} ]}
Errors:
400 Bad Request (filter specified doesn't match requirements)
PUT /games/<id>/cells/<boxIndex>/<cellIndex>
Place specified value at in game at boxIndex, cellIndex
Parameters: none
Body: {"value":<value>}
Status code: 200 OK
Response: none
none
Errors:
400 Bad Request (boxIndex is out of range 0 ... 8) 400 Bad Request (cellIndex is out of range 0 ... 8) 400 Bad Request (value is out of range 1 ... 9 or null)
JSON Encoding[edit]
JSON Decoding[edit]
Issue Request from Client to Server[edit]
Server-side Query String Access[edit]
let difficulty: String? = request.query["difficulty"]
Server-side Parameter Access and Error Handling[edit]
guard let boxIndex = req.parameters.get("boxIndex", as: Int.self),
let cellIndex = req.parameters.get("cellIndex", as: Int.self) else {
throw Abort(.badRequest, reason: "boxIndex and cellIndex MUST be integers")
}
Server-side Returning "No Content"[edit]
return Response(status: .noContent)
Conversion to Dynamic Library[edit]
- In a directory parallel to the root of your project, execute:
git clone https://github.com/TheCoderMerlin/VaporShell
- Enter your project's root directory
- Execute the following:
cp ../VaporShell/make.sh . cp ../VaporShell/Package.swift . cp ../VaporShell/dylib.manifest . cp -r ../VaporShell/Sources/CBase32 Sources/ cp -r ../VaporShell/Sources/CBcrypt Sources/ mkdir Sources/VaporShell mv Sources/App Sources/VaporShell/ mv Sources/Run Sources/VaporShell/ swift package clean rm .build -rf
- Remove the line "import App" from Sources/VaporShell/Run/main.swift