Intial board config for GameProposalCreate

- victory tests without hardcode
- better server logs
- unmodifiable getters for game board
- totalMoves counter for GameResult
This commit is contained in:
djmil 2023-10-02 13:54:38 +02:00
parent 07ce05bf01
commit f9f6920512
15 changed files with 143 additions and 109 deletions

View File

@ -3,6 +3,7 @@ package djmil.cordacheckers.cordaclient;
import static java.util.Objects.requireNonNull;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@ -101,14 +102,20 @@ public class CordaClient {
}
public GameState gameProposalCreate(HoldingIdentity issuer, HoldingIdentity acquier, Stone.Color acquierColor,
String message
) {
String message) {
return gameProposalCreate(issuer, acquier, acquierColor, GameState.defaultGameBoard, message);
}
public GameState gameProposalCreate(HoldingIdentity issuer, HoldingIdentity acquier, Stone.Color acquierColor,
Map<Integer, Stone> board, String message) {
final RequestBody requestBody = new RequestBody(
"gp.create-" + UUID.randomUUID(),
"djmil.cordacheckers.gameproposal.CreateFlow",
new ReqGameProposalCreate(
acquier.x500Name(),
acquierColor,
board,
message));
return cordaFlowExecute(issuer, requestBody,RspGameState.class)

View File

@ -27,4 +27,32 @@ public record GameState(
GAME_RESULT_YOU_LOOSE;
}
public final static Map<Integer, Stone> defaultGameBoard = Map.ofEntries(
// Inspired by Checkers notation rules: https://www.bobnewell.net/nucleus/checkers.php
Map.entry( 1, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 2, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 3, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 4, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 5, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 6, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 7, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 8, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry( 9, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(10, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(11, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(12, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(21, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(22, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(23, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(24, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(25, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(26, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(27, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(28, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(29, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(30, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(31, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(32, new Stone(Stone.Color.WHITE, Stone.Type.MAN))
);
}

View File

@ -1,10 +1,13 @@
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
import java.util.Map;
import djmil.cordacheckers.cordaclient.dao.Stone;
public record ReqGameProposalCreate(
String opponentName,
Stone.Color opponentColor,
Map<Integer, Stone> board,
String message
) {

View File

@ -1,5 +1,6 @@
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.flow.RequestBody;
public interface Rsp <T> {
@ -8,8 +9,14 @@ public interface Rsp <T> {
public default T getResponce(RequestBody requestBody) {
if (failureStatus() == null) {
System.out.println(requestBody.clientRequestId() +" [OK]");
return successStatus();
final var responce = successStatus();
final String gameUuid = (responce instanceof GameState)
? "GameUUID " +((GameState)responce).uuid().toString()
: "";
System.out.println(requestBody.clientRequestId() +" [OK] " +gameUuid);
return responce;
}
System.err.println(requestBody.clientRequestId() +" has failed: " +failureStatus());

View File

@ -5,6 +5,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@ -31,6 +32,17 @@ public class GameBoardTests {
final static Stone BLACK_MAN = new Stone(Stone.Color.BLACK, Stone.Type.MAN);
final static Stone BLACK_KING = new Stone(Stone.Color.BLACK, Stone.Type.KING);
final static Map<Integer, Stone> victoryTestBoard1 = Map.ofEntries(
Map.entry(15, BLACK_MAN),
Map.entry(23, WHITE_MAN)
);
final static Map<Integer, Stone> victoryTestBoard2 = Map.ofEntries(
Map.entry(21, BLACK_MAN),
Map.entry(29, WHITE_MAN),
Map.entry(30, WHITE_MAN)
);
@Test
void testSurrender() {
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
@ -39,8 +51,6 @@ public class GameBoardTests {
final GameState game = cordaClient.gameProposalCreate(
hiWhite, hiBlack, Stone.Color.BLACK, "GameBoard SURRENDER test");
System.out.println("Game UUID " +game.uuid());
final GameState acceptedGameBlackView = cordaClient.gameProposalAccept(
hiBlack, game.uuid());
@ -54,6 +64,7 @@ public class GameBoardTests {
assertThat(surrendererGameView.opponentName()).isEqualToIgnoringCase(whitePlayerName);
assertThat(surrendererGameView.opponentColor()).isEqualByComparingTo(Stone.Color.WHITE);
assertThat(surrendererGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_LOOSE);
assertThat(surrendererGameView.moveNumber() == 0);
assertThatThrownBy(() -> { // White can not surrender, since Black already did
cordaClient.gameBoardSurrender(
@ -66,6 +77,7 @@ public class GameBoardTests {
assertThat(winnerGameView.opponentName()).isEqualToIgnoringCase(blackPlayerName);
assertThat(winnerGameView.opponentColor()).isEqualByComparingTo(Stone.Color.BLACK);
assertThat(winnerGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_WON);
assertThat(winnerGameView.moveNumber() == 0);
}
@Test
@ -75,7 +87,6 @@ public class GameBoardTests {
final GameState game = cordaClient.gameProposalCreate(
hiWhite, hiBlack, Stone.Color.BLACK, "GameBoard MOVE test");
System.out.println("Game UUID " +game.uuid());
final var m0 = cordaClient.gameProposalAccept(hiBlack, game.uuid());
assertThat(m0.previousMove()).isNull();
@ -186,27 +197,23 @@ public class GameBoardTests {
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
final var hiBlack = holdingIdentityResolver.getByUsername(blackPlayerName);
final GameState game = cordaClient.gameProposalCreate(
hiWhite, hiBlack, Stone.Color.BLACK, "GameBoard Vitcory test 1");
final GameState game = cordaClient.gameProposalCreate(hiBlack, hiWhite, Stone.Color.WHITE,
victoryTestBoard1, "GameBoard Vitcory test 1");
System.out.println("Game UUID " +game.uuid());
final GameState m0 = cordaClient.gameProposalAccept(hiBlack, game.uuid());
// For this test to work, uncoment proper initialBoard state configuration in
// cordacheckers/contracts/GameBoardContract.java
// i'm too lazy to implement this test properly =^.^=
assertThat(m0.board().size() == 2);
assertThat(m0.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
final GameState m0 = cordaClient.gameProposalAccept(hiWhite, game.uuid());
assertThat(m0.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_YOU);
assertThat(m0.board()).containsAllEntriesOf(victoryTestBoard1);
final var m1 = cordaClient.gameBoardMove(hiWhite, game.uuid(), move(23, 18), null);
assertThat(m1.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
final var m2 = cordaClient.gameBoardMove(hiBlack, game.uuid(), move(15, 22), null);
assertThat(m2.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_WON);
assertThat(m2.moveNumber() == 2);
final var m2WhiteView = cordaClient.gameStateGet(hiWhite, game.uuid());
assertThat(m2WhiteView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_LOOSE);
assertThat(m2WhiteView.moveNumber() == 2);
}
@Test
@ -214,27 +221,23 @@ public class GameBoardTests {
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
final var hiBlack = holdingIdentityResolver.getByUsername(blackPlayerName);
final GameState game = cordaClient.gameProposalCreate(
hiWhite, hiBlack, Stone.Color.BLACK, "GameBoard Vitcory test 2");
System.out.println("Game UUID " +game.uuid());
final GameState game = cordaClient.gameProposalCreate(hiWhite, hiBlack, Stone.Color.BLACK,
victoryTestBoard2, "GameBoard Vitcory test 2");
final GameState m0 = cordaClient.gameProposalAccept(hiBlack, game.uuid());
// For this test to work, uncoment proper initialBoard state configuration in
// cordacheckers/contracts/GameBoardContract.java
// i'm too lazy to implement this test properly =^.^=
assertThat(m0.board().size() == 3);
assertThat(m0.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
assertThat(m0.board()).containsAllEntriesOf(victoryTestBoard2);
final var m0WhiteView = cordaClient.gameStateGet(hiWhite, game.uuid());
assertThat(m0WhiteView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_YOU);
final var m1 = cordaClient.gameBoardMove(hiWhite, game.uuid(), move(29, 25), null);
assertThat(m1.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_WON);
assertThat(m1.moveNumber() == 1);
final var m1BlackView = cordaClient.gameStateGet(hiBlack, game.uuid());
assertThat(m1BlackView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_LOOSE);
assertThat(m1BlackView.moveNumber() == 1);
}
ArrayList<Integer> move(int from, int to) {

View File

@ -32,12 +32,7 @@ public class GameProposalTests {
final String message = "GameProposal CREATE test";
final GameState issuerGameView = cordaClient.gameProposalCreate(
hiIssuer,
hiAcquier,
acquierColor,
message);
System.out.println("Game UUID " +issuerGameView.uuid());
hiIssuer, hiAcquier, acquierColor, message);
/*
* Issuers perspective on a newly created GameProposal
@ -45,6 +40,9 @@ public class GameProposalTests {
assertThat(issuerGameView.status()).isEqualByComparingTo(Status.GAME_PROPOSAL_WAIT_FOR_OPPONENT);
assertThat(issuerGameView.opponentName()).isEqualToIgnoringCase(acquier);
assertThat(issuerGameView.opponentColor()).isEqualByComparingTo(acquierColor);
assertThat(issuerGameView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
assertThat(issuerGameView.previousMove()).isEmpty();
assertThat(issuerGameView.moveNumber() == 0);
assertThat(issuerGameView.message()).isEqualToIgnoringCase(message);
assertThat(issuerGameView.uuid()).isNotNull();
@ -62,6 +60,9 @@ public class GameProposalTests {
assertThat(acquierGameView.status()).isEqualByComparingTo(Status.GAME_PROPOSAL_WAIT_FOR_YOU);
assertThat(acquierGameView.opponentName()).isEqualToIgnoringCase(issuer);
assertThat(acquierGameView.opponentColor()).isEqualByComparingTo(acquierColor.opposite());
assertThat(acquierGameView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
assertThat(acquierGameView.previousMove()).isEmpty();
assertThat(acquierGameView.moveNumber() == 0);
assertThat(acquierGameView.message()).isEqualToIgnoringCase(message);
assertThat(acquierGameView.uuid()).isEqualByComparingTo(issuerGameView.uuid());
}
@ -70,12 +71,9 @@ public class GameProposalTests {
void testReject() {
final var hiIssuer = holdingIdentityResolver.getByUsername(issuer);
final var hiAcquier = holdingIdentityResolver.getByUsername(acquier);
final String message = "GameProposal REJECT test";
final GameState game = cordaClient.gameProposalCreate(
hiIssuer, hiAcquier, acquierColor, message);
System.out.println("Game UUID " +game.uuid());
hiIssuer, hiAcquier, acquierColor, "GameProposal REJECT test");
assertThatThrownBy(() -> { // Issuer can not reject
cordaClient.gameProposalReject(
@ -102,12 +100,9 @@ public class GameProposalTests {
void testCancel() {
final var hiIssuer = holdingIdentityResolver.getByUsername(issuer);
final var hiAcquier = holdingIdentityResolver.getByUsername(acquier);
final String message = "GameProposal CANCEL test";
final GameState game = cordaClient.gameProposalCreate(
hiIssuer, hiAcquier, acquierColor, message);
System.out.println("Game UUID " +game.uuid());
hiIssuer, hiAcquier, acquierColor, "GameProposal CANCEL test");
assertThatThrownBy(() -> { // Acquier can not cancel
cordaClient.gameProposalCancel(
@ -134,12 +129,9 @@ public class GameProposalTests {
void testAccept() {
final var hiIssuer = holdingIdentityResolver.getByUsername(issuer);
final var hiAcquier = holdingIdentityResolver.getByUsername(acquier);
final String message = "GameProposal ACCEPT test";
final GameState game = cordaClient.gameProposalCreate(
hiIssuer, hiAcquier, acquierColor, message);
System.out.println("Game UUID " +game.uuid());
hiIssuer, hiAcquier, acquierColor, "GameProposal ACCEPT test");
assertThatThrownBy(() -> { // Issuer can not accept
cordaClient.gameProposalAccept(
@ -151,6 +143,9 @@ public class GameProposalTests {
assertThat(acceptedGameAcquierView.opponentName()).isEqualToIgnoringCase(issuer);
assertThat(acceptedGameAcquierView.opponentColor()).isEqualByComparingTo(acquierColor.opposite());
assertThat(acceptedGameAcquierView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
assertThat(acceptedGameAcquierView.previousMove()).isEmpty();
assertThat(acceptedGameAcquierView.moveNumber() == 0);
assertThat(acceptedGameAcquierView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_YOU);
assertThat(acceptedGameAcquierView.uuid()).isEqualByComparingTo(game.uuid());
@ -164,6 +159,9 @@ public class GameProposalTests {
assertThat(acceptedGameIssuerView.opponentName()).isEqualToIgnoringCase(acquier);
assertThat(acceptedGameIssuerView.opponentColor()).isEqualByComparingTo(acquierColor);
assertThat(acceptedGameIssuerView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
assertThat(acceptedGameIssuerView.previousMove()).isEmpty();
assertThat(acceptedGameIssuerView.moveNumber() == 0);
assertThat(acceptedGameIssuerView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
assertThat(acceptedGameIssuerView.uuid()).isEqualByComparingTo(game.uuid());
}

View File

@ -34,6 +34,12 @@ public class Stone {
private final Color color;
private final Type type;
// Serialisation service requires a default constructor
public Stone() {
this.color = null;
this.type = null;
}
@ConstructorForDeserialization
public Stone(Color color, Type type) {
this.color = color;

View File

@ -3,12 +3,9 @@ package djmil.cordacheckers.contracts;
import static djmil.cordacheckers.contracts.GameCommand.requireThat;
import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import djmil.cordacheckers.checkers.Stone;
import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction;
public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
@ -17,7 +14,7 @@ public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
@Override
public void verify(UtxoLedgerTransaction trx) {
log.info("GameBoardContract.verify() called");
log.info("GameBoardContract verify");
requireThat(trx.getCommands().size() == 1, GameCommand.REQUIRE_SINGLE_COMMAND);
final GameCommand command = getSingleCommand(trx, GameCommand.class);
@ -44,44 +41,4 @@ public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
}
}
public final static Map<Integer, Stone> initialBoard = Map.ofEntries(
// Inspired by Checkers notation rules: https://www.bobnewell.net/nucleus/checkers.php
// Map.entry( 1, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 2, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 3, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 4, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 5, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 6, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 7, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 8, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry( 9, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry(10, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry(11, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry(12, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry(21, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(22, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(23, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(24, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(25, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(26, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(27, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(28, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(29, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(30, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(31, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
// Map.entry(32, new Stone(Stone.Color.WHITE, Stone.Type.MAN))
/* VICTORY TEST 1 */
// Map.entry(15, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
// Map.entry(23, new Stone(Stone.Color.WHITE, Stone.Type.MAN))
/* VICTORY TEST 2 */
Map.entry(21, new Stone(Stone.Color.BLACK, Stone.Type.MAN)),
Map.entry(29, new Stone(Stone.Color.WHITE, Stone.Type.MAN)),
Map.entry(30, new Stone(Stone.Color.WHITE, Stone.Type.MAN))
);
}

View File

@ -140,7 +140,7 @@ public class GameCommand implements Command {
/*
* Major command logick check
*/
requireThat(outGameBoard.getBoard().equals(GameBoardContract.initialBoard), "Bad GameBoard initial state");
requireThat(outGameBoard.getBoard().size() > 0, "GameBoard initial state was not found");
}
public void validateGameProposalReject(UtxoLedgerTransaction trx) {
@ -192,6 +192,8 @@ public class GameCommand implements Command {
requireThat(outGameResult.getLooserName().compareTo(outGameResult.getBlackPlayer()) == 0 ||
outGameResult.getLooserName().compareTo(outGameResult.getWhitePlayer()) == 0,
"Surenderer must be either Black or White player");
requireThat(outGameResult.getTotalMoves() == inGameBoard.getMoveNumber(), GAME_RESULT_MOVES);
}
public void validateGameBoardVictory(UtxoLedgerTransaction trx) {
@ -212,6 +214,7 @@ public class GameCommand implements Command {
requireThat(possibleMoves.isEmpty(), "Victory condition violation");
requireThat(outGameResult.getWinnerName().compareTo(inGameBoard.getIdelPlayerName()) == 0, "Bad winner name");
requireThat(outGameResult.getTotalMoves() == inGameBoard.getMoveNumber(), GAME_RESULT_MOVES);
}
public static void requireThat(boolean asserted, String errorMessage) {
@ -245,4 +248,6 @@ public class GameCommand implements Command {
static final String VICTORY_INPUT_STATE = "VICTORY command should have exactly one GameBoardState input state";
static final String VICTORY_OUTPUT_STATE = "VICTORY command should have exactly one GameResultState output state";
static final String GAME_RESULT_MOVES = "Wrong number of total moves";
}

View File

@ -1,6 +1,7 @@
package djmil.cordacheckers.states;
import java.security.PublicKey;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -23,7 +24,7 @@ public class GameBoardState extends GameState {
super(gameProposalState.whitePlayer, gameProposalState.blackPlayer,
gameProposalState.gameUuid, gameProposalState.message, gameProposalState.participants);
this.board = new LinkedHashMap<Integer, Stone>(GameBoardContract.initialBoard);
this.board = gameProposalState.getBoard();
this.activeColor = Stone.Color.WHITE;
this.moveNumber = 0;
}
@ -68,7 +69,7 @@ public class GameBoardState extends GameState {
}
public Map<Integer, Stone> getBoard() {
return board;
return Collections.unmodifiableMap(board);
}
@Override

View File

@ -1,9 +1,12 @@
package djmil.cordacheckers.states;
import java.security.PublicKey;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import djmil.cordacheckers.checkers.Stone;
import djmil.cordacheckers.contracts.GameProposalContract;
import net.corda.v5.base.annotations.ConstructorForDeserialization;
import net.corda.v5.base.types.MemberX500Name;
@ -13,12 +16,15 @@ import net.corda.v5.ledger.utxo.BelongsToContract;
public class GameProposalState extends GameState {
private final MemberX500Name issuerName;
private final Map<Integer, Stone> board;
@ConstructorForDeserialization
public GameProposalState(MemberX500Name whitePlayer, MemberX500Name blackPlayer, MemberX500Name issuerName,
UUID gameUuid, String message, List<PublicKey> participants) {
UUID gameUuid, Map<Integer, Stone> board, String message, List<PublicKey> participants) {
super(whitePlayer, blackPlayer, gameUuid, message, participants);
this.issuerName = issuerName;
this.board = board;
}
public MemberX500Name getIssuerName() {
@ -29,4 +35,8 @@ public class GameProposalState extends GameState {
return getOpponentName(issuerName);
}
public Map<Integer, Stone> getBoard() {
return Collections.unmodifiableMap(board);
}
}

View File

@ -13,17 +13,20 @@ import net.corda.v5.ledger.utxo.BelongsToContract;
public class GameResultState extends GameState {
private final MemberX500Name winnerName;
private final Integer totalMoves;
@ConstructorForDeserialization
public GameResultState(MemberX500Name whitePlayer, MemberX500Name blackPlayer, MemberX500Name winnerName,
UUID gameUuid, String message, List<PublicKey> participants) {
Integer totalMoves, UUID gameUuid, String message, List<PublicKey> participants) {
super(whitePlayer, blackPlayer, gameUuid, message, participants);
this.winnerName = winnerName;
this.totalMoves = totalMoves;
}
public GameResultState(MemberX500Name winnerName, GameBoardState gameBoardState, PublicKey custodianPubicKey) {
super(gameBoardState.whitePlayer, gameBoardState.blackPlayer, gameBoardState.gameUuid, null, gameBoardState.participants, custodianPubicKey);
this.winnerName = winnerName;
this.totalMoves = gameBoardState.getMoveNumber();
}
public MemberX500Name getWinnerName() {
@ -34,4 +37,8 @@ public class GameResultState extends GameState {
return getOpponentName(getWinnerName());
}
public Integer getTotalMoves() {
return totalMoves;
}
}

View File

@ -90,29 +90,25 @@ public class CreateFlow implements ClientStartableFlow{
GameProposalState buildGameProposalStateFrom(ClientRequestBody requestBody) {
final CreateFlowArgs args = requestBody.getRequestBodyAs(jsonMarshallingService, CreateFlowArgs.class);
final Stone.Color opponentColor = Stone.Color.valueOf(args.opponentColor);
if (opponentColor == null) {
throw new RuntimeException("Allowed values for opponentColor are: "
+ Stone.Color.WHITE.name() +", " + Stone.Color.BLACK.name()
+ ". Actual value was: " + args.opponentColor);
}
final MemberInfo myInfo = memberLookup.myInfo();
final MemberInfo opponentInfo = requireNonNull(
memberLookup.lookup(MemberX500Name.parse(args.opponentName)),
"MemberLookup can't find opponentName specified in flow arguments: " + args.opponentName
);
final MemberInfo whitePlayerInfo = opponentColor == Stone.Color.WHITE ? opponentInfo : myInfo;
final MemberInfo blackPlayerInfo = opponentColor == Stone.Color.BLACK ? opponentInfo : myInfo;
final MemberInfo whitePlayerInfo = args.opponentColor == Stone.Color.WHITE ? opponentInfo : myInfo;
final MemberInfo blackPlayerInfo = args.opponentColor == Stone.Color.BLACK ? opponentInfo : myInfo;
return new GameProposalState(
whitePlayerInfo.getName(),
blackPlayerInfo.getName(),
myInfo.getName(), // <<--- GameProposal issuer
UUID.randomUUID(),
args.board,
args.message,
Arrays.asList(myInfo.getLedgerKeys().get(0), opponentInfo.getLedgerKeys().get(0))
Arrays.asList(
myInfo.getLedgerKeys().get(0),
opponentInfo.getLedgerKeys().get(0))
);
}

View File

@ -1,14 +1,20 @@
package djmil.cordacheckers.gameproposal;
import java.util.Map;
import djmil.cordacheckers.checkers.Stone;
public class CreateFlowArgs {
public final String opponentName;
public final String opponentColor;
public final Stone.Color opponentColor;
public final Map<Integer, Stone> board;
public final String message;
// Serialisation service requires a default constructor
public CreateFlowArgs() {
opponentName = null;
opponentColor = null;
board = null;
message = null;
}
}

View File

@ -52,9 +52,9 @@ public class View {
this.status = status;
this.opponentName = gameProposal.getOpponentName(myName).getCommonName();
this.opponentColor = gameProposal.getOpponentColor(myName);
this.board = null;
this.moveNumber = null;
this.board = gameProposal.getBoard();
this.previousMove = null;
this.moveNumber = 0;
this.message = gameProposal.getMessage();
this.uuid = gameProposal.getGameUuid();
}
@ -64,8 +64,8 @@ public class View {
this.opponentName = gameBoard.getOpponentName(myName).getCommonName();
this.opponentColor = gameBoard.getOpponentColor(myName);
this.board = gameBoard.getBoard();
this.moveNumber = gameBoard.getMoveNumber();
this.previousMove = previousMove;
this.moveNumber = gameBoard.getMoveNumber();
this.message = gameBoard.getMessage();
this.uuid = gameBoard.getGameUuid();
}
@ -75,8 +75,8 @@ public class View {
this.opponentName = gameResult.getOpponentName(myName).getCommonName();
this.opponentColor = gameResult.getOpponentColor(myName);
this.board = null;
this.moveNumber = null;
this.previousMove = null;
this.moveNumber = gameResult.getTotalMoves();
this.message = gameResult.getMessage();
this.uuid = gameResult.getGameUuid();
}