ca.cutterslade.match.scheduler.Scheduler.java Source code

Java tutorial

Introduction

Here is the source code for ca.cutterslade.match.scheduler.Scheduler.java

Source

/*
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package ca.cutterslade.match.scheduler;

import java.util.Set;

import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;

public final class Scheduler {

    private final Configuration config;

    private final ImmutableSet<Gym> gyms;

    private final ImmutableSet<Court> courts;

    private final ImmutableSet<Day> days;

    private final ImmutableSet<Time> times;

    private final ImmutableSet<Slot> slots;

    private final ImmutableSet<Tier> tiers;

    private final ImmutableSet<Team> teams;

    private final ImmutableSet<Match> matches;

    private final ImmutableMap<Day, ImmutableMap<Time, ImmutableSet<Match>>> dayTimeMatches;

    private final ImmutableMap<Day, ImmutableSet<Match>> dayMatches;

    private final ImmutableMap<Slot, Match> slotMatches;

    public Scheduler(Configuration config, Set<String> teams, Set<String> tiers, Set<String> gyms,
            Set<String> courts, Set<String> times, Set<String> days, int teamSize) throws InterruptedException {
        if (null == config)
            throw new IllegalArgumentException("config may not be null");
        if (null == teams)
            throw new IllegalArgumentException("teams may not be null");
        if (null == tiers)
            throw new IllegalArgumentException("tiers may not be null");
        if (null == gyms)
            throw new IllegalArgumentException("gyms may not be null");
        if (null == courts)
            throw new IllegalArgumentException("courts may not be null");
        if (null == times)
            throw new IllegalArgumentException("times may not be null");
        if (null == days)
            throw new IllegalArgumentException("days may not be null");
        this.config = config;
        this.gyms = Gym.forNames(gyms);
        this.courts = Court.forNames(courts, this.gyms);
        this.days = Day.forNames(days);
        this.times = Time.forNames(times);
        this.slots = Slot.forNames(this.times, this.courts, this.days);
        this.tiers = Tier.forNames(tiers);
        int slotsPerDay = gyms.size() * courts.size() * times.size();
        int possibleTeams = slotsPerDay * teamSize;
        ImmutableSet<Team> realTeams = Team.forNames(teams, this.tiers,
                (int) Math.ceil(possibleTeams / (double) this.tiers.size()));
        if (teams.size() > possibleTeams)
            throw new IllegalArgumentException(
                    teams.size() + " teams cannot play in " + slotsPerDay + " slots per day");
        else if (teams.size() < possibleTeams)
            this.teams = padWithByes(this.tiers, realTeams, possibleTeams / this.tiers.size());
        else
            this.teams = realTeams;
        this.matches = new MatchMaker(config, slots, this.teams, teamSize).getMatches();
        ImmutableMap.Builder<Day, ImmutableMap<Time, ImmutableSet<Match>>> dayTimeMatches = ImmutableMap.builder();
        for (Day day : this.days) {
            ImmutableMap.Builder<Time, ImmutableSet<Match>> timeMatches = ImmutableMap.builder();
            for (Time time : this.times) {
                ImmutableSet.Builder<Match> b = ImmutableSet.builder();
                for (Match m : matches)
                    if (m.getDay().equals(day) && m.getTime().equals(time))
                        b.add(m);
                timeMatches.put(time, b.build());
            }
            dayTimeMatches.put(day, timeMatches.build());
        }
        this.dayTimeMatches = dayTimeMatches.build();
        ImmutableMap.Builder<Day, ImmutableSet<Match>> dayMatches = ImmutableMap.builder();
        for (Day day : this.days)
            dayMatches.put(day, ImmutableSet.copyOf(Iterables.concat(this.dayTimeMatches.get(day).values())));
        this.dayMatches = dayMatches.build();
        slotMatches = Maps.uniqueIndex(matches, new Function<Match, Slot>() {

            @Override
            public Slot apply(Match match) {
                return match.getSlot();
            }
        });
    }

    private static ImmutableSet<Team> padWithByes(ImmutableSet<Tier> tiers, ImmutableSet<Team> realTeams,
            int teamsPerTier) {
        ImmutableSet.Builder<Team> b = ImmutableSet.builder();
        for (Tier tier : tiers) {
            ImmutableSet<Team> tierTeams = ImmutableSet.copyOf(tier.getTeams(realTeams));
            b.addAll(tierTeams);
            if (tierTeams.size() > teamsPerTier)
                throw new AssertionError("More than allowed number of teams");
            if (tierTeams.size() < teamsPerTier)
                for (int i = 0, n = teamsPerTier - tierTeams.size(); i < n; i++)
                    b.add(new Team("B" + i, tier));
        }
        return b.build();
    }

    public Scheduler(Configuration config, int nTeams, int nTiers, int nGyms, int nCourts, int nTimes, int nDays,
            int size) throws InterruptedException {
        this(config, setOf(nTeams), setOf(nTiers), setOf(nGyms), setOf(nCourts), setOf(nTimes), setOf(nDays), size);
    }

    private static ImmutableSet<String> setOf(int n) {
        ImmutableSet.Builder<String> b = ImmutableSet.builder();
        for (int i = 0; i < n; i++)
            b.add(String.valueOf(i));
        return b.build();
    }

    public Configuration getConfig() {
        return config;
    }

    public ImmutableSet<Gym> getGyms() {
        return gyms;
    }

    public ImmutableSet<Court> getCourts() {
        return courts;
    }

    public ImmutableSet<Day> getDays() {
        return days;
    }

    public ImmutableSet<Time> getTimes() {
        return times;
    }

    public ImmutableSet<Slot> getSlots() {
        return slots;
    }

    public ImmutableSet<Tier> getTiers() {
        return tiers;
    }

    public ImmutableSet<Team> getTeams() {
        return teams;
    }

    public ImmutableSet<Match> getMatches() {
        return matches;
    }

    public ImmutableSet<Match> getMatches(Day day) {
        return dayMatches.get(day);
    }

    public ImmutableSet<Match> getMatches(Day day, Time time) {
        return dayTimeMatches.get(day).get(time);
    }

    public Match getMatch(Day day, Time time, Court court) {
        return slotMatches.get(new Slot(time, day, court));
    }

}