Files
swiss-backend/src/main/java/nl/connectedit/swiss/service/TournamentDivideService.java
Michel ten Voorde e89a7d4bff
All checks were successful
Gitea/swiss-backend/pipeline/head This commit looks good
Various improvements
2025-08-25 23:37:35 +02:00

166 lines
5.1 KiB
Java

package nl.connectedit.swiss.service;
import jakarta.transaction.Transactional;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
import nl.connectedit.swiss.domain.EventType;
import nl.connectedit.swiss.domain.Status;
import nl.connectedit.swiss.domain.TournamentStatus;
import nl.connectedit.swiss.domain.entity.Event;
import nl.connectedit.swiss.domain.entity.Group;
import nl.connectedit.swiss.domain.entity.Registration;
import nl.connectedit.swiss.domain.entity.Team;
import nl.connectedit.swiss.domain.entity.Tournament;
import nl.connectedit.swiss.repository.TournamentRepository;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class TournamentDivideService {
private final TournamentValidationService tournamentValidationService;
private final TournamentRepository tournamentRepository;
@Transactional
public Tournament divide(Tournament tournament) {
if (tournamentValidationService.validate(tournament).hasErrors()) {
return tournament;
}
for (var event : tournament.getEvents()) {
if ((event.getType().isDoublesEvent() && event.getRegistrations().size() >= 8)
|| (!event.getType().isDoublesEvent() && event.getRegistrations().size() >= 4)) {
divide(event);
}
}
tournament.setStatus(TournamentStatus.DIVIDED);
tournamentRepository.save(tournament);
return tournament;
}
public void divide(Event event) {
List<Registration> registrations;
if (event.getType().isDoublesEvent()) {
registrations = groupRegistrations(event.getRegistrations());
} else {
registrations = event.getRegistrations();
}
event.setGroups(new ArrayList<>());
if (registrations.size() <= 16) {
var group = getGroup(registrations, event.getType());
group.setEvent(event);
event.getGroups().add(group);
} else {
var groups = getGroups(registrations, event.getType());
groups.forEach(group -> group.setEvent(event));
event.getGroups().addAll(groups);
}
}
private List<Registration> groupRegistrations(List<Registration> registrations) {
var groupedRegistrations = new ArrayList<Registration>();
nextRegistration:
for (var registration : registrations) {
for (var groupedRegistration : groupedRegistrations) {
if (Objects.equals(groupedRegistration.getPartner(), registration.getPlayer())) {
continue nextRegistration;
}
}
groupedRegistrations.add(registration);
}
return groupedRegistrations;
}
private Group getGroup(List<Registration> registrations, EventType type) {
var group = new Group();
group.setName(type.getText());
group.setType(type);
group.setStatus(Status.IN_PROGRESS);
group.setTeams(new ArrayList<>());
for (var registration : registrations) {
group.getTeams().add(getTeam(registration, group));
}
return group;
}
private List<Group> getGroups(List<Registration> orgRegistrations, EventType type) {
var registrations = new ArrayList<>(orgRegistrations);
var group1 = new Group();
group1.setName(type.getText() + " 1");
group1.setType(type);
group1.setStatus(Status.IN_PROGRESS);
group1.setTeams(new ArrayList<>());
var group2 = new Group();
group2.setName(type.getText() + " 2");
group2.setType(type);
group2.setStatus(Status.IN_PROGRESS);
group2.setTeams(new ArrayList<>());
var registrationStrengthMap = new HashMap<Registration, Integer>();
for (var registration : registrations) {
var strength = registration.getPlayer().getStrength().getCoefficient();
if (registration.getPartner() != null) {
strength += registration.getPartner().getStrength().getCoefficient();
}
registrationStrengthMap.put(registration, strength);
}
var sortedRegistrations = registrationStrengthMap
.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.map(Map.Entry::getKey)
.toList();
for (Iterator<Registration> i = sortedRegistrations.iterator(); i.hasNext(); ) {
group1.getTeams().add(getTeam(i.next(), group1));
if (i.hasNext()) {
group2.getTeams().add(getTeam(i.next(), group2));
}
}
if (group1.getTeams().size() % 2 == 1 && group2.getTeams().size() % 2 == 1) {
group1.getTeams().add(group2.getTeams().getLast());
group2.getTeams().removeLast();
}
return List.of(group1, group2);
}
private Team getTeam(Registration registration, Group group) {
var team = new Team();
team.setPlayer1(registration.getPlayer());
team.setPlayer2(registration.getPartner());
team.setGroups(List.of(group));
return team;
}
public Tournament clear(Tournament tournament) {
for (var event : tournament.getEvents()) {
event.getGroups().clear();
}
tournament.setStatus(TournamentStatus.UPCOMING);
tournamentRepository.save(tournament);
return tournament;
}
}