lydichris.smashbracket.services.BracketService.java Source code

Java tutorial

Introduction

Here is the source code for lydichris.smashbracket.services.BracketService.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package lydichris.smashbracket.services;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import lydichris.smashbracket.models.Entrant;
import lydichris.smashbracket.models.Match;
import lydichris.smashbracket.models.SeedComparator;
import lydichris.smashbracket.models.Tournament;
import lydichris.smashbracket.persistence.MatchPersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 *
 * @author cgmcandrews
 */
@Service("bracketService")
public class BracketService {

    @Autowired
    TournamentService tournamentService;
    @Autowired
    EntrantService entrantService;
    @Autowired
    MatchPersistence matchPersistence;

    Entrant bye = new Entrant();

    public List<Match> createBrackets(String tournamentUuid) {
        Tournament tournament = tournamentService.getTournament(tournamentUuid);
        dropExistingBracket(tournament);
        return generateBracket(tournament);
    }

    private List<Match> generateBracket(Tournament tournament) {
        switch (tournament.getTournamentType()) {
        case SINGLE_ELIMINATION:
            return generateSingleElimationTournament(tournament);
        default:
            return null;
        }
    }

    private List<Match> generateSingleElimationTournament(Tournament tournament) {
        List<Entrant> entrants = entrantService.getEntrantsInTournament(tournament.getId());
        Collections.sort(entrants, new SeedComparator());
        int entrantsSizeToFillWithByesUntil = 0;

        entrantsSizeToFillWithByesUntil = calculateHigherPowerOfTwo(entrants.size());

        while (entrants.size() < entrantsSizeToFillWithByesUntil) {
            entrants.add(bye);
        }

        List<Match> rounds = generateFirstRounds(entrants, tournament);
        rounds.addAll(generateRemainingRounds(rounds, 1, tournament));
        return matchPersistence.persistMatches(rounds);
    }

    private int calculateHigherPowerOfTwo(Integer size) {
        if ((size & (size - 1)) == 0) {
            return (size);
        }

        while ((size & (size - 1)) != 0) {
            size = size & (size - 1);
        }

        size = size << 1;
        return size;
    }

    private List<Match> generateFirstRounds(List<Entrant> entrants, Tournament tournament) {
        //Defect 1 is a power of 2 :/ need to prevent that
        //Todo the first rounds need to forward reference the next
        List<Entrant> toPlace = new ArrayList<>(entrants);
        List<Match> matches = new ArrayList<>();
        int topSeed = 0;
        int round = 1;
        while (toPlace.size() > 0) {
            int bottomSeed = toPlace.size() - 1;
            Match match = new Match();
            match.setId(UUID.randomUUID().toString());
            match.setTournamentUuid(tournament.getId());
            match.setEntrantOne(toPlace.get(topSeed).getUuid());
            match.setEntrantTwo(toPlace.get(bottomSeed).getUuid());
            match.setRoundNumber(round);
            matches.add(match);
            toPlace.remove(bottomSeed);
            toPlace.remove(topSeed);
        }
        return matches;
    }

    private List<Match> generateRemainingRounds(List<Match> priorRounds, int roundNumber, Tournament tournament) {
        List<Match> currentRounds = generateCurrentRound(priorRounds, roundNumber, tournament);

        if (currentRounds.size() > 1) {
            currentRounds.addAll(generateRemainingRounds(currentRounds, roundNumber + 1, tournament));
        }
        return currentRounds;
    }

    private List<Match> generateCurrentRound(List<Match> priorRounds, int roundNumber, Tournament tournament) {
        List<Match> toPlace = new ArrayList<>(priorRounds);
        List<Match> currentRound = new ArrayList<>();
        int topMatch = 0;
        int bottomMatch = 1;
        while (toPlace.size() > 1) {
            Match match = new Match();
            match.setId(UUID.randomUUID().toString());
            match.setTournamentUuid(tournament.getId());
            match.setFirstPreviousMatch(toPlace.get(topMatch).getId());
            match.setSecondPreviousMatch(toPlace.get(bottomMatch).getId());
            match.setRoundNumber(roundNumber + 1);
            currentRound.add(match);
            toPlace.remove(bottomMatch);
            toPlace.remove(topMatch);
        }

        if (toPlace.size() == 1) {
            return currentRound;
        }

        return currentRound;
    }

    private void dropExistingBracket(Tournament tournament) {
        matchPersistence.removeMatches(tournament.getId());
    }

}