Esempio n. 1
0
 public ViewModel(RoundTeamMatchup Parent)
 {
     _Parent = Parent;
 }
Esempio n. 2
0
        public ActionResult GenerateConfirmed()
        {
            if (Session["SelectedEventId"] == null) return Redirect("Events");
            if (Session["SelectedRoundId"] == null) return Redirect("Rounds");

            int RoundID = 0;
            int.TryParse(Session["SelectedRoundId"].ToString(), out RoundID);
            int EventID = 0;
            int.TryParse(Session["SelectedEventId"].ToString(), out EventID);

            int RoundNumber = (from p in db.Rounds where p.RoundId == RoundID && p.EventId == EventID select p.Sequence).First ();


            //Ensure the Bye team exists and remove all existing player and team matchups for the round
            PerformPreGenerateDataCleanup(EventID, RoundID);
                        
            //Hold a list of Teams and the number of Wins they have
            Dictionary<Team, int> TeamWins = GenerateTeamWins(EventID);
            
            // remove drops
            foreach (var team in (from p in TeamWins where p.Key.DropRound >= RoundNumber select p).ToList())
                TeamWins.Remove(team.Key );
            
            var UnPairedTeams = (from p in TeamWins select p.Key).ToList();
         
            var rand = new Random();
            var RetryCount = 0;


            // this loop will continue until all teams have been successfully paired. 
            // If something prevents a full pairing (crap random # generator, or invalid data, or a bug) it will try to run the pairings engine 5 times before failing.
            while (UnPairedTeams.Count > 0 )
            {
                //clear bye/pairdown for this round
                var q = (from p in UnPairedTeams where p.ByeRound == RoundNumber select p);
                foreach (var p in q)
                    p.ByeRound = null;
                q = (from p in UnPairedTeams where p.PairedDownRound == RoundNumber select p);
                foreach (var p in q)
                    p.PairedDownRound = null;
                
                //check for multiple/max attempts 
                RetryCount += 1;
                if (RetryCount>0)
                {
                    TeamWins = GenerateTeamWins(EventID);
                    // remove drops
                    foreach (var team in (from p in TeamWins where p.Key.DropRound >= RoundNumber select p).ToList())
                        TeamWins.Remove(team.Key);
                }
                if (RetryCount > 5)
                {
                    //Something is preventing all pairings
                    throw new Exception("Unable to complete pairings! Please use manual Round Team Matchups.");
                }


                try
                {
                    var Wins = (from p in TeamWins orderby p.Value descending select p.Value).FirstOrDefault();

                    while (Wins >= -1)
                    {
                        // Pre pairing cleanup, identify pairdown and byes
                        var AvailableTeams = (from p in TeamWins where p.Value == Wins select p).ToList();

                        // If we're in the 0 wins group and there are an odd number of teams, drop the BYE team
                        if (Wins == 0 && AvailableTeams.Count() % 2 == 1)
                        {
                            var ByeTeam = (from p in AvailableTeams where p.Key.Name == "BYE" select p).First ();
                            AvailableTeams.Remove(ByeTeam);
                            TeamWins.Remove(ByeTeam.Key );
                            UnPairedTeams.Remove(ByeTeam.Key );
                        }

                        if (AvailableTeams.Count() % 2 != 0)
                        {
                            //Pairdown Logic
                            var PairdownCandidates = from p in AvailableTeams where p.Key.PairedDownRound == null select p.Key;
                            var Pairdown = PairdownCandidates.ElementAt(rand.Next(PairdownCandidates.Count()));
                            Pairdown.PairedDownRound = RoundNumber;
                            TeamWins[Pairdown] -= 1; //force the team into the next lower wins bucket
                                
                            AvailableTeams = (from p in TeamWins where p.Value == Wins select p).ToList();
                        }

                        // Find pairings for all available teams (in this win bucket)
                        while (AvailableTeams.Count > 0)
                        {

                            // get a random team from this wins bucket (or Bye if it's available)
                            var Team1 = AvailableTeams.ElementAt(rand.Next(AvailableTeams.Count()));
                            if ((from p in AvailableTeams where p.Key.Name == "BYE" select p).Count () > 0)
                            {
                                Team1 = (from p in AvailableTeams where p.Key.Name == "BYE" select p).First();
                            }
                            
                            // build a list of previous opponents
                            var PreviousOpponents = (from p in db.RoundTeamMatchups where p.Team1.TeamId == Team1.Key.TeamId select p.Team2).ToList();
                            PreviousOpponents.AddRange((from p in db.RoundTeamMatchups where p.Team2.TeamId == Team1.Key.TeamId select p.Team1).ToList());

                            // pull a list of possible opponents (teams in this win bucket excluding previous opponents)
                            var AvailableOpponents = (from p in AvailableTeams where !PreviousOpponents.Contains(p.Key) && p.Key != Team1.Key select p).ToList();
                            if (AvailableOpponents.Count() == 0)
                            {
                                // something really bad just happened.
                                throw new Exception("No valid opponents.");
                            }

                            // get a random team from the available opponents bucket
                            var Team2 = AvailableOpponents.ElementAt(rand.Next(AvailableOpponents.Count()));

                            // get a list of all tablezones played on by either team
                            var PreviousTables = (from p in db.RoundTeamMatchups where p.Team1Id == Team1.Key.TeamId || p.Team2Id == Team1.Key.TeamId || p.Team1Id == Team2.Key.TeamId || p.Team2Id == Team2.Key.TeamId select p.TableZone).ToList();

                            // get a list of all tablezones in use thie round
                            var UsedTables = (from p in db.RoundTeamMatchups where p.RoundId == RoundID select p.TableZone).ToList();

                            // get the max tablezone #
                            var MaxTableZoneNumber = ((from p in db.Teams where p.EventId == EventID select p).Count() / 2 +1);

                            // get a list of ALL tables
                            var AvailableTables = Enumerable.Range(1, MaxTableZoneNumber).ToList();

                            // Get all tables not currently in use
                            AvailableTables = (from p in AvailableTables where !UsedTables.Contains(p) select p).ToList();

                            var FreshTables = (from p in AvailableTables where !PreviousTables.Contains(p) select p).ToList();
                            if (FreshTables.Count() == 0)
                            {
                                // No fresh tables available, someone is getting a repeat
                                FreshTables = AvailableTables;
                            }
                            if (FreshTables.Count() == 0)
                            {
                                // Something really bad just happened. 
                                throw new Exception("No valid tables.");
                            }

                            var Table = FreshTables.ElementAt(rand.Next(FreshTables.Count()));

                            // save the pairing
                            var RoundTeamMatchup = new RoundTeamMatchup();
                            RoundTeamMatchup.RoundId = RoundID;
                            RoundTeamMatchup.Team1Id = Team1.Key.TeamId;
                            RoundTeamMatchup.Team2Id = Team2.Key.TeamId;
                            RoundTeamMatchup.TableZone = Table;
                            db.RoundTeamMatchups.Add(RoundTeamMatchup);

                            if (Team1.Key.Name=="BYE")
                            {
                                Team2.Key.ByeRound = RoundNumber;
                                var ByePlayer = (from p in db.Players where p.Team.Name == "BYE" && p.Team.EventId == EventID select p).First();
                                var Players = (from p in db.Players where p.TeamId == Team2.Key.TeamId select p);
                                foreach (var player in Players )
                                {
                                    var matchup = new Matchup();
                                    matchup.Player1Id = ByePlayer.PlayerId;
                                    matchup.Player2Id = player.PlayerId;
                                    matchup.WinnerId = player.PlayerId;
                                    matchup.Player2APD = 50;
                                    matchup.Player2CP = 3;
                                    db.Matchups.Add(matchup);
                                }
                            }
                            
                            db.SaveChanges();

                            //Cleanup for next pass
                            AvailableTeams.Remove(Team1);
                            AvailableTeams.Remove(Team2);
                            UnPairedTeams.Remove(Team1.Key);
                            UnPairedTeams.Remove(Team2.Key);
                        }
                        Wins -= 1;
                    }
                }
                catch { }
            }

            return RedirectToAction("Index", "RoundTeamMatchups");
        }