Table of Contents

  1. Overview of Play Mode
    1. The Play Mode States
    2. Details of the Game View View-Model Data
  2. Playing My Turn State
    1. Ajax Actions for the Playing My Turn State
    2. The Move Data Type
    3. The Position Data Type
  3. Waiting for My Turn State
    1. Ajax Actions for the Waiting for My Turn State
  4. End-of-Game User Experience

Purpose

This page describes the interface required for the basic game play features that are a focus for Sprint 2; specifically, the state model of the Game View in Play mode. UI actions, such as moving a piece on the board or clicking an active button, trigger transitions in the browser's Game View state machine. These actions send HTTP Ajax requests to perform the action on the server. You must create Spark Route classes to handle these Ajax URL patterns. Example actions include: validating a move, submitting a completed turn, backing up from a move or resigning the game.

Overview of Play Mode

When playing a game of checkers there are only three possible states:

These three states control the behavior of the Game View client-side (JavaScript) code.

The Play Mode States

The following statechart defines the Game View behavior in Play mode.

State model of the Game View on the browser.

As seen in the state model above there are two guard variables that determine which state is used: isGameOver and isMyTurn.

The isGameOver guard variable is supplied directly in the modeOptions object; see: End-of-Game UX: modeOptionsAsJSON. If this object is not supplied, then the isGameOver variable is assumed to be false.

The isMyTurn guard is determined by this code:

function isMyTurn() {
  return (currentUser === redPlayer && activeColor === 'RED')
    || (currentUser === whitePlayer && activeColor === 'WHITE');
};

Details of the Game View View-Model Data

This section describes how the game.ftl Game View template provides data for the client-side code and how that code determines which state to use for a given user.

In Sprint 1, for the Start a Game story, your team created the GetGameRoute UI Controller to populate the View-Model of the game.ftl FreeMarker template. The data in the View-Model provides complete data that the client-side code uses to determine which of the three main states to control the behavior of the View. The following code is a snippet from the game.ftl template code:

<script>
window.gameData = {
  "currentUser" : "${currentUser.name}",
  "viewMode" : "${viewMode}",
  "modeOptions" : ${modeOptionsAsJSON!'{}'},
  "redPlayer" : "${redPlayer.name}",
  "whitePlayer" : "${whitePlayer.name}",
  "activeColor" : "${activeColor}"
};
</script>

These variables are used to determine the starting state of the Game View. The three examples are shown here:

Playing My Turn Example
<script>
window.gameData = {
  "currentUser" : "Jane",
  "viewMode" : "PLAY",
  "modeOptions" : {},
  "redPlayer" : "Jane",
  "whitePlayer" : "Fred",
  "activeColor" : "RED"
};
</script>

Jane is the signed in user viewing the game. The activeColor attribute determines whose turn it is. This example shows that it is the red player's turn and that happens to be Jane. Therefore, Jane's Game View will allow her to make moves and submit a turn.

Waiting for Turn Example
<script>
window.gameData = {
  "currentUser" : "Fred",
  "viewMode" : "PLAY",
  "modeOptions" : {},
  "redPlayer" : "Jane",
  "whitePlayer" : "Fred",
  "activeColor" : "RED"
};
</script>

Fred is viewing the game and it is Jane's turn. Fred's view of the game is relatively static and the browser occasionally polls the server to determine when Jane has completed her turn.

Game Over Example
<script>
window.gameData = {
  "currentUser" : "Jane",
  "viewMode" : "PLAY",
  "modeOptions" : {
    "isGameOver": true,
    "gameOverMessage": "Fred resigned."
  },
  "redPlayer" : "Jane",
  "whitePlayer" : "Fred",
  "activeColor" : "RED"
};
</script>

Jane is viewing the game but now the Game View code determines that the game is over and the reason was because Fred resigned; this information is supplied in the modeOptions attribute. See End-of-Game User Experience for more details.

Playing My Turn State

The Playing My Turn state is a composite state and the following is its internal state model:

The sub-state model for the 'Playing My Turn' composite state.

When the Game View enters the Playing My Turn state it immediately transitions to the Empty Turn state. In this state the user may drag any piece to an open space on the board. When the piece is dropped on an open space the JavaScript code transitions to the Waiting for Move Validation state, which sends an Ajax request to the server to validate the move; this is the POST /validateMove Ajax action detailed below. If the move is valid then the client-side code transitions to the Stable Turn state. In this state the Game View only has the starting piece active; no other piece can be moved (dragged-and-dropped).

At this point the user can click the Submit turn button that issues an Ajax HTTP request to the POST /submitTurn action and transition to the Waiting for Turn Validation state. If the whole turn is valid then the user's turn is done and the Game View will refresh, by invoking the GET /game URL showing the result of the turn. If the turn is not valid then the Ajax call must return a message of type ERROR with a text string explaining why the turn is not valid.

Also in the Stable Turn state the player may decide they didn't like the last move. The user can click the Backup button to tell the server to undo this move. This action is handled by the POST /backupMove Ajax HTTP request. This tells the server to remove the most recent move the user issued; the server returns a message object telling the client-side code that the action was taken and the client-side code then moves the user's piece back to the most recent starting point. If the user backs out of all of their moves then they are returned to the Empty Turn state at which point all of their pieces are enabled and they can choose a different sequence of moves.

There is one other Ajax action not shown in the diagram: the Resign button allows either player to resign from the game. If the user is waiting for their turn then they can click the Resign button at any time. If the user is taking their turn then the Resign button is only active in the Empty Turn state. Once they start a move the Resign button is disabled. They can back-out of all of their moves and then resign.

Below are details about how to code each of these page-level and Ajax actions. If you have any questions please post the question to the Term Project topic in the myCourse Discussions List.

Ajax Actions for the Playing My Turn State

There are four Ajax-based actions that can occur in this composite state:

HTTP Method URL Query Params HTTP Response Body Description

POST

/validateMove

Param Name Description

gameID

A optional, unique identifier for the game.

actionData

Move
(class definition)

Message
(class defintion)

This action submits a single move for validation. The server must keep track of each proposed move for a single turn in the user's game state. The response body must be a message that has type INFO if the move is valid or ERROR if it is invalid. The text of the message must tell the user why a move is invalid.

POST

/submitTurn

Param Name Description

gameID

A optional, unique identifier for the game.

Message
(class defintion)

This action submits the user's turn. The Submit turn button will only be active when the Game View is in the Stable Turn state.

The response body must be a message that has type INFO if the turn, as a whole, is valid and the server has processed the turn. At this point the GameView stops and refreshes the page by re-requesting the GET /game URL.

The server must return an ERROR message if the turn is invalid with a text message explaining why the turn is invalid. For example, if the user takes a single move turn but that user has a jump turn somewhere else that single move is not a valid turn. The user needs to take the jump instead; so the GameView returns to the Stable Turn state and the user must then backup the single move and take a jump turn. A similar situation arises after a user makes a jump move and the moved piece is in position to make another jump which must be made.

POST

/backupMove

Param Name Description

gameID

A optional, unique identifier for the game.

Message
(class defintion)

This action asks the server to remove the last move that was previously validated. The server must update the user's turn in the user's game state. The response body must be a message that has type INFO if the action was successful or ERROR if it was unsuccessful. The text of the message must tell the user what the action did.

POST

/resignGame

Param Name Description

gameID

A optional, unique identifier for the game.

Message
(class defintion)

This action tells the server that this player is resigning the game. If it's this user's turn then the is only enabled in the Empty Turn state. Once the user makes a valid move then this button is disabled. The user may backup from the move to go back to the Empty Turn state, which will reenable the Resign button.

The response body must be a message that has type INFO if the action was successful or ERROR if it was unsuccessful. When successful the client-side code will send the user back to the Home page.

The Move Data Type

The POST /validateMove action requires the client to send a JSON representation of a move, which holds a start and end position of the move. Here's a UML representation of this data type:
UML representation of the message data type.

A Move data type must contain the following attributes:

Variable Name Return Type Description

getStart

Position

The starting position of the move.

getEnd

Position

The ending position of the move.

The Position Data Type

A Position data type must contain the following attributes:

Variable Name Return Type Description

getRow

int from zero to seven

The row index of this position.

getCell

int from zero to seven

The cell (column) index of this position.

Waiting for My Turn State

The Waiting for My Turn state is used when it is not the current user's turn and the game has not ended. This composite state has two inner states that oscillate until the opponent's latest turn has been completed.

The sub-state model for the 'Waiting for My Turn' composite state.

The Waiting for 5 Second Delay state tells the browser to wait for 5 seconds. After the timeout the Game View transitions to the Checking for My Turn state. An Ajax call to the server, the POST /checkTurn action, is invoked on the transition. The Checking for My Turn state waits for the server response. The server responds with a Message object with type of INFO and the message text must be either "true" or "false": true if it is this user's turn or false if the user must continue waiting.

When it becomes the user's turn then the client-side code will issue a page-level HTTP request to GET /game to have the server update the Game View to show the opponent's move. The Game View leaves the Waiting for My Turn state and halts.

Ajax Actions for the Waiting for My Turn State

There are two possible Ajax-based actions that take place within the Waiting for My Turn composite state:

HTTP Method URL Query Params HTTP Response Body Description

POST

/checkTurn

Param Name Description

gameID

A optional, unique identifier for the game.

Message
(class defintion)

This action checks to see if the opponent has submitted their turn. The HTTP response must return message with type of INFO and the text of the message is either true if it's now this user's turn or false if the opponent is still taking their turn.

If the opponent resigns the game then this Ajax calls must return an INFO message with true; and when the Game View is rendered it must inform this user that their opponent resigned the game.

POST

/resignGame

Param Name Description

gameID

A optional, unique identifier for the game.

Message
(class definition)

This action tells the server that this player is resigning the game.

The response body must be a message that has type INFO if the action was successful or ERROR if it was unsuccessful. When successful the client-side code will send the user back to the Home page.

End-of-Game User Experience

There is a special Game View state that tells the client-side code when the game is over. The following screenshot shows the Game View is this state:

Screenshot of the Game View when the Game ends.

The Info panel must show the names of the two players of the game. The Controls panel provides a single button:

This state will be used by the Game End Conditions and Resignation stories. Both of these features require that no additional turns/moves can be made and that both users can see the end state of the board and the message of how the game ended.

To get the Game View into this new state you need to create a mode options map that tells the client-side Game View code to transition to the game over state. The map must also supply the message from the server about how the game ended: capture all pieces, block all pieces or resignation. This message is shown in bold in the message box above the controls.

The View-Model attributes for the game.ftl View component are the same as for Sprint 1: Game View-Model Specification. But now we use the modeOptionsAsJSON variable to hold data especially designed to represent the end of game to the user.

Variable Name Data Type Description

modeOptionsAsJSON

Map<String,Object>; a Java map of attributes that is stored in the View-Model converted into a JSON string.

Map Key Description

isGameOver

A boolean value; true if the game has come to an end; whether from a win or resignation.

gameOverMessage

A String representing how the game ended. Such as:

  • Bryan has captured all of the pieces.
  • Fred has resigned.

This attribute must be stored in the View-Model as a JSON string of a Java Map. This is sample code of how to do that:

final Map<String, Object> modeOptions = new HashMap<>(2);
modeOptions.put("isGameOver", true);
modeOptions.put("gameOverMessage", /* get end of game message */);
vm.put("modeOptionsAsJSON", gson.toJson(modeOptions));

The team's goal when coding the Game End Conditions and Resignation stories is to determine when a game ends or when a player resigns and render the Game View for the user to see the last board state and the reason why the game ended. These mode options supply that information to the Game View client-side (JavaScript) code.