package app.data.service;
|
|
|
|
import app.data.bean.CalculatedMatch;
|
|
import app.data.bean.PlayerForTable;
|
|
import app.data.entity.Matchday;
|
|
import app.data.entity.Player;
|
|
import app.data.repository.PlayerRepository;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.stereotype.Service;
|
|
import org.vaadin.artur.helpers.CrudService;
|
|
|
|
import java.util.*;
|
|
import java.util.function.Function;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
|
|
@Service
|
|
public class PlayerService extends CrudService<Player, Integer> {
|
|
|
|
private final PlayerRepository repository;
|
|
|
|
private final MatchdayService matchdayService;
|
|
private final MatchService matchService;
|
|
|
|
public PlayerService(@Autowired PlayerRepository repository, @Autowired MatchdayService matchdayService, @Autowired MatchService matchService) {
|
|
this.repository = repository;
|
|
this.matchdayService = matchdayService;
|
|
this.matchService = matchService;
|
|
}
|
|
|
|
@Override
|
|
protected PlayerRepository getRepository() {
|
|
return repository;
|
|
}
|
|
|
|
public List<PlayerForTable> getPlayersForTable(Matchday matchday) {
|
|
return new PlayerForTableProvider(matchday).getPlayersForTableSorted();
|
|
}
|
|
|
|
private class PlayerForTableProvider {
|
|
List<Matchday> matchdays = new ArrayList<>();
|
|
List<CalculatedMatch> calculatedMatches = new ArrayList<>();
|
|
List<Player> players = repository.findAll();
|
|
|
|
public PlayerForTableProvider(Matchday matchday) {
|
|
matchdays.addAll(matchdayService.getMatchdaysSorted(matchday.getSeason()).stream()
|
|
.filter(matchdayToFilter -> matchdayToFilter.getNumber() <= matchday.getNumber())
|
|
.collect(Collectors.toList()));
|
|
|
|
calculatedMatches.addAll(matchdays.stream()
|
|
.flatMap((Function<Matchday, Stream<CalculatedMatch>>) matchdayToMap -> matchService.getCalculatedMatches(matchdayToMap).stream())
|
|
.collect(Collectors.toList()));
|
|
}
|
|
|
|
private List<PlayerForTable> getPlayersForTableSorted() {
|
|
List<PlayerForTable> playerForTableList = players.stream()
|
|
.map(this::getPlayerForTable)
|
|
.sorted(Comparator.comparingDouble(PlayerForTable::getGamePointsForSelf).reversed())
|
|
.sorted(Comparator.comparingDouble(PlayerForTable::getGamePointDiff).reversed())
|
|
.sorted(Comparator.comparingInt(PlayerForTable::getMatchPoints).reversed())
|
|
.collect(Collectors.toList());
|
|
int offset = 0;
|
|
PlayerForTable lastPlayer;
|
|
PlayerForTable currentPlayer;
|
|
for (int i = 0; i < playerForTableList.size(); i++) {
|
|
currentPlayer = playerForTableList.get(i);
|
|
if (i > 0) {
|
|
lastPlayer = playerForTableList.get(i - 1);
|
|
// TODO: add direct comparison below
|
|
if (Objects.equals(currentPlayer.getMatchPoints(), lastPlayer.getMatchPoints())
|
|
&& Objects.equals(currentPlayer.getGamePointsForSelf(), lastPlayer.getGamePointsForSelf())
|
|
&& Objects.equals(currentPlayer.getGamePointsForOpponents(), lastPlayer.getGamePointsForOpponents())) {
|
|
offset += 1;
|
|
} else {
|
|
offset = 0;
|
|
}
|
|
}
|
|
currentPlayer.setPlace(i + 1 - offset);
|
|
currentPlayer.setPlaceString(offset == 0 ? String.valueOf(i + 1) : "");
|
|
}
|
|
// TODO: add diff to last matchday
|
|
return playerForTableList;
|
|
}
|
|
|
|
private PlayerForTable getPlayerForTable(Player player) {
|
|
List<CalculatedMatch> matchesAsPlayer1 = getMatchesAsPlayer1(player);
|
|
List<CalculatedMatch> matchesAsPlayer2 = getMatchesAsPlayer2(player);
|
|
|
|
Map<WinState, List<CalculatedMatch>> map = getWinStateLists(matchesAsPlayer1, matchesAsPlayer2);
|
|
|
|
int amountOfMatchesWon = map.get(WinState.WON).size();
|
|
int amountOfMatchesDrawn = map.get(WinState.DRAWN).size();
|
|
int amountOfMatchesLost = map.get(WinState.LOST).size();
|
|
|
|
int amountOfMatches = amountOfMatchesWon + amountOfMatchesDrawn + amountOfMatchesLost;
|
|
|
|
int matchPoints = amountOfMatchesWon * 2 + amountOfMatchesDrawn;
|
|
|
|
double gamePointsForSelf = 0;
|
|
gamePointsForSelf += matchesAsPlayer1.stream().mapToDouble(CalculatedMatch::getScore1).sum();
|
|
gamePointsForSelf += matchesAsPlayer2.stream().mapToDouble(CalculatedMatch::getScore2).sum();
|
|
|
|
double gamePointsForOpponents = 0;
|
|
gamePointsForOpponents += matchesAsPlayer1.stream().mapToDouble(CalculatedMatch::getScore2).sum();
|
|
gamePointsForOpponents += matchesAsPlayer2.stream().mapToDouble(CalculatedMatch::getScore1).sum();
|
|
|
|
double gamePointDiff = gamePointsForSelf - gamePointsForOpponents;
|
|
|
|
return new PlayerForTable(player,
|
|
matchPoints,
|
|
amountOfMatches,
|
|
amountOfMatchesWon,
|
|
amountOfMatchesDrawn,
|
|
amountOfMatchesLost,
|
|
gamePointsForSelf,
|
|
gamePointsForOpponents,
|
|
gamePointDiff);
|
|
}
|
|
|
|
private List<CalculatedMatch> getMatchesAsPlayer1(Player player) {
|
|
return calculatedMatches.stream()
|
|
.filter(match -> match.getPlayer1().equals(player))
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
private List<CalculatedMatch> getMatchesAsPlayer2(Player player) {
|
|
return calculatedMatches.stream()
|
|
.filter(match -> match.getPlayer2().equals(player))
|
|
.collect(Collectors.toList());
|
|
}
|
|
|
|
private Map<WinState, List<CalculatedMatch>> getWinStateLists(List<CalculatedMatch> matchesAsPlayer1, List<CalculatedMatch> matchesAsPlayer2) {
|
|
Map<WinState, List<CalculatedMatch>> map = new HashMap<>();
|
|
map.put(WinState.WON, new ArrayList<>());
|
|
map.put(WinState.DRAWN, new ArrayList<>());
|
|
map.put(WinState.LOST, new ArrayList<>());
|
|
|
|
for (CalculatedMatch match : matchesAsPlayer1) {
|
|
if (match.getScore1() > match.getScore2()) {
|
|
map.get(WinState.WON).add(match);
|
|
continue;
|
|
}
|
|
if (match.getScore1() < match.getScore2()) {
|
|
map.get(WinState.LOST).add(match);
|
|
continue;
|
|
}
|
|
if (match.getScore1() > 0) {
|
|
map.get(WinState.DRAWN).add(match);
|
|
}
|
|
}
|
|
|
|
for (CalculatedMatch match : matchesAsPlayer2) {
|
|
if (match.getScore2() > match.getScore1()) {
|
|
map.get(WinState.WON).add(match);
|
|
continue;
|
|
}
|
|
if (match.getScore2() < match.getScore1()) {
|
|
map.get(WinState.LOST).add(match);
|
|
continue;
|
|
}
|
|
if (match.getScore2() > 0) {
|
|
map.get(WinState.DRAWN).add(match);
|
|
}
|
|
}
|
|
return map;
|
|
}
|
|
}
|
|
|
|
private enum WinState {
|
|
WON, DRAWN, LOST
|
|
}
|
|
}
|