All checks were successful
Gitea/swiss-backend/pipeline/head This commit looks good
343 lines
11 KiB
Java
343 lines
11 KiB
Java
package nl.connectedit.swiss.service;
|
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.extern.java.Log;
|
|
import nl.connectedit.swiss.domain.EventType;
|
|
import nl.connectedit.swiss.domain.StandingsEntry;
|
|
import nl.connectedit.swiss.domain.Status;
|
|
import nl.connectedit.swiss.domain.TournamentStatus;
|
|
import nl.connectedit.swiss.domain.entity.*;
|
|
import nl.connectedit.swiss.dto.ResultDto;
|
|
import nl.connectedit.swiss.repository.TournamentRepository;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.stream.Collectors;
|
|
|
|
import static nl.connectedit.swiss.service.ServiceUtil.*;
|
|
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
@Log
|
|
public class TournamentPlayService {
|
|
|
|
private final TournamentRepository tournamentRepository;
|
|
|
|
private final StandingsService standingsService;
|
|
|
|
public Tournament startRound(Tournament tournament, Long roundId) {
|
|
getRound(tournament, roundId).setStatus(Status.IN_PROGRESS);
|
|
tournament.setStatus(TournamentStatus.ONGOING);
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
public Tournament finishRound(Tournament tournament, Long roundId) {
|
|
getRound(tournament, roundId).setStatus(Status.FINISHED);
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
public Tournament finishGroup(Tournament tournament, Long groupId) {
|
|
var group = getGroup(tournament, groupId);
|
|
group.setStatus(Status.FINISHED);
|
|
|
|
checkForEventCompletion(tournament, group.getType());
|
|
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
private void checkForEventCompletion(Tournament tournament, EventType type) {
|
|
Group group1 = null;
|
|
Group group2 = null;
|
|
Event event = null;
|
|
|
|
for (var e : tournament.getEvents()) {
|
|
if (e.getType() == type) {
|
|
if (e.getGroups().size() != 2) {
|
|
return;
|
|
}
|
|
group1 = e.getGroups().getFirst();
|
|
if (group1.getStatus() != Status.FINISHED) {
|
|
return;
|
|
}
|
|
|
|
group2 = e.getGroups().getLast();
|
|
if (group2.getStatus() != Status.FINISHED) {
|
|
return;
|
|
}
|
|
event = e;
|
|
}
|
|
}
|
|
|
|
var finalsGroup = new Group();
|
|
finalsGroup.setName(type.getText());
|
|
finalsGroup.setType(type);
|
|
finalsGroup.setStatus(Status.IN_PROGRESS);
|
|
finalsGroup.setEvent(group1.getEvent());
|
|
|
|
var standings1 = standingsService.getStandings(group1.getRounds(), group1.getTeams());
|
|
var standings2 = standingsService.getStandings(group2.getRounds(), group2.getTeams());
|
|
|
|
var team1_1 = standings1.get(0).getTeam();
|
|
var team1_2 = standings1.get(1).getTeam();
|
|
var team2_1 = standings2.get(0).getTeam();
|
|
var team2_2 = standings2.get(1).getTeam();
|
|
|
|
team1_1.getGroups().add(finalsGroup);
|
|
team1_2.getGroups().add(finalsGroup);
|
|
team2_1.getGroups().add(finalsGroup);
|
|
team2_2.getGroups().add(finalsGroup);
|
|
|
|
finalsGroup.setTeams(List.of(team1_1, team1_2, team2_1, team2_2));
|
|
|
|
var finalsRound = new Round();
|
|
finalsRound.setGroup(finalsGroup);
|
|
finalsRound.setStatus(Status.NOT_STARTED);
|
|
finalsRound.setName("Finales");
|
|
finalsRound.setIsFinalsRound(Boolean.TRUE);
|
|
|
|
var match1 = new Match();
|
|
match1.setRound(finalsRound);
|
|
match1.setType(type);
|
|
match1.setStatus(Status.NOT_STARTED);
|
|
match1.setPlayed(false);
|
|
match1.setTeam1(standings1.get(0).getTeam());
|
|
match1.setTeam2(standings2.get(0).getTeam());
|
|
|
|
var match2 = new Match();
|
|
match2.setRound(finalsRound);
|
|
match2.setType(type);
|
|
match2.setStatus(Status.NOT_STARTED);
|
|
match2.setPlayed(false);
|
|
match2.setTeam1(standings1.get(1).getTeam());
|
|
match2.setTeam2(standings2.get(1).getTeam());
|
|
|
|
finalsRound.setMatches(List.of(match1, match2));
|
|
finalsGroup.setRounds(List.of(finalsRound));
|
|
event.getGroups().add(finalsGroup);
|
|
}
|
|
|
|
public Tournament reopenGroup(Tournament tournament, Long groupId) {
|
|
getGroup(tournament, groupId).setStatus(Status.IN_PROGRESS);
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
public Tournament newRound(Tournament tournament, Long groupId) {
|
|
var group = getGroup(tournament, groupId);
|
|
|
|
var standings = standingsService.getStandings(group.getRounds(), group.getTeams());
|
|
var remainingTeams = standings.stream()
|
|
.map(StandingsEntry::getTeam)
|
|
.collect(Collectors.toCollection(ArrayList::new));
|
|
|
|
var round = new Round();
|
|
round.setName("Ronde " + (group.getRounds().size() + 1));
|
|
round.setGroup(group);
|
|
round.setStatus(Status.NOT_STARTED);
|
|
|
|
if (remainingTeams.size() % 2 == 1) {
|
|
var playersNotToBeDrawnOut = tournament.getDrawnOutPlayers();
|
|
playersNotToBeDrawnOut.addAll(tournament.getPlayersPlayingOnlyOneEvent());
|
|
var tryPosition = remainingTeams.size() - 1;
|
|
do {
|
|
var tryDrawOutTeam = remainingTeams.get(tryPosition);
|
|
if (!playersNotToBeDrawnOut.contains(tryDrawOutTeam.getPlayer1()) && (tryDrawOutTeam.getPlayer2() == null || !playersNotToBeDrawnOut.contains(tryDrawOutTeam.getPlayer2()))) {
|
|
remainingTeams.remove(tryDrawOutTeam);
|
|
round.setDrawnOut(tryDrawOutTeam);
|
|
break;
|
|
}
|
|
tryPosition--;
|
|
} while(true);
|
|
}
|
|
|
|
var matches = tryMatches(remainingTeams, group).reversed();
|
|
|
|
for (var match : matches) {
|
|
match.setType(group.getType());
|
|
match.setStatus(Status.NOT_STARTED);
|
|
match.setPlayed(false);
|
|
match.setRound(round);
|
|
}
|
|
|
|
round.setMatches(matches);
|
|
|
|
printRound(round, standings);
|
|
|
|
group.getRounds().add(round);
|
|
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
private void printRound(Round round, List<StandingsEntry> standings) {
|
|
for (var match: round.getMatches()) {
|
|
log.info("%s - %s".formatted(
|
|
String.valueOf(standings.stream().filter(entry -> entry.getTeam().equals(match.getTeam1())).map(StandingsEntry::getPosition).findFirst().get()),
|
|
String.valueOf(standings.stream().filter(entry -> entry.getTeam().equals(match.getTeam2())).map(StandingsEntry::getPosition).findFirst().get())));
|
|
}
|
|
}
|
|
|
|
private static class ConflictInDrawException extends RuntimeException {}
|
|
|
|
private List<Match> tryMatches(List<Team> remainingTeams, Group group) {
|
|
var newMatches = new ArrayList<Match>();
|
|
if (remainingTeams.isEmpty()) {
|
|
return newMatches;
|
|
}
|
|
var newMatch = new Match();
|
|
newMatch.setTeam1(remainingTeams.getFirst());
|
|
for (var opponentIndex = 1; opponentIndex < remainingTeams.size(); opponentIndex++) {
|
|
if (!findPreviousMatchOccurence(newMatch.getTeam1(), remainingTeams.get(opponentIndex), group)) {
|
|
newMatch.setTeam2(remainingTeams.get(opponentIndex));
|
|
} else {
|
|
log.info("Wedstrijd %s - %s kwam al eerder voor.".formatted(newMatch.getTeam1().toString(), remainingTeams.get(opponentIndex).toString()));
|
|
continue;
|
|
}
|
|
var newRemainingTeams = getRemainingTeams(remainingTeams, opponentIndex);
|
|
if (newRemainingTeams.size() == 1) {
|
|
newMatches.add(newMatch);
|
|
break;
|
|
} else {
|
|
try {
|
|
newMatches.addAll(tryMatches(newRemainingTeams, group));
|
|
newMatches.add(newMatch);
|
|
break;
|
|
} catch (ConflictInDrawException ignored) {
|
|
}
|
|
}
|
|
}
|
|
if (newMatch.getTeam2() == null) {
|
|
log.info("Geen tegenstander gevonden voor %s.".formatted(newMatch.getTeam1().toString()));
|
|
throw new ConflictInDrawException();
|
|
}
|
|
|
|
return newMatches;
|
|
}
|
|
|
|
private List<Team> getRemainingTeams(List<Team> remainingTeams, int opponentIndex) {
|
|
var newRemainingTeams = new ArrayList<Team>();
|
|
for (var remainingTeamIndex = 1; remainingTeamIndex < remainingTeams.size(); remainingTeamIndex++) {
|
|
if (remainingTeamIndex == opponentIndex) continue;
|
|
newRemainingTeams.add(remainingTeams.get(remainingTeamIndex));
|
|
}
|
|
return newRemainingTeams;
|
|
}
|
|
|
|
private boolean findPreviousMatchOccurence(Team team1, Team team2, Group group) {
|
|
for (var round : group.getRounds()) {
|
|
for (var match : round.getMatches()) {
|
|
if ((Objects.equals(match.getTeam1(), team1) && Objects.equals(match.getTeam2(), team2))
|
|
|| (Objects.equals(match.getTeam1(), team2) && Objects.equals(match.getTeam2(), team1))) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public Tournament startMatch(Tournament tournament, Long matchId, Long court, Long counter) {
|
|
var match = getMatch(tournament, matchId);
|
|
match.setStatus(Status.IN_PROGRESS);
|
|
match.setStartTime(LocalDateTime.now());
|
|
match.setCourt(court);
|
|
|
|
var countingPlayer = getPlayer(tournament, counter);
|
|
countingPlayer.setCounting(true);
|
|
match.setCounter(countingPlayer.getPlayer());
|
|
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
private TournamentPlayer getPlayer(Tournament tournament, Long playerId) {
|
|
for (var tournamentPlayer : tournament.getTournamentPlayers()) {
|
|
if (playerId.equals(tournamentPlayer.getPlayer().getId())) {
|
|
return tournamentPlayer;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public Tournament stopMatch(Tournament tournament, Long matchId) {
|
|
var match = getMatch(tournament, matchId);
|
|
match.setStatus(Status.NOT_STARTED);
|
|
match.setStartTime(null);
|
|
match.setCourt(null);
|
|
|
|
var countingPlayer = getPlayer(tournament, match.getCounter().getId());
|
|
countingPlayer.setCounting(false);
|
|
match.setCounter(null);
|
|
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
public Tournament saveResult(Tournament tournament, Long matchId, ResultDto result) {
|
|
var match = getMatch(tournament, matchId);
|
|
if (match.getGames().isEmpty()) {
|
|
match.setEndTime(LocalDateTime.now());
|
|
match.setStatus(Status.FINISHED);
|
|
match.setPlayed(true);
|
|
}
|
|
match.getGames().clear();
|
|
match.getGames().addAll(resultToGames(result, match));
|
|
|
|
var counter = match.getCounter();
|
|
if (counter != null) { // match was already saved, this is a correction
|
|
var countingPlayer = getPlayer(tournament, counter.getId());
|
|
countingPlayer.setCounting(false);
|
|
countingPlayer.incrementCounts();
|
|
match.setCounter(null);
|
|
}
|
|
|
|
tournamentRepository.save(tournament);
|
|
return tournament;
|
|
}
|
|
|
|
private List<Game> resultToGames(ResultDto result, Match match) {
|
|
var games = new ArrayList<Game>();
|
|
for (var game : result.getGames()) {
|
|
if (game.getScore1() != null) {
|
|
games.add(Game.builder()
|
|
.score1(game.getScore1())
|
|
.score2(game.getScore2())
|
|
.match(match)
|
|
.build());
|
|
}
|
|
}
|
|
|
|
return games;
|
|
}
|
|
|
|
public void updatePaid(Tournament tournament, Long playerId, Boolean paid) {
|
|
var tournamentPlayer = tournament.getTournamentPlayers()
|
|
.stream()
|
|
.filter(player -> player.getPlayer().getId().equals(playerId))
|
|
.findFirst()
|
|
.get();
|
|
|
|
tournamentPlayer.setPaid(paid);
|
|
|
|
tournamentRepository.save(tournament);
|
|
}
|
|
|
|
public void updatePresent(Tournament tournament, Long playerId, Boolean present) {
|
|
var tournamentPlayer = tournament.getTournamentPlayers()
|
|
.stream()
|
|
.filter(player -> player.getPlayer().getId().equals(playerId))
|
|
.findFirst()
|
|
.get();
|
|
|
|
tournamentPlayer.setPresent(present);
|
|
|
|
tournamentRepository.save(tournament);
|
|
}
|
|
|
|
}
|