Пример #1
0
        public void ComposeBallots(BallotCompositionMethod method)
        {
            FinalBallots = new Dictionary<int, MeetingElectionCandidates>();

            QuotedMasterList = GenerateBallot(rawElectionResult, -1, BallotCompositionMethod.Unmixed);
            if (geographicLists.Count == 0)
            {
                GenerateGeographicLists();
            }

            foreach (Geography ballotGeography in BallotGeographies)
            {
                FinalBallots[ballotGeography.Identity] = GenerateBallot(geographicLists[ballotGeography.Identity], 22,
                                                                        method);
            }
        }
Пример #2
0
        public void ComposeBallots(BallotCompositionMethod method)
        {
            FinalBallots = new Dictionary <int, MeetingElectionCandidates>();

            QuotedMasterList = GenerateBallot(rawElectionResult, -1, BallotCompositionMethod.Unmixed);
            if (geographicLists.Count == 0)
            {
                GenerateGeographicLists();
            }

            foreach (Geography ballotGeography in BallotGeographies)
            {
                FinalBallots[ballotGeography.Identity] = GenerateBallot(geographicLists[ballotGeography.Identity], 22,
                                                                        method);
            }
        }
Пример #3
0
        /// <summary>
        ///     Gets the position of the master list to use for this position on the local list.
        /// </summary>
        /// <param name="currentPosition">The position of a particular ballot.</param>
        /// <param name="method">The composition method to use.</param>
        /// <returns>The position to pick from the master list, or zero if not from the master list.</returns>
        private int GetMasterListPosition(int currentPosition, BallotCompositionMethod method)
        {
            if (method == BallotCompositionMethod.Unmixed)
            {
                return(0); // always use local
            }

            if (method == BallotCompositionMethod.TopTenNational)
            {
                if (currentPosition <= 10)
                {
                    return(currentPosition);
                }

                return(0);
            }

            if (method == BallotCompositionMethod.TopFiveNational)
            {
                if (currentPosition <= 5)
                {
                    return(currentPosition);
                }

                return(0);
            }

            if (method == BallotCompositionMethod.InterleavedTenNational)
            {
                if ((currentPosition % 2 == 1) && currentPosition < 20)
                {
                    return(currentPosition / 2 + 1);
                }

                return(0);
            }

            throw new NotImplementedException("Unimplemented method");
        }
Пример #4
0
        private MeetingElectionCandidates GenerateBallot(MeetingElectionCandidates rawList, int candidateCount,
                                                         BallotCompositionMethod method)
        {
            MeetingElectionCandidates result          = new MeetingElectionCandidates();
            Dictionary <int, bool>    takenCandidates = new Dictionary <int, bool>();

            if (candidateCount == -1)
            {
                candidateCount = rawList.Count;
            }

            // First, cancel out the defected candidates. Expensive op, but don't care.

            for (int rawIndex = 0; rawIndex < rawList.Count; rawIndex++)
            {
                if (CandidatePersonIdDefected(rawList[rawIndex].PersonId))
                {
                    takenCandidates[rawIndex] = true;
                }
            }

            if (candidateCount == rawList.Count)
            {
                candidateCount -= takenCandidates.Count;
            }

            // Assemble list.

            while (result.Count < candidateCount)
            {
                // Add a candidate.
                //
                // Should we add a candidate from the raw list or from the quoted master list?

                int masterPosition = GetMasterListPosition(result.Count + 1, method);

                if (masterPosition > 0)
                {
                    // We should add a candidate from the master list, no quota calculations, BUT ONLY if this candidate
                    // hasn't already been added from the district list.

                    int rawListIndex = FindCandidateIndex(QuotedMasterList[masterPosition - 1].InternalPollCandidateId,
                                                          rawList);

                    if (rawListIndex >= 0 && !takenCandidates.ContainsKey(rawListIndex))
                    {
                        // The master list candidate is also on the district list, but has not been added. Add
                        // the candidate in the master list position.

                        result.Add(QuotedMasterList[masterPosition - 1]);
                        takenCandidates[rawListIndex] = true;
                        continue;
                    }

                    if (rawListIndex == -1)
                    {
                        // The master list candidate is not on the district list. Add the candidate.

                        result.Add(QuotedMasterList[masterPosition - 1]);
                        continue;
                    }

                    // Getting here, the candidate on the master position had already been placed on the list through his
                    // or her district, so fallthrough to local candidates for this master position
                }

                // Add a candidate from the local list. First, try adding the next available candidate.
                // If this puts us outside of the allowed gender quota, pick the next candidate of the
                // underrepresented gender instead.

                int nextCandidateIndex = 0;

                while (takenCandidates.ContainsKey(nextCandidateIndex))
                {
                    nextCandidateIndex++;
                }

                PersonGender candidateGender = rawList[nextCandidateIndex].Person.Gender;

                double currentMaleQuota = CalculateListMaleQuota(result, candidateGender);

                // Here, we account an extremely rare situation where the correct quota is not even obtainable, e.g.
                // for position #3 where #1 is male and #2 is female and with a quota of 40%. Either way, it will
                // fall outside of bounds (33% or 66%). If so, ignore the quota if it is not obtainable.

                PersonGender oppositeGender = (candidateGender == PersonGender.Male
                    ? PersonGender.Female
                    : PersonGender.Male);

                double alternateMaleQuota = CalculateListMaleQuota(result, oppositeGender);

                // If currentMaleQuota is outside of bounds AND the alternate quota IS inside of bounds...

                if (currentMaleQuota < GenderQuota || currentMaleQuota > (1.0 - GenderQuota))
                {
                    if (alternateMaleQuota >= GenderQuota && alternateMaleQuota <= (1.0 - GenderQuota))
                    {
                        // ...pick the alternate (underrepresented) candidate

                        try
                        {
                            nextCandidateIndex = GetNextSpecificGenderCandidate(rawList, takenCandidates,
                                                                                oppositeGender);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            // there isn't any more candidate of the requested gender, so go with what we have
                        }
                    }
                }

                result.Add(rawList[nextCandidateIndex]);
                takenCandidates[nextCandidateIndex] = true;
            }

            return(result);
        }
Пример #5
0
        /// <summary>
        /// Gets the position of the master list to use for this position on the local list.
        /// </summary>
        /// <param name="currentPosition">The position of a particular ballot.</param>
        /// <param name="method">The composition method to use.</param>
        /// <returns>The position to pick from the master list, or zero if not from the master list.</returns>
        private int GetMasterListPosition (int currentPosition, BallotCompositionMethod method)
        {
            if (method == BallotCompositionMethod.Unmixed)
            {
                return 0; // always use local
            }

            if (method == BallotCompositionMethod.TopTenNational)
            {
                if (currentPosition <= 10)
                {
                    return currentPosition;
                }

                return 0;
            }

            if (method == BallotCompositionMethod.TopFiveNational)
            {
                if (currentPosition <= 5)
                {
                    return currentPosition;
                }

                return 0;
            }

            if (method == BallotCompositionMethod.InterleavedTenNational)
            {
                if ((currentPosition % 2 == 1) && currentPosition < 20)
                {
                    return (currentPosition/2 + 1);
                }

                return 0;
            }

            throw new NotImplementedException("Unimplemented method");
        }
Пример #6
0
        private MeetingElectionCandidates GenerateBallot (MeetingElectionCandidates rawList, int candidateCount, BallotCompositionMethod method)
        {
            MeetingElectionCandidates result = new MeetingElectionCandidates();
            Dictionary<int, bool> takenCandidates = new Dictionary<int, bool>();

            if (candidateCount == -1)
            {
                candidateCount = rawList.Count;
            }

            // First, cancel out the defected candidates. Expensive op, but don't care.

            for (int rawIndex = 0; rawIndex < rawList.Count; rawIndex++)
            {
                if (this.CandidatePersonIdDefected(rawList [rawIndex].PersonId))
                {
                    takenCandidates[rawIndex] = true;
                }
            }

            if (candidateCount == rawList.Count)
            {
                candidateCount -= takenCandidates.Count;
            }

            // Assemble list.

            while (result.Count < candidateCount)
            {
                // Add a candidate.
                //
                // Should we add a candidate from the raw list or from the quoted master list?

                int masterPosition = GetMasterListPosition (result.Count + 1, method);

                if (masterPosition > 0)
                {
                    // We should add a candidate from the master list, no quota calculations, BUT ONLY if this candidate
                    // hasn't already been added from the district list.

                    int rawListIndex = FindCandidateIndex (QuotedMasterList[masterPosition - 1].InternalPollCandidateId,
                                                     rawList);

                    if (rawListIndex >= 0 && !takenCandidates.ContainsKey(rawListIndex))
                    {
                        // The master list candidate is also on the district list, but has not been added. Add
                        // the candidate in the master list position.

                        result.Add(QuotedMasterList[masterPosition - 1]);
                        takenCandidates[rawListIndex] = true;
                        continue;
                    }

                    if (rawListIndex == -1)
                    {
                        // The master list candidate is not on the district list. Add the candidate.

                        result.Add(QuotedMasterList[masterPosition - 1]);
                        continue;
                    }

                    // Getting here, the candidate on the master position had already been placed on the list through his
                    // or her district, so fallthrough to local candidates for this master position
                }

                // Add a candidate from the local list. First, try adding the next available candidate.
                // If this puts us outside of the allowed gender quota, pick the next candidate of the 
                // underrepresented gender instead.

                int nextCandidateIndex = 0;

                while (takenCandidates.ContainsKey(nextCandidateIndex))
                {
                    nextCandidateIndex++;
                }

                PersonGender candidateGender = rawList[nextCandidateIndex].Person.Gender;

                double currentMaleQuota = CalculateListMaleQuota(result, candidateGender);

                // Here, we account an extremely rare situation where the correct quota is not even obtainable, e.g. 
                // for position #3 where #1 is male and #2 is female and with a quota of 40%. Either way, it will
                // fall outside of bounds (33% or 66%). If so, ignore the quota if it is not obtainable.

                PersonGender oppositeGender = (candidateGender == PersonGender.Male
                                                   ? PersonGender.Female
                                                   : PersonGender.Male);

                double alternateMaleQuota = CalculateListMaleQuota(result, oppositeGender);

                // If currentMaleQuota is outside of bounds AND the alternate quota IS inside of bounds...

                if (currentMaleQuota < GenderQuota || currentMaleQuota > (1.0 - GenderQuota))
                {
                    if (alternateMaleQuota >= GenderQuota && alternateMaleQuota <= (1.0 - GenderQuota))
                    {
                        // ...pick the alternate (underrepresented) candidate

                        try
                        {
                            nextCandidateIndex = GetNextSpecificGenderCandidate(rawList, takenCandidates, oppositeGender);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            // there isn't any more candidate of the requested gender, so go with what we have
                        }
                    }
                }

                result.Add(rawList[nextCandidateIndex]);
                takenCandidates[nextCandidateIndex] = true;
                
            }

            return result;
        }