Ranking: use Map instead of List
This commit is contained in:
parent
f9f6920512
commit
7fe2898eef
@ -67,7 +67,7 @@ public class CordaClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use custodian holding identity to get ranking table of all players
|
// use custodian holding identity to get ranking table of all players
|
||||||
public List<Rank> fetchRanking(HoldingIdentity holdingIdentity) {
|
public Map<String, Rank> fetchRanking(HoldingIdentity holdingIdentity) {
|
||||||
final RequestBody requestBody = new RequestBody(
|
final RequestBody requestBody = new RequestBody(
|
||||||
"ranking-" +UUID.randomUUID(),
|
"ranking-" +UUID.randomUUID(),
|
||||||
"djmil.cordacheckers.gameresult.RankingFlow",
|
"djmil.cordacheckers.gameresult.RankingFlow",
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package djmil.cordacheckers.cordaclient.dao;
|
package djmil.cordacheckers.cordaclient.dao;
|
||||||
|
|
||||||
public record Rank(
|
public record Rank(
|
||||||
String name,
|
|
||||||
Integer gamesPlayed,
|
Integer gamesPlayed,
|
||||||
Integer gamesWon
|
Integer gamesWon
|
||||||
) {
|
) {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
|
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
import djmil.cordacheckers.cordaclient.dao.Rank;
|
import djmil.cordacheckers.cordaclient.dao.Rank;
|
||||||
|
|
||||||
public record RspRankList(
|
public record RspRankList(
|
||||||
List<Rank> successStatus,
|
Map<String, Rank> successStatus,
|
||||||
String failureStatus) implements Rsp<List<Rank>> {
|
String failureStatus) implements Rsp<Map<String, Rank>> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ public class GameProposalTests {
|
|||||||
assertThat(acceptedGameAcquierView.opponentName()).isEqualToIgnoringCase(issuer);
|
assertThat(acceptedGameAcquierView.opponentName()).isEqualToIgnoringCase(issuer);
|
||||||
assertThat(acceptedGameAcquierView.opponentColor()).isEqualByComparingTo(acquierColor.opposite());
|
assertThat(acceptedGameAcquierView.opponentColor()).isEqualByComparingTo(acquierColor.opposite());
|
||||||
assertThat(acceptedGameAcquierView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
|
assertThat(acceptedGameAcquierView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
|
||||||
assertThat(acceptedGameAcquierView.previousMove()).isEmpty();
|
assertThat(acceptedGameAcquierView.previousMove()).isNull();
|
||||||
assertThat(acceptedGameAcquierView.moveNumber() == 0);
|
assertThat(acceptedGameAcquierView.moveNumber() == 0);
|
||||||
assertThat(acceptedGameAcquierView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_YOU);
|
assertThat(acceptedGameAcquierView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_YOU);
|
||||||
assertThat(acceptedGameAcquierView.uuid()).isEqualByComparingTo(game.uuid());
|
assertThat(acceptedGameAcquierView.uuid()).isEqualByComparingTo(game.uuid());
|
||||||
@ -160,7 +160,7 @@ public class GameProposalTests {
|
|||||||
assertThat(acceptedGameIssuerView.opponentName()).isEqualToIgnoringCase(acquier);
|
assertThat(acceptedGameIssuerView.opponentName()).isEqualToIgnoringCase(acquier);
|
||||||
assertThat(acceptedGameIssuerView.opponentColor()).isEqualByComparingTo(acquierColor);
|
assertThat(acceptedGameIssuerView.opponentColor()).isEqualByComparingTo(acquierColor);
|
||||||
assertThat(acceptedGameIssuerView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
|
assertThat(acceptedGameIssuerView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
|
||||||
assertThat(acceptedGameIssuerView.previousMove()).isEmpty();
|
assertThat(acceptedGameIssuerView.previousMove()).isNull();
|
||||||
assertThat(acceptedGameIssuerView.moveNumber() == 0);
|
assertThat(acceptedGameIssuerView.moveNumber() == 0);
|
||||||
assertThat(acceptedGameIssuerView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
assertThat(acceptedGameIssuerView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||||
assertThat(acceptedGameIssuerView.uuid()).isEqualByComparingTo(game.uuid());
|
assertThat(acceptedGameIssuerView.uuid()).isEqualByComparingTo(game.uuid());
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
package djmil.cordacheckers.cordaclient;
|
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.assertThatNoException;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.naming.InvalidNameException;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@ -24,33 +28,77 @@ public class RankingTests {
|
|||||||
final String player1 = "kumar";
|
final String player1 = "kumar";
|
||||||
final String player2 = "bobik";
|
final String player2 = "bobik";
|
||||||
|
|
||||||
|
final static Stone WHITE_MAN = new Stone(Stone.Color.WHITE, Stone.Type.MAN);
|
||||||
|
final static Stone WHITE_KING = new Stone(Stone.Color.WHITE, Stone.Type.KING);
|
||||||
|
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> board1 = Map.ofEntries(
|
||||||
|
Map.entry(10, BLACK_KING),
|
||||||
|
Map.entry(7, WHITE_KING)
|
||||||
|
);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testGlobalRanking() {
|
void testSurrender() throws InvalidNameException {
|
||||||
final var hiCustodian = holdingIdentityResolver.getCustodian();
|
final var hiCustodian = holdingIdentityResolver.getCustodian();
|
||||||
assertThat(hiCustodian).isNotNull();
|
assertThat(hiCustodian).isNotNull();
|
||||||
|
|
||||||
final List<Rank> liderboard1 = cordaClient.fetchRanking(hiCustodian);
|
final Map<String, Rank> liderboard1 = cordaClient.fetchRanking(hiCustodian);
|
||||||
|
|
||||||
final var hiWinner = holdingIdentityResolver.getByUsername(player1);
|
final var hiWinner = holdingIdentityResolver.getByUsername(player1);
|
||||||
final var hiLooser = holdingIdentityResolver.getByUsername(player2);
|
final var hiLooser = holdingIdentityResolver.getByUsername(player2);
|
||||||
|
final var winnerName = hiWinner.getName();
|
||||||
|
final var losserName = hiLooser.getName();
|
||||||
|
|
||||||
final GameState game = cordaClient.gameProposalCreate(
|
final GameState game = cordaClient.gameProposalCreate(hiWinner, hiLooser, Stone.Color.WHITE,
|
||||||
hiWinner, hiLooser, Stone.Color.WHITE, "GameBoard GLOBAL_RANKING test");
|
"GameBoard GLOBAL_RANKING surrender test");
|
||||||
|
|
||||||
cordaClient.gameProposalAccept(hiLooser, game.uuid());
|
cordaClient.gameProposalAccept(hiLooser, game.uuid());
|
||||||
cordaClient.gameBoardSurrender(hiLooser, game.uuid());
|
cordaClient.gameBoardSurrender(hiLooser, game.uuid());
|
||||||
|
|
||||||
final List<Rank> liderboard2 = cordaClient.fetchRanking(hiCustodian);
|
final Map<String, Rank> liderboard2 = cordaClient.fetchRanking(hiCustodian);
|
||||||
|
|
||||||
System.out.println(liderboard1);
|
assertThat(liderboard1.get(winnerName).gamesWon() +1 == liderboard2.get(winnerName).gamesWon() );
|
||||||
System.out.println(liderboard2);
|
assertThat(liderboard1.get(winnerName).gamesPlayed() +1 == liderboard2.get(winnerName).gamesPlayed());
|
||||||
|
|
||||||
|
assertThat(liderboard1.get(losserName).gamesWon() == liderboard2.get(losserName).gamesWon() );
|
||||||
|
assertThat(liderboard1.get(losserName).gamesPlayed() +1 == liderboard2.get(losserName).gamesPlayed());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testVictory() throws InvalidNameException {
|
||||||
|
final var hiCustodian = holdingIdentityResolver.getCustodian();
|
||||||
|
assertThat(hiCustodian).isNotNull();
|
||||||
|
|
||||||
|
final Map<String, Rank> liderboard1 = cordaClient.fetchRanking(hiCustodian);
|
||||||
|
|
||||||
|
final var hiWinner = holdingIdentityResolver.getByUsername(player2);
|
||||||
|
final var hiLooser = holdingIdentityResolver.getByUsername(player1);
|
||||||
|
final var winnerName = hiWinner.getName();
|
||||||
|
final var losserName = hiLooser.getName();
|
||||||
|
|
||||||
|
final GameState game = cordaClient.gameProposalCreate(hiWinner, hiLooser, Stone.Color.BLACK,
|
||||||
|
board1, "GameBoard GLOBAL_RANKING victory test");
|
||||||
|
|
||||||
|
cordaClient.gameProposalAccept(hiLooser, game.uuid());
|
||||||
|
cordaClient.gameBoardMove(hiWinner, game.uuid(), Arrays.asList(7, 14), null);
|
||||||
|
|
||||||
|
final Map<String, Rank> liderboard2 = cordaClient.fetchRanking(hiCustodian);
|
||||||
|
|
||||||
|
assertThat(liderboard1.get(winnerName).gamesWon() +1 == liderboard2.get(winnerName).gamesWon() );
|
||||||
|
assertThat(liderboard1.get(winnerName).gamesPlayed() +1 == liderboard2.get(winnerName).gamesPlayed());
|
||||||
|
|
||||||
|
assertThat(liderboard1.get(losserName).gamesWon() == liderboard2.get(losserName).gamesWon() );
|
||||||
|
assertThat(liderboard1.get(losserName).gamesPlayed() +1 == liderboard2.get(losserName).gamesPlayed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testIndividualRanking() {
|
void testIndividualRanking() {
|
||||||
final var hiCustodian = holdingIdentityResolver.getByUsername(player2);
|
final var hiCustodian = holdingIdentityResolver.getByUsername(player2);
|
||||||
final List<Rank> liderboard = cordaClient.fetchRanking(hiCustodian);
|
|
||||||
System.out.println(liderboard);
|
assertThatNoException().isThrownBy( () ->
|
||||||
|
cordaClient.fetchRanking(hiCustodian)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,20 +8,30 @@ import net.corda.v5.membership.NotaryInfo;
|
|||||||
|
|
||||||
public class VNode {
|
public class VNode {
|
||||||
static final String CHECKERS = "Checkers"; // O aka Organization
|
static final String CHECKERS = "Checkers"; // O aka Organization
|
||||||
|
static final String PLAYER = "Player"; // OU aka OrganizationUnit
|
||||||
static final String CUSTODIAN = "Custodian"; // OU aka OrganizationUnit
|
static final String CUSTODIAN = "Custodian"; // OU aka OrganizationUnit
|
||||||
static final String NOTARY = "Notary"; // OU aka OrganizationUnit
|
static final String NOTARY = "Notary"; // OU aka OrganizationUnit
|
||||||
|
|
||||||
@CordaInject
|
@CordaInject
|
||||||
MemberLookup memberLookup;
|
MemberLookup memberLookup;
|
||||||
|
|
||||||
|
public static boolean isCordaCherckersPlayer(MemberInfo memberInfo) {
|
||||||
|
final MemberX500Name memberName = memberInfo.getName();
|
||||||
|
|
||||||
|
return memberName.getOrganization().equals(CHECKERS) &&
|
||||||
|
memberName.getOrganizationUnit().equals(PLAYER);
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isCordaCherckersCustodian(MemberInfo memberInfo) {
|
public static boolean isCordaCherckersCustodian(MemberInfo memberInfo) {
|
||||||
final MemberX500Name memberName = memberInfo.getName();
|
final MemberX500Name memberName = memberInfo.getName();
|
||||||
|
|
||||||
return memberName.getOrganization().equals(CHECKERS) &&
|
return memberName.getOrganization().equals(CHECKERS) &&
|
||||||
memberName.getOrganizationUnit().equals(CUSTODIAN);
|
memberName.getOrganizationUnit().equals(CUSTODIAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isCordaCherckersNotary(NotaryInfo notaryInfo) {
|
public static boolean isCordaCherckersNotary(NotaryInfo notaryInfo) {
|
||||||
final MemberX500Name memberName = notaryInfo.getName();
|
final MemberX500Name memberName = notaryInfo.getName();
|
||||||
|
|
||||||
return memberName.getOrganization().equals(CHECKERS) &&
|
return memberName.getOrganization().equals(CHECKERS) &&
|
||||||
memberName.getOrganizationUnit().equals(NOTARY);
|
memberName.getOrganizationUnit().equals(NOTARY);
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,36 @@
|
|||||||
package djmil.cordacheckers.gameresult;
|
package djmil.cordacheckers.gameresult;
|
||||||
|
|
||||||
public class Rank {
|
public class Rank {
|
||||||
public final String name;
|
private Integer gamesPlayed;
|
||||||
public final Integer gamesPlayed;
|
private Integer gamesWon;
|
||||||
public final Integer gamesWon;
|
|
||||||
|
|
||||||
// Serialisation service requires a default constructor
|
// Serialisation service requires a default constructor
|
||||||
Rank() {
|
public Rank() {
|
||||||
name = null;
|
gamesPlayed = 0;
|
||||||
gamesPlayed = null;
|
gamesWon = 0;
|
||||||
gamesWon = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rank(String name, Integer gamesPlayed, Integer gamesWon) {
|
public Rank(Integer gamesPlayed, Integer gamesWon) {
|
||||||
this.name = name;
|
|
||||||
this.gamesPlayed = gamesPlayed;
|
this.gamesPlayed = gamesPlayed;
|
||||||
this.gamesWon = gamesWon;
|
this.gamesWon = gamesWon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rank gamePlayed() {
|
||||||
|
gamesPlayed++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rank gameWon() {
|
||||||
|
gamesWon++;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGamesPlayed() {
|
||||||
|
return gamesPlayed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getGamesWon() {
|
||||||
|
return gamesWon;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package djmil.cordacheckers.gameresult;
|
package djmil.cordacheckers.gameresult;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -9,12 +8,13 @@ import java.util.stream.Collectors;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import djmil.cordacheckers.VNode;
|
||||||
import djmil.cordacheckers.states.GameResultState;
|
import djmil.cordacheckers.states.GameResultState;
|
||||||
import net.corda.v5.application.flows.ClientRequestBody;
|
import net.corda.v5.application.flows.ClientRequestBody;
|
||||||
import net.corda.v5.application.flows.ClientStartableFlow;
|
import net.corda.v5.application.flows.ClientStartableFlow;
|
||||||
import net.corda.v5.application.flows.CordaInject;
|
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.marshalling.JsonMarshallingService;
|
||||||
|
import net.corda.v5.application.membership.MemberLookup;
|
||||||
import net.corda.v5.base.annotations.Suspendable;
|
import net.corda.v5.base.annotations.Suspendable;
|
||||||
import net.corda.v5.ledger.utxo.UtxoLedgerService;
|
import net.corda.v5.ledger.utxo.UtxoLedgerService;
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ public class RankingFlow implements ClientStartableFlow {
|
|||||||
public JsonMarshallingService jsonMarshallingService;
|
public JsonMarshallingService jsonMarshallingService;
|
||||||
|
|
||||||
@CordaInject
|
@CordaInject
|
||||||
public FlowEngine flowEngine;
|
public MemberLookup memberLookup;
|
||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
@Override
|
@Override
|
||||||
@ -37,27 +37,23 @@ public class RankingFlow implements ClientStartableFlow {
|
|||||||
try {
|
try {
|
||||||
final List<GameResultState> gameStateResutList = getGameResultsList();
|
final List<GameResultState> gameStateResutList = getGameResultsList();
|
||||||
|
|
||||||
Map<String, Integer> won = new HashMap<>();
|
Map<String, Rank> leaderboard = newLeaderboard();
|
||||||
for (GameResultState gs : gameStateResutList) {
|
for (GameResultState gs : gameStateResutList) {
|
||||||
final var winner = gs.getWinnerName().getCommonName();
|
final var winner = gs.getWinnerName().getCommonName();
|
||||||
won.put(winner, won.getOrDefault(winner, 0) +1);
|
if (winner != null)
|
||||||
}
|
leaderboard.put(winner, leaderboard.get(winner).gameWon() );
|
||||||
|
|
||||||
|
final var blackPlayer = gs.getBlackPlayer().getCommonName();
|
||||||
|
leaderboard.put(blackPlayer, leaderboard.get(blackPlayer).gamePlayed() );
|
||||||
|
|
||||||
Map<String, Integer> played = new HashMap<>(won);
|
final var whitePlayer = gs.getWhitePlayer().getCommonName();
|
||||||
for (GameResultState gs : gameStateResutList) {
|
leaderboard.put(whitePlayer, leaderboard.get(whitePlayer).gamePlayed() );
|
||||||
final var looseer = gs.getLooserName().getCommonName();
|
|
||||||
played.put(looseer, played.getOrDefault(looseer, 0) +1);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Rank> board = new LinkedList<Rank>();
|
|
||||||
for (String name : played.keySet()) {
|
|
||||||
board.add(new Rank(name, played.getOrDefault(name, 0), won.getOrDefault(name, 0)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RankingFlowResponce(board)
|
return new RankingFlowResponce(leaderboard)
|
||||||
.toJsonEncodedString(jsonMarshallingService);
|
.toJsonEncodedString(jsonMarshallingService);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.warn("Exception during processing " + requestBody + " request: " + e.getMessage());
|
log.warn(requestBody + " [ERROR] " +e.toString());
|
||||||
return new RankingFlowResponce(e)
|
return new RankingFlowResponce(e)
|
||||||
.toJsonEncodedString(jsonMarshallingService);
|
.toJsonEncodedString(jsonMarshallingService);
|
||||||
}
|
}
|
||||||
@ -72,4 +68,16 @@ public class RankingFlow implements ClientStartableFlow {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
Map<String, Rank> newLeaderboard() {
|
||||||
|
Map<String, Rank> leaderboard = new HashMap<>();
|
||||||
|
|
||||||
|
memberLookup.lookup()
|
||||||
|
.stream()
|
||||||
|
.filter(member -> VNode.isCordaCherckersPlayer(member) )
|
||||||
|
.forEach(member -> leaderboard.put(member.getName().getCommonName(), new Rank()) );
|
||||||
|
|
||||||
|
return leaderboard;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package djmil.cordacheckers.gameresult;
|
package djmil.cordacheckers.gameresult;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.corda.v5.application.marshalling.JsonMarshallingService;
|
import net.corda.v5.application.marshalling.JsonMarshallingService;
|
||||||
|
|
||||||
public class RankingFlowResponce {
|
public class RankingFlowResponce {
|
||||||
public final List<Rank> successStatus;
|
public final Map<String, Rank> successStatus;
|
||||||
public final String failureStatus;
|
public final String failureStatus;
|
||||||
|
|
||||||
public RankingFlowResponce(List<Rank> success) {
|
public RankingFlowResponce(Map<String, Rank> success) {
|
||||||
this.successStatus = success;
|
this.successStatus = success;
|
||||||
this.failureStatus = null;
|
this.failureStatus = null;
|
||||||
}
|
}
|
||||||
@ -21,5 +21,5 @@ public class RankingFlowResponce {
|
|||||||
public String toJsonEncodedString(JsonMarshallingService jsonMarshallingService) {
|
public String toJsonEncodedString(JsonMarshallingService jsonMarshallingService) {
|
||||||
return jsonMarshallingService.format(this);
|
return jsonMarshallingService.format(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user