package net.olemartin.domain; import com.google.gson.*; import net.olemartin.tools.rating.EloRatingSystem; import org.neo4j.ogm.annotation.GraphId; import org.neo4j.ogm.annotation.NodeEntity; import org.neo4j.ogm.annotation.Relationship; import java.lang.reflect.Type; import java.util.HashSet; import java.util.Set; import static java.util.Optional.ofNullable; import static java.util.stream.Collectors.toList; @NodeEntity public class Tournament { @GraphId private Long id; private String name; @Relationship(type = "PLAYS_IN", direction = Relationship.INCOMING) private Set<Player> players = new HashSet<>();; @Relationship(type = "ROUND_OF", direction = Relationship.OUTGOING) private Set<Round> rounds = new HashSet<>();; @Relationship(type = "CURRENT_ROUND", direction = Relationship.UNDIRECTED) private Round currentRound; private boolean finished; private String engine; @SuppressWarnings("UnusedDeclaration") private Tournament() { } public Tournament(String name) { this.name = name; } public void calculateRatings(EloRatingSystem system) { for (Round round : rounds.stream().sorted().collect(toList())) { for (Match match : round.getMatches().stream().filter(m -> !m.isWalkover()).collect(toList())) { if (match.getResult() == Result.REMIS) { Person white = match.getWhite().getPerson(); Person black = match.getBlack().getPerson(); white.setCurrentRating( system.getNewRating( white.getCurrentRating(), black.getCurrentRating(), PlayerResult.DRAW)); black.setCurrentRating( system.getNewRating( black.getCurrentRating(), white.getCurrentRating(), PlayerResult.DRAW)); } else { Person winner = match.getWinner().getPerson(); Person looser = match.getLooser().getPerson(); winner.setCurrentRating( system.getNewRating( winner.getCurrentRating(), looser.getCurrentRating(), PlayerResult.WIN)); looser.setCurrentRating( system.getNewRating( looser.getCurrentRating(), winner.getCurrentRating(), PlayerResult.LOSS)); } } } } public String getName() { return name; } public void addPlayer(Player player) { players.add(player); } public Set<Player> getPlayers() { return players; } public void addRound(Round round) { rounds.add(round); } public boolean isCurrentRoundFinished() { return currentRound == null || currentRound.isFinished(); } public Set<Round> getRounds() { return rounds; } public void setFinished(boolean finished) { this.finished = finished; } public boolean isFinished() { return finished; } public Long getId() { return id; } public String getEngine() { return engine; } public Tournament setEngine(String engine) { this.engine = engine; return this; } public Round startNewRound() { int currentRoundNumber = ofNullable(currentRound).map(Round::getNumber).orElse(0); this.currentRound = new Round(currentRoundNumber + 1); addRound(this.currentRound); return this.currentRound; } public Round getCurrentRound() { return currentRound; } public static class TournamentSerializer implements JsonSerializer<Tournament> { @Override public JsonElement serialize(Tournament tournament, Type typeOfSrc, JsonSerializationContext context) { JsonSerializer<Player> playerSerializer = new Player.PlayerSerializer(); JsonSerializer<Round> roundSerializer = new Round.RoundSerializer(); JsonObject root = new JsonObject(); root.addProperty("id", tournament.id); root.addProperty("name", tournament.name); JsonArray playerArray = new JsonArray(); tournament.players.stream().sorted().forEach(player -> playerArray.add(playerSerializer.serialize(player, Player.class, context))); root.add("players", playerArray); JsonArray roundsArray = new JsonArray(); tournament.rounds.stream().sorted().forEach( round -> roundsArray.add(roundSerializer.serialize(round, Round.class, context))); root.add("rounds", roundsArray); if (tournament.currentRound != null) { root.add("currentRound", roundSerializer.serialize(tournament.currentRound, Round.class, context)); } root.addProperty("finished", tournament.finished); return root; } } }