You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

172 lines
7.3 KiB

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
}
}