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
|
||||
public List<Rank> fetchRanking(HoldingIdentity holdingIdentity) {
|
||||
public Map<String, Rank> fetchRanking(HoldingIdentity holdingIdentity) {
|
||||
final RequestBody requestBody = new RequestBody(
|
||||
"ranking-" +UUID.randomUUID(),
|
||||
"djmil.cordacheckers.gameresult.RankingFlow",
|
||||
|
@ -1,7 +1,6 @@
|
||||
package djmil.cordacheckers.cordaclient.dao;
|
||||
|
||||
public record Rank(
|
||||
String name,
|
||||
Integer gamesPlayed,
|
||||
Integer gamesWon
|
||||
) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
package djmil.cordacheckers.cordaclient.dao.flow.arguments;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import djmil.cordacheckers.cordaclient.dao.Rank;
|
||||
|
||||
public record RspRankList(
|
||||
List<Rank> successStatus,
|
||||
String failureStatus) implements Rsp<List<Rank>> {
|
||||
Map<String, Rank> successStatus,
|
||||
String failureStatus) implements Rsp<Map<String, Rank>> {
|
||||
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ public class GameProposalTests {
|
||||
assertThat(acceptedGameAcquierView.opponentName()).isEqualToIgnoringCase(issuer);
|
||||
assertThat(acceptedGameAcquierView.opponentColor()).isEqualByComparingTo(acquierColor.opposite());
|
||||
assertThat(acceptedGameAcquierView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
|
||||
assertThat(acceptedGameAcquierView.previousMove()).isEmpty();
|
||||
assertThat(acceptedGameAcquierView.previousMove()).isNull();
|
||||
assertThat(acceptedGameAcquierView.moveNumber() == 0);
|
||||
assertThat(acceptedGameAcquierView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_YOU);
|
||||
assertThat(acceptedGameAcquierView.uuid()).isEqualByComparingTo(game.uuid());
|
||||
@ -160,7 +160,7 @@ public class GameProposalTests {
|
||||
assertThat(acceptedGameIssuerView.opponentName()).isEqualToIgnoringCase(acquier);
|
||||
assertThat(acceptedGameIssuerView.opponentColor()).isEqualByComparingTo(acquierColor);
|
||||
assertThat(acceptedGameIssuerView.board()).containsAllEntriesOf(GameState.defaultGameBoard);
|
||||
assertThat(acceptedGameIssuerView.previousMove()).isEmpty();
|
||||
assertThat(acceptedGameIssuerView.previousMove()).isNull();
|
||||
assertThat(acceptedGameIssuerView.moveNumber() == 0);
|
||||
assertThat(acceptedGameIssuerView.status()).isEqualByComparingTo(Status.GAME_BOARD_WAIT_FOR_OPPONENT);
|
||||
assertThat(acceptedGameIssuerView.uuid()).isEqualByComparingTo(game.uuid());
|
||||
|
@ -1,8 +1,12 @@
|
||||
package djmil.cordacheckers.cordaclient;
|
||||
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
@ -24,33 +28,77 @@ public class RankingTests {
|
||||
final String player1 = "kumar";
|
||||
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
|
||||
void testGlobalRanking() {
|
||||
void testSurrender() throws InvalidNameException {
|
||||
final var hiCustodian = holdingIdentityResolver.getCustodian();
|
||||
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 hiLooser = holdingIdentityResolver.getByUsername(player2);
|
||||
final var winnerName = hiWinner.getName();
|
||||
final var losserName = hiLooser.getName();
|
||||
|
||||
final GameState game = cordaClient.gameProposalCreate(
|
||||
hiWinner, hiLooser, Stone.Color.WHITE, "GameBoard GLOBAL_RANKING test");
|
||||
final GameState game = cordaClient.gameProposalCreate(hiWinner, hiLooser, Stone.Color.WHITE,
|
||||
"GameBoard GLOBAL_RANKING surrender test");
|
||||
|
||||
cordaClient.gameProposalAccept(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);
|
||||
System.out.println(liderboard2);
|
||||
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
|
||||
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
|
||||
void testIndividualRanking() {
|
||||
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 {
|
||||
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 NOTARY = "Notary"; // OU aka OrganizationUnit
|
||||
|
||||
@CordaInject
|
||||
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) {
|
||||
final MemberX500Name memberName = memberInfo.getName();
|
||||
|
||||
return memberName.getOrganization().equals(CHECKERS) &&
|
||||
memberName.getOrganizationUnit().equals(CUSTODIAN);
|
||||
}
|
||||
|
||||
public static boolean isCordaCherckersNotary(NotaryInfo notaryInfo) {
|
||||
final MemberX500Name memberName = notaryInfo.getName();
|
||||
|
||||
return memberName.getOrganization().equals(CHECKERS) &&
|
||||
memberName.getOrganizationUnit().equals(NOTARY);
|
||||
}
|
||||
|
@ -1,20 +1,36 @@
|
||||
package djmil.cordacheckers.gameresult;
|
||||
|
||||
public class Rank {
|
||||
public final String name;
|
||||
public final Integer gamesPlayed;
|
||||
public final Integer gamesWon;
|
||||
private Integer gamesPlayed;
|
||||
private Integer gamesWon;
|
||||
|
||||
// Serialisation service requires a default constructor
|
||||
Rank() {
|
||||
name = null;
|
||||
gamesPlayed = null;
|
||||
gamesWon = null;
|
||||
public Rank() {
|
||||
gamesPlayed = 0;
|
||||
gamesWon = 0;
|
||||
}
|
||||
|
||||
public Rank(String name, Integer gamesPlayed, Integer gamesWon) {
|
||||
this.name = name;
|
||||
public Rank(Integer gamesPlayed, Integer gamesWon) {
|
||||
this.gamesPlayed = gamesPlayed;
|
||||
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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@ -9,12 +8,13 @@ import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import djmil.cordacheckers.VNode;
|
||||
import djmil.cordacheckers.states.GameResultState;
|
||||
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.application.membership.MemberLookup;
|
||||
import net.corda.v5.base.annotations.Suspendable;
|
||||
import net.corda.v5.ledger.utxo.UtxoLedgerService;
|
||||
|
||||
@ -29,7 +29,7 @@ public class RankingFlow implements ClientStartableFlow {
|
||||
public JsonMarshallingService jsonMarshallingService;
|
||||
|
||||
@CordaInject
|
||||
public FlowEngine flowEngine;
|
||||
public MemberLookup memberLookup;
|
||||
|
||||
@Suspendable
|
||||
@Override
|
||||
@ -37,27 +37,23 @@ public class RankingFlow implements ClientStartableFlow {
|
||||
try {
|
||||
final List<GameResultState> gameStateResutList = getGameResultsList();
|
||||
|
||||
Map<String, Integer> won = new HashMap<>();
|
||||
Map<String, Rank> leaderboard = newLeaderboard();
|
||||
for (GameResultState gs : gameStateResutList) {
|
||||
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() );
|
||||
|
||||
final var whitePlayer = gs.getWhitePlayer().getCommonName();
|
||||
leaderboard.put(whitePlayer, leaderboard.get(whitePlayer).gamePlayed() );
|
||||
}
|
||||
|
||||
Map<String, Integer> played = new HashMap<>(won);
|
||||
for (GameResultState gs : gameStateResutList) {
|
||||
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);
|
||||
} catch (Exception e) {
|
||||
log.warn("Exception during processing " + requestBody + " request: " + e.getMessage());
|
||||
log.warn(requestBody + " [ERROR] " +e.toString());
|
||||
return new RankingFlowResponce(e)
|
||||
.toJsonEncodedString(jsonMarshallingService);
|
||||
}
|
||||
@ -72,4 +68,16 @@ public class RankingFlow implements ClientStartableFlow {
|
||||
.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;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import net.corda.v5.application.marshalling.JsonMarshallingService;
|
||||
|
||||
public class RankingFlowResponce {
|
||||
public final List<Rank> successStatus;
|
||||
public final Map<String, Rank> successStatus;
|
||||
public final String failureStatus;
|
||||
|
||||
public RankingFlowResponce(List<Rank> success) {
|
||||
public RankingFlowResponce(Map<String, Rank> success) {
|
||||
this.successStatus = success;
|
||||
this.failureStatus = null;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user