public Task GoBackAsync() { return(this.DoReadWriteActionOnCurrentTournamentAsync( async currentTournament => { bool sendMessage = true; switch (currentTournament.Stage) { case TournamentStage.SetRoundRobins: currentTournament.TryClearReaders(); break; case TournamentStage.AddTeams: currentTournament.RoundRobinsCount = 0; break; case TournamentStage.AddPlayers: currentTournament.TryClearTeams(); currentTournament.ClearSymbolsToTeam(); List <Task <IMessage> > getJoinTeamMessagesTasks = new List <Task <IMessage> >(); foreach (ulong id in currentTournament.JoinTeamMessageIds) { getJoinTeamMessagesTasks.Add(this.Context.Channel.GetMessageAsync(id)); } IMessage[] joinTeamMessages = await Task.WhenAll(getJoinTeamMessagesTasks); await Task.WhenAll(joinTeamMessages .Select(message => this.Context.Channel.DeleteMessageAsync(message))); currentTournament.ClearJoinTeamMessageIds(); break; case TournamentStage.Rebracketing: // Don't send the message about the tournament starting again sendMessage = false; break; default: // Nothing to go back to, so do nothing. this.Logger.Debug("Could not go back on stage {stage}", currentTournament.Stage); await this.SendChannelMessage(BotStrings.CannotGoBack(currentTournament.Stage)); return; } TournamentStage previousStage = currentTournament.Stage == TournamentStage.Finals ? TournamentStage.RunningTournament : currentTournament.Stage - 1; await this.UpdateStageAsync(currentTournament, previousStage, sendMessage); })); }
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; } }
private async Task <GroupCoords> CreateTournamentAndStages(IDbConnection c, IDbTransaction t, Competition competition) { var result = new GroupCoords(); var tournament = new Tournament { Name = competition.Caption, Status = (int)TournamentStatus.Playing, Type = 1 }; tournament.Id = await c.InsertAsync(tournament, t); result.IdTournament = tournament.Id; result.Tournament = tournament; var stage = new TournamentStage { Name = "Liga", IdTournament = result.IdTournament, SequenceOrder = 1, Type = (int)CalendarType.League }; stage.Id = await c.InsertAsync(stage, t); result.IdStage = stage.Id; result.Stage = stage; var group = new StageGroup { Name = "Grupo único", IdTournament = result.IdTournament, IdStage = result.IdStage, SequenceOrder = 1, NumTeams = competition.NumberOfTeams, NumRounds = 1 }; group.Id = await c.InsertAsync(group, t); result.IdGroup = group.Id; result.Group = group; return(result); }
private async Task <IUserMessage> UpdateStageAsync(ITournamentState state, TournamentStage stage, bool sendMessage = true) { state.UpdateStage(stage, out string title, out string instructions); if (title == null && instructions == null) { return(null); } IUserMessage updateMessage = null; if (sendMessage) { EmbedBuilder embedBuilder = new EmbedBuilder { Title = title, Description = instructions }; updateMessage = await this.Context.Channel.SendMessageAsync( embed : embedBuilder.Build(), options : RequestOptionsSettings.Default); } this.Logger.Debug("Moved to stage {stage}", stage); return(updateMessage); }
public void Slice() { if (this.m_Stage == TournamentStage.Signup) { TimeSpan until = (this.m_SignupStart + this.m_SignupPeriod) - DateTime.Now; if (until <= TimeSpan.Zero) { for (int i = this.m_Participants.Count - 1; i >= 0; --i) { TournyParticipant part = (TournyParticipant)this.m_Participants[i]; bool bad = false; for (int j = 0; j < part.Players.Count; ++j) { Mobile check = (Mobile)part.Players[j]; if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || Factions.Sigil.ExistsOn(check) || check.Region.IsPartOf(typeof(Regions.Jail))) { bad = true; break; } } if (bad) { for (int j = 0; j < part.Players.Count; ++j) ((Mobile)part.Players[j]).SendMessage("You have been disqualified from the tournament."); this.m_Participants.RemoveAt(i); } } if (this.m_Participants.Count >= 2) { this.m_Stage = TournamentStage.Fighting; this.m_Undefeated.Clear(); this.m_Pyramid.Levels.Clear(); this.m_Pyramid.AddLevel(this.m_ParticipantsPerMatch, this.m_Participants, this.m_GroupType, this.m_TournyType); PyramidLevel level = (PyramidLevel)this.m_Pyramid.Levels[0]; if (level.FreeAdvance != null) this.m_Undefeated.Add(level.FreeAdvance); for (int i = 0; i < level.Matches.Count; ++i) { TournyMatch match = (TournyMatch)level.Matches[i]; this.m_Undefeated.AddRange(match.Participants); } this.Alert("Hear ye! Hear ye!", "The tournament will begin shortly."); } else { this.Alert("Is this all?", "Pitiful. Signup extended."); this.m_SignupStart = DateTime.Now; } } else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(1.0).TotalSeconds) < (SliceInterval.TotalSeconds / 2)) { this.Alert("Last call!", "If you wish to enter the tournament, sign up with the registrar now."); } else if (Math.Abs(until.TotalSeconds - TimeSpan.FromMinutes(5.0).TotalSeconds) < (SliceInterval.TotalSeconds / 2)) { this.Alert("The tournament will begin in 5 minutes.", "Sign up now before it's too late."); } } else if (this.m_Stage == TournamentStage.Fighting) { if (this.m_Undefeated.Count == 1) { TournyParticipant winner = (TournyParticipant)this.m_Undefeated[0]; try { if (this.m_EventController != null) this.Alert("The tournament has completed!", String.Format("Team {0} has won!", m_EventController.GetTeamName(((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf(winner)))); else if (this.m_TournyType == TournyType.RandomTeam) this.Alert("The tournament has completed!", String.Format("Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf(winner) + 1)); else if (this.m_TournyType == TournyType.RedVsBlue) this.Alert("The tournament has completed!", String.Format("Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf(winner) == 0 ? "Red" : "Blue")); else this.Alert("The tournament has completed!", String.Format("{0} {1} the champion{2}.", winner.NameList, winner.Players.Count > 1 ? "are" : "is", winner.Players.Count == 1 ? "" : "s")); } catch { } this.GiveAwards(); this.m_Stage = TournamentStage.Inactive; this.m_Undefeated.Clear(); } else if (this.m_Pyramid.Levels.Count > 0) { PyramidLevel activeLevel = (PyramidLevel)this.m_Pyramid.Levels[this.m_Pyramid.Levels.Count - 1]; bool stillGoing = false; for (int i = 0; i < activeLevel.Matches.Count; ++i) { TournyMatch match = (TournyMatch)activeLevel.Matches[i]; if (match.Winner == null) { stillGoing = true; if (!match.InProgress) { for (int j = 0; j < this.m_Arenas.Count; ++j) { Arena arena = (Arena)this.m_Arenas[j]; if (!arena.IsOccupied) { match.Start(arena, this); break; } } } } } if (!stillGoing) { for (int i = this.m_Undefeated.Count - 1; i >= 0; --i) { TournyParticipant part = (TournyParticipant)this.m_Undefeated[i]; bool bad = false; for (int j = 0; j < part.Players.Count; ++j) { Mobile check = (Mobile)part.Players[j]; if (check.Deleted || check.Map == null || check.Map == Map.Internal || !check.Alive || Factions.Sigil.ExistsOn(check) || check.Region.IsPartOf(typeof(Regions.Jail))) { bad = true; break; } } if (bad) { for (int j = 0; j < part.Players.Count; ++j) ((Mobile)part.Players[j]).SendMessage("You have been disqualified from the tournament."); this.m_Undefeated.RemoveAt(i); if (this.m_Undefeated.Count == 1) { TournyParticipant winner = (TournyParticipant)this.m_Undefeated[0]; try { if (this.m_EventController != null) this.Alert("The tournament has completed!", String.Format("Team {0} has won", m_EventController.GetTeamName(((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf(winner)))); else if (this.m_TournyType == TournyType.RandomTeam) this.Alert("The tournament has completed!", String.Format("Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf(winner) + 1)); else if (this.m_TournyType == TournyType.RedVsBlue) this.Alert("The tournament has completed!", String.Format("Team {0} has won!", ((TournyMatch)((PyramidLevel)m_Pyramid.Levels[0]).Matches[0]).Participants.IndexOf(winner) == 0 ? "Red" : "Blue")); else this.Alert("The tournament has completed!", String.Format("{0} {1} the champion{2}.", winner.NameList, winner.Players.Count > 1 ? "are" : "is", winner.Players.Count == 1 ? "" : "s")); } catch { } this.GiveAwards(); this.m_Stage = TournamentStage.Inactive; this.m_Undefeated.Clear(); break; } } } if (this.m_Undefeated.Count > 1) this.m_Pyramid.AddLevel(this.m_ParticipantsPerMatch, this.m_Undefeated, this.m_GroupType, this.m_TournyType); } } } }
public Tournament(GenericReader reader) { int version = reader.ReadEncodedInt(); switch ( version ) { case 4: { this.m_EventController = reader.ReadItem() as EventController; goto case 3; } case 3: { this.m_SuddenDeathRounds = reader.ReadEncodedInt(); goto case 2; } case 2: { this.m_TournyType = (TournyType)reader.ReadEncodedInt(); goto case 1; } case 1: { this.m_GroupType = (GroupingType)reader.ReadEncodedInt(); this.m_TieType = (TieType)reader.ReadEncodedInt(); this.m_SignupPeriod = reader.ReadTimeSpan(); goto case 0; } case 0: { if (version < 3) this.m_SuddenDeathRounds = 3; this.m_ParticipantsPerMatch = reader.ReadEncodedInt(); this.m_PlayersPerParticipant = reader.ReadEncodedInt(); this.m_SignupPeriod = reader.ReadTimeSpan(); this.m_Stage = TournamentStage.Inactive; this.m_Pyramid = new TournyPyramid(); this.m_Ruleset = new Ruleset(RulesetLayout.Root); this.m_Ruleset.ApplyDefault(this.m_Ruleset.Layout.Defaults[0]); this.m_Participants = new ArrayList(); this.m_Undefeated = new ArrayList(); this.m_Arenas = new ArrayList(); break; } } Timer.DelayCall(SliceInterval, SliceInterval, new TimerCallback(Slice)); }
//this function generate the matches for the final stages public bool GenerateFinalsMatches(int tournamentID) { CupDBContainer db = new CupDBContainer(); Tournament t = db.TournamentSet.Find(tournamentID); foreach (Division d in t.Divisions) { //get all pools that are auto generated List<Pool> finalsPools = d.Pools.Where(x => x.IsAuto).ToList(); foreach (Pool finalPool in finalsPools) { if (finalPool.Teams.Count <2) { throw new Exception("not enough teams"); } List<Team> teams = new List<Team>(); teams.AddRange(finalPool.Teams); //if finals are round robin same as above if (d.TournamentStructure == TournamentStructure.RoundRobin) { TournamentStage tStage = new TournamentStage(); tStage = db.TournamentStageSet.Add(new TournamentStage() { Pool = finalPool, DivisionTournament = d.DivisionTournament, TournamentStructure = d.TournamentStructure, TimeInterval = new TimeInterval() { StartTime = DateTime.MinValue, EndTime = t.TimeIntervals.Last().EndTime } }); for (int k = 0; k < teams.Count; k++) { for (int l = k + 1; l < teams.Count; l++) { db.MatchSet.Add(new Match() { Teams = { teams[k], teams[l] }, TournamentStage = tStage, Duration = d.MatchDuration, Number = matchNumber++ }); } } } //if finals are knockout else { Pool KOPool = new Pool(); TournamentStage tournyStage = new TournamentStage(); int pow = 0; //counts up so 2^pow is as close to but not below the number of teams while (Math.Pow(2, pow) <= teams.Count) { pow++; } // gets the number of teams that fit into a normal knockout stage int powOfTwo = (int)Math.Pow(2, pow - 1); // if this number is lower than the actual number of teams if (powOfTwo < teams.Count) { //number of teams that need to compete an extra round to qualify int numOfExtraTeams = (teams.Count - powOfTwo) * 2; //order the list after poolplacement and take the worst seeded teams from the list and into extraTeams teams = teams.OrderByDescending(x => x.PoolPlacement).ToList(); List<Team> extraTeams = new List<Team>(); extraTeams.AddRange(teams.Take(numOfExtraTeams)); teams = teams.Skip(numOfExtraTeams).ToList(); //determine what kind of extra round is needed to get the number of teams down to 2^pow-1 switch (powOfTwo) { case 2: KOPool = db.PoolSet.Add(new Pool() { Name = finalPool.Name + " semi finaler", Division = d, IsAuto = true }); break; case 4: KOPool = db.PoolSet.Add(new Pool() { Name = finalPool.Name + " kvart finaler", Division = d, IsAuto = true }); break; default: KOPool = db.PoolSet.Add(new Pool() { Name = finalPool.Name + " " + powOfTwo + ". dels finaler", Division = d, IsAuto = true }); break; } tournyStage = db.TournamentStageSet.Add(new TournamentStage() { Pool = KOPool, DivisionTournament = d.DivisionTournament, TournamentStructure = d.TournamentStructure, TimeInterval = new TimeInterval() { StartTime = DateTime.MinValue, EndTime = t.TimeIntervals.Last().EndTime } }); //matches the first teams agains the last to get the worst seeds to play agains the best // each match generated also generates a team representing the winner and adds it back to the original teams list for (int i = 0; i < extraTeams.Count; i++) { if (extraTeams[i].Matches.Count == 0) { for (int j = extraTeams.Count - 1; j > i; j--) { //makes sure the teams are not from the same pool if (extraTeams[i].PrevPool != extraTeams[j].PrevPool && extraTeams[j].Matches.Count == 0) { Team winnerTeam = new Team() { Name = "Vinder af kamp " + matchNumber, IsAuto = true, PrevPool = KOPool }; teams.Add(winnerTeam); Match m = db.MatchSet.Add(new Match() { Teams = { extraTeams[i], extraTeams[j] }, Duration = d.MatchDuration, TournamentStage = tournyStage, Number = matchNumber++ }); break; } } // if the team didnt get set up for a match, every other team that does not already have a match must be from the same pool // therefor we just match the best and worst team against each other if (extraTeams[i].Matches.Count == 0) { for (int j = extraTeams.Count - 1; j > i; j--) { if (extraTeams[j].Matches.Count == 0) { Team winnerTeam = new Team() { Name = "Vinder af kamp " + matchNumber, IsAuto = true, PrevPool = KOPool }; teams.Add(winnerTeam); Match m = db.MatchSet.Add(new Match() { Teams = { extraTeams[i], extraTeams[j] }, Duration = d.MatchDuration, TournamentStage = tournyStage, Number = matchNumber++ }); break; } } } } extraTeams[i].Pool = KOPool; db.TeamSet.Add(extraTeams[i]); extraTeams[i].TimeIntervals = SameTimeInterval(extraTeams[i].PrevPool); } } List<Team> teamsToAdd = new List<Team>(); //this while loop keeps going untill there is no more teams // each round all the teams are taken from the list, which makes it empty // but the winners of all matches generated this iteration gets added back into the team list // this continues untill only two teams are left and no more teams are added back into the team list while (teams.Count > 0) { teamsToAdd.AddRange(teams); teams.Clear(); //determines the kind of round we have gotten to at this point switch (teamsToAdd.Count) { case 1: throw new Exception("Not enough teams"); case 2: KOPool = db.PoolSet.Add(new Pool() { Name = finalPool.Name + " finale", Division = d, IsAuto = true }); break; case 4: KOPool = db.PoolSet.Add(new Pool() { Name = finalPool.Name + " semi finaler", Division = d, IsAuto = true }); break; case 8: KOPool = db.PoolSet.Add(new Pool() { Name = finalPool.Name + " kvart finaler", Division = d, IsAuto = true }); break; default: KOPool = db.PoolSet.Add(new Pool() { Name = finalPool.Name + " " + teamsToAdd.Count / 2 + ". dels finaler", Division = d, IsAuto = true }); break; } if (teams.Count != 1) { tournyStage = db.TournamentStageSet.Add(new TournamentStage() { Pool = KOPool, DivisionTournament = d.DivisionTournament, TournamentStructure = d.TournamentStructure, TimeInterval = new TimeInterval() { StartTime = DateTime.MinValue, EndTime = t.TimeIntervals.Last().EndTime } }); // if there is 2 teams we are at the finals and no winner team should be added to the list, we are done if (teamsToAdd.Count == 2) { Match m = db.MatchSet.Add(new Match() { Teams = { teamsToAdd[0], teamsToAdd[1] }, Duration = d.MatchDuration, TournamentStage = tournyStage, Number = matchNumber++ }); teamsToAdd[0].Pool = KOPool; teamsToAdd[1].Pool = KOPool; db.TeamSet.AddRange(teamsToAdd); teamsToAdd[0].TimeIntervals = SameTimeInterval(teamsToAdd[0].PrevPool); teamsToAdd[1].TimeIntervals = SameTimeInterval(teamsToAdd[1].PrevPool); } else { //same procedure as above for (int i = 0; i < teamsToAdd.Count; i++) { if (teamsToAdd[i].Matches.Count == 0) { for (int j = teamsToAdd.Count - 1; j > i; j--) { if (teamsToAdd[i].PrevPool != teamsToAdd[j].PrevPool && teamsToAdd[j].Matches.Count == 0) { Team winnerTeam = new Team() { Name = "Vinder af kamp " + matchNumber, IsAuto = true, PrevPool = KOPool }; teams.Add(winnerTeam); Match m = db.MatchSet.Add(new Match() { Teams = { teamsToAdd[i], teamsToAdd[j] }, Duration = d.MatchDuration, TournamentStage = tournyStage, Number = matchNumber++ }); break; } } if (teamsToAdd[i].Matches.Count == 0) { for (int j = teamsToAdd.Count - 1; j > i; j--) { if (teamsToAdd[j].Matches.Count == 0) { Team winnerTeam = new Team() { Name = "Vinder af kamp " + matchNumber, IsAuto = true, PrevPool = KOPool }; teams.Add(winnerTeam); Match m = db.MatchSet.Add(new Match() { Teams = { teamsToAdd[i], teamsToAdd[j] }, Duration = d.MatchDuration, TournamentStage = tournyStage, Number = matchNumber++ }); break; } } } } teamsToAdd[i].Pool = KOPool; db.TeamSet.Add(teamsToAdd[i]); teamsToAdd[i].TimeIntervals = SameTimeInterval(teamsToAdd[i].PrevPool); } } } teamsToAdd.Clear(); db.SaveChanges(); } List<Team> teamsToClearUp = db.TeamSet.Where(x => x.Pool.Id == finalPool.Id).ToList(); foreach (Team team in teamsToClearUp) { db.TimeIntervalSet.RemoveRange(team.TimeIntervals); } db.TeamSet.RemoveRange(teamsToClearUp); db.PoolSet.Remove(finalPool); db.SaveChanges(); } } } db.SaveChanges(); return true; }
public static string CannotGoBack(TournamentStage stage) { return($"Cannot go back from the stage {stage}."); }
private IEnumerable <TeamDayResult> GetLeagueClassification(IDbConnection c, IDbTransaction t, TournamentStage stage, int daySequenceNumber) { var sql = @" SELECT tg.idGroup, t.id as idTeam, -1 as idDay, COALESCE(sum(gamesplayed), 0) as gamesplayed, COALESCE(sum(gameswon), 0) as gameswon, COALESCE(sum(gamesdraw), 0) as gamesdraw, COALESCE(sum(gameslost), 0) as gameslost, COALESCE(sum(points), 0) as points, COALESCE(sum(pointsAgainst), 0) as pointsAgainst, COALESCE(sum(pointdiff), 0) as pointdiff, COALESCE(sum(sanctions), 0) as sanctions, COALESCE(sum(tournamentpoints), 0) as tournamentpoints FROM teams t JOIN teamgroups tg ON tg.idteam = t.id AND tg.idstage = @idStage LEFT JOIN teamdayresults td ON td.idteam = t.id AND td.idStage = @idStage GROUP BY tg.idGroup, t.id, t.name ORDER BY tournamentpoints DESC, pointdiff DESC, gameswon DESC; "; var result = c.Query <TeamDayResult>(sql, new { idStage = stage.Id }, t); if (!string.IsNullOrWhiteSpace(stage.ClassificationCriteria)) { MatchFilter matchFilter = null; var criteria = JsonConvert.DeserializeObject <int[]>(stage.ClassificationCriteria); result = LeagueClassification.SortClassification(result, criteria, (teamA, teamB) => { if (matchFilter == null) { var matches = c.Query <Match>("SELECT idhometeam, idvisitorteam, homescore, visitorscore FROM matches WHERE idStage = @idStage", new { idStage = stage.Id }, t); if (matches == null) { throw new Exception("Error.NoMatches"); } matchFilter = new MatchFilter(matches.ToList()); } return(matchFilter.GetMatchesForTeams(teamA, teamB)); }); } return(result); }