Mastermind is a code-breaking game for two players.

Introduction

Decoding Board

Traditionally, the game is played using:

  • a decoding board, with a shield at one end covering a row of four large holes, and twelve additional rows containing four large holes next to a set of four small holes

  • code pegs of six different colours, which will be placed in the large holes on the board

  • small key pegs, some coloured black, some white, which will be placed in the small holes on the board

source: Wikipedia

In the conventional Mastermind game there are two players:

  • CodeMaker - chooses a pattern of four code pegs and places them in the four holes covered by the shield. This secret code is only visible to the CodeMaker.

  • CodeBreaker - tries to guess the secret code withing twelve turns, in both order and colour. Each guess is made by placing a row of code pegs on the decoding board. Once placed, the CodeMaker provides feedback by placing zero to four key pegs in the small holes of the row with the guess.

Feedback is provided with key pegs:

  • a black key peg is placed for each code peg from the guess which is correct in both colour and position

  • a white key peg is placed for each code peg from the guess which is correct in colour but in a wrong position

  • if there are duplicate colours in the guess, they can only be awarded a key peg if they correspond to the same number of duplicate colours in the secret code

Overview

System Context

The system context diagram below presents the Mastermind system in the context of users and other systems.

System context

Functional Overview

The Mastermind software is a single player code-breaking game. This is different to the classic Mastermind which is a two player game. In the digitalised version the CodeMaker player is replaced by the system.

In the game of Mastermind, the CodeBreaker has the capability to:

  • Start a new game - a new secret code is randomly generated each time the game is started.

  • Make a guess - CodeBreaker has a number of attempts to break the code. Feedback is given on each attempt.

Expectations

Quality Attributes

Since this is a pet project the expectations below are mostly made up.

Performance

  • The system needs to handle 1,000 simultaneous games every hour for consecutive 8hrs.

Scalability

  • The system needs to cope with 10,000 games a day for the next 5 years.

Availability

  • The game should be available to the end users 24x7.

  • Occasional downtime of less than 1hr a week can be tolerated.

Failover

  • There’s no need for a failover.

Security

  • The game should be anonymous and open to everyone.

Audit

  • The following events must be recorded in the system audit log:

    • Game started

    • Move Made

Fault tolerance and resilience

  • All errors should be logged.

Internationalization and localization

  • all user interfaces, messages, and communication should be English only

Monitoring and management

  • an e-mail notification should be sent in case:

    • a fatal error happens

    • a system healthcheck fails

Data retention and archiving

  • data should be retained indefinitely

  • data should be archived daily

Interoperability

  • No interoperability requirements

Constraints

Time, budget, resources

  • since this is a pet project, there’s no time, budget, nor resource constraints.

Approved technology lists

  • JVM/Kotlin

  • PostgreSQL

  • vlingo

Target deployment platform

Anywhere that runs docker.

Candidates:

  • DigitalOcean

  • GCP

  • AWS

Standard protocols

  • JSON based HTTP API

Principles

  • Follow test driven development

  • Favour automation over documentation

  • Have fun and learn

Implementation

Software architecture

Container view

The diagram below focuses on high level responsibilities and technology choices within the Mastermind system.

Container view

Component view

The diagram below drills into the Mastermind API container to illustrate its main components.

Component view

Code

This section describes the significant implementation details of the Mastermind system.

Event Sourcing Implementation

vlingo/lattice is used for implementation of event sourcing.

Lattice is part of the vlingo/PLATFORM project. It’s an Open Source platform that aims to simplify the creation of event-driven reactive architectures.

More can be found on the platform’s website: https://docs.vlingo.io.

Data

Development environment

  • Java 11

  • Docker >= 19.03

  • IntelliJ IDEA with Kotlin 1.3

Executing tests

Tests can be triggered from IntelliJ or with gradle:

./gradlew test

Running the application

The simplest way to run the application is by executing the main function from IntelliJ. The main function can be found in the Application class.

The application can also be run in command line with gradle:

./gradlew run

The port number and configuration can be optionally passed as arguments:

./gradlew run --args 'classpath:in-memory.properties 9090'

A custom configuration file can also be loaded with:

./gradlew run --args 'path/to/my.properties'

There are two persistence strategies to choose from to run the application:

  • in-memory (default) - classpath:in-memory.properties

  • postgresql - classpath:postgresql.properties

A running postgresql server is needed for the postgresql strategy. It can be started with the provided docker-compose configuration:

docker-compose up -d

Building the application jar

To build a fat jar with all the necessary dependencies run:

./gradlew shadowJar

Now the jar can be executed with:

java -jar build/libs/mastermind-1.0-SNAPSHOT.jar

Arguments can be provided as well:

java -jar build/libs/mastermind-1.0-SNAPSHOT.jar classpath:postgresql.properties 9090

HTTP API

Game Resource

Start a game

request
POST /games
Accept: application/json
response
HTTP/1.1 201 Created
Content-Length: 49
Content-Type: application/json
Location: /games/b2ee7966-6c58-41ae-905c-11176bafe910

{
    "gameId": "b2ee7966-6c58-41ae-905c-11176bafe910"
}
example (httpie)
http POST http://localhost:8080/games

Make a guess

request
POST /games/b2ee7966-6c58-41ae-905c-11176bafe910
Accept: application/json
Content-Type: application/json

{
    "guess": ["RED", "GREEN", "BLUE", "YELLOW"]
}
response
HTTP/1.1 200 OK
Content-Length: 103
Content-Type: application/json

{
    "feedback": {
        "outcome": "IN_PROGRESS",
        "pegs": [
            "WHITE"
        ]
    },
    "gameId": "b2ee7966-6c58-41ae-905c-11176bafe910"
}
error response
HTTP/1.1 400 Bad Request
Content-Length: 111
Content-Type: application/json

{
    "error": "The code is 3 colours long but expected it to be 4.",
    "gameId": "b2ee7966-6c58-41ae-905c-11176bafe910"
}
example (httpie)
http POST http://localhost:8080/games/b2ee7966-6c58-41ae-905c-11176bafe910 guess:='["RED", "GREEN", "BLUE", "YELLOW"]'

View a decoding board

request
GET /games/b2ee7966-6c58-41ae-905c-11176bafe910
Accept: application/json
response
HTTP/1.1 200 OK
Content-Length: 136
Content-Type: application/json

{
    "gameId": "b2ee7966-6c58-41ae-905c-11176bafe910",
    "maxMoves": 12,
    "moves": [
        {
            "feedback": [
                "WHITE"
            ],
            "guess": [
                "RED",
                "GREEN",
                "BLUE",
                "YELLOW"
            ]
        }
    ]
}
example (httpie)
http GET http://localhost:8080/games/b2ee7966-6c58-41ae-905c-11176bafe910

Operation

Infrastructure architecture

Deployment

Operation and support

History

Decision log

This section lists all the significant architecture and technology choices.

1. Record architecture decisions

Date: 2020-01-23

Status

Accepted

Context

We need to record the architectural decisions made on this project.

Decision

We will use Architecture Decision Records, as described by Michael Nygard.

Consequences

See Michael Nygard’s article, linked above. For a lightweight ADR toolset, see Nat Pryce’s adr-tools.

2. Choose software architecture

Date: 2020-01-23

Status

Accepted

Context

The sole purpose of this project is to practice CQRS and Event Souring architecture patterns with the https://docs.vlingo.io/vlingo-lattice/entity-cqrs:vlingo/lattice library.

Decision

By definition this project has to use event sourcing.

Consequences

Software architecture of the project will follow what vlingo’s documentation and examples demonstrate. Decoupling from vlingo is not going to be the focus at this point.

3. Choose the database software

Date: 2020-01-23

Status

Accepted

Context

The application needs two types of persistence:

  • event store - to persist the stream of events

  • view store - to persist views generated by projections

vlingo supports many popular database systems via its JDBC driver. Some database systems got its dedicated driver.

Decision

PostgreSQL will be used for both stores as it’s a popular, easy to set up, and efficient database system that the team has experience with.

Consequences

As a consequence the project can be started quickly, with PostgreSQL running in a docker container. Shall the need ever arise, the decision can be revisited at a later stage to migrate one of the stores to a different system.