private static double CalculateListMaleQuota(MeetingElectionCandidates candidates, PersonGender nextCandidateGender) { if (candidates.Count < 1) { return(0.5); // Division by zero protection, here and in caller } double malesTotal = 0.0; foreach (MeetingElectionCandidate candidate in candidates) { if (candidate.Person.Gender == PersonGender.Male) { malesTotal += 1.0; } } if (nextCandidateGender == PersonGender.Male) { malesTotal += 1.0; } return(malesTotal / (candidates.Count + 1.0)); }
private static void MailRawElectionResults(MeetingElection poll, SchulzeProcessor processor, bool stillOpen) { MeetingElectionCandidates candidates = processor.FinalOrder; Dictionary <int, bool> dropoutLookup = new Dictionary <int, bool>(); // TODO SOMETIME: implement and populate dropouts here string body = "These are " + (stillOpen ? "intermediate" : "THE FINAL") + " results for the poll \"" + poll.Name + "\". Note that the Dist field is purely informative and not part of the Schulze ranking.\r\n\r\n"; body += "Rank Dist Candidate\r\n"; for (int candidateIndex = 0; candidateIndex < candidates.Count; candidateIndex++) { int distance = processor.GetCandidateDistance(candidateIndex); body += String.Format("{0:D3}. {1} {2}{3}\r\n", candidateIndex + 1, (distance > 0 ? distance.ToString("D4") : "----"), candidates[candidateIndex].Person.Canonical, dropoutLookup.ContainsKey(candidates[candidateIndex].PersonId) ? " [hoppat av]" : string.Empty); } int[] recipients = new int[] { 1, poll.CreatedByPersonId }; // Send to Rick too while stabilizing functionality -- remove as soon as Rick is running in any poll string subject = (stillOpen ? "Intermediate" : "FINAL") + " results for poll - " + poll.Name; foreach (int personId in recipients) { Person.FromIdentity(personId).SendNotice( subject, body, Organization.PPSEid); } }
// Randomizes the order of candidates on the open polls. public static void Run() { // TODO: Foreach open poll... MeetingElectionCandidates candidates = MeetingElectionCandidates.ForPoll(MeetingElection.Primaries2010); foreach (MeetingElectionCandidate candidate in candidates) { candidate.RandomizeSortOrder(); } }
private static int FindCandidateIndex(int candidateId, MeetingElectionCandidates list) { for (int index = 0; index < list.Count; index++) { if (list[index].Identity == candidateId) { return(index); } } return(-1); }
private static int GetNextSpecificGenderCandidate(MeetingElectionCandidates candidates, Dictionary <int, bool> takenCandidates, PersonGender desiredGender) { int index = 0; while (takenCandidates.ContainsKey(index) || candidates[index].Person.Gender != desiredGender) { index++; // potential out-of-range exception here, if there aren't enough candidates } return(index); }
protected void Page_Load(object sender, EventArgs e) { MeetingElectionCandidates candidates = MeetingElectionCandidates.ForPoll(MeetingElection.Primaries2010); string pollIdString = Request.QueryString["PollId"]; if (!string.IsNullOrEmpty(pollIdString)) { int pollId = Int32.Parse(pollIdString); candidates = MeetingElectionCandidates.ForPoll(MeetingElection.FromIdentity(pollId)); } this.RepeaterCandidates.DataSource = candidates; this.RepeaterCandidates.DataBind(); }
protected void Page_Load(object sender, EventArgs e) { Dictionary <int, bool> personLookup = new Dictionary <int, bool>(); for (int pollId = 9; pollId <= 36; pollId++) { MeetingElectionCandidates candidates = MeetingElectionCandidates.ForPoll(MeetingElection.FromIdentity(pollId)); foreach (MeetingElectionCandidate candidate in candidates) { personLookup[candidate.PersonId] = true; } } foreach (int personId in personLookup.Keys) { this.LiteralMailAddresses.Text += Person.FromIdentity(personId).Email + "<br/>"; } }
public void PopulateLists(MeetingElection poll, string verificationCode) { MeetingElectionCandidates candidates = poll.Candidates; Dictionary <int, bool> lookup = new Dictionary <int, bool>(); if (!string.IsNullOrEmpty(verificationCode)) { MeetingElectionVote vote = MeetingElectionVote.FromVerificationCode(verificationCode); if (poll.Identity != vote.InternalPollId) { throw new ArgumentException("Verification Code does not exist or does not match Poll Identity"); } int[] candidateIds = vote.SelectedCandidateIdsInOrder; foreach (int candidateId in candidateIds) { lookup[candidateId] = true; MeetingElectionCandidate candidate = MeetingElectionCandidate.FromIdentity(candidateId); this.ListVote.Items.Add(new RadListBoxItem(candidate.Person.Canonical, candidate.Identity.ToString())); } } foreach (MeetingElectionCandidate candidate in candidates) { if (!lookup.ContainsKey(candidate.Identity)) { this.ListCandidates.Items.Add(new RadListBoxItem(candidate.Person.Canonical, candidate.Identity.ToString())); } } this.ListCandidates.DataBind(); }
protected void PersonCandidate_SelectedPersonChanged(object sender, EventArgs e) { Person candidate = this.PersonCandidate.SelectedPerson; int pollId = Int32.Parse(Request.QueryString["PollId"]); MeetingElection poll = MeetingElection.FromIdentity(pollId); this.ImageCandidatePhoto.ImageUrl = "http://data.piratpartiet.se/Handlers/DisplayPortrait.aspx?YSize=300&PersonId=" + candidate.Identity.ToString(); this.LabelCandidateName1.Text = this.LabelCandidateName2.Text = this.LabelCandidateName3.Text = candidate.Canonical; // Already running? MeetingElectionCandidates candidates = poll.Candidates; bool alreadyCandidate = false; foreach (MeetingElectionCandidate testCandidate in candidates) { if (candidate.PersonId == testCandidate.PersonId) { alreadyCandidate = true; break; } } this.PanelCandidacy.Visible = !alreadyCandidate; this.PanelAlreadyCandidate.Visible = alreadyCandidate; if (!alreadyCandidate) { this.TextBlogUrl.Text = candidate.BlogUrl; this.TextBlogName.Text = candidate.BlogName; this.TextPhotographer.Text = candidate.PortraitPhotographer; this.TextPersonalNumber.Text = candidate.PersonalNumber; } }
private void AssembleFinalOrder() { Console.WriteLine("Assembling final list."); MeetingElectionCandidates result = new MeetingElectionCandidates(); Dictionary<int, bool> candidateAdded = new Dictionary<int, bool>(); int candidatesRemaining = candidateIds.Count; int count = 1; while (candidatesRemaining > 0) { Console.Write("\r - remaining: {0:D4}", candidatesRemaining); // Find the first nontaken candidate int winningCandidateIndex = 0; while (candidateAdded.ContainsKey(winningCandidateIndex)) { winningCandidateIndex++; } // Iterate over all linkStrength[X,*] and [*,X]; this candidate is only a winner if // all [X,*] are >= all [*,X]. bool allSuperior = false; while (!allSuperior) { allSuperior = true; for (int compareCandidateIndex = 0; compareCandidateIndex < candidateIds.Count; compareCandidateIndex++) { if (candidateAdded.ContainsKey(compareCandidateIndex)) { continue; } if (linkStrengthXtoY[winningCandidateIndex, compareCandidateIndex] < linkStrengthXtoY[compareCandidateIndex,winningCandidateIndex]) { // the compareCandidateIndex had a greater link strength, so jump there and take it as // a new potential winner, restarting the comparison winningCandidateIndex = compareCandidateIndex; allSuperior = false; break; } } } // We have the winning candidate among the not-yet-ranked candidates: MeetingElectionCandidate candidate = MeetingElectionCandidate.FromIdentity(candidateIds[winningCandidateIndex]); candidateAdded[winningCandidateIndex] = true; result.Add(candidate); candidatesRemaining--; count++; } FinalOrder = result; Console.WriteLine(", done."); }
protected void Page_Load(object sender, EventArgs e) { this.TextCandidacy.Style[HtmlTextWriterStyle.Width] = "400px"; this.TextEditCandidacy.Style[HtmlTextWriterStyle.Width] = "400px"; if (!Page.IsPostBack) { MeetingElection poll = MeetingElection.Primaries2010; MeetingElectionCandidates candidates = MeetingElection.Primaries2010.Candidates; bool thisUserIsCandidate = false; MeetingElectionCandidate thisCandidate = null; foreach (MeetingElectionCandidate candidate in candidates) { if (candidate.PersonId == _currentUser.Identity) { thisUserIsCandidate = true; thisCandidate = candidate; break; } } if (!poll.RunningOpen) { this.PanelCallForCandidatesIntro.Visible = false; this.PanelCallForCandidatesClosed.Visible = true; } if (!_currentUser.MemberOf(Organization.PPSE)) { this.PanelNotEligible.Visible = true; this.PanelCandidacy.Visible = false; this.PanelCandidate.Visible = false; } else if (thisUserIsCandidate) { this.PanelCandidate.Visible = true; this.PanelCandidacy.Visible = false; this.PanelEditCandidacy.Visible = true; this.TextEditCandidacy.Text = thisCandidate.CandidacyStatement; } this.TextPersonalNumber.Text = _currentUser.PersonalNumber; this.TextPhotographer.Text = _currentUser.PortraitPhotographer; this.TextBlogName.Text = _currentUser.BlogName; if (String.IsNullOrEmpty(_currentUser.BlogUrl)) { this.TextBlogUrl.Text = "http://"; } else { this.TextBlogUrl.Text = _currentUser.BlogUrl; } string tShirtSize = _currentUser.TShirtSize; if (!String.IsNullOrEmpty(tShirtSize)) { this.DropTShirtSizes.SelectedValue = tShirtSize; } } }
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); }
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; }
private static int FindCandidateIndex (int candidateId, MeetingElectionCandidates list) { for (int index = 0; index < list.Count; index++) { if (list [index].Identity == candidateId) { return index; } } return -1; }
private void AssembleFinalOrder() { Console.WriteLine("Assembling final list."); MeetingElectionCandidates result = new MeetingElectionCandidates(); Dictionary <int, bool> candidateAdded = new Dictionary <int, bool>(); int candidatesRemaining = this.candidateIds.Count; int count = 1; while (candidatesRemaining > 0) { Console.Write("\r - remaining: {0:D4}", candidatesRemaining); // Find the first nontaken candidate int winningCandidateIndex = 0; while (candidateAdded.ContainsKey(winningCandidateIndex)) { winningCandidateIndex++; } // Iterate over all linkStrength[X,*] and [*,X]; this candidate is only a winner if // all [X,*] are >= all [*,X]. bool allSuperior = false; while (!allSuperior) { allSuperior = true; for (int compareCandidateIndex = 0; compareCandidateIndex < this.candidateIds.Count; compareCandidateIndex++) { if (candidateAdded.ContainsKey(compareCandidateIndex)) { continue; } if (this.linkStrengthXtoY[winningCandidateIndex, compareCandidateIndex] < this.linkStrengthXtoY[compareCandidateIndex, winningCandidateIndex]) { // the compareCandidateIndex had a greater link strength, so jump there and take it as // a new potential winner, restarting the comparison winningCandidateIndex = compareCandidateIndex; allSuperior = false; break; } } } // We have the winning candidate among the not-yet-ranked candidates: MeetingElectionCandidate candidate = MeetingElectionCandidate.FromIdentity(this.candidateIds[winningCandidateIndex]); candidateAdded[winningCandidateIndex] = true; result.Add(candidate); candidatesRemaining--; count++; } FinalOrder = result; Console.WriteLine(", done."); }
private static double CalculateListMaleQuota (MeetingElectionCandidates candidates, PersonGender nextCandidateGender) { if (candidates.Count < 1) { return 0.5; // Division by zero protection, here and in caller } double malesTotal = 0.0; foreach (MeetingElectionCandidate candidate in candidates) { if (candidate.Person.Gender == PersonGender.Male) { malesTotal += 1.0; } } if (nextCandidateGender == PersonGender.Male) { malesTotal += 1.0; } return malesTotal/(candidates.Count + 1.0); }
protected void ButtonAdd_Click(object sender, EventArgs e) { Organization org = Organization.PPSE; Geography geo = this.DropGeographies.SelectedGeography; Election election = Election.September2010; string ballotName = this.TextName.Text; MeetingElectionCandidates candidates = MeetingElection.FromIdentity(Int32.Parse(this.DropPolls.SelectedValue)).Candidates; Ballot ballot = Ballot.Create(election, org, geo, ballotName, 0, string.Empty); Dictionary <string, int> nameLookup = new Dictionary <string, int>(); foreach (MeetingElectionCandidate candidate in candidates) { nameLookup[candidate.Person.Name.ToLowerInvariant()] = candidate.PersonId; } string[] candidateNames = this.TextCandidates.Text.Split('\r', '\n'); foreach (string candidateNameSource in candidateNames) { int personId = 0; int idStartIndex = candidateNameSource.LastIndexOf("(#"); if (idStartIndex > 0) { string identityString = candidateNameSource.Substring(idStartIndex + 2); int idEndIndex = identityString.IndexOf(")"); identityString = identityString.Substring(0, idEndIndex); personId = Int32.Parse(identityString); } if (personId == 0) { // Derive from name string candidateName = candidateNameSource; int parenIndex = candidateName.IndexOfAny(new char[] { '(', ',' }); if (parenIndex >= 0) { candidateName = candidateName.Substring(0, parenIndex); } candidateName = candidateName.ToLowerInvariant().Trim(); if (candidateName.Length < 1) { continue; } personId = nameLookup[candidateName]; } ballot.AddCandidate(Person.FromIdentity(personId)); } Page.ClientScript.RegisterStartupScript(typeof(Page), "OkMessage", @"alert ('Valsedel #" + ballot.Identity + " registrerades.');", true); }
private static int GetNextSpecificGenderCandidate (MeetingElectionCandidates candidates, Dictionary<int,bool> takenCandidates, PersonGender desiredGender) { int index = 0; while (takenCandidates.ContainsKey(index) || candidates [index].Person.Gender != desiredGender) { index++; // potential out-of-range exception here, if there aren't enough candidates } return index; }