public void TestNotFirstStep()
        {
            var people = new Person[] { new Person(0, 1, 2) };
            var old = new CandiateRanking[][] { };

            var s = new ESKeepThoseBetterThan(0.5);
            s.RunStep(people, old);
        }
        /// <summary>
        /// Run the election
        /// </summary>
        /// <param name="people"></param>
        /// <param name="previousResults"></param>
        /// <returns></returns>
        public CandiateRanking[] RunStep(Person[] people, CandiateRanking[][] previousResults)
        {
            if (previousResults == null || previousResults.Length == 0)
                throw new InvalidOperationException("Can't run a Keep Best N candidates election step as first step in an election!");

            return (from r in previousResults.Last()
                    orderby r.ranking descending
                    select r).Take((int)CandidatesToKeep).ToArray();
        }
 /// <summary>
 /// Run the election itself.
 /// </summary>
 /// <param name="people"></param>
 /// <param name="previousResults"></param>
 /// <returns></returns>
 public CandiateRanking[] RunStep(Person[] people, CandiateRanking[][] previousResults)
 {
     var summedWeights = from p in people
                         from ranking in p.FullRanking()
                         group ranking.ranking by ranking.candidate into candidateRankings
                         select new CandiateRanking()
                         {
                             candidate = candidateRankings.Key,
                             ranking = candidateRankings.Sum()
                         };
     return summedWeights.ToArray();
 }
        public async Task TestSimpleStepRuturnNoCandidates()
        {
            var step = new ElectionDriver.Fakes.StubIElectionStep();
            CandiateRanking[] rankings = new CandiateRanking[0];
            step.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) =>
            {
                return rankings;
            };

            var e = new Election();
            e.AddStep(step);
            var result = await e.RunSingleElection();
        }
 /// <summary>
 /// Given a candidate ranking, create a person.
 /// </summary>
 /// <param name="enumerable"></param>
 public Person(CandiateRanking[] candidateList)
 {
     var maxCandidateNumber = candidateList.Select(c => c.candidate).Max();
     _candidateOrdering = new int[maxCandidateNumber+1];
     for (int i = 0; i < _candidateOrdering.Length; i++)
     {
         _candidateOrdering[i] = -1;
     }
     foreach (var c in candidateList)
     {
         _candidateOrdering[c.candidate] = c.ranking;
     }
 }
        public void TestSimpleRunNoOneFailWhen()
        {
            var people = new Person[] {
                new Person(0, 1, 2),
                new Person(0, 1, 2),
                new Person(0, 1, 2),
                new Person(0, 1, 2),
            };
            var old = new CandiateRanking[][] { new CandiateRanking[] { new CandiateRanking(0, 2), new CandiateRanking(1, 2) } };

            var s = new ESKeepThoseBetterThan(0.7) { DoNothingIfNoOnePasses=false };
            var r = s.RunStep(people, old);
            Assert.AreEqual(0, r.Length, "# of candidates ranked");
        }
        /// <summary>
        /// Calculate weights for all candidates by the #1 choice out there.
        /// </summary>
        /// <param name="people"></param>
        /// <returns></returns>
        public CandiateRanking[] RunStep(Person[] people, CandiateRanking[][] previousResults)
        {
            // Weights only work for the best candidate.
            var bestvote = from p in people
                             let ranking = p.FullRanking()
                             let bestRanking = from r in ranking
                                               orderby r.ranking descending
                                               select r
                             select bestRanking.First().candidate;

            // Group them by their best vote and tally them up!
            return (from bc in bestvote
                   group bc by bc into candidatecounts
                   select new CandiateRanking (candidatecounts.Key, candidatecounts.Count())).ToArray();
        }
        public void TestSimpleRun()
        {
            var people = new Person[] {
                new Person(0, 1, 2),
                new Person(0, 1, 2),
                new Person(0, 1, 2),
                new Person(0, 1, 2),
            };
            var old = new CandiateRanking[][] { new CandiateRanking[] { new CandiateRanking(0, 3), new CandiateRanking(1, 1) } };

            var s = new ESKeepThoseBetterThan(0.7);
            var r = s.RunStep(people, old);
            Assert.AreEqual(1, r.Length, "# of candidates ranked");
            Assert.AreEqual(0, r[0].candidate, "Incorrect candidate came back");
        }
        /// <summary>
        /// Window out the list of candidates.
        /// </summary>
        /// <param name="people"></param>
        /// <param name="previousResults"></param>
        /// <returns></returns>
        public CandiateRanking[] RunStep(Person[] people, CandiateRanking[][] previousResults)
        {
            if (previousResults == null || previousResults.Length == 0)
                throw new ArgumentException("Cant run the elections step that keeps the best guys if we don't have the result of an election!");

            var lastStepResults = previousResults[previousResults.Length-1];
            var passed = (from c in lastStepResults
                          where ((double)c.ranking) / ((double)people.Length) > MinimumFraction
                          select c).ToArray();

            if (passed.Length == 0)
            {
                if (DoNothingIfNoOnePasses)
                    return lastStepResults;
                return new CandiateRanking[] { };
            }

            return passed;
        }
        public async void TestSimpleReturn()
        {
            var step = new ElectionDriver.Fakes.StubIElectionStep();
            int numPeople = 0;
            int numCandidates = 0;
            CandiateRanking[] r = new CandiateRanking[] { new CandiateRanking(0, 1) };
            step.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) =>
            {
                numPeople = people.Length;
                numCandidates = people[0].FullRanking().Count();
                return r;
            };

            var e = new Election();
            e.NumberOfCandidates = 15;
            e.NumberOfPeople = 350;
            e.AddStep(step);
            var result = await e.RunSingleElection();

            Assert.AreEqual(350, numPeople, "# of people");
            Assert.AreEqual(15, numCandidates, "# of candidates");

            Assert.AreEqual(r, result, "Candidate ranking that came back isn't right");
        }
        public async void TestElectionReturnOrder()
        {
            var step = new ElectionDriver.Fakes.StubIElectionStep();
            CandiateRanking[] r = new CandiateRanking[] { new CandiateRanking(0, 1), new CandiateRanking(1, 10) };
            step.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) =>
            {
                return r;
            };

            var e = new Election();
            e.NumberOfCandidates = 15;
            e.NumberOfPeople = 350;
            e.AddStep(step);
            var result = await e.RunSingleElection();

            Assert.AreEqual(1, result[0].candidate, "Winner was not listed first");
        }
        public async void TestElectionWindowing()
        {
            var step1 = new ElectionDriver.Fakes.StubIElectionStep();
            CandiateRanking[] ranking1 = new CandiateRanking[] { new CandiateRanking(0, 1), new CandiateRanking(1, 2), new CandiateRanking(2, 3) };
            step1.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) =>
                {
                    Assert.IsTrue(people.All(p => p.FullRanking().Count() == 4), "Not always three candidates");
                    return ranking1;
                };

            var step2 = new ElectionDriver.Fakes.StubIElectionStep();
            CandiateRanking[] ranking2 = new CandiateRanking[] { new CandiateRanking(1, 1), new CandiateRanking(0, 1) };
            step2.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) => 
                {
                    Assert.IsTrue(people.All(p => p.FullRanking().Count() == 3), "Not always two candidates");
                    return ranking2;
                };

            var step3 = new ElectionDriver.Fakes.StubIElectionStep();
            CandiateRanking[] ranking3 = new CandiateRanking[] { new CandiateRanking(1, 1)};
            step3.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) =>
            {
                Assert.IsTrue(people.All(p => p.FullRanking().Count() == 2), "Not always two candidates");
                return ranking3;
            };

            var e = new Election();
            e.NumberOfCandidates = 4;
            e.AddStep(step1);
            e.AddStep(step2);
            e.AddStep(step3);
            var result = await e.RunSingleElection();

            Assert.AreEqual(ranking3, result, "Candidate ranking should be what came out of step 1");
        }
        public async void TestTwoStepElectionSimple()
        {
            var step1 = new ElectionDriver.Fakes.StubIElectionStep();
            CandiateRanking[] ranking1 = new CandiateRanking[] { new CandiateRanking(0, 1), new CandiateRanking(1, 2) };
            step1.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) => ranking1;

            var step2 = new ElectionDriver.Fakes.StubIElectionStep();
            CandiateRanking[] ranking2 = new CandiateRanking[] { new CandiateRanking(1, 1) };
            step2.RunStepPersonArrayCandiateRankingArrayArray = (people, prev) => ranking2;

            var e = new Election();
            e.AddStep(step1);
            e.AddStep(step2);
            var result = await e.RunSingleElection();

            Assert.AreEqual(ranking2, result, "Candidate ranking should be what came out of step 1");
        }
 /// <summary>
 /// Reorder the tranking for a list of candidates. We assume they are in order, with the loser
 /// first (lowest ranking) to highest. Reordering is done in-place.
 /// </summary>
 /// <param name="rankings">candidate list in order from lowest ranking to highest</param>
 private static void ReorderRanking(CandiateRanking[] rankings)
 {
     for (int i = 0; i < rankings.Length; i++)
     {
         rankings[i].ranking = i;
     }
 }