// GET: Division/Details/5 - Fetches the details of the class, takes the "id" parameter to determine the corresponding Divison object. // Returns a Json object, which contains a copy of the corresponding Divisions variables. public ActionResult Details(int id) { try { Validator validator = new Validator(); Division d = db.DivisionSet.Find(id); Tournament tourny = db.TournamentSet.Find(d.Tournament.Id); List<object> pools = new List<object>(); List<object> teams = new List<object>(); List<object> matches = new List<object>(); List<object> finalslinks = new List<object>(); bool FrontendValidation = validator.IsScheduleReady(tourny.Id); bool enoughTeams = false; // For finalstage string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // Get all pools in the division and their teams if (d.Pools != null) { foreach (Pool p in d.Pools) { teams = new List<object>(); if (p.Teams.Count >= 2) { enoughTeams = true; } foreach (Team t in p.Teams) { teams.Add(new { Name = t.Name, Id = t.Id }); } pools.Add(new { Id = p.Id, Name = p.Name, Teams = teams }); } } // Get matches in division if (d.DivisionTournament != null && d.DivisionTournament.TournamentStage.Count > 0) { foreach (TournamentStage ts in d.DivisionTournament.TournamentStage) { if (ts.Matches.Count > 0) { foreach (Match m in ts.Matches) { Team team1 = m.Teams.ToList()[0]; Team team2 = m.Teams.ToList()[1]; matches.Add(new { Id = m.Id, Number = m.Number, StartTime = m.StartTime, /*FieldName = m.Field.Name,*/ Pool = new { Id = team1.Pool.Id, Name = team1.Pool.Name }, Team1 = new { name = team1.Name, Id = team1.Id }, Team2 = new { name = team2.Name, Id = team2.Id } }); } } } } // Get finals links if (d.FinalsLinks.Count > 0) { foreach (FinalsLink fl in d.FinalsLinks) { finalslinks.Add(new { Id = fl.Id, PoolPlacement = fl.PoolPlacement, Finalsstage = letters[fl.Finalstage - 1] }); } } object obj = new { status = "success", Id = d.Id, Name = d.Name, FinalsStage = d.TournamentStructure, Pools = pools, Teams = teams, FieldSize = d.FieldSize, MatchDuration = d.MatchDuration, Matches = matches, FinalsLinks = finalslinks, isValid = FrontendValidation, isTeamsValid = enoughTeams }; return Json(obj, JsonRequestBehavior.AllowGet); } catch (Exception ex) { return Json(new { status = "error", message = "Could not find division", details = ex.Message }, JsonRequestBehavior.AllowGet); } }
// tries to schedule every match in a tournament that is to be played on a field with size = fSize. // it is also restricted to numberOfFields number of fields public bool scheduleAll(int tournamentID, FieldSize fSize, int numberOfFields) { CupDBContainer db = new CupDBContainer(); MatchGeneration mg = new MatchGeneration(); Validator validator = new Validator(); Tournament t = db.TournamentSet.Find(tournamentID); //set op a list of every tournamentStage, a list of all group stage tournamentStages and a list of all matches List<TournamentStage> TournamentStages = db.TournamentStageSet.Where(x => x.DivisionTournament.Division.Tournament.Id == t.Id && x.DivisionTournament.Division.FieldSize == fSize).ToList(); List<TournamentStage> TournamentStagesToSchedule = TournamentStages.Where(x => !x.Pool.IsAuto).ToList(); List<Match> allMatches = db.MatchSet.Where(x => x.TournamentStage.DivisionTournament.Division.Tournament.Id == t.Id && x.TournamentStage.DivisionTournament.Division.FieldSize == fSize).ToList(); //selector is used to get the next tournamentStages in the list if the previous one was not usable int selector = 0; //dayCount restricts the number of days available for the algorithm at the start. it will be incremented as the algorithm goes on int dayCount = 1; //indicator is used to select either the first or the last match from a tournamentStage int indicator = 1; //IsScheduled is used to see if the algorithm is successfull bool IsScheduled = false; while (!IsScheduled) { //list of all unscheduled tournamentStages ordered by number of matches, in decending order List<TournamentStage> unscheduledTournamentstages = TournamentStagesToSchedule.Where(x => !x.IsScheduled).OrderByDescending(x => x.Matches.Count(y => !y.IsScheduled)).ToList(); //if there is no more unscheduled tournamentStages, we are either done with the groupstages of done with the shole schedule if (unscheduledTournamentstages.Count == 0) { if (TournamentStagesToSchedule.All(x => !x.Pool.IsAuto)) { TournamentStagesToSchedule.Clear(); TournamentStagesToSchedule = TournamentStages.Where(x => x.Pool.IsAuto).ToList(); continue; } else { IsScheduled = true; continue; } } //if after an update to the number of unscheduled tournamentstages the selector is out of range, reset it if (selector >= unscheduledTournamentstages.Count) { selector = 0; } // select the first tournamentStage in the list unless it is not usable use the next, if that is not usable select the next and so on. TournamentStage ts = unscheduledTournamentstages.ElementAt(selector); { //check if any teams has a previous pool that is not scheduled yet bool isReady = true; foreach (Team team in ts.Pool.Teams) { if (team.PrevPool == null) { continue; } else if (team.PrevPool.TournamentStage.IsScheduled) { if (ts.TimeInterval.StartTime < team.PrevPool.TournamentStage.TimeInterval.EndTime) { ts.TimeInterval.StartTime = team.PrevPool.TournamentStage.TimeInterval.EndTime; } } else { isReady = false; break; } } if (!isReady) { selector++; } else { //get all uncheduled matches in the tournamentStage List<Match> unscheduledMatches = ts.Matches.Where(x => !x.IsScheduled).ToList(); Match matchToSchedule; //set the tournamentStage to scheduled in there are no unscheduled matches if (unscheduledMatches.Count == 0) { DateTime lastMatchStart = ts.Matches.Max(x => x.StartTime); ts.TimeInterval.EndTime = lastMatchStart.AddMinutes(ts.DivisionTournament.Division.MatchDuration * 2); ts.IsScheduled = true; continue; } //select the first or last match else if (indicator > 0) { matchToSchedule = unscheduledMatches.First(); } else { matchToSchedule = unscheduledMatches.Last(); //if we get the last match increment selector. this is done such that we go to the next tournamentStage if this match is not schedule in the following code selector++; } //list of all fields List<Field> fields = matchToSchedule.TournamentStage.DivisionTournament.Division.Tournament.Fields.Where(x => x.Size == fSize).Take(numberOfFields).ToList(); List<Field> fieldsNotChecked = new List<Field>(); fieldsNotChecked.AddRange(fields); //goes through each day available so far for (int i = 0; i < dayCount; i++) { //order the fields by number of matches on the particular day fieldsNotChecked = fieldsNotChecked.OrderBy(x => x.Matches.Count(y => y.StartTime.Date == x.NextFreeTime.ElementAt(i).FreeTime.Date)).ToList(); //check is the match can be scheduled at any fields nextFreeTime foreach (Field field in fieldsNotChecked) { if (validator.areTeamsFree(matchToSchedule, field.NextFreeTime.ElementAt(i).FreeTime)) { matchToSchedule.StartTime = field.NextFreeTime.ElementAt(i).FreeTime; matchToSchedule.Field = field; field.NextFreeTime.ElementAt(i).FreeTime = field.NextFreeTime.ElementAt(i).FreeTime.AddMinutes(matchToSchedule.Duration); matchToSchedule.IsScheduled = true; db.Entry(field).State = System.Data.Entity.EntityState.Modified; break; } } if (matchToSchedule.IsScheduled) { break; } } // if the match is scheduled reset our selector and indicator if (matchToSchedule.IsScheduled) { indicator = 1; selector = 0; db.Entry(matchToSchedule).State = System.Data.Entity.EntityState.Modified; } } } // if we got through every tournamentStage and all of the where not usable, this will force a match into the schedule by adding minutes to the fields nextFreeTimes untill a mach will fit if (selector >= unscheduledTournamentstages.Count ) { List<Match> allUnscheduledMatches = allMatches.Where(x => !x.IsScheduled).ToList(); //newDayCount to force a match in at the first day possible int newDayCount = 1; // viriable to increase the nextFreeTimes for the fields int k = 0; //shile loop that keeps going untill a new match is scheduled or the algorithm fails bool done = false; List<Field> fields = allUnscheduledMatches.First().TournamentStage.DivisionTournament.Division.Tournament.Fields.Where(x => x.Size == fSize).Take(numberOfFields).ToList(); while (!done) { k += 10; //if every fields nextFreeTime added k minutes is passed the endtime of the tournament each give this part of the algorithm an extra day, give the shole algorithm an extra day or // return false if (fields.All(x => x.NextFreeTime.ElementAt(newDayCount - 1).FreeTime.AddMinutes(k) > t.TimeIntervals.ElementAt(newDayCount - 1).EndTime)) { if (newDayCount < dayCount) { newDayCount++; k = 0; continue; } else if (dayCount < t.TimeIntervals.Count()) { dayCount++; done = true; continue; } else { return false; } } // go through each match and see if it can be scheduled at any field with the added k minutes foreach (Match match in allUnscheduledMatches.Where(x => x.TournamentStage.TimeInterval.StartTime != DateTime.MinValue)) { List<Field> fieldsNotChecked = new List<Field>(); fieldsNotChecked.AddRange(fields); fieldsNotChecked = fieldsNotChecked.OrderBy(x => x.Matches.Count(y => y.StartTime.Date == x.NextFreeTime.ElementAt(newDayCount - 1).FreeTime.Date)).ToList(); foreach (Field field in fieldsNotChecked) { if (field.NextFreeTime.ElementAt(newDayCount - 1).FreeTime.AddMinutes(k) >= t.TimeIntervals.ElementAt(newDayCount - 1).EndTime) { continue; } if (validator.areTeamsFree(match, field.NextFreeTime.ElementAt(newDayCount - 1).FreeTime.AddMinutes(k))) { field.NextFreeTime.ElementAt(newDayCount - 1).FreeTime = field.NextFreeTime.ElementAt(newDayCount - 1).FreeTime.AddMinutes(k); match.StartTime = field.NextFreeTime.ElementAt(newDayCount - 1).FreeTime; match.Field = field; field.NextFreeTime.ElementAt(newDayCount - 1).FreeTime = field.NextFreeTime.ElementAt(newDayCount - 1).FreeTime.AddMinutes(match.Duration); match.IsScheduled = true; db.Entry(field).State = System.Data.Entity.EntityState.Modified; break; } } if (match.IsScheduled) { selector = 0; done = true; break; } } } } // get the indicator to the other side of 0 so we get the other end of the tournamentStages indicator *= -1; } db.SaveChanges(); return true; }
// GET: Tournament/Details/5 // Define a list with divisions, fields and times. // Going through all the divisiosns, add some divisions with name and id. // Return a JSON object if there is a tournamet with a password, id, name, fields and divisions. // If there doesnt exist a tournament it will return a JSON object and get a error. public ActionResult Details(int id) { try { Validator validator = new Validator(); Tournament t = db.TournamentSet.Find(id); List<object> divs = new List<object>(); List<object> fields = new List<object>(); List<object> times = new List<object>(); //isScheduleReady - for frontend use. bool FrontendValidation = validator.IsScheduleReady(t.Id); // Get all divisions if (t.Divisions != null) { foreach (Division d in t.Divisions) { divs.Add(new { Id = d.Id, Name = d.Name }); } } // Get all time intervals if (t.TimeIntervals != null) { foreach (TimeInterval ti in t.TimeIntervals) { times.Add(new { Id = ti.Id, StartTime = ti.StartTime, EndTime = ti.EndTime }); } } // Get all fields if (t.Fields != null) { foreach (Field f in t.Fields) { fields.Add(new { Id = f.Id, Name = f.Name, fieldSize = f.Size }); } } object obj = new { status = "success", Id = t.Id, Name = t.Name, Password = t.Password, Divisions = divs, TimeIntervals = times, Fields = fields, isValid = FrontendValidation, IsScheduled = t.IsScheduled }; return Json(obj, JsonRequestBehavior.AllowGet); } catch (Exception ex) { return Json(new { status = "error", message = "Could not find tournament", details = ex.Message }, JsonRequestBehavior.AllowGet); } }
// GET: Pool/Details/5 - The Details function will get the details of the Pool class, with the pools id as a parameter. // The function will get the details of the Teams, FavoriteFields and Matches for the pool. // A JSON object will be returned with the data and send an status message with it if it either have succeeded or failed. public ActionResult Details(int id) { try { Pool p = db.PoolSet.Find(id); Tournament tourny = db.TournamentSet.Find(p.Division.Tournament.Id); Validator validator = new Validator(); List<object> teams = new List<object>(); List<object> ffs = new List<object>(); List<object> matches = new List<object>(); bool FrontendValidation = validator.IsScheduleReady(tourny.Id); // Get teams in pool if (p.Teams != null) { foreach (Team t in p.Teams) { teams.Add(new { Id = t.Id, Name = t.Name }); } } // Get favorite fields in pool if (p.FavoriteFields != null) { foreach (Field f in p.FavoriteFields) { ffs.Add(new { Id = f.Id, Name = f.Name }); } } // Get matches in pool if (p.TournamentStage != null && p.TournamentStage.Matches.Count > 0) { foreach (Match m in p.TournamentStage.Matches) { Team team1 = m.Teams.ToList()[0]; Team team2 = m.Teams.ToList()[1]; matches.Add(new { Id = m.Id, Number = m.Number, StartTime = m.StartTime, FieldName = m.Field.Name, Team1 = new { name = team1.Name, Id = team1.Id }, Team2 = new { name = team2.Name, Id = team2.Id } }); } } object obj = new { status = "success", Id = p.Id, Name = p.Name, FieldSize = p.Division.FieldSize, Teams = teams, FavoriteFields = ffs, Matches = matches, isValid = FrontendValidation }; return Json(obj, JsonRequestBehavior.AllowGet); } catch (Exception ex) { return Json(new { status = "error", message = "Could not find pool", details = ex.Message }, JsonRequestBehavior.AllowGet); } }