diff --git a/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/flow/arguments/Rsp.java b/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/flow/arguments/Rsp.java index 8b03a2b..d2ff720 100644 --- a/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/flow/arguments/Rsp.java +++ b/backend/src/main/java/djmil/cordacheckers/cordaclient/dao/flow/arguments/Rsp.java @@ -9,7 +9,7 @@ public interface Rsp { public default T getResponce(RequestBody requestBody) { if (failureStatus() != null) { final String msg = requestBody.flowClassName() +" requestId " +requestBody.clientRequestId() +" has failed: " +failureStatus(); - System.err.println(msg +". Reson " +failureStatus()); + System.err.println(msg); throw new RuntimeException(msg); } diff --git a/backend/src/test/java/djmil/cordacheckers/cordaclient/GameBoardTests.java b/backend/src/test/java/djmil/cordacheckers/cordaclient/GameBoardTests.java index e131684..5108986 100644 --- a/backend/src/test/java/djmil/cordacheckers/cordaclient/GameBoardTests.java +++ b/backend/src/test/java/djmil/cordacheckers/cordaclient/GameBoardTests.java @@ -48,23 +48,24 @@ public class GameBoardTests { assertThat(acceptedGameBlackView.opponentColor()).isEqualByComparingTo(Stone.Color.WHITE); assertThat(acceptedGameBlackView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT); - assertThatThrownBy(() -> { // Black can not surrender, since it is opponent's turn - cordaClient.gameBoardSurrender( - hiBlack, game.uuid()); - }); - + // Black shall be able to surrender, even if it is not his turn final GameState surrendererGameView = cordaClient.gameBoardSurrender( - hiWhite, game.uuid()); - - assertThat(surrendererGameView.opponentName()).isEqualToIgnoringCase(blackPlayerName); - assertThat(surrendererGameView.opponentColor()).isEqualByComparingTo(Stone.Color.BLACK); - assertThat(surrendererGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_LOOSE); - - final GameState winnerGameView = cordaClient.gameStateGet( hiBlack, game.uuid()); - assertThat(winnerGameView.opponentName()).isEqualToIgnoringCase(whitePlayerName); - assertThat(winnerGameView.opponentColor()).isEqualByComparingTo(Stone.Color.WHITE); + assertThat(surrendererGameView.opponentName()).isEqualToIgnoringCase(whitePlayerName); + assertThat(surrendererGameView.opponentColor()).isEqualByComparingTo(Stone.Color.WHITE); + assertThat(surrendererGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_LOOSE); + + assertThatThrownBy(() -> { // White can not surrender, since Black already did + cordaClient.gameBoardSurrender( + hiWhite, game.uuid()); + }); + + final GameState winnerGameView = cordaClient.gameStateGet( + hiWhite, game.uuid()); + + assertThat(winnerGameView.opponentName()).isEqualToIgnoringCase(blackPlayerName); + assertThat(winnerGameView.opponentColor()).isEqualByComparingTo(Stone.Color.BLACK); assertThat(winnerGameView.status()).isEqualByComparingTo(Status.GAME_RESULT_YOU_WON); } diff --git a/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameCommand.java b/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameCommand.java index 0c9bd79..d6648cd 100644 --- a/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameCommand.java +++ b/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameCommand.java @@ -27,8 +27,7 @@ public class GameCommand implements Command { GAME_BOARD_MOVE, GAME_BOARD_SURRENDER, - - GAME_RESULT_CREATE; + GAME_BOARD_VICTORY; } private final Action action; @@ -72,61 +71,42 @@ public class GameCommand implements Command { public List getMove() { return move; } - - /* - * Session initiator/respondent - */ public MemberX500Name getCounterparty(StateAndRef gameStateSar) { - final GameState gameState = gameStateSar.getState().getContractState(); - return gameState.getOpponentName(getInitiator(gameState)); + return getCounterparty(gameStateSar.getState().getContractState()); } - + public MemberX500Name getCounterparty(GameState gameState) { - return gameState.getOpponentName(getInitiator(gameState)); - } - - public MemberX500Name getInitiator(StateAndRef gameStateSar) { - return getInitiator(gameStateSar.getState().getContractState()); - } - - public MemberX500Name getInitiator(GameState gameState) { - switch (action) { + switch (this.action) { case GAME_PROPOSAL_CREATE: case GAME_PROPOSAL_CANCEL: - if (gameState instanceof GameProposalState) - return ((GameProposalState)gameState).getIssuerName(); - break; - - case GAME_PROPOSAL_REJECT: if (gameState instanceof GameProposalState) return ((GameProposalState)gameState).getAcquierName(); break; - - case GAME_PROPOSAL_ACCEPT: - if (gameState instanceof GameProposalState) // <<-- Session validation perspective - return ((GameProposalState)gameState).getAcquierName(); - if (gameState instanceof GameBoardState) // <<-- GameViewBuilder perspective - return ((GameBoardState)gameState).getActivePlayerName(); - break; - case GAME_BOARD_SURRENDER: - if (gameState instanceof GameBoardState) // <<-- Session validation perspective - return ((GameBoardState)gameState).getActivePlayerName(); - if (gameState instanceof GameResultState) // <<-- GameViewBuilder perspective - return ((GameResultState)gameState).getLooserName(); + case GAME_PROPOSAL_ACCEPT: + case GAME_PROPOSAL_REJECT: + if (gameState instanceof GameProposalState) + return ((GameProposalState)gameState).getIssuerName(); break; case GAME_BOARD_MOVE: - if (gameState instanceof GameBoardState) - return ((GameBoardState)gameState).getActivePlayerName(); + if (gameState instanceof GameBoardState) { + final var activePlayer = ((GameBoardState)gameState).getActivePlayerName(); + return gameState.getOpponentName(activePlayer); + } break; - - case GAME_RESULT_CREATE: + + case GAME_BOARD_SURRENDER: if (gameState instanceof GameResultState) return ((GameResultState)gameState).getWinnerName(); break; + case GAME_BOARD_VICTORY: + if (gameState instanceof GameResultState) + return ((GameResultState)gameState).getLooserName(); + break; + default: throw new ActionException(); } @@ -192,10 +172,10 @@ public class GameCommand implements Command { requireThat(inActors.containsAll(outActors) && outActors.containsAll(inActors), IN_OUT_PARTICIPANTS); - final var activePlayerName = getInitiator(inGameBoardState); - final var expectedWinnerName = inGameBoardState.getOpponentName(activePlayerName); - requireThat(outGameResultState.getWinnerName().compareTo(expectedWinnerName) == 0, - "Expected winner "+expectedWinnerName.getCommonName() +", proposed winner " +outGameResultState.getWinnerName().getCommonName()); + final GameInfo gameInfo = new GameInfo(trx); + final var winnerName = inGameBoardState.getOpponentName(gameInfo.issuer); + requireThat(outGameResultState.getWinnerName().compareTo(winnerName) == 0, + "Expected winner "+winnerName.getCommonName() +", proposed winner " +outGameResultState.getWinnerName().getCommonName()); } public void validateGameBoardMove(UtxoLedgerTransaction trx, List move) { diff --git a/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameInfo.java b/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameInfo.java new file mode 100644 index 0000000..075a403 --- /dev/null +++ b/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameInfo.java @@ -0,0 +1,79 @@ +package djmil.cordacheckers.contracts; + +import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand; +import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleInputState; +import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleOutputState; + +import djmil.cordacheckers.contracts.GameCommand.ActionException; +import djmil.cordacheckers.states.GameBoardState; +import djmil.cordacheckers.states.GameProposalState; +import djmil.cordacheckers.states.GameResultState; +import djmil.cordacheckers.states.GameState; +import net.corda.v5.base.types.MemberX500Name; +import net.corda.v5.ledger.utxo.transaction.UtxoLedgerTransaction; + +public class GameInfo { + + public final GameCommand command; + public final MemberX500Name issuer; // a person who has created/updated state (important for CommitSubFlowResponder) + public final MemberX500Name actor; // a person who is expected to act on a state (inmportnat for ViewBuilder) + public final GameState state; // lates, most actual state + + public GameInfo(UtxoLedgerTransaction utxoTrx) { + this.command = getSingleCommand(utxoTrx, GameCommand.class); + + switch (this.command.getAction()) { + case GAME_PROPOSAL_CREATE: + this.state = getSingleOutputState(utxoTrx, GameProposalState.class); + this.issuer = ((GameProposalState)this.state).getIssuerName(); + this.actor = ((GameProposalState)this.state).getAcquierName(); + return; + + case GAME_PROPOSAL_CANCEL: + this.state = getSingleInputState(utxoTrx, GameProposalState.class); + this.issuer = ((GameProposalState)this.state).getIssuerName(); + this.actor = null; + return; + + case GAME_PROPOSAL_REJECT: + this.state = getSingleInputState(utxoTrx, GameProposalState.class); + this.issuer = ((GameProposalState)this.state).getAcquierName(); + this.actor = null; + return; + + case GAME_PROPOSAL_ACCEPT: + this.state = getSingleOutputState(utxoTrx, GameBoardState.class); + this.issuer = getSingleInputState(utxoTrx, GameProposalState.class).getAcquierName(); + this.actor = ((GameBoardState)this.state).getActivePlayerName(); + return; + + case GAME_BOARD_MOVE: + this.state = getSingleOutputState(utxoTrx, GameBoardState.class); + this.issuer = getSingleInputState(utxoTrx, GameBoardState.class).getActivePlayerName(); + this.actor = ((GameBoardState)this.state).getActivePlayerName(); + return; + + case GAME_BOARD_VICTORY: + this.state = getSingleOutputState(utxoTrx, GameResultState.class); + this.issuer = ((GameResultState)this.state).getWinnerName(); + this.actor = null; + return; + + case GAME_BOARD_SURRENDER: + this.state = getSingleOutputState(utxoTrx, GameResultState.class); + this.issuer = ((GameResultState)this.state).getLooserName(); + this.actor = null; + return; + } + + throw new ActionException(); + } + + public boolean isMyAction(MemberX500Name myName) { + if (this.actor == null) + return false; + + return this.actor.compareTo(myName) == 0; + } + +} diff --git a/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameResultContract.java b/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameResultContract.java index bf2d960..d41ba4e 100644 --- a/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameResultContract.java +++ b/corda/contracts/src/main/java/djmil/cordacheckers/contracts/GameResultContract.java @@ -24,7 +24,7 @@ public class GameResultContract implements net.corda.v5.ledger.utxo.Contract { command.validateGameBoardSurrender(trx); break; - case GAME_RESULT_CREATE: + case GAME_BOARD_VICTORY: command.validateGameResultCreate(trx); break; diff --git a/corda/contracts/src/main/java/djmil/cordacheckers/states/GameBoardState.java b/corda/contracts/src/main/java/djmil/cordacheckers/states/GameBoardState.java index cfc56ed..938a283 100644 --- a/corda/contracts/src/main/java/djmil/cordacheckers/states/GameBoardState.java +++ b/corda/contracts/src/main/java/djmil/cordacheckers/states/GameBoardState.java @@ -91,5 +91,4 @@ public class GameBoardState extends GameState { return true; } - } diff --git a/corda/workflows/src/main/java/djmil/cordacheckers/gameboard/SurrenderFlow.java b/corda/workflows/src/main/java/djmil/cordacheckers/gameboard/SurrenderFlow.java index 558db02..ccce6de 100644 --- a/corda/workflows/src/main/java/djmil/cordacheckers/gameboard/SurrenderFlow.java +++ b/corda/workflows/src/main/java/djmil/cordacheckers/gameboard/SurrenderFlow.java @@ -67,7 +67,7 @@ public class SurrenderFlow implements ClientStartableFlow{ utxoTrxId = this.flowEngine .subFlow(new CommitSubFlow(gameBoardSurrenderTrx, - command.getCounterparty(gameBoardSar), + command.getCounterparty(out.gameResult), out.custodyName)); final View gameStateView = this.flowEngine diff --git a/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/CommitSubFlowResponder.java b/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/CommitSubFlowResponder.java index 9f5ee0d..346c1e9 100644 --- a/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/CommitSubFlowResponder.java +++ b/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/CommitSubFlowResponder.java @@ -1,17 +1,9 @@ package djmil.cordacheckers.gamestate; -import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand; -import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleOutputState; -import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleInputState; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import djmil.cordacheckers.contracts.GameCommand; -import djmil.cordacheckers.states.GameBoardState; -import djmil.cordacheckers.states.GameProposalState; -import djmil.cordacheckers.states.GameResultState; -import djmil.cordacheckers.states.GameState; +import djmil.cordacheckers.contracts.GameInfo; import net.corda.v5.application.flows.CordaInject; import net.corda.v5.application.flows.InitiatedBy; import net.corda.v5.application.flows.ResponderFlow; @@ -40,10 +32,7 @@ public class CommitSubFlowResponder implements ResponderFlow { public void call(FlowSession session) { UtxoTransactionValidator txValidator = trxToValidate -> { try { - final GameCommand gameCommand = getSingleCommand(trxToValidate, GameCommand.class); - final GameState gameState = getActualGameStateFromTransaction(trxToValidate, gameCommand); - - checkParticipants(session, gameCommand, gameState); + checkParticipants(session, trxToValidate); /* * Other checks / actions ? @@ -66,52 +55,20 @@ public class CommitSubFlowResponder implements ResponderFlow { } } - /** - * - * @param gameStateTransaction an utxo ledger transaction, that involves GameState - * @param command - * @return the most recent (from perspective of session participants validation) GameState for a given transaction - * - * @see djmil.cordacheckers.gamestate.ViewBuilder#getLatestGameStateFromTransaction(UtxoLedgerTransaction, GameCommand) - */ @Suspendable - GameState getActualGameStateFromTransaction(UtxoLedgerTransaction gameStateTransaction, GameCommand command) { - switch (command.getAction()) { - case GAME_PROPOSAL_CREATE: - return getSingleOutputState(gameStateTransaction, GameProposalState.class); - - case GAME_PROPOSAL_ACCEPT: - case GAME_PROPOSAL_REJECT: - case GAME_PROPOSAL_CANCEL: - return getSingleInputState(gameStateTransaction, GameProposalState.class); - - case GAME_BOARD_SURRENDER: - return getSingleInputState(gameStateTransaction, GameBoardState.class); - - case GAME_BOARD_MOVE: - return getSingleInputState(gameStateTransaction, GameBoardState.class); - - case GAME_RESULT_CREATE: - return getSingleOutputState(gameStateTransaction, GameResultState.class); - } - - throw new GameCommand.ActionException(); - } - - @Suspendable - void checkParticipants(FlowSession session, GameCommand gameCommand, GameState gameState) throws ParticipantException { + void checkParticipants(FlowSession session, UtxoLedgerTransaction gameStateUtxo) throws ParticipantException { + final GameInfo info = new GameInfo(gameStateUtxo); final var conterpartyName = session.getCounterparty(); - final var actorName = gameCommand.getInitiator(gameState); - if (actorName.compareTo(conterpartyName) != 0) - throw new ParticipantException("Actor", conterpartyName, actorName); + if (info.issuer.compareTo(conterpartyName) != 0) + throw new ParticipantException("Issuer", conterpartyName, info.issuer); final var myName = memberLookup.myInfo().getName(); if (myName.getOrganizationUnit().equals("Custodian")) return; // Custodian shall not validate state's counterparty - final var opponentName = gameState.getOpponentName(myName); // throws NotInvolved + final var opponentName = info.state.getOpponentName(myName); // throws NotInvolved if (conterpartyName.compareTo(opponentName) != 0) - throw new ParticipantException("Counterparty", conterpartyName, opponentName); + throw new ParticipantException("Opponent", conterpartyName, opponentName); } public static class ParticipantException extends Exception { diff --git a/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/View.java b/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/View.java index a6e2737..dbc3b48 100644 --- a/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/View.java +++ b/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/View.java @@ -48,7 +48,7 @@ public class View { this.uuid = null; } - public View(View.Status status, GameProposalState gameProposal, MemberX500Name myName) { + public View(View.Status status, MemberX500Name myName, GameProposalState gameProposal) { this.status = status; this.opponentName = gameProposal.getOpponentName(myName).getCommonName(); this.opponentColor = gameProposal.getOpponentColor(myName); @@ -59,18 +59,7 @@ public class View { this.uuid = gameProposal.getGameUuid(); } - public View(View.Status status, GameBoardState gameBoard, MemberX500Name myName) { - this.status = status; - this.opponentName = gameBoard.getOpponentName(myName).getCommonName(); - this.opponentColor = gameBoard.getOpponentColor(myName); - this.board = gameBoard.getBoard(); - this.moveNumber = gameBoard.getMoveNumber(); - this.previousMove = null; - this.message = gameBoard.getMessage(); - this.uuid = gameBoard.getGameUuid(); - } - - public View(View.Status status, GameBoardState gameBoard, List previousMove, MemberX500Name myName) { + public View(View.Status status, MemberX500Name myName, GameBoardState gameBoard, List previousMove) { this.status = status; this.opponentName = gameBoard.getOpponentName(myName).getCommonName(); this.opponentColor = gameBoard.getOpponentColor(myName); @@ -81,7 +70,7 @@ public class View { this.uuid = gameBoard.getGameUuid(); } - public View(View.Status status, GameResultState gameResult, MemberX500Name myName) { + public View(View.Status status, MemberX500Name myName, GameResultState gameResult) { this.status = status; this.opponentName = gameResult.getOpponentName(myName).getCommonName(); this.opponentColor = gameResult.getOpponentColor(myName); diff --git a/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/ViewBuilder.java b/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/ViewBuilder.java index 257934d..dc18050 100644 --- a/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/ViewBuilder.java +++ b/corda/workflows/src/main/java/djmil/cordacheckers/gamestate/ViewBuilder.java @@ -1,14 +1,11 @@ package djmil.cordacheckers.gamestate; -import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleCommand; -import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleOutputState; -import static djmil.cordacheckers.contracts.UtxoLedgerTransactionUtil.getSingleInputState; import djmil.cordacheckers.contracts.GameCommand; +import djmil.cordacheckers.contracts.GameInfo; import djmil.cordacheckers.states.GameBoardState; import djmil.cordacheckers.states.GameProposalState; import djmil.cordacheckers.states.GameResultState; -import djmil.cordacheckers.states.GameState; import net.corda.v5.application.flows.CordaInject; import net.corda.v5.application.flows.SubFlow; import net.corda.v5.application.membership.MemberLookup; @@ -45,76 +42,32 @@ public class ViewBuilder implements SubFlow { @Suspendable View buildGameStateView(UtxoLedgerTransaction gameStateUtxo) { - MemberX500Name myName = memberLookup.myInfo().getName(); + final GameInfo game = new GameInfo(gameStateUtxo); + + final MemberX500Name myName = memberLookup.myInfo().getName(); + final View.Status viewStatus = action2status(game, myName); - final GameCommand command = getSingleCommand(gameStateUtxo, GameCommand.class); - final GameState state = getLatestGameStateFromTransaction(gameStateUtxo, command); - final View.Status viewStatus = action2status(command, state, myName); + if (game.state instanceof GameProposalState) + return new View(viewStatus, myName, (GameProposalState) game.state); - switch (command.getAction()) { - case GAME_PROPOSAL_CREATE: - case GAME_PROPOSAL_CANCEL: - case GAME_PROPOSAL_REJECT: - if (state instanceof GameProposalState) - return new View(viewStatus, (GameProposalState)state, myName); - break; + if (game.state instanceof GameBoardState) + return new View(viewStatus, myName, (GameBoardState) game.state, game.command.getMove()); - case GAME_PROPOSAL_ACCEPT: - case GAME_BOARD_MOVE: - if (state instanceof GameBoardState) - return new View(viewStatus, (GameBoardState)state, command.getMove(), myName); - break; - - case GAME_BOARD_SURRENDER: - case GAME_RESULT_CREATE: - if (state instanceof GameResultState) - return new View(viewStatus, (GameResultState)state, myName); - break; - } + if (game.state instanceof GameResultState) + return new View(viewStatus, myName, (GameResultState) game.state); - throw new GameCommand.ActionException(); - } - - /** - * - * @param gameStateTransaction an utxo ledger transaction, that involves GameState - * @param command - * @return the most recent (from perspective of building a GameView) GameState for a given transaction - * - * @see djmil.cordacheckers.gamestate.CommitSubFlowResponder#getActualGameStateFromTransaction(UtxoLedgerTransaction, GameCommand) - */ - @Suspendable - GameState getLatestGameStateFromTransaction(UtxoLedgerTransaction gameStateTransaction, GameCommand command) { - switch (command.getAction()) { - case GAME_PROPOSAL_CREATE: - return getSingleOutputState(gameStateTransaction, GameProposalState.class); - - case GAME_PROPOSAL_REJECT: - case GAME_PROPOSAL_CANCEL: - return getSingleInputState(gameStateTransaction, GameProposalState.class); - - case GAME_PROPOSAL_ACCEPT: - case GAME_BOARD_MOVE: - return getSingleOutputState(gameStateTransaction, GameBoardState.class); - - case GAME_BOARD_SURRENDER: - case GAME_RESULT_CREATE: - return getSingleOutputState(gameStateTransaction, GameResultState.class); - } - - throw new GameCommand.ActionException(); + throw new RuntimeException("Unexpected GameState"); } @Suspendable - View.Status action2status(GameCommand command, GameState state, MemberX500Name myName) { - final boolean myAction = command.getInitiator(state).compareTo(myName) == 0; + View.Status action2status(GameInfo game, MemberX500Name myName) { - switch (command.getAction()) { + switch (game.command.getAction()) { case GAME_PROPOSAL_CREATE: - if (myAction) - return View.Status.GAME_PROPOSAL_WAIT_FOR_OPPONENT; - else + if (game.isMyAction(myName)) return View.Status.GAME_PROPOSAL_WAIT_FOR_YOU; + else + return View.Status.GAME_PROPOSAL_WAIT_FOR_OPPONENT; case GAME_PROPOSAL_REJECT: return View.Status.GAME_PROPOSAL_REJECTED; @@ -124,19 +77,19 @@ public class ViewBuilder implements SubFlow { case GAME_PROPOSAL_ACCEPT: case GAME_BOARD_MOVE: - if (myAction) + if (game.isMyAction(myName)) return View.Status.GAME_BOARD_WAIT_FOR_YOU; else return View.Status.GAME_BOARD_WAIT_FOR_OPPONENT; case GAME_BOARD_SURRENDER: - if (myAction) + if (game.issuer.compareTo(myName) == 0) return View.Status.GAME_RESULT_YOU_LOOSE; else return View.Status.GAME_RESULT_YOU_WON; - case GAME_RESULT_CREATE: - if (myAction) + case GAME_BOARD_VICTORY: + if (game.issuer.compareTo(myName) == 0) return View.Status.GAME_RESULT_YOU_WON; else return View.Status.GAME_RESULT_YOU_LOOSE;