Exemple #1
0
 public void Start()
 {
     if (Seed == -1)
     {
         Random random = new Random();
         Seed = random.Next();
     }
     Shuffled.Copy(Variation.Deck);
     Shuffled.Shuffle(Seed);
     Tableau.PrepareLayout(Shuffled);
 }
Exemple #2
0
        public void Shuffle()
        {
            Random rng = new Random();

            for (int i = 0; i < 5; ++i)
            {
                for (int j = 0; j < cards.Count; ++j)
                {
                    int  swapIndex = rng.Next(cards.Count);
                    Card temp      = cards[j];
                    cards[j]         = cards[swapIndex];
                    cards[swapIndex] = temp;
                }
            }

            Shuffled?.Invoke(this, EventArgs.Empty);
        }
        /**
         * <summary>
         * Runs the lottery algorithm for an individual school.
         * A specific list of applicants is used for the lottery run.
         * </summary>
         *
         * <remarks>TODO Optimize this later. There are a lot of repeated loops.</remarks>
         *
         * <param name="school">School to run the algorithm for</param>
         * <param name="applicantList">Applicants to use for selection in the lottery run</param>
         * <returns>The school passed in</returns>
         */
        public School Run(School school, List <Applicant> applicantList, bool shuffleApplicantList)
        {
            // Order the selected and waitlists by rank
            var selecteds          = school.Selecteds.OrderBy(s => s.Rank).ToList();
            var selectedApplicants = Utils.GetApplicants(selecteds);

            var waitlisteds          = school.Waitlisteds.OrderBy(w => w.Rank).ToList();
            var waitlistedApplicants = Utils.GetApplicants(waitlisteds);

            // Clear selected and waitlisteds
            db.Selecteds.RemoveRange(selecteds);
            db.Waitlisteds.RemoveRange(waitlisteds);

            // Counts the existing numbers of selected applicants for the school
            var countMale             = 0;
            var countFemale           = 0;
            var countBelowPovertyLine = 0;
            var countAbovePovertyLine = 0;

            foreach (var applicant in selectedApplicants)
            {
                // Gender counts
                if (applicant.StudentGender == Gender.Male)
                {
                    countMale++;
                }
                else
                {
                    countFemale++;
                }

                // Poverty counts
                if (incomeCalculator.IsBelowPovertyLine(applicant))
                {
                    countBelowPovertyLine++;
                }
                else
                {
                    countAbovePovertyLine++;
                }
            }

            // Initial calculations
            var numStudents         = school.Seats;
            var numMale             = (int)Math.Round(numStudents * school.GenderBalance);
            var numFemale           = numStudents - numMale;
            var numBelowPovertyLine = (int)Math.Round(numStudents * school.PovertyRate);
            var numAbovePovertyLine = numStudents - numBelowPovertyLine;

            // Copy the list to preserve the passed in list
            var applicants = new List <Applicant>(applicantList);


            // Randomly sort the list
            if (shuffleApplicantList)
            {
                // Clear existing shuffled (there really shouldn't be any) // TODO make a utility method for this
                var existingShuffleds = db.Shuffleds.Where(s => s.SchoolID == school.ID).ToList();
                db.Shuffleds.RemoveRange(existingShuffleds);

                // Randomly shuffle the applicants
                applicants.Shuffle(new Random());

                // Record the shuffling
                var shuffledApplicants = new List <Applicant>(applicants);

                // Preserve the shuffle order
                var shuffleds = new List <Shuffled>(shuffledApplicants.Count);
                for (var i = 0; i < shuffledApplicants.Count; i++)
                {
                    var shuffled = new Shuffled
                    {
                        Applicant = shuffledApplicants[i],
                        School    = school,
                        Rank      = i
                    };
                    shuffleds.Add(shuffled);
                }
                db.Shuffleds.AddRange(shuffleds);
                db.SaveChanges();
            }

            // Select low income students
            var lowIncomeApplicants = GetByPovertyStatus(applicants, true);

            foreach (var a in lowIncomeApplicants)
            {
                // If the low income quota has been met, move on
                if (countBelowPovertyLine >= numBelowPovertyLine || selectedApplicants.Count >= numStudents)
                {
                    break;
                }

                // Add the student if the male/female ratio hasn't been violated
                if (a.StudentGender == Gender.Male && countMale < numMale)
                {
                    selectedApplicants.Add(a);
                    applicants.Remove(a);

                    countBelowPovertyLine++;
                    countMale++;
                }
                else if (a.StudentGender == Gender.Female && countFemale < numFemale)
                {
                    selectedApplicants.Add(a);
                    applicants.Remove(a);

                    countBelowPovertyLine++;
                    countFemale++;
                }
            }

            // Do a second pass on the below poverty line students in case gender balance prevented it from getting fulfilled
            // RIDE: Income balance takes priority over male to female ratio
            // Gender agnostic, income checked pass
            if (countBelowPovertyLine < numBelowPovertyLine)
            {
                lowIncomeApplicants = GetByPovertyStatus(applicants, true);
                foreach (var a in lowIncomeApplicants)
                {
                    // If the low income quota has been met, move on
                    if (countBelowPovertyLine >= numBelowPovertyLine || selectedApplicants.Count >= numStudents)
                    {
                        break;
                    }

                    // Add the student
                    if (a.StudentGender == Gender.Male)
                    {
                        selectedApplicants.Add(a);
                        applicants.Remove(a);

                        countBelowPovertyLine++;
                        countMale++;
                    }
                    else if (a.StudentGender == Gender.Female)
                    {
                        selectedApplicants.Add(a);
                        applicants.Remove(a);

                        countBelowPovertyLine++;
                        countFemale++;
                    }
                }
            }

            // Select higher income students
            // TODO refactor -- almost the same as the above loop
            var higherIncomeApplicants = GetByPovertyStatus(applicants, false);

            foreach (var a in higherIncomeApplicants)
            {
                // If the higher income quota has been met, move on
                if (countAbovePovertyLine >= numAbovePovertyLine || selectedApplicants.Count >= numStudents)
                {
                    break;
                }

                // Add the student if the male/female ratio hasn't been violated
                if (a.StudentGender == Gender.Male && countMale < numMale)
                {
                    selectedApplicants.Add(a);
                    applicants.Remove(a);

                    countAbovePovertyLine++;
                    countMale++;
                }
                else if (a.StudentGender == Gender.Female && countFemale < numFemale)
                {
                    selectedApplicants.Add(a);
                    applicants.Remove(a);

                    countAbovePovertyLine++;
                    countFemale++;
                }
            }

            // Do a second pass on the above poverty line students in case gender balance prevented it from getting fulfilled
            // RIDE: Income balance takes priority over male to female ratio
            // Gender agnostic, income checked pass
            if (countAbovePovertyLine < numAbovePovertyLine)
            {
                higherIncomeApplicants = GetByPovertyStatus(applicants, false);
                foreach (var a in higherIncomeApplicants)
                {
                    // If the low income quota has been met, move on
                    if (countAbovePovertyLine >= numAbovePovertyLine || selectedApplicants.Count >= numStudents)
                    {
                        break;
                    }

                    // Add the student
                    if (a.StudentGender == Gender.Male)
                    {
                        selectedApplicants.Add(a);
                        applicants.Remove(a);

                        countBelowPovertyLine++;
                        countMale++;
                    }
                    else if (a.StudentGender == Gender.Female)
                    {
                        selectedApplicants.Add(a);
                        applicants.Remove(a);

                        countBelowPovertyLine++;
                        countFemale++;
                    }
                }
            }

            // Are there still openings? (income agnostic, gender checked selection)
            foreach (var a in new List <Applicant>(applicants)) // prevents modification during iteration
            {
                if (selectedApplicants.Count >= numStudents)
                {
                    break;
                }

                //TODO refactor -- this chunk of code is similar to other male/female selections
                // Add the student if the male/female ratio hasn't been violated
                if (a.StudentGender == Gender.Male && countMale < numMale)
                {
                    selectedApplicants.Add(a);
                    applicants.Remove(a);

                    countMale++;
                }
                else if (a.StudentGender == Gender.Female && countFemale < numFemale)
                {
                    selectedApplicants.Add(a);
                    applicants.Remove(a);

                    countFemale++;
                }
            }

            // Are there still openings? (income and gender agnostic selection)
            foreach (var a in new List <Applicant>(applicants))
            {
                if (selectedApplicants.Count >= numStudents)
                {
                    break;
                }

                selectedApplicants.Add(a);
                applicants.Remove(a);
            }

            // Wait list the rest
            waitlistedApplicants.Clear();
            waitlistedApplicants.AddRange(applicants);

            // Preserve the ranks
            var newSelecteds = new List <Selected>(selectedApplicants.Count);

            for (var i = 0; i < selectedApplicants.Count; i++)
            {
                var selected = new Selected
                {
                    Applicant = selectedApplicants[i],
                    School    = school,
                    Rank      = i
                };
                newSelecteds.Add(selected);
            }
            db.Selecteds.AddRange(newSelecteds);

            var newWaitlisteds = new List <Waitlisted>(waitlistedApplicants.Count);

            for (var i = 0; i < waitlistedApplicants.Count; i++)
            {
                var waitlisted = new Waitlisted
                {
                    Applicant = waitlistedApplicants[i],
                    School    = school,
                    Rank      = i
                };
                newWaitlisteds.Add(waitlisted);
            }
            db.Waitlisteds.AddRange(newWaitlisteds);


            db.SaveChanges();


            return(school);
        }
Exemple #4
0
 public async Task Shuffle()
 {
     Thread.Sleep(500);
     PokerService.Instance.Shuffle();
     await Shuffled?.Invoke(this);
 }
Exemple #5
0
 public void Clear()
 {
     Shuffled.Clear();
     Tableau.Clear();
 }