예제 #1
0
        private List <Bracket> CreateBrackets(IEnumerable <ISet <Team> > teams, ISet <Reader> readers)
        {
            int teamsCount = teams.Count();

            if (teamsCount / 2 > readers.Count)
            {
                throw new ArgumentException(TournamentStrings.NotEnoughReadersForTeams(readers.Count, teamsCount));
            }

            List <Bracket> brackets = new List <Bracket>();

            using (IEnumerator <Reader> readersEnumerator = readers.GetEnumerator())
            {
                foreach (ISet <Team> teamsInBracket in teams)
                {
                    // We're adding a reader for every 2 teams, so start at 1 and increment by 2.
                    List <Reader> bracketReaders = new List <Reader>();
                    for (int i = 1; i < teamsInBracket.Count; i += 2)
                    {
                        readersEnumerator.MoveNext();
                        bracketReaders.Add(readersEnumerator.Current);
                    }

                    bool hasBye = teamsInBracket.Count % 2 == 1;
                    int  rounds = checked (this.roundRobins * (hasBye ? teamsInBracket.Count : teamsInBracket.Count - 1));

                    GetInitialRows(teamsInBracket, out Team[] topRow, out Team[] bottomRow);
예제 #2
0
        public void UpdateStage(TournamentStage newStage, out string nextStageTitle, out string nextStageInstructions)
        {
            this.Stage = newStage;
            switch (newStage)
            {
            case TournamentStage.AddReaders:
                nextStageTitle        = TournamentStrings.AddReaders;
                nextStageInstructions = TournamentStrings.ListMentionsOfAllReaders;
                break;

            case TournamentStage.SetRoundRobins:
                nextStageTitle        = TournamentStrings.SetNumberRoundRobins;
                nextStageInstructions = TournamentStrings.SpecifyNumberRoundRobins(MaxRoundRobins);
                break;

            case TournamentStage.AddTeams:
                nextStageTitle        = TournamentStrings.AddTeams;
                nextStageInstructions = TournamentStrings.AddListCommaSeparatedTeams(this.GetMaximumTeamCount());
                break;

            case TournamentStage.BotSetup:
                nextStageTitle        = TournamentStrings.SettingUpTournament;
                nextStageInstructions = TournamentStrings.InitializingSchedule;
                break;

            case TournamentStage.RunningTournament:
                nextStageTitle        = TournamentStrings.TournamentStarted;
                nextStageInstructions = TournamentStrings.TournamentStartedDirections(this.Name);
                break;

            case TournamentStage.Rebracketing:
                nextStageTitle        = TournamentStrings.Rebracket;
                nextStageInstructions = TournamentStrings.RebracketInstructions;
                break;

            case TournamentStage.Complete:
                nextStageTitle        = TournamentStrings.TournamentCompleted;
                nextStageInstructions = TournamentStrings.AllTournamentChannelsRolesRemoved(this.Name);
                break;

            default:
                nextStageTitle        = null;
                nextStageInstructions = null;
                break;
            }
        }
예제 #3
0
        public bool TrySetCurrentTournament(string name, out string errorMessage)
        {
            if (!(this.currentTournamentLock.TryEnterUpgradeableReadLock(mutexTimeoutMs) &&
                  this.currentTournamentLock.TryEnterWriteLock(mutexTimeoutMs)))
            {
                errorMessage = TournamentStrings.UnableAccessCurrentTournament;
                return(false);
            }

            try
            {
                if (this.CurrentTournament != null)
                {
                    errorMessage = TournamentStrings.TournamentAlreadyRunning(this.CurrentTournament.Name);
                    return(false);
                }

                if (!this.pendingTournaments.TryGetValue(name, out ITournamentState state))
                {
                    errorMessage = TournamentStrings.TournamentCannotBeFound(name);
                    return(false);
                }

                this.CurrentTournament = state;

                if (!this.pendingTournaments.TryRemove(name, out state))
                {
                    // Couldn't set the current tournament, so roll back the change
                    errorMessage           = TournamentStrings.CannotMoveTournamentFromPending(this.CurrentTournament.Name);
                    this.CurrentTournament = null;
                    return(false);
                }

                errorMessage = null;
                return(true);
            }
            finally
            {
                this.currentTournamentLock.ExitWriteLock();
                this.currentTournamentLock.ExitUpgradeableReadLock();
            }
        }
예제 #4
0
        public Schedule Generate(IEnumerable <ISet <Team> > teams, ISet <Reader> readers)
        {
            Verify.IsNotNull(teams, nameof(teams));
            Verify.IsNotNull(readers, nameof(readers));

            if (this.roundRobins <= 0)
            {
                throw new InvalidOperationException(TournamentStrings.RoundRobinsMustBePositive(this.roundRobins));
            }

            int bracketsCount = teams.Count();

            if (bracketsCount > MaximumBrackets)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(teams), TournamentStrings.OnlyAtMostNBrackets(bracketsCount));
            }

            int teamsCount = teams.Sum(t => t.Count);

            if (teamsCount <= 1)
            {
                throw new ArgumentOutOfRangeException(
                          nameof(teams), TournamentStrings.MustHaveMoreThanOneTeam(teamsCount));
            }
            else if (teams.Any(t => t.Count <= 1))
            {
                throw new ArgumentOutOfRangeException(
                          nameof(teams), TournamentStrings.MustHaveMoreThanOneTeamPerBracket);
            }
            else if (readers.Count == 0)
            {
                throw new ArgumentOutOfRangeException(nameof(readers), TournamentStrings.MustHaveReader);
            }

            Schedule       schedule      = new Schedule();
            List <Bracket> brackets      = this.CreateBrackets(teams, readers);
            int            maximumRounds = brackets.Max(bracket => bracket.Rounds);

            Round[] rounds = Enumerable.Range(0, maximumRounds)
                             .Select(number => new Round())
                             .ToArray();

            // TODO: Investigate if it makes sense to parallelize this. Note that Random is not thread-safe, so we'd
            // need to switch to a thread safe randomizer, or use a different Random instance in each.
            foreach (Bracket bracket in brackets)
            {
                Reader[] bracketReaders = bracket.Readers.ToArray();
                for (int i = 0; i < bracket.Rounds; i++)
                {
                    this.AddBracketGamesToRound(rounds[i], bracket, bracketReaders);
                }
            }

            foreach (Round round in rounds)
            {
                schedule.AddRound(round);
            }

            return(schedule);
        }