Files
swiss-backend/src/main/java/nl/connectedit/swiss/service/TournamentPlayService.java
Michel ten Voorde 45c50924bc
All checks were successful
Gitea/swiss-backend/pipeline/head This commit looks good
Invallers
2025-09-23 23:21:18 +02:00

400 lines
13 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.dto.TournamentPlayerSubstitutionDto;
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())));
}
}
public Tournament playerSubstitutions(Tournament tournament, Long playerId, TournamentPlayerSubstitutionDto[] substitutions) {
var tournamentPlayer = getTournamentPlayer(tournament, playerId);
var playerSubstitutions = new ArrayList<TournamentPlayerSubstitution>();
for (var substitution : substitutions) {
var playerSubstitution = new TournamentPlayerSubstitution();
var eventType = EventType.valueOf(substitution.getEvent());
var event = getEventByType(tournament, eventType);
playerSubstitution.setEvent(event);
TournamentPlayer substitute;
if (substitution.getSubstitute() != null) {
substitute = getTournamentPlayerById(tournament, substitution.getSubstitute());
} else {
substitute = null;
}
playerSubstitution.setSubstitute(substitute);
playerSubstitutions.add(playerSubstitution);
}
tournamentPlayer.setSubstitutions(playerSubstitutions);
tournamentRepository.save(tournament);
return tournament;
}
private Event getEvent(Tournament tournament, Long eventId) {
for (var event : tournament.getEvents()) {
if (event.getId().equals(eventId)) {
return event;
}
}
return null;
}
private Event getEventByType(Tournament tournament, EventType eventType) {
for (var event : tournament.getEvents()) {
if (event.getType().equals(eventType)) {
return event;
}
}
return null;
}
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 = getTournamentPlayer(tournament, counter);
countingPlayer.setCounting(true);
match.setCounter(countingPlayer.getPlayer());
tournamentRepository.save(tournament);
return tournament;
}
private TournamentPlayer getTournamentPlayerById(Tournament tournament, Long id) {
for (var tournamentPlayer : tournament.getTournamentPlayers()) {
if (id.equals(tournamentPlayer.getId())) {
return tournamentPlayer;
}
}
return null;
}
private TournamentPlayer getTournamentPlayer(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 = getTournamentPlayer(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 = getTournamentPlayer(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);
}
}