GameID
a universal ID shared between GameProposal, GameBoard and a GameResult
This commit is contained in:
parent
a34ea39dfb
commit
e26cfe0d91
@ -35,6 +35,7 @@ import djmil.cordacheckers.cordaclient.dao.flow.arguments.Empty;
|
|||||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardCommandReq;
|
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardCommandReq;
|
||||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardResGameResult;
|
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardResGameResult;
|
||||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardListRes;
|
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardListRes;
|
||||||
|
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameBoardResGameBoard;
|
||||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCommandAcceptRes;
|
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCommandAcceptRes;
|
||||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCommandReq;
|
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCommandReq;
|
||||||
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCommandRes;
|
import djmil.cordacheckers.cordaclient.dao.flow.arguments.GameProposalCommandRes;
|
||||||
@ -227,6 +228,33 @@ public class CordaClient {
|
|||||||
return moveResult.successStatus();
|
return moveResult.successStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public GameBoard gameBoardMove(
|
||||||
|
HoldingIdentity myHoldingIdentity,
|
||||||
|
UUID gameBoardUuid,
|
||||||
|
List<Integer> move
|
||||||
|
) {
|
||||||
|
final RequestBody requestBody = new RequestBody(
|
||||||
|
"gb.move-" +UUID.randomUUID(),
|
||||||
|
"djmil.cordacheckers.gameboard.CommandFlow",
|
||||||
|
new GameBoardCommandReq(
|
||||||
|
gameBoardUuid,
|
||||||
|
new GameBoardCommand(move))
|
||||||
|
);
|
||||||
|
|
||||||
|
final GameBoardResGameBoard moveResult = cordaFlowExecute(
|
||||||
|
myHoldingIdentity,
|
||||||
|
requestBody,
|
||||||
|
GameBoardResGameBoard.class
|
||||||
|
);
|
||||||
|
|
||||||
|
if (moveResult.failureStatus() != null) {
|
||||||
|
System.out.println("GameBoard.CommandFlow failed: " + moveResult.failureStatus());
|
||||||
|
throw new RuntimeException("GameBoard: CommandFlow execution has failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return moveResult.successStatus();
|
||||||
|
}
|
||||||
|
|
||||||
private <T> T cordaFlowExecute(HoldingIdentity holdingIdentity, RequestBody requestBody, Class<T> flowResultType) {
|
private <T> T cordaFlowExecute(HoldingIdentity holdingIdentity, RequestBody requestBody, Class<T> flowResultType) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -10,6 +10,7 @@ public record GameBoard(
|
|||||||
String opponentName,
|
String opponentName,
|
||||||
Piece.Color opponentColor,
|
Piece.Color opponentColor,
|
||||||
Boolean opponentMove,
|
Boolean opponentMove,
|
||||||
|
Integer moveNumber,
|
||||||
Map<Integer, Piece> board,
|
Map<Integer, Piece> board,
|
||||||
GameBoardCommand previousCommand,
|
GameBoardCommand previousCommand,
|
||||||
String message,
|
String message,
|
||||||
|
@ -6,9 +6,7 @@ public class GameBoardCommand {
|
|||||||
public static enum Type {
|
public static enum Type {
|
||||||
MOVE,
|
MOVE,
|
||||||
SURRENDER,
|
SURRENDER,
|
||||||
DRAW,
|
VICTORY;
|
||||||
VICTORY,
|
|
||||||
ACCEPT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Type type;
|
private final Type type;
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
|
||||||
|
|
||||||
|
import djmil.cordacheckers.cordaclient.dao.GameBoard;
|
||||||
|
|
||||||
|
public record GameBoardResGameBoard(GameBoard successStatus, String failureStatus) {
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@ package djmil.cordacheckers.cordaclient;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@ -215,6 +216,35 @@ public class CordaClientTest {
|
|||||||
assertThat(gameResult.victoryColor()).isEqualByComparingTo(Piece.Color.BLACK);
|
assertThat(gameResult.victoryColor()).isEqualByComparingTo(Piece.Color.BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testGameBoardMove() throws JsonMappingException, JsonProcessingException, InvalidNameException {
|
||||||
|
final var hiAlice = holdingIdentityResolver.getByUsername("alice");
|
||||||
|
final var hiBob = holdingIdentityResolver.getByUsername("bob");
|
||||||
|
final var bobColor = Piece.Color.WHITE;
|
||||||
|
|
||||||
|
final UUID gpUuid = cordaClient.gameProposalCreate(
|
||||||
|
hiAlice, hiBob,
|
||||||
|
bobColor, "GameBoard MOVE test"
|
||||||
|
);
|
||||||
|
|
||||||
|
System.out.println("New GameProposal UUID "+ gpUuid);
|
||||||
|
|
||||||
|
final GameBoard gbState = cordaClient.gameProposalAccept(
|
||||||
|
hiBob, gpUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
System.out.println("New GameBoard UUID "+ gbState.id());
|
||||||
|
|
||||||
|
assertThatThrownBy(() -> { // Alice can not move, since it is Bob's turn
|
||||||
|
cordaClient.gameBoardMove(
|
||||||
|
hiAlice, gbState.id(),
|
||||||
|
Arrays.asList(1, 2));
|
||||||
|
});
|
||||||
|
|
||||||
|
final GameBoard gameBoard = cordaClient.gameBoardMove(
|
||||||
|
hiBob, gbState.id(), Arrays.asList(1, 2));
|
||||||
|
}
|
||||||
|
|
||||||
private <T extends CordaState> T findByUuid(List<T> statesList, UUID uuid) {
|
private <T extends CordaState> T findByUuid(List<T> statesList, UUID uuid) {
|
||||||
for (T state : statesList) {
|
for (T state : statesList) {
|
||||||
if (state.id().compareTo(uuid) == 0)
|
if (state.id().compareTo(uuid) == 0)
|
||||||
|
@ -21,9 +21,7 @@ public class GameBoardCommand implements Command {
|
|||||||
public static enum Type {
|
public static enum Type {
|
||||||
MOVE,
|
MOVE,
|
||||||
SURRENDER,
|
SURRENDER,
|
||||||
DRAW,
|
FINISH;
|
||||||
VICTORY,
|
|
||||||
ACCEPT; // aka accept opponents DRAW or VICTORY request
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Type type;
|
private final Type type;
|
||||||
@ -81,11 +79,41 @@ public class GameBoardCommand implements Command {
|
|||||||
requireThat(inGameBoardState.getBlackPlayerName().compareTo(outGameResultState.getBlackPlayerName()) == 0, IN_OUT_PARTICIPANTS);
|
requireThat(inGameBoardState.getBlackPlayerName().compareTo(outGameResultState.getBlackPlayerName()) == 0, IN_OUT_PARTICIPANTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void validateMoveTrx(UtxoLedgerTransaction trx) {
|
||||||
|
requireThat(trx.getInputContractStates().size() == 1, MOVE_INPUT_STATE);
|
||||||
|
final var inGameBoardState = getSingleInputState(trx, GameBoardState.class);
|
||||||
|
|
||||||
|
requireThat(trx.getOutputContractStates().size() == 1, MOVE_OUTPUT_STATE);
|
||||||
|
final var outGameBoardState = getSingleOutputState(trx, GameBoardState.class);
|
||||||
|
|
||||||
|
requireThat(inGameBoardState.getWhitePlayerName().compareTo(outGameBoardState.getWhitePlayerName()) == 0, IN_OUT_PARTICIPANTS);
|
||||||
|
requireThat(inGameBoardState.getBlackPlayerName().compareTo(outGameBoardState.getBlackPlayerName()) == 0, IN_OUT_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void validateFinishTrx(UtxoLedgerTransaction trx) {
|
||||||
|
requireThat(trx.getInputContractStates().size() == 1, FINAL_MOVE_INPUT_STATE);
|
||||||
|
final var inGameBoardState = getSingleInputState(trx, GameBoardState.class);
|
||||||
|
|
||||||
|
requireThat(trx.getOutputContractStates().size() == 1, FINAL_MOVE_OUTPUT_STATE);
|
||||||
|
final var outGameResultState = getSingleOutputState(trx, GameResultState.class);
|
||||||
|
|
||||||
|
requireThat(inGameBoardState.getWhitePlayerName().compareTo(outGameResultState.getWhitePlayerName()) == 0, IN_OUT_PARTICIPANTS);
|
||||||
|
requireThat(inGameBoardState.getBlackPlayerName().compareTo(outGameResultState.getBlackPlayerName()) == 0, IN_OUT_PARTICIPANTS);
|
||||||
|
}
|
||||||
|
|
||||||
static final String BAD_ACTIONMOVE_CONSTRUCTOR = "Bad constructor for Action.MOVE";
|
static final String BAD_ACTIONMOVE_CONSTRUCTOR = "Bad constructor for Action.MOVE";
|
||||||
|
|
||||||
static final String SURRENDER_INPUT_STATE = "SURRENDER command should have exactly one GameBoardState input state";
|
static final String SURRENDER_INPUT_STATE = "SURRENDER command should have exactly one GameBoardState input state";
|
||||||
static final String SURRENDER_OUTPUT_STATE = "SURRENDER command should have exactly one GameResultState output state";
|
static final String SURRENDER_OUTPUT_STATE = "SURRENDER command should have exactly one GameResultState output state";
|
||||||
|
|
||||||
|
static final String MOVE_INPUT_STATE = "MOVE command should have exactly one GameBoardState input state";
|
||||||
|
static final String MOVE_OUTPUT_STATE = "MOVE command should have exactly one GameBoardState output state";
|
||||||
|
static final String MOVE_OUT_BOARD = "MOVE command: move checkers rules violation";
|
||||||
|
static final String MOVE_OUT_COLOR = "MOVE command: moveColor checkers rules violation";
|
||||||
|
|
||||||
|
static final String FINAL_MOVE_INPUT_STATE = "FINAL_MOVE command should have exactly one GameBoardState input state";
|
||||||
|
static final String FINAL_MOVE_OUTPUT_STATE = "FINAL_MOVE command should have exactly one GameResultState output state";
|
||||||
|
|
||||||
static final String IN_OUT_PARTICIPANTS = "InputState and OutputState participants do not match";
|
static final String IN_OUT_PARTICIPANTS = "InputState and OutputState participants do not match";
|
||||||
|
|
||||||
public static class CommandTypeException extends RuntimeException {
|
public static class CommandTypeException extends RuntimeException {
|
||||||
|
@ -1,17 +1,12 @@
|
|||||||
package djmil.cordacheckers.contracts;
|
package djmil.cordacheckers.contracts;
|
||||||
|
|
||||||
import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand;
|
import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand;
|
||||||
import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleInputSar;
|
|
||||||
import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleReferenceSar;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import djmil.cordacheckers.states.GameProposalState;
|
|
||||||
import net.corda.v5.base.annotations.Suspendable;
|
|
||||||
import net.corda.v5.base.exceptions.CordaRuntimeException;
|
import net.corda.v5.base.exceptions.CordaRuntimeException;
|
||||||
import net.corda.v5.ledger.utxo.Command;
|
import net.corda.v5.ledger.utxo.Command;
|
||||||
import net.corda.v5.ledger.utxo.StateAndRef;
|
|
||||||
import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction;
|
import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction;
|
||||||
|
|
||||||
public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
|
public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
|
||||||
@ -40,18 +35,17 @@ public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
|
|||||||
log.info("GameBoardContract.verify() as GameBoardCommand "+((GameBoardCommand)command).getType());
|
log.info("GameBoardContract.verify() as GameBoardCommand "+((GameBoardCommand)command).getType());
|
||||||
switch (((GameBoardCommand)command).getType()) {
|
switch (((GameBoardCommand)command).getType()) {
|
||||||
case MOVE:
|
case MOVE:
|
||||||
break;
|
GameBoardCommand.validateMoveTrx(trx);
|
||||||
|
break;
|
||||||
|
|
||||||
case SURRENDER:
|
case SURRENDER:
|
||||||
GameBoardCommand.validateSurrenderTrx(trx);
|
GameBoardCommand.validateSurrenderTrx(trx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DRAW:
|
case FINISH:
|
||||||
break;
|
GameBoardCommand.validateFinishTrx(trx);
|
||||||
case VICTORY:
|
break;
|
||||||
break;
|
|
||||||
case ACCEPT:
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw new GameBoardCommand.CommandTypeException();
|
throw new GameBoardCommand.CommandTypeException();
|
||||||
}
|
}
|
||||||
|
@ -24,10 +24,11 @@ public class GameResultContract implements net.corda.v5.ledger.utxo.Contract {
|
|||||||
switch (command.getType()) {
|
switch (command.getType()) {
|
||||||
case SURRENDER:
|
case SURRENDER:
|
||||||
GameBoardCommand.validateSurrenderTrx(trx);
|
GameBoardCommand.validateSurrenderTrx(trx);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// case ACCEPT:
|
case FINISH:
|
||||||
// break;
|
GameBoardCommand.validateFinishTrx(trx);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new CordaRuntimeException(UNKNOWN_COMMAND);
|
throw new CordaRuntimeException(UNKNOWN_COMMAND);
|
||||||
|
@ -20,6 +20,7 @@ public class GameBoardState implements ContractState, Counterparty {
|
|||||||
private final MemberX500Name blackPlayerName;
|
private final MemberX500Name blackPlayerName;
|
||||||
|
|
||||||
private final Piece.Color moveColor;
|
private final Piece.Color moveColor;
|
||||||
|
private final Integer moveNumber;
|
||||||
private final Map<Integer, Piece> board;
|
private final Map<Integer, Piece> board;
|
||||||
private final String message;
|
private final String message;
|
||||||
|
|
||||||
@ -27,27 +28,45 @@ public class GameBoardState implements ContractState, Counterparty {
|
|||||||
private final List<PublicKey> participants;
|
private final List<PublicKey> participants;
|
||||||
|
|
||||||
public GameBoardState(
|
public GameBoardState(
|
||||||
GameProposalState gameBoard
|
GameProposalState gameProposalState
|
||||||
) {
|
) {
|
||||||
this.whitePlayerName = gameBoard.getWhitePlayerName();
|
this.whitePlayerName = gameProposalState.getWhitePlayerName();
|
||||||
this.blackPlayerName = gameBoard.getBlackPlayerName();
|
this.blackPlayerName = gameProposalState.getBlackPlayerName();
|
||||||
|
|
||||||
// Initial GameBoard state
|
// Initial GameBoard state
|
||||||
this.moveColor = Piece.Color.WHITE;
|
this.moveColor = Piece.Color.WHITE;
|
||||||
|
this.moveNumber = 0;
|
||||||
this.board = new LinkedHashMap<Integer, Piece>(initialBoard);
|
this.board = new LinkedHashMap<Integer, Piece>(initialBoard);
|
||||||
this.message = null;
|
this.message = null;
|
||||||
|
|
||||||
this.id = UUID.randomUUID();
|
this.id = gameProposalState.getId();
|
||||||
this.participants = gameBoard.getParticipants();
|
this.participants = gameProposalState.getParticipants();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameBoardState(
|
||||||
|
GameBoardState oldGameBoardState, Map<Integer, Piece> newBoard, Piece.Color moveColor
|
||||||
|
) {
|
||||||
|
this.whitePlayerName = oldGameBoardState.getWhitePlayerName();
|
||||||
|
this.blackPlayerName = oldGameBoardState.getBlackPlayerName();
|
||||||
|
|
||||||
|
// Initial GameBoard state
|
||||||
|
this.moveColor = moveColor;
|
||||||
|
this.moveNumber = oldGameBoardState.getMoveNumber() +1;
|
||||||
|
this.board = newBoard;
|
||||||
|
this.message = null;
|
||||||
|
|
||||||
|
this.id = oldGameBoardState.getId();
|
||||||
|
this.participants = oldGameBoardState.getParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ConstructorForDeserialization
|
@ConstructorForDeserialization
|
||||||
public GameBoardState(MemberX500Name whitePlayerName, MemberX500Name blackPlayerName,
|
public GameBoardState(MemberX500Name whitePlayerName, MemberX500Name blackPlayerName,
|
||||||
Color moveColor, Map<Integer, Piece> board, String message,
|
Color moveColor, Integer moveNumber, Map<Integer, Piece> board, String message,
|
||||||
UUID id, List<PublicKey> participants) {
|
UUID id, List<PublicKey> participants) {
|
||||||
this.whitePlayerName = whitePlayerName;
|
this.whitePlayerName = whitePlayerName;
|
||||||
this.blackPlayerName = blackPlayerName;
|
this.blackPlayerName = blackPlayerName;
|
||||||
this.moveColor = moveColor;
|
this.moveColor = moveColor;
|
||||||
|
this.moveNumber = moveNumber;
|
||||||
this.board = board;
|
this.board = board;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
@ -66,6 +85,10 @@ public class GameBoardState implements ContractState, Counterparty {
|
|||||||
return moveColor;
|
return moveColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getMoveNumber() {
|
||||||
|
return moveNumber;
|
||||||
|
}
|
||||||
|
|
||||||
public Map<Integer, Piece> getBoard() {
|
public Map<Integer, Piece> getBoard() {
|
||||||
return board;
|
return board;
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class GameResultState implements ContractState, Counterparty {
|
|||||||
this.blackPlayerName = stateGameBoard.getBlackPlayerName();
|
this.blackPlayerName = stateGameBoard.getBlackPlayerName();
|
||||||
this.victoryColor = victoryColor;
|
this.victoryColor = victoryColor;
|
||||||
|
|
||||||
this.id = UUID.randomUUID();
|
this.id = stateGameBoard.getId();
|
||||||
this.participants = stateGameBoard.getParticipants();
|
this.participants = stateGameBoard.getParticipants();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,20 +102,29 @@ public class CommandFlow implements ClientStartableFlow {
|
|||||||
UtxoTransactionBuilder trxBuilder = utxoLedgerService.createTransactionBuilder()
|
UtxoTransactionBuilder trxBuilder = utxoLedgerService.createTransactionBuilder()
|
||||||
.setNotary(utxoSarGameBoard.getState().getNotaryName())
|
.setNotary(utxoSarGameBoard.getState().getNotaryName())
|
||||||
.setTimeWindowBetween(Instant.now(), Instant.now().plusMillis(Duration.ofDays(1).toMillis()))
|
.setTimeWindowBetween(Instant.now(), Instant.now().plusMillis(Duration.ofDays(1).toMillis()))
|
||||||
.addInputState(utxoSarGameBoard.getRef())
|
|
||||||
.addCommand(command)
|
.addCommand(command)
|
||||||
|
.addInputState(utxoSarGameBoard.getRef())
|
||||||
.addSignatories(stateGameBoard.getParticipants());
|
.addSignatories(stateGameBoard.getParticipants());
|
||||||
|
|
||||||
switch (command.getType()) {
|
switch (command.getType()) {
|
||||||
case SURRENDER:
|
case SURRENDER:
|
||||||
case ACCEPT:
|
|
||||||
final Piece.Color winnerColor = winnerColor(command, stateGameBoard, myName);
|
|
||||||
trxBuilder = trxBuilder
|
trxBuilder = trxBuilder
|
||||||
.addOutputState( new GameResultState(stateGameBoard, winnerColor) );
|
.addOutputState( new GameResultState(
|
||||||
|
stateGameBoard,
|
||||||
|
stateGameBoard.getCounterpartyColor(myName)) // winner color
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MOVE:
|
||||||
|
trxBuilder = trxBuilder
|
||||||
|
.addOutputState( new GameBoardState(stateGameBoard, stateGameBoard.getBoard(), stateGameBoard.getMoveColor())); // TODO: advance color
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FINISH:
|
||||||
|
throw new CommandTypeException("GameBoard.CommandFlow can not process externaly issued FINISH commnd");
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new CommandTypeException("GameBoard.CommandFlow doTransaction()");
|
throw new CommandTypeException("GameBoard.CommandFlow doTransaction(): Unknown command");
|
||||||
}
|
}
|
||||||
|
|
||||||
return commit(
|
return commit(
|
||||||
@ -123,22 +132,6 @@ public class CommandFlow implements ClientStartableFlow {
|
|||||||
opponentName);
|
opponentName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suspendable
|
|
||||||
Piece.Color winnerColor(GameBoardCommand command, GameBoardState stateGameBoard, MemberX500Name myName) {
|
|
||||||
|
|
||||||
switch (command.getType()) {
|
|
||||||
case SURRENDER:
|
|
||||||
return stateGameBoard.getCounterpartyColor(myName);
|
|
||||||
|
|
||||||
case ACCEPT:
|
|
||||||
//stateGameBoard.getMoveColor();
|
|
||||||
throw new RuntimeException("Unimplemented");
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new CommandTypeException("GameBoard.CommandFlow winnerColor()");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
SecureHash commit(UtxoSignedTransaction candidateTrx, MemberX500Name counterpartyName) {
|
SecureHash commit(UtxoSignedTransaction candidateTrx, MemberX500Name counterpartyName) {
|
||||||
log.info("About to commit " +candidateTrx.getId());
|
log.info("About to commit " +candidateTrx.getId());
|
||||||
@ -170,12 +163,17 @@ public class CommandFlow implements ClientStartableFlow {
|
|||||||
|
|
||||||
switch (command.getType()) {
|
switch (command.getType()) {
|
||||||
case SURRENDER:
|
case SURRENDER:
|
||||||
case ACCEPT:
|
|
||||||
return viewGameResult(utxoTrx);
|
return viewGameResult(utxoTrx);
|
||||||
|
|
||||||
case MOVE:
|
case MOVE:
|
||||||
case VICTORY: // request, shall be accepted by opponent
|
// 1. create initial GameBoardView
|
||||||
case DRAW: // request, shall be accepted by opponent
|
// 2. check for winning conditions
|
||||||
|
// - run subcommnd FINISH that will consume current gbUtxo and will produce GameResult state
|
||||||
|
// - update GameBoardView to have FINISH command
|
||||||
|
// 3. return GameBoardView
|
||||||
|
return viewGameBoard(utxoTrx);
|
||||||
|
|
||||||
|
case FINISH:
|
||||||
return viewGameBoard(utxoTrx);
|
return viewGameBoard(utxoTrx);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -65,12 +65,10 @@ public class CommandResponderFlow implements ResponderFlow {
|
|||||||
GameBoardState getGameBoardState(UtxoLedgerTransaction utxoGameBoard, GameBoardCommand command) {
|
GameBoardState getGameBoardState(UtxoLedgerTransaction utxoGameBoard, GameBoardCommand command) {
|
||||||
switch (command.getType()) {
|
switch (command.getType()) {
|
||||||
case SURRENDER:
|
case SURRENDER:
|
||||||
case ACCEPT:
|
case FINISH:
|
||||||
return getSingleInputState(utxoGameBoard, GameBoardState.class);
|
return getSingleInputState(utxoGameBoard, GameBoardState.class);
|
||||||
|
|
||||||
case MOVE:
|
case MOVE:
|
||||||
case VICTORY:
|
|
||||||
case DRAW:
|
|
||||||
return getSingleOutputState(utxoGameBoard, GameBoardState.class);
|
return getSingleOutputState(utxoGameBoard, GameBoardState.class);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -17,16 +17,26 @@ public class GameBoardView {
|
|||||||
public final String opponentName;
|
public final String opponentName;
|
||||||
public final Piece.Color opponentColor;
|
public final Piece.Color opponentColor;
|
||||||
public final Boolean opponentMove;
|
public final Boolean opponentMove;
|
||||||
|
public final Integer moveNumber;
|
||||||
public final Map<Integer, Piece> board;
|
public final Map<Integer, Piece> board;
|
||||||
public final GameBoardCommand previousCommand;
|
public final GameBoardCommand previousCommand;
|
||||||
public final String message;
|
public final String message;
|
||||||
public final UUID id;
|
public final UUID id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GameStatus enum:
|
||||||
|
* - YOUR_TURN
|
||||||
|
* - WAIT_FOR_OPPONENT
|
||||||
|
* - VICTORY
|
||||||
|
* - YOU_LOOSE
|
||||||
|
*/
|
||||||
|
|
||||||
// Serialisation service requires a default constructor
|
// Serialisation service requires a default constructor
|
||||||
public GameBoardView() {
|
public GameBoardView() {
|
||||||
this.opponentName = null;
|
this.opponentName = null;
|
||||||
this.opponentColor = null;
|
this.opponentColor = null;
|
||||||
this.opponentMove = null;
|
this.opponentMove = null;
|
||||||
|
this.moveNumber = null;
|
||||||
this.board = null;
|
this.board = null;
|
||||||
this.previousCommand = null;
|
this.previousCommand = null;
|
||||||
this.message = null;
|
this.message = null;
|
||||||
@ -36,6 +46,11 @@ public class GameBoardView {
|
|||||||
// A view from a perspective of a concrete player, on a ledger transaction that has
|
// A view from a perspective of a concrete player, on a ledger transaction that has
|
||||||
// produced new GameBoardState
|
// produced new GameBoardState
|
||||||
public GameBoardView(UtxoLedgerTransaction utxoGameBoard, MemberX500Name myName) throws NotInvolved {
|
public GameBoardView(UtxoLedgerTransaction utxoGameBoard, MemberX500Name myName) throws NotInvolved {
|
||||||
|
// TODO check command type: MOVE vs FINNISH | SURRENDER
|
||||||
|
// SingleOutPut vs SingleInput
|
||||||
|
this.previousCommand = UtxoLedgerTransactionUtil
|
||||||
|
.getOptionalCommand(utxoGameBoard, GameBoardCommand.class)
|
||||||
|
.orElseGet(() -> null); // there is no previous command for GameProposal.Accept case
|
||||||
|
|
||||||
final GameBoardState stateGameBoard = UtxoLedgerTransactionUtil
|
final GameBoardState stateGameBoard = UtxoLedgerTransactionUtil
|
||||||
.getSingleOutputState(utxoGameBoard, GameBoardState.class);
|
.getSingleOutputState(utxoGameBoard, GameBoardState.class);
|
||||||
@ -44,13 +59,10 @@ public class GameBoardView {
|
|||||||
this.opponentColor = stateGameBoard.getCounterpartyColor(myName);
|
this.opponentColor = stateGameBoard.getCounterpartyColor(myName);
|
||||||
|
|
||||||
this.opponentMove = this.opponentColor == stateGameBoard.getMoveColor();
|
this.opponentMove = this.opponentColor == stateGameBoard.getMoveColor();
|
||||||
|
this.moveNumber = stateGameBoard.getMoveNumber();
|
||||||
this.board = stateGameBoard.getBoard();
|
this.board = stateGameBoard.getBoard();
|
||||||
this.message = stateGameBoard.getMessage();
|
this.message = stateGameBoard.getMessage();
|
||||||
this.id = stateGameBoard.getId();
|
this.id = stateGameBoard.getId();
|
||||||
|
|
||||||
this.previousCommand = UtxoLedgerTransactionUtil
|
|
||||||
.getOptionalCommand(utxoGameBoard, GameBoardCommand.class)
|
|
||||||
.orElseGet(() -> null); // there is no previous command for GameProposal.Accept case
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ public class CommitResponderFlow implements ResponderFlow {
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
@Override
|
@Override
|
||||||
public void call(FlowSession session) {
|
public void call(FlowSession session) {
|
||||||
|
log.info("GameProposal: Commit responder flow");
|
||||||
try {
|
try {
|
||||||
UtxoTransactionValidator txValidator = ledgerTransaction -> {
|
UtxoTransactionValidator txValidator = ledgerTransaction -> {
|
||||||
final GameProposalCommand command = ledgerTransaction.getCommands(GameProposalCommand.class).get(0);
|
final GameProposalCommand command = ledgerTransaction.getCommands(GameProposalCommand.class).get(0);
|
||||||
|
Loading…
Reference in New Issue
Block a user