# Web API for the use by the Rule Game client - first batch

Ver 1.027, 2020-10-09

The "first batch" (prefix=`/GameService`) of the Rule Game web API consists of calls that can be used for players that do not participate in any experiment (i.e. don't have player IDs, don't have any trial lists associated with them, etc). This is suitable e.g. for the research interface, for the research team members to develop and test rule sets.

This API includes several HTTP request/response pairs that can be used by the TypeScript/React GUI. Conceptually, its functionality is fairly similar to that of the Captive Game Server (used by the ML programs), but is customized for the needs of a GUI app used by human players. And, of course, the client communicates with it over HTTP, instead of pipes or the socket level.

### Deprecated methods for players enrolled in experiments

Methods described in this section were developed before it was clearly understood how the logic is to be divided between the client and server code; so they are not to be used, and the methods from the Second Batch are to be used instead.

1. POST `startTrial:` Start a player's interaction with the system, and obtain a randomly selected trial list for this player

   The input parameter is the player ID (a string). In the future, the system will determine, based on the player ID, what experiment the person is enrolled into (e.g MTurkers vs. psych students vs. ourselves testing a particular game); at present, the player ID does not really matter, as everybody is considered to be enrolled in the experiment called "default".

   Return value: a JSON structure containing the content of one trial list, randomly selected among all trial lists used in this experiment. This structure is a list of ParaSet structure, each of them is similar to those that `getParaSet` would select. A typical returned structure:

         [{"clearing_threshold":1.3,"max_points":10,"b":1.5,"min_points":2,"max_colors":4,"f":4,"feedback_switches":"fixed","min_objects":4,"m":9,"n":1,"clear_how_many":2,"bonus_extra_pts":3,"rule_id":"TD-01","max_objects":6,"grid_memory_show_order":false,"min_shapes":4,"stack_memory_show_order":false,"max_shapes":4,"min_colors":3,"stack_memory_depth":6,"max_boards":5,"activate_bonus_at":2},
         {"clearing_threshold":1.3,"max_points":10,"b":1.5,"min_points":2,"max_colors":4,"f":4,"feedback_switches":"fixed","min_objects":4,"m":9,"n":1,"clear_how_many":2,"bonus_extra_pts":3,"rule_id":"TD-02","max_objects":6,"grid_memory_show_order":false,"min_shapes":4,"stack_memory_show_order":false,"max_shapes":4,"min_colors":3,"stack_memory_depth":6,"max_boards":5,"activate_bonus_at":2},
         {"clearing_threshold":1.3,"max_points":10,"b":1.5,"min_points":2,"max_colors":4,"f":4,"feedback_switches":"fixed","min_objects":4,"m":9,"n":1,"clear_how_many":2,"bonus_extra_pts":3,"rule_id":"TD-03","max_objects":6,"grid_memory_show_order":false,"min_shapes":4,"stack_memory_show_order":false,"max_shapes":4,"min_colors":3,"stack_memory_depth":6,"max_boards":5,"activate_bonus_at":2},
         ...
         ...
         ]

2. [Note: this method is not needed anymore, as it is superseded by `startTrial:`!] GET getParaSet: Retrieve a parameter set: Name:

   The argument is the name of the parameter set.

   The return value is a JSON object, which may look like this: `{"max_points":10, "min_points":3, "max_colors":4, "feedback_switches":"fixed", "error":false, "clear_how_many":4, "max_objects":8, "grid_memory_show_order":true, "min_shapes":2, "stack_memory_show_order":true, "activate_bonus_at":3, "clearing_threshold":1.2, "b":0.1, "f":0.2, "errmsg":"No error", "min_objects":2, "m":10, "n":4, "bonus_extra_pts":10, "rule_id":"rule-1", "name":"param-1", "max_shapes":4, "min_colors":1, "stack_memory_depth":16, "max_boards":5}` . In the return value, the boolean field `error` contains `false` if the parameter set has been successfully retrieved, or `true` if an error has been encountered (e.g. no parameter set with this name exists). The field `errmsg`, if provided, may contain a human-readable error message.

   (The data will be retrieved from a CSV file in the directory `/opt/tomcat/game-data/param/` on the server. The file name consists of the name of the parameter set and extension ".csv").

   The server does not know the semantics of the fields in the CSV file, nor does it know what the type of each field is supposed to be (integer vs. boolean vs. string). If the value in a field looks like a number or a boolean, the server treats it accordingly; otherwise, the field value is treated as a string.

### Researcher interface methods

1. POST `newEpisode` (a): Create a new episode: Rule set name (given in the param set `rule_id`; refers to a TXT file in `game-data/rules`, without the extension):
   Number of pieces (a number within the [min_objects, max_objects] range given in the param set):
2. POST `newEpisode` (b): with additional parameters: the number of shapes and the number of colors: Rule set name (given in the param set `rule_id`):
   Number of pieces (a number within the [min_objects, max_objects] range given in the param set):
   Number of shapes:
   Number of colors:
3. POST `newEpisode` (c): with additional parameters: the initial board: Rule set name (given in the param set `rule_id`):
   Initial board name (refers to a JSON file in `game-data/boards`, without the extension):

   This returns a JSON object which contains the `error` field (true on an error, false on success), the optional `errmsg` field, and the `episodeId` field. The `episodeId` field contains the ID (a string) of the episode object, which can be used in the later `move` calls. The returned structure also contains the description of the current board at the beginning of the episode (in the same format as in the `move` call, below).

   A typical return value: on success

       {"board":
        {"longId":0,"id":0,
         "value":[
          {"buckets":[3],"color":"BLUE","id":0,"shape":"SQUARE","x":1,"y":2},
          {"buckets":[],"color":"BLUE","id":0,"shape":"CIRCLE","x":2,"y":3},
          {"buckets":[],"color":"BLUE","id":0,"shape":"STAR","x":2,"y":4},
          {"buckets":[1],"color":"YELLOW","id":0,"shape":"CIRCLE","x":6,"y":5}]},
        "episodeId":"20200811-163531-8K175O",
        "error":false}

   On failure:

       {"errmsg":
        "Cannot read rule file: /opt/tomcat/game-data/rules/nonesuch.txt",
        "error":true}

4. GET `display`: Display the current board: Episode ID (returned by an earlier newEpisode call):

   Returns the same JSON structure as was returned by the most recent `move` or `newEpisode` call, describing the current board and the current `finishCode`, except that the `code` value on success is -8 (JUST_A_DISPLAY, indicating that this was a "display" call, rather than a "move" call).

5. POST `move`: Make a move: Episode ID (returned by an earlier newEpisode call):
   Piece to move: column=x=, row=y= (both ranging 1 thru 6)
   Destination bucket (identified by bucket_column=bx=, bucket_row=by= (possible values are 0 and 7)
   Attempted move count so far (the number of previous calls to `move` in this episode)

   The return value is a JSON object (Display) which contains:

   - the boolean `error` flag;
   - the `code` value that may provide more details on the operation results;
   - the `finishCode` value which indicates whether the game still goes on, has finished (the board has been cleared), or has stalemated;
   - the `board` object that desribes the current board (what pieces are currently on the board, and whither they can be moved). The code is negative if the request was not understood (reference to a non-existent episode, missing or malformed parameters etc), positive if the request was valid but the piece could not be moved, and 0 if the requested piece has been moved.
   - The value `attemptCnt` is incremented by one on each valid request (regardless of whether the piece requested was moved or not). Therefore, when calling `move`, the supplied value of the `attemptCnt` parameter should be 0 on the first move; on subsequent calls, it should be equal to the value of attemptCnt returned by the previous `move` call.

   For the semantics of the `code` and `finishCode` fields, see the entry on the MOVE command in the documentation on the Captive Game Server.

   A typical return value: on success

       {"attemptCnt":1,
        "board":{"longId":0,"id":0,
        "value":[
          {"buckets":[],"color":"BLUE","id":0,"shape":"SQUARE","x":6,"y":4},
          {"buckets":[0,1],"color":"RED","id":0,"shape":"TRIANGLE","x":2,"y":5}]},
       "code":0,
       "finishCode":0}

   On failure:

       {"attemptCnt":0,"code":-6,"errmsg":"# Invalid episode ID"}

   or

       {"attemptCnt":1,
        "board":{"longId":0,"id":0,"value":[{"buckets":[],"color":"BLUE","id":0,"shape":"SQUARE","x":6,"y":4}, ... ]},
       "code":-7,
       "errmsg":"Given attemptCnt=0, expected 1"}

6. GET `writeFile`: see Write file (including append)
7. GET `/listRules`: lists rule sets files in the standard input directory (/opt/tomcat/game-data/rules) on the server. Any of the returned values can be used as the name=... parameter in /newEpisode.
8. GET `/listInitialBoards`: lists initial board files in the standard input directory (/opt/tomcat/game-data/boards) on the server. Any of the returned values can be used as the board=... parameter in /newEpisode.

### HTML play (for testing individual rule sets directly, without creating player accounts or experiment plans)

Note: rule set and board file names can be specified by a complete qualified file name on sapir (with a path beginning with a slash, e.g. `/home/vmenkov/w2020/game/game-data/rules/rules-01.txt`, or `/home/vmenkov/w2020/game/game-data/boards/four-corners.json`), or just by the rule set name or board name (without the directory name and withour extension, e.g. `rules-01`, or `four-corners`). In the latter case, the data files will be looked by the server in the appropriate subdirectory of `/opt/tomcat/game-data`.

You can have subdirectories in the rule directory or the board directory. For example, if the board name is specified as `project1/foo`, the server will look for r `/home/vmenkov/w2020/game/game-data/boards/project1/foo.json`

- POST `/newEpisodeHtml`: (a): Create a new episode: Rule set name (given in the param set `rule_id`; refers to a TXT file in `game-data/rules`, without the extension):
  Number of pieces (a number within the [min_objects, max_objects] range given in the param set):
- POST `/newEpisodeHtml` (b): with additional parameters: the number of shapes and the number of colors: Rule set name (given in the param set `rule_id`):
  Number of pieces (a number within the [min_objects, max_objects] range given in the param set):
  Number of shapes:
  Number of colors:
- POST `/newEpisodeHtml` (c): with additional parameters: the initial board: Rule set name (given in the param set `rule_id`):
  Initial board name (either refers to a JSON file in `game-data/boards`, without the extension, or is a complete path name):
- /moveHtml Episode ID (returned by an earlier newEpisode call):
  Piece to move: column=x=, row=y= (both ranging 1 thru 6)
  Destination bucket (identified by bucket_column=bx=, bucket_row=by= (possible values are 0 and 7)
  Attempted move count so far (the number of previous calls to `move` in this episode. This can also be interpreted as 0-based number of this move attempt)