Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
TournamentService.java 12.28 KiB
package hdm.mi.sthbackend.service;

import hdm.mi.sthbackend.dto.MatchDTO;
import hdm.mi.sthbackend.dto.PlayerDTO;
import hdm.mi.sthbackend.dto.TeamDTO;
import hdm.mi.sthbackend.exeptions.*;
import hdm.mi.sthbackend.mapper.ModelToDTOMapper;
import hdm.mi.sthbackend.model.*;
import hdm.mi.sthbackend.repository.IMatchRepository;
import hdm.mi.sthbackend.repository.IPlayerRepository;
import hdm.mi.sthbackend.repository.ITeamRepository;
import hdm.mi.sthbackend.repository.ITournamentRepository;
import lombok.AllArgsConstructor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@AllArgsConstructor
public class TournamentService {

    private final Logger log = LogManager.getLogger(TournamentService.class);

    ITournamentRepository tournamentRepository;

    @Autowired
    ModelToDTOMapper mapper;

    public PlayerDTO addPlayerToTeam(UUID tournamentId, UUID teamId,
                                  String playerName) throws TournamentIdNotFoundException, TeamIdNotFoundException {
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException( tournamentId));

        Team team = Optional.ofNullable( tournament.getTeams().get( teamId )).orElseThrow(() -> new TeamIdNotFoundException(teamId)) ;

        Player newPlayer = new Player(UUID.randomUUID(), playerName);
        team.getTeamMembers()
                .add(newPlayer.getPlayerId());

        playerRepository.insert(newPlayer);
        teamRepository.save(team);
        log.debug("Player " + newPlayer.getPlayerId() + " added to Team " + teamId);
        return mapper.mapToPlayerDTO(newPlayer);
    }

    public PlayerDTO findPlayerById(UUID playerId) throws PlayerIdNotFoundException {
        Player player = playerRepository.findById(playerId)
                .orElseThrow(() -> new PlayerIdNotFoundException(playerId));

        return mapper.mapToPlayerDTO(player);
    }

    /*
    Wie gehen wir damit um, wenn zwei Player denselben Namen haben? Also: Stefan vs Stefan = Stefan gewinnt
    Sollte man hier in den Methoden das ausschließen und dann geben die Spieler ihren ersten Buchstaben vom Nachnamen an? z.B. Stefan S. vs Stefan w.
    oder geben wir die UUID auch mit an zum PlayerName
     */

    public PlayerDTO removePlayerFromTeam(UUID teamId,
                                          UUID playerId) throws PlayerIdNotFoundException, TeamIdNotFoundException {
        Team team = teamRepository.findById(teamId)
                .orElseThrow(() -> new TeamIdNotFoundException(teamId));
        Player playerToDelete = playerRepository.findById(playerId)
                .orElseThrow(() -> new PlayerIdNotFoundException(playerId));
        try {
            team.getTeamMembers()
                    .remove(playerToDelete.getPlayerId());
        } catch (NullPointerException e) {
            throw new PlayerIdNotFoundException(playerId);
        }

        playerRepository.delete(playerToDelete);
        teamRepository.save(team);
        log.debug("Player " + playerId + " removed from Team " + teamId);

        return mapper.mapToPlayerDTO(playerToDelete);
    }

    /*
    Kann es passieren, dass hier bei der Methode removePlayerFromTeam() es den Player gar nicht gibt?
    und dann eine PlayerIdNotFoundException geworfen werden muss? oder ist durch die Übergabe von UUID playerId schon safe die playerId vorhanden
     */

    public UUID updatePlayerName(UUID playerId,
                                 String newPlayerName) throws PlayerIdNotFoundException {
        Player player = playerRepository.findById(playerId)
                .orElseThrow(() -> new PlayerIdNotFoundException(playerId));
        player.setName(newPlayerName);
        playerRepository.save(player);
        return playerId;
    }

    public TeamDTO findTeamById(UUID teamId) throws TeamIdNotFoundException {
        Team team = teamRepository.findById(teamId)
                .orElseThrow(() -> new TeamIdNotFoundException(teamId));

        Map<UUID, PlayerDTO> teamMembers = new HashMap<>();

        team.getTeamMembers().
                forEach(pId -> playerRepository.findById(pId)
                        .ifPresent(p -> teamMembers.put(p.getPlayerId(), new PlayerDTO(p.getPlayerId(), p.getName()))));

        return mapper.mapToTeamDTO(team);
    }

    public TeamDTO createAndAddTeamToTournament(UUID tournamentId, String teamName) throws TournamentIdNotFoundException {
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));

        Team newTeam = new Team(teamName);

        tournament.getTeams()
                .add(newTeam);

        teamRepository.insert(newTeam);
        tournamentRepository.save(tournament);
        return mapper.mapToTeamDTO(newTeam);
    }

    public UUID deleteAndRemoveTeamFromTournament(UUID tournamentId,
                                                  UUID teamId) throws TournamentIdNotFoundException, TeamIdNotFoundException {
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));

        Team teamToDelete = teamRepository.findById(teamId)
                .orElseThrow(() -> new TeamIdNotFoundException(teamId));
        try {
            tournament.getTeams()
                    .remove(teamToDelete.getTeamId());
        } catch (NullPointerException e) {
            throw new TeamIdNotFoundException(tournamentId);
        }
        teamRepository.delete(teamToDelete);
        tournamentRepository.save(tournament);
        log.debug("Team " + teamId + " added to Tournament " + tournamentId);
        return teamId;
    }

    public Tournament createTournament(Tournament tournament) {

        tournamentRepository.insert(tournament);
        log.info("created Tournament " + tournament.getTournamentId());
        return tournament;
    }

    public UUID determineWinner (UUID matchId) throws MatchIdNotFoundException, WinnerNotDeterminedException {
        Match match = matchRepository.findById(matchId).orElseThrow(() -> new MatchIdNotFoundException(matchId));

        UUID winnerTeamId = match.getTeamScores().entrySet().stream()
                .max(Comparator.comparing(Map.Entry::getKey))
                .map(Map.Entry::getKey)
                .orElseThrow(() -> new WinnerNotDeterminedException(matchId));

        match.setWinnerTeamId(winnerTeamId);
        matchRepository.save(match);
        log.debug("The Winner " + winnerTeamId + " is determined for Match " + matchId);
        return winnerTeamId;
    }

    public Tournament assignTeamToMatch(UUID tournamentId, int bracketRound, UUID matchId, UUID teamId, int score) throws TournamentIdNotFoundException, MatchIdNotFoundException {
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));
        try{
            tournament
                    .getBracket()
                    .get(bracketRound)
                    .getMatches()
                    .get(matchId)
                    .getTeamScores()
                    .put(teamId, score);
        }
        catch (Exception e){
            throw new MatchIdNotFoundException(matchId);
        }

        tournamentRepository.save(tournament);
        log.debug("Team " + teamId + " assign to Match " + matchId );
        return tournament;
    }


    public MatchDTO updateTeamScore(UUID matchId, UUID teamId, int newScore)throws MatchIdNotFoundException, TeamIdNotFoundException{
        Match match = matchRepository.findById(matchId).orElseThrow(() -> new MatchIdNotFoundException(matchId));

        if (!match.getTeamScores().containsKey(teamId)) {
            throw new TeamIdNotFoundException(teamId);
        }
        match.getTeamScores().put(teamId, newScore);
        matchRepository.save(match);
        log.debug("Score of Team " + teamId + " updated to " + newScore);
        return mapper.mapToMatchDTO(match);
    }


    public TeamDTO updateTeamName(UUID teamId, String newTeamName) throws TeamIdNotFoundException {
        Team team = teamRepository.findById(teamId)
                .orElseThrow(() -> new TeamIdNotFoundException(teamId));
        team.setTeamName(newTeamName);
        teamRepository.save(team);
        log.debug("Teamname of " + teamId + " updated to " + newTeamName);
        return mapper.mapToTeamDTO(team);
    }

    public UUID updateTournamentName(UUID tournamentId, String newTournamentName)throws TournamentIdNotFoundException{
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));
        tournament.setTournamentName(newTournamentName);
        tournamentRepository.save(tournament);
        log.debug("Tournament Name for TournamentID " + tournamentId + " updated to " + newTournamentName);
        return tournamentId;
    }
    public Tournament getTournament(UUID tournamentId) throws TournamentIdNotFoundException {
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));

        log.debug(tournament + "is found");
        return tournament;
    }

    public Tournament deleteTournament(UUID tournamentId) throws TournamentIdNotFoundException {
        Tournament tournamentToDelete = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));

        tournamentRepository.delete(tournamentToDelete);
        log.debug("Tournament " + tournamentId + " has been deleted");
        return tournamentToDelete;
    }

    public Tournament createBracket(UUID tournamentId) throws TournamentIdNotFoundException, InsufficientTeamsException, BracketAlreadyInitializedException{
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));
        List<Team> teams = tournament.getTeams();

        if(teams.size() < 2){
            throw new InsufficientTeamsException(tournamentId);
        }

        // log zur Basis 2 von der Anzahl der Teams (aufgerundet)
        int roundCount = (int) Math.ceil(Math.log(teams.size()) / Math.log(2));

        if(tournament.getBracket().size() == 0){
            tournament.setBracket(new ArrayList<>());
            for(int i = 0; i < roundCount; i++){
                // richtige Anzahl an BracketRounds hinzufügen
                tournament.getBracket().add(new BracketRound(i));

                // anzahl der matches errechnen
                int matchCount = (int) (Math.pow(2, roundCount)) / (int) Math.pow(2, i + 1);

                for(int j = 0; j < matchCount; j++){
                    // matches hinzufügen
                    UUID matchId = UUID.randomUUID();
                    tournament.getBracket().get(i).getMatches().put(matchId, new Match(matchId));
                }
            }
        }
        else{
            throw new BracketAlreadyInitializedException(tournamentId);
        }
        tournamentRepository.save(tournament);
        return tournament;
    }

    public Tournament fillBracketRandom(UUID tournamentId) throws TournamentIdNotFoundException {
        Tournament tournament = tournamentRepository.findById(tournamentId)
                .orElseThrow(() -> new TournamentIdNotFoundException(tournamentId));
        List<Team> teams = tournament.getTeams();

        Random random = new Random();
        for(int i = 0; i < 2; i++){
            for(Match match: tournament.getBracket().get(0).getMatches().values()){
                if(teams.size() > 0){
                    int teamIndex = random.nextInt(0, teams.size());
                    match.getTeamScores().put(teams.get(teamIndex).getTeamId(), 0);
                    teams.remove(teamIndex);
                }
                else{
                    break;
                }
            }
        }
        tournamentRepository.save(tournament);
        return tournament;
    }
    /*
    Weitere Methoden:
    UpdateTeamScore  Marius
    Tunier beenden
    GetTournament   Leon
    DeleteTournament   Leon
    User   Mattis
     */


}