public async Task SetupFinalsAsync(IGuildUser readerUser, string rawTeamNameParts) { ITextChannel channel = null; await this.DoReadWriteActionOnCurrentTournamentAsync( async currentTournament => { if (currentTournament?.Stage != TournamentStage.RunningTournament) { this.Logger.Debug("Could not start finals in stage {stage}", currentTournament?.Stage); await this.SendChannelMessage(BotStrings.ErrorFinalsOnlySetDuringPrelimsOrPlayoffs); return; } if (!currentTournament.TryGetReader(readerUser.Id, out Reader reader)) { this.Logger.Debug("Could not start finals because {1} is not a reader", readerUser.Id); await this.SendChannelMessage(BotStrings.ErrorGivenUserIsntAReader); return; } if (rawTeamNameParts == null) { this.Logger.Debug( "Could not start finals because no teams were specified"); await this.SendChannelMessage(BotStrings.ErrorNoTeamsSpecified); return; } string combinedTeamNames = string.Join(" ", rawTeamNameParts).Trim(); if (!TeamNameParser.TryGetTeamNamesFromParts( combinedTeamNames, out IList <string> teamNames, out string errorMessage)) { this.Logger.Debug( "Could not start finals because of this error: {errorMessage}", errorMessage); await this.SendChannelMessage(BotStrings.ErrorGenericMessage(errorMessage)); return; } if (teamNames.Count != 2) { this.Logger.Debug( "Could not start finals because {count} teams were specified", teamNames.Count); await this.SendChannelMessage(BotStrings.ErrorTwoTeamsMustBeSpecifiedFinals(teamNames.Count)); return; } Team[] teams = teamNames.Select(name => new Team() { Name = name }) .ToArray(); if (currentTournament.Teams.Intersect(teams).Count() != teams.Length) { this.Logger.Debug( "Could not start finals because some teams were not in the tournament", teamNames.Count); await this.SendChannelMessage( BotStrings.ErrorAtLeastOneTeamNotInTournament(string.Join(", ", teamNames))); return; } // Create a finals channel and give access to the teams and readers Game finalsGame = new Game() { Reader = reader, Teams = teams }; int finalsRoundNumber = currentTournament.Schedule.Rounds.Count + 1; IList <Game> finalGames = currentTournament.Schedule.Rounds[currentTournament.Schedule.Rounds.Count - 1].Games; int roomIndex = 0; foreach (Game game in finalGames) { if (game.Reader.Equals(reader)) { break; } roomIndex++; } if (roomIndex >= finalGames.Count) { // Need to have a fall-back somehow. For now default to the first room. roomIndex = 0; } // TODO: Look into creating the channels after the update stage so we can release the lock // sooner. However, this does mean that a failure to create channels will leave us in a bad // state. channel = await this.ChannelManager.CreateChannelsForFinals( this.Context.Client.CurrentUser, currentTournament, finalsGame, finalsRoundNumber, roomIndex); currentTournament.UpdateStage( TournamentStage.Finals, out string nextStageTitle, out string nextStageInstructions); }); if (channel != null) { this.Logger.Debug("Finals started successfully"); await this.Context.Channel.SendMessageAsync( BotStrings.FinalsParticipantsPleaseJoin(channel.Mention), options : RequestOptionsSettings.Default); } }