# A Game Deadline

synopsis

Make sure you have all you need before proceeding:

In the previous section you introduced a FIFO that keeps the oldest games at its head and the most recently updated games at its tail.

Just because a game has not been updated in a while does not mean that it has expired. To ascertain this you need to add a new field, deadline, to a game and test against it. Time to prepare the field.

# New information

To prepare the field, add in the StoredGame's Protobuf definition:

Copy message StoredGame { ... string deadline = 10; } proto checkers stored_game.proto View source

To have Starport and Protobuf recompile this file. You can use:

Copy $ starport generate proto-go

On each update the deadline will always be now plus a fixed duration. In this context, now refers to the block's time. Declare this duration as a new constant, along with how the date is to be represented, i.e. encoded in the saved game as a string:

Copy const ( MaxTurnDurationInSeconds = time.Duration(24 * 3_600 * 1000_000_000) // 1 day DeadlineLayout = "2006-01-02 15:04:05.999999999 +0000 UTC" ) x checkers types keys.go View source

# Date manipulation

You can make your life easier by using helper functions that encode and decode the deadline in the storage.

  1. First define a new error:

    Copy ErrInvalidDeadline = sdkerrors.Register(ModuleName, 1110, "deadline cannot be parsed: %s") x checkers types errors.go View source
  2. Now you can add your date helpers. A reasonable location to pick is full_game.go:

    Copy func (storedGame *StoredGame) GetDeadlineAsTime() (deadline time.Time, err error) { deadline, errDeadline := time.Parse(DeadlineLayout, storedGame.Deadline) return deadline, sdkerrors.Wrapf(errDeadline, ErrInvalidDeadline.Error(), storedGame.Deadline) } func FormatDeadline(deadline time.Time) string { return deadline.UTC().Format(DeadlineLayout) } x checkers types full_game.go View source

    Of note in the above is that sdkerrors.Wrapf(err, ...) returns nil if err is nil. This is very convenient.

  3. Add a function that encapsulates the knowledge of how the next deadline is calculated in the same file:

    Copy func GetNextDeadline(ctx sdk.Context) time.Time { return ctx.BlockTime().Add(MaxTurnDurationInSeconds) } x checkers types full_game.go View source

# Updated deadline

Next you need to update this new field with its appropriate value:

  1. At creation in the message handler for game creation:

    Copy ... storedGame := types.StoredGame{ ... Deadline: types.FormatDeadline(types.GetNextDeadline(ctx)), } x checkers keeper msg_server_create_game.go View source
  2. And after a move in the message handler:

    Copy ... storedGame.MoveCount++ storedGame.Deadline = types.FormatDeadline(types.GetNextDeadline(ctx)) ... x checkers keeper msg_server_play_move.go View source

Now confirm that your project still compiles:

Copy $ starport chain build

You have created and updated the deadline. The section two steps ahead describes how to use the deadline and the FIFO to expire games that reached their deadline.

Before you can do that there is one other field you need to add. Discover which in the next section.