GameBoard: naive MOVE implementation

This commit is contained in:
djmil 2023-09-25 15:13:27 +02:00
parent 8971462c74
commit 1f2ff242e4
17 changed files with 331 additions and 90 deletions

View File

@ -85,20 +85,17 @@ public class CordaClient {
.getResponce(requestBody);
}
public GameState gameStateGet(HoldingIdentity holdingIdentity, UUID gameStateUuid) {
public GameState gameStateGet(HoldingIdentity holdingIdentity, UUID gameUuid) {
final RequestBody requestBody = new RequestBody(
"gs.get-" + UUID.randomUUID(),
"djmil.cordacheckers.gamestate.GetFlow",
gameStateUuid);
gameUuid);
return cordaFlowExecute(holdingIdentity, requestBody, RspGameState.class)
.getResponce(requestBody);
}
public GameState gameProposalCreate(
HoldingIdentity issuer,
HoldingIdentity acquier,
Piece.Color acquierColor,
public GameState gameProposalCreate(HoldingIdentity issuer, HoldingIdentity acquier, Piece.Color acquierColor,
String message
) {
final RequestBody requestBody = new RequestBody(
@ -113,53 +110,53 @@ public class CordaClient {
.getResponce(requestBody);
}
public GameState gameProposalReject(HoldingIdentity holdingIdentity, UUID gameProposalUuid) {
public GameState gameProposalReject(HoldingIdentity holdingIdentity, UUID gameUuid) {
final RequestBody requestBody = new RequestBody(
"gp.reject-" +UUID.randomUUID(),
"djmil.cordacheckers.gameproposal.RejectFlow",
gameProposalUuid);
gameUuid);
return cordaFlowExecute(holdingIdentity, requestBody, RspGameState.class)
.getResponce(requestBody);
}
public GameState gameProposalCancel(HoldingIdentity holdingIdentity, UUID gameProposalUuid) {
public GameState gameProposalCancel(HoldingIdentity holdingIdentity, UUID gameUuid) {
final RequestBody requestBody = new RequestBody(
"gp.reject-" +UUID.randomUUID(),
"djmil.cordacheckers.gameproposal.CancelFlow",
gameProposalUuid);
gameUuid);
return cordaFlowExecute(holdingIdentity, requestBody, RspGameState.class)
.getResponce(requestBody);
}
public GameState gameProposalAccept(HoldingIdentity holdingIdentity, UUID gameProposalUuid) {
public GameState gameProposalAccept(HoldingIdentity holdingIdentity, UUID gameUuid) {
final RequestBody requestBody = new RequestBody(
"gp.accept-" +UUID.randomUUID(),
"djmil.cordacheckers.gameproposal.AcceptFlow",
gameProposalUuid);
gameUuid);
return cordaFlowExecute(holdingIdentity, requestBody, RspGameState.class)
.getResponce(requestBody);
}
public GameState gameBoardSurrender(HoldingIdentity holdingIdentity, UUID gameBoardUuid) {
public GameState gameBoardSurrender(HoldingIdentity holdingIdentity, UUID gameUuid) {
final RequestBody requestBody = new RequestBody(
"gb.surrender-" +UUID.randomUUID(),
"djmil.cordacheckers.gameboard.SurrenderFlow",
gameBoardUuid);
gameUuid);
return cordaFlowExecute(holdingIdentity, requestBody, RspGameState.class)
.getResponce(requestBody);
}
public GameState gameBoardMove(HoldingIdentity holdingIdentity, UUID gameBoardUuid, List<Integer> move) {
public GameState gameBoardMove(HoldingIdentity holdingIdentity, UUID gameUuid, List<Integer> move,
String message) {
final RequestBody requestBody = new RequestBody(
"gb.move-" +UUID.randomUUID(),
"djmil.cordacheckers.gameboard.CommandFlow",
"djmil.cordacheckers.gameboard.MoveFlow",
new ReqGameBoardMove(
gameBoardUuid,
move));
move, gameUuid, message));
return cordaFlowExecute(holdingIdentity, requestBody, RspGameState.class)
.getResponce(requestBody);

View File

@ -42,4 +42,20 @@ public class Piece {
return color +"." +type;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Piece other = (Piece) obj;
if (color != other.color)
return false;
if (type != other.type)
return false;
return true;
}
}

View File

@ -4,8 +4,9 @@ import java.util.List;
import java.util.UUID;
public record ReqGameBoardMove(
UUID gameBoardUuid,
List<Integer> move
List<Integer> move,
UUID gameUuid,
String message
) {
}

View File

@ -3,6 +3,9 @@ package djmil.cordacheckers.cordaclient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@ -23,6 +26,11 @@ public class GameBoardTests {
final String whitePlayerName = "alice";
final String blackPlayerName = "bob";
final static Piece WHITE_MAN = new Piece(Piece.Color.WHITE, Piece.Type.MAN);
final static Piece WHITE_KING = new Piece(Piece.Color.WHITE, Piece.Type.KING);
final static Piece BLACK_MAN = new Piece(Piece.Color.BLACK, Piece.Type.MAN);
final static Piece BLACK_KING = new Piece(Piece.Color.BLACK, Piece.Type.KING);
@Test
void testSurrender() {
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
@ -60,4 +68,37 @@ public class GameBoardTests {
assertThat(winnerGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_WON);
}
@Test
void testMove() {
final var hiWhite = holdingIdentityResolver.getByUsername(whitePlayerName);
final var hiBlack = holdingIdentityResolver.getByUsername(blackPlayerName);
final String message = "GameBoard MOVE test";
final GameState game = cordaClient.gameProposalCreate(
hiWhite, hiBlack, Piece.Color.BLACK, message);
System.out.println("Game UUID " +game.uuid());
final var m0 = cordaClient.gameProposalAccept(hiBlack, game.uuid());
assertThatThrownBy(() -> {
cordaClient.gameBoardMove(hiBlack, game.uuid(), move(12, 16),
"Black can not move, since it is opponent's turn");
});
assertThatThrownBy(() -> {
cordaClient.gameBoardMove(hiWhite, game.uuid(), move(17, 14),
"Trying to move an empty tile");
});
final var m1 = cordaClient.gameBoardMove(hiWhite, game.uuid(), move(22, 18), null);
assertThat(m0.board().get(22)).isEqualTo(WHITE_MAN);
assertThat(m0.board().get(18)).isNull();
assertThat(m1.board().get(22)).isNull();
assertThat(m1.board().get(18)).isEqualTo(WHITE_MAN);
assertThat(m1.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
}
ArrayList<Integer> move(int from, int to) {
return new ArrayList<Integer>(Arrays.asList(from, to));
}
}

View File

@ -9,7 +9,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import djmil.cordacheckers.cordaclient.dao.GameState;
import djmil.cordacheckers.cordaclient.dao.GameState.Status;
import djmil.cordacheckers.cordaclient.dao.Piece;
import djmil.cordacheckers.cordaclient.dao.Rank;
import djmil.cordacheckers.user.HoldingIdentityResolver;
@ -25,6 +24,8 @@ public class RankingTests {
@Test
void testGlobalRanking() {
final var hiCustodian = holdingIdentityResolver.getCustodian();
assertThat(hiCustodian).isNotNull();
final List<Rank> liderboard1 = cordaClient.fetchRanking(hiCustodian);
final var hiWinner = holdingIdentityResolver.getByUsername("Charlie");

View File

@ -3,13 +3,35 @@ package djmil.cordacheckers.contracts;
import static djmil.cordacheckers.contracts.GameCommand.requireThat;
import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import djmil.cordacheckers.states.Piece;
import djmil.cordacheckers.states.Piece.Color;
import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction;
public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
public static class MoveResult {
final public Map<Integer, Piece> board;
final public Piece.Color moveColor;
public MoveResult(Map<Integer, Piece> board, Color moveColor) {
this.board = board;
this.moveColor = moveColor;
}
public static class Exception extends RuntimeException {
public Exception(String message) {
super(message);
}
}
}
private final static Logger log = LoggerFactory.getLogger(GameBoardContract.class);
@Override
@ -19,13 +41,13 @@ public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
requireThat(trx.getCommands().size() == 1, GameCommand.REQUIRE_SINGLE_COMMAND);
final GameCommand command = getSingleCommand(trx, GameCommand.class);
switch (command.action) {
switch (command.getAction()) {
case GAME_PROPOSAL_ACCEPT:
command.validateGameProposalAccept(trx);
break;
case GAME_BOARD_MOVE:
command.validateGameBoardMove(trx);
command.validateGameBoardMove(trx, command.getMove());
break;
case GAME_BOARD_SURRENDER:
@ -37,4 +59,60 @@ public class GameBoardContract implements net.corda.v5.ledger.utxo.Contract {
}
}
public static MoveResult applyMove(List<Integer> move, Map<Integer, Piece> board, Piece.Color moveColor) {
final int mFrom = move.get(0);
final int mTo = move.get(1);
final Piece piece = board.get(mFrom);
if (piece == null)
throw new MoveResult.Exception("An empty starting tile");
if (piece.getColor() != moveColor)
throw new MoveResult.Exception("Can not move opponent's piece");
if (board.get(mTo) != null)
throw new MoveResult.Exception("An occupied finishing tile");
final Map<Integer, Piece> newBoard = new LinkedHashMap<Integer, Piece>(board);
newBoard.remove(mFrom);
newBoard.put(mTo, piece);
return new GameBoardContract.MoveResult(newBoard, moveColor.opposite());
}
final static Piece WHITE_MAN = new Piece(Piece.Color.WHITE, Piece.Type.MAN);
final static Piece WHITE_KING = new Piece(Piece.Color.WHITE, Piece.Type.KING);
final static Piece BLACK_MAN = new Piece(Piece.Color.BLACK, Piece.Type.MAN);
final static Piece BLACK_KING = new Piece(Piece.Color.BLACK, Piece.Type.KING);
public final static Map<Integer, Piece> initialBoard = Map.ofEntries(
// Inspired by Checkers notation rules: https://www.bobnewell.net/nucleus/checkers.php
Map.entry( 1, BLACK_MAN),
Map.entry( 2, BLACK_MAN),
Map.entry( 3, BLACK_MAN),
Map.entry( 4, BLACK_MAN),
Map.entry( 5, BLACK_MAN),
Map.entry( 6, BLACK_MAN),
Map.entry( 7, BLACK_MAN),
Map.entry( 8, BLACK_MAN),
Map.entry( 9, BLACK_MAN),
Map.entry(10, BLACK_MAN),
Map.entry(11, BLACK_MAN),
Map.entry(12, BLACK_MAN),
Map.entry(21, WHITE_MAN),
Map.entry(22, WHITE_MAN),
Map.entry(23, WHITE_MAN),
Map.entry(24, WHITE_MAN),
Map.entry(25, WHITE_MAN),
Map.entry(26, WHITE_MAN),
Map.entry(27, WHITE_MAN),
Map.entry(28, WHITE_MAN),
Map.entry(29, WHITE_MAN),
Map.entry(30, WHITE_MAN),
Map.entry(31, WHITE_MAN),
Map.entry(32, WHITE_MAN)
);
}

View File

@ -31,8 +31,8 @@ public class GameCommand implements Command {
GAME_RESULT_CREATE;
}
public final Action action;
public final List<Integer> move; // [0] from, [1] to
private final Action action;
private final List<Integer> move;
public static class ActionException extends RuntimeException {
public ActionException() {
@ -156,6 +156,7 @@ public class GameCommand implements Command {
final GameBoardState outGameBoard = getSingleOutputState(trx, GameBoardState.class);
requireThat(inGameProposal.getParticipants().containsAll(outGameBoard.getParticipants()), IN_OUT_PARTICIPANTS);
requireThat(outGameBoard.getBoard().equals(GameBoardContract.initialBoard), "Bad GameBoard initial state");
}
public void validateGameProposalReject(UtxoLedgerTransaction trx) {
@ -197,7 +198,7 @@ public class GameCommand implements Command {
"Expected winner "+expectedWinnerName.getCommonName() +", proposed winner " +outGameResultState.getWinnerName().getCommonName());
}
public void validateGameBoardMove(UtxoLedgerTransaction trx) {
public void validateGameBoardMove(UtxoLedgerTransaction trx, List<Integer> move) {
requireThat(trx.getInputContractStates().size() == 1, MOVE_INPUT_STATE);
final var inGameBoardState = getSingleInputState(trx, GameBoardState.class);
@ -206,6 +207,9 @@ public class GameCommand implements Command {
requireThat(inGameBoardState.getWhitePlayer().compareTo(outGameBoardState.getWhitePlayer()) == 0, IN_OUT_PARTICIPANTS);
requireThat(inGameBoardState.getBlackPlayer().compareTo(outGameBoardState.getBlackPlayer()) == 0, IN_OUT_PARTICIPANTS);
final var newGameBoard = new GameBoardState(inGameBoardState, move, outGameBoardState.getMessage());
requireThat(outGameBoardState.equals(newGameBoard), "Unexpected output state");
}
public void validateGameResultCreate(UtxoLedgerTransaction trx) {

View File

@ -19,7 +19,7 @@ public class GameProposalContract implements net.corda.v5.ledger.utxo.Contract {
requireThat(trx.getCommands().size() == 1, GameCommand.REQUIRE_SINGLE_COMMAND);
final GameCommand command = getSingleCommand(trx, GameCommand.class);
switch (command.action) {
switch (command.getAction()) {
case GAME_PROPOSAL_CREATE:
command.validateGameProposalCreate(trx);
break;

View File

@ -19,7 +19,7 @@ public class GameResultContract implements net.corda.v5.ledger.utxo.Contract {
requireThat(trx.getCommands().size() == 1, GameCommand.REQUIRE_SINGLE_COMMAND);
final GameCommand command = getSingleCommand(trx, GameCommand.class);
switch (command.action) {
switch (command.getAction()) {
case GAME_BOARD_SURRENDER:
command.validateGameBoardSurrender(trx);
break;

View File

@ -7,6 +7,7 @@ import java.util.Map;
import java.util.UUID;
import djmil.cordacheckers.contracts.GameBoardContract;
import djmil.cordacheckers.contracts.GameBoardContract.MoveResult;
import djmil.cordacheckers.states.Piece.Color;
import net.corda.v5.base.annotations.ConstructorForDeserialization;
import net.corda.v5.base.types.MemberX500Name;
@ -22,19 +23,22 @@ public class GameBoardState extends GameState {
super(gameProposalState.whitePlayer, gameProposalState.blackPlayer,
gameProposalState.gameUuid, gameProposalState.message, gameProposalState.participants);
// Initial GameBoard state
this.board = new LinkedHashMap<Integer, Piece>(GameBoardContract.initialBoard);
this.moveColor = Piece.Color.WHITE;
this.moveNumber = 0;
this.board = new LinkedHashMap<Integer, Piece>(initialBoard);
}
public GameBoardState(GameBoardState oldGameBoardState, Map<Integer, Piece> newBoard, Piece.Color moveColor) {
super(oldGameBoardState.whitePlayer, oldGameBoardState.blackPlayer,
oldGameBoardState.gameUuid, oldGameBoardState.message, oldGameBoardState.participants);
public GameBoardState(GameBoardState currentGameBoardState, List<Integer> move, String message) {
super(currentGameBoardState.whitePlayer, currentGameBoardState.blackPlayer, currentGameBoardState.gameUuid,
message, currentGameBoardState.participants);
this.moveColor = moveColor;
this.moveNumber = oldGameBoardState.getMoveNumber() +1;
this.board = newBoard;
final MoveResult moveResult = GameBoardContract.applyMove(move, currentGameBoardState.getBoard(), currentGameBoardState.getMoveColor());
this.moveColor = moveResult.moveColor;
this.board = moveResult.board;
this.moveNumber = (currentGameBoardState.moveColor == this.moveColor)
? currentGameBoardState.getMoveNumber() // current player has not finished his move jet
: currentGameBoardState.getMoveNumber() +1;
}
@ConstructorForDeserialization
@ -64,33 +68,29 @@ public class GameBoardState extends GameState {
return board;
}
// TODO: move to contract
public final static Map<Integer, Piece> initialBoard = Map.ofEntries(
// Inspired by Checkers notation rules: https://www.bobnewell.net/nucleus/checkers.php
Map.entry( 1, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 2, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 3, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 4, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 5, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 6, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 7, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 8, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry( 9, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry(10, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry(11, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry(12, new Piece(Piece.Color.BLACK, Piece.Type.MAN)),
Map.entry(21, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(22, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(23, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(24, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(25, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(26, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(27, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(28, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(29, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(30, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(31, new Piece(Piece.Color.WHITE, Piece.Type.MAN)),
Map.entry(32, new Piece(Piece.Color.WHITE, Piece.Type.MAN))
);
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
GameBoardState other = (GameBoardState) obj;
if (moveColor != other.moveColor)
return false;
if (moveNumber == null) {
if (other.moveNumber != null)
return false;
} else if (!moveNumber.equals(other.moveNumber))
return false;
if (board == null) {
if (other.board != null)
return false;
} else if (!board.equals(other.board))
return false;
return true;
}
}

View File

@ -17,21 +17,14 @@ public class Piece {
WHITE,
BLACK;
public static Color oppositOf(Color color) {
switch (color) {
public Color opposite() {
switch (this) {
case WHITE:
return BLACK;
case BLACK:
return WHITE;
default:
throw new UnknownException();
}
}
public static class UnknownException extends RuntimeException {
public UnknownException() {
super("Unknown Color value");
}
throw new RuntimeException("Unknown Color");
}
}
@ -52,4 +45,20 @@ public class Piece {
return type;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Piece other = (Piece) obj;
if (color != other.color)
return false;
if (type != other.type)
return false;
return true;
}
}

View File

@ -0,0 +1,85 @@
package djmil.cordacheckers.gameboard;
import java.time.Duration;
import java.time.Instant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import djmil.cordacheckers.contracts.GameCommand;
import djmil.cordacheckers.gamestate.CommitSubFlow;
import djmil.cordacheckers.gamestate.FlowResponce;
import djmil.cordacheckers.gamestate.GetFlow;
import djmil.cordacheckers.gamestate.View;
import djmil.cordacheckers.gamestate.ViewBuilder;
import djmil.cordacheckers.states.GameBoardState;
import djmil.cordacheckers.states.GameState;
import net.corda.v5.application.flows.ClientRequestBody;
import net.corda.v5.application.flows.ClientStartableFlow;
import net.corda.v5.application.flows.CordaInject;
import net.corda.v5.application.flows.FlowEngine;
import net.corda.v5.application.marshalling.JsonMarshallingService;
import net.corda.v5.base.annotations.Suspendable;
import net.corda.v5.crypto.SecureHash;
import net.corda.v5.ledger.utxo.StateAndRef;
import net.corda.v5.ledger.utxo.UtxoLedgerService;
import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction;
public class MoveFlow implements ClientStartableFlow{
private final static Logger log = LoggerFactory.getLogger(MoveFlow.class);
@CordaInject
public JsonMarshallingService jsonMarshallingService;
@CordaInject
public UtxoLedgerService utxoLedgerService;
@CordaInject
public FlowEngine flowEngine;
@Suspendable
@Override
public String call(ClientRequestBody requestBody) {
SecureHash utxoTrxId = null;
try {
final MoveFlowArgs args = requestBody.getRequestBodyAs(jsonMarshallingService, MoveFlowArgs.class);
final GameCommand command = new GameCommand(args.move);
final StateAndRef<GameState> currntGameBoardSar = this.flowEngine
.subFlow(new GetFlow(args.gameUuid));
final GameBoardState newGameBoard = new GameBoardState(
(GameBoardState)currntGameBoardSar.getState().getContractState(),
args.move,
args.message);
final UtxoSignedTransaction gameBoardMoveTrx = utxoLedgerService.createTransactionBuilder()
.addCommand(command)
.addInputState(currntGameBoardSar.getRef())
.addOutputState(newGameBoard)
.addSignatories(newGameBoard.getParticipants())
.setNotary(currntGameBoardSar.getState().getNotaryName())
.setTimeWindowUntil(Instant.now().plusMillis(Duration.ofDays(1).toMillis()))
.toSignedTransaction();
utxoTrxId = this.flowEngine
.subFlow(new CommitSubFlow(gameBoardMoveTrx, command.getCounterparty(currntGameBoardSar)));
final View gameStateView = this.flowEngine
.subFlow(new ViewBuilder(utxoTrxId));
return new FlowResponce(gameStateView, utxoTrxId)
.toJsonEncodedString(jsonMarshallingService);
}
catch (Exception e) {
log.warn(requestBody + " " +e.getClass() +": " +e.getMessage());
e.printStackTrace(System.out);
return new FlowResponce(e, utxoTrxId)
.toJsonEncodedString(jsonMarshallingService);
}
}
}

View File

@ -0,0 +1,17 @@
package djmil.cordacheckers.gameboard;
import java.util.List;
import java.util.UUID;
public class MoveFlowArgs {
public final List<Integer> move;
public final UUID gameUuid;
public final String message;
// Serialisation service requires a default constructor
public MoveFlowArgs() {
this.move = null;
this.gameUuid = null;
this.message = null;
}
}

View File

@ -21,10 +21,8 @@ import net.corda.v5.application.flows.ClientStartableFlow;
import net.corda.v5.application.flows.CordaInject;
import net.corda.v5.application.flows.FlowEngine;
import net.corda.v5.application.marshalling.JsonMarshallingService;
import net.corda.v5.application.membership.MemberLookup;
import net.corda.v5.base.annotations.Suspendable;
import net.corda.v5.crypto.SecureHash;
import net.corda.v5.ledger.common.NotaryLookup;
import net.corda.v5.ledger.utxo.StateAndRef;
import net.corda.v5.ledger.utxo.UtxoLedgerService;
import net.corda.v5.ledger.utxo.transaction.UtxoSignedTransaction;
@ -36,12 +34,6 @@ public class SurrenderFlow implements ClientStartableFlow{
@CordaInject
public JsonMarshallingService jsonMarshallingService;
@CordaInject
public MemberLookup memberLookup;
@CordaInject
public NotaryLookup notaryLookup;
@CordaInject
public UtxoLedgerService utxoLedgerService;

View File

@ -76,7 +76,7 @@ public class CommitSubFlowResponder implements ResponderFlow {
*/
@Suspendable
GameState getActualGameStateFromTransaction(UtxoLedgerTransaction gameStateTransaction, GameCommand command) {
switch (command.action) {
switch (command.getAction()) {
case GAME_PROPOSAL_CREATE:
return getSingleOutputState(gameStateTransaction, GameProposalState.class);
@ -89,7 +89,7 @@ public class CommitSubFlowResponder implements ResponderFlow {
return getSingleInputState(gameStateTransaction, GameBoardState.class);
case GAME_BOARD_MOVE:
return getSingleOutputState(gameStateTransaction, GameBoardState.class);
return getSingleInputState(gameStateTransaction, GameBoardState.class);
case GAME_RESULT_CREATE:
return getSingleOutputState(gameStateTransaction, GameResultState.class);

View File

@ -17,7 +17,7 @@ public class FlowResponce {
public FlowResponce(Exception exception, SecureHash transactionId) {
this.successStatus = null;
this.transactionId = transactionId;
this.failureStatus = exception.getMessage();
this.failureStatus = exception.toString();
}
public String toJsonEncodedString(JsonMarshallingService jsonMarshallingService) {

View File

@ -51,7 +51,7 @@ public class ViewBuilder implements SubFlow<View> {
final GameState state = getLatestGameStateFromTransaction(gameStateUtxo, command);
final View.Status viewStatus = action2status(command, state, myName);
switch (command.action) {
switch (command.getAction()) {
case GAME_PROPOSAL_CREATE:
case GAME_PROPOSAL_CANCEL:
case GAME_PROPOSAL_REJECT:
@ -62,7 +62,7 @@ public class ViewBuilder implements SubFlow<View> {
case GAME_PROPOSAL_ACCEPT:
case GAME_BOARD_MOVE:
if (state instanceof GameBoardState)
return new View(viewStatus, (GameBoardState)state, command.move, myName);
return new View(viewStatus, (GameBoardState)state, command.getMove(), myName);
break;
case GAME_BOARD_SURRENDER:
@ -85,7 +85,7 @@ public class ViewBuilder implements SubFlow<View> {
*/
@Suspendable
GameState getLatestGameStateFromTransaction(UtxoLedgerTransaction gameStateTransaction, GameCommand command) {
switch (command.action) {
switch (command.getAction()) {
case GAME_PROPOSAL_CREATE:
return getSingleOutputState(gameStateTransaction, GameProposalState.class);
@ -109,7 +109,7 @@ public class ViewBuilder implements SubFlow<View> {
View.Status action2status(GameCommand command, GameState state, MemberX500Name myName) {
final boolean myAction = command.getInitiator(state).compareTo(myName) == 0;
switch (command.action) {
switch (command.getAction()) {
case GAME_PROPOSAL_CREATE:
if (myAction)
return View.Status.GAME_PROPOSAL_WAIT_FOR_OPPONENT;