Skip to content

API and Callbacks for reader and viewer

Markus Liebelt edited this page Apr 20, 2024 · 13 revisions

Overview

There are many tickets that touch the topic of the API. Here is an (incomplete) list for some details:

  • #175: Definition of useful external API
  • #266: How to get current move? How to get current board?
  • #176: Allow notification to PgnViewerJS

and many more. What is the problem?

By using the base API, it is not at all obvious how to use it programmatically besides constructing a board, viewer or editor. The API currently provided may help in implementing additional functionality, but not in just using the viewer as a library, that provides a useful API that can be used directly.

Steps to do

  • Collect the most basic API that should be available.
  • Do that for the reader (first) and the viewer (second).
  • The reader could then be used inside node.js, and play e.g. through PGN, and asking the reader any time necessary information. So others could use the reader alone, to construct a new viewer without any change necessary.
  • Compare the future API with the current one, and define how to come from current to future.
  • Define events that are reasonable to be interested in.
  • Define for those callback possibilities, that can be used by the user.

Reader API

The reader API is developed in the new repo pgn-reader, but the requirements of that API are documented here. From the perspective of the viewer, the reader

  • must ensure that the PGN / file is correctly read
  • provides a sufficient API to play through the moves then XOR to allow adding new moves/comments/NAGs/... to the PGN while editing it.
  • Change: the reader should be responsible for only one game at a time, so all APIs to manage the games will be removed
  • split the viewer and editor API

Check the relevant parts of the reader for having the concrete API:

  • Extract from the reader the current exported functions ✔️
  • Go through each of them on the usage side (viewer) and comment on it (done in file api-comments.md) ✔️
  • Restructure the remaining functions, to get a more clean API.

Viewer API

I would like to have different APIs depending on the mode the viewer is in. In the long run, it would be nice to have a wrapper object, which is automatically built by calling the (currently) 4 base modes: pgnBoard, pgnPrint, pgnView and pgnEdit.

Before doing it concrete in the table, here a new try to isolate the interesting parts:

  • read(config): should read a PGN / file, there may be variants for readGame, readGames. Focus here is to read the pgn, check the moves, build the static structure of the moves, and return that structure then. This is the requirement to pgn-reader, so not built in the viewer then.
    • parse(pgn|file, config): first step, calls the parser, not too much additionally.
    • check(game, config): validates the game read, converts the game into something that then can be played/edited.
  • view(game, config): returns something, that has then the right API to play the game in the viewer.
    • setPosition(fen): search in the moves for the first position that matches the fen.
    • makeMove(san): search in the moves the position, where that move was done. Make that move then. Error if move cannot be found.
  • edit(game): returns something, that allows to edit then the game based on the given game. Similar to view, but some of the API calls will work different.

The problem I have to solve is, how state is handled here. When a move is made, it is known to the viewer what the current position is. So the state that is known is:

  • PgnGame: tags, gameComment and moves

The following is a trial, how to structure it, so that it can be written and changed, and is readable.

API Description Modes
changeConfig(<Map<Key,Value>>):PgnViewerConfiguration Allows to change the currently existing configuration. This will then be merged with the current configuration. New values overwrite existing ones then. For the viewer, the current position will be restored (setPosition), for the editor, the current PGN will replace the one given in the original configuration. Returns the merged configuration. all
getConfig():PgnViewerConfiguration Returns the current configuration of the viewer. all
getPosition():FEN Returns the current position as FEN string. board, view, edit
setPosition(<FEN|number>):Move|null Sets the current position of the board. Depending on the mode, this may have a different effect: board --> just show that position; view, edit --> see if one of the moves leads to that position, and go to that. If the argument is a number, it is the move number of the main line, starting with 0. Returns the move that is done then on the board (null for the board). board, view, edit
move(<Move>):PgnReaderMove From the current position, try to do that move. Be flexible in the representation for the move. Returns the generated (or existing) move that was then played on the board. Returns null in case of an error. view, edit
getReader():PgnReader Returns the pgn-reader that is used by the viewer. May be necessary to have more control over chess capabilities. board, view, edit
getChess():Chess Chess object, to have some chess capabilities not given by the reader.
startTimer() Starts the timer of the viewer. view, edit
stopTimer() Stops the timer of the viewer. view, edit

Remarks

  • setPosition is similar to makeMove, which is really complicated, and will not work with the number of different arguments you can try. This would be the chance to change that API to something much simpler.

Notifications

For notifications, I will try to do a similar approach. Collect possible events and callbacks, and describe for each how they could be used. They should as well depend on the mode that is used.

Event Description Modes
afterMove Inform the listener about a move done. The move itself will be part of the event. view, edit
afterChangeConfig Inform about a change in the configuration. Give the changes as argument. board, view, edit