/// <summary> /// Calculates the result. /// </summary> /// <param name="votingProcess">The voting process.</param> /// <returns></returns> /// <exception cref="VoteInException">Impossible to calculate the results : The voting process is null</exception> public IResultatModel CalculateResult(VotingProcessModel votingProcess) { if (votingProcess == null) { throw new VoteInException("Impossible to calculate the results : The voting process is null"); } decimal nbTotalVote = votingProcess.Options.SelectMany(o => o.Suffrages).Count(s => s.Value == ChoosenValue); var resultat = new ResultatMajorityVotingProcessModel { IndividualResults = votingProcess.Options .Select(o => CreateResultatIndividuel(nbTotalVote, o)) .OrderByDescending(ri => ri.Votes) .ToList() }; resultat.IsValidResult = IsResultatValide(resultat, votingProcess); var first = resultat.IndividualResults.FirstOrDefault(); if (resultat.IsValidResult && first != null && (first.Percentage > 50m || votingProcess.IsLastRound)) { resultat.Winner = first.Option; } return(resultat); }
/// <summary> /// Calculs the condorcet. /// </summary> /// <param name="scrutin">The scrutin.</param> /// <returns></returns> private ResultatCondorcet CalculCondorcet(VotingProcessModel scrutin) { var resultat = new ResultatCondorcet { Duels = new List <DuelCondorcet>() }; var bulletins = scrutin.Ballots; var total = bulletins.Count(); resultat.Voters = total; var n = scrutin.Options.Count; for (var i = 0; i < n; ++i) { var option1 = scrutin.Options.ElementAt(i); for (var j = 0; j < n; ++j) { var option2 = scrutin.Options.ElementAt(j); var duel = new DuelCondorcet { Option1 = option1, Option2 = option2, PreferencesOption1 = bulletins.Count(b => b.Acts.First(a => a.IdOption == option1.Id).Value < b.Acts.First(a => a.IdOption == option2.Id).Value) }; duel.PreferencesOption2 = total - duel.PreferencesOption1; if (duel.PreferencesOption1 > duel.PreferencesOption2) { duel.Winner = option1; } else if (duel.PreferencesOption2 > duel.PreferencesOption1) { duel.Winner = option2; } resultat.Duels.Add(duel); } } resultat.Scores = new List <ScoreCondorcet>(); foreach (var option in scrutin.Options) { var score = new ScoreCondorcet { Option = option, Score = resultat.Duels.Count(d => d.Option1.Id == option.Id && d.Winner != null && d.Winner.Id == option.Id) }; resultat.Scores.Add(score); } var max = scrutin.Options.Count; if (resultat.Scores.Count(s => s.Score == max) == 1) { resultat.Winner = resultat.Scores.First(s => s.Score == max).Option; } return(resultat); }
public void MapScrutinMajoritaireResultatModelToResultat() { var scrutinModel = new VotingProcessModel { Id = 52, Mode = "scrutin-majoritaire" }; var optionVainqueur = new OptionsModel { Id = 28, Name = "Winner" }; var optionPerdant = new OptionsModel { Id = 32, Name = "Loser" }; var resultatGagnant = new ResultatIndividualMajorityVotingProcessModel { Option = optionVainqueur, Votes = 3, Percentage = 75m }; var resultatPerdant = new ResultatIndividualMajorityVotingProcessModel { Option = optionPerdant, Votes = 1, Percentage = 25m }; var resultatModel = new ResultatMajorityVotingProcessModel { Id = 96, IsValidResult = true, Voters = 4, Winner = optionVainqueur, IndividualResults = { resultatGagnant, resultatPerdant } }; var resultat = _mapper.MapResultatModelToResultat(scrutinModel, resultatModel); Check.That(resultat.IdVotingProcess).IsEqualTo(scrutinModel.Id); Check.That(resultat.IsValid).IsEqualTo(resultatModel.IsValidResult); Check.That(resultat.NbVoters).IsEqualTo(resultatModel.Voters); Check.That(resultat.IdWinningOption).IsEqualTo(resultatModel.Winner.Id); var scoreDetails = JsonConvert.DeserializeObject <List <ResultatIndividualMajorityVotingProcessModel> >(resultat.ScoreDetail); Check.That(scoreDetails[0].Votes).IsEqualTo(resultatGagnant.Votes); Check.That(scoreDetails[0].Percentage).IsEqualTo(resultatGagnant.Percentage); Check.That(scoreDetails[0].Option.Id).IsEqualTo(resultatGagnant.Option.Id); Check.That(scoreDetails[1].Votes).IsEqualTo(resultatPerdant.Votes); Check.That(scoreDetails[1].Percentage).IsEqualTo(resultatPerdant.Percentage); Check.That(scoreDetails[1].Option.Id).IsEqualTo(resultatPerdant.Option.Id); }
/// <summary> /// Calculates the result. /// </summary> /// <param name="scrutin">The scrutin.</param> /// <returns></returns> public IResultatModel CalculateResult(VotingProcessModel scrutin) { var resultat = new ResultatCondorcetRandomiseModel(); var resultatCondorcet = CalculCondorcet(scrutin); if (resultatCondorcet.Winner == null) { resultat.WinningLottery = linearSolverLoterie(resultatCondorcet.Duels, scrutin); } else { resultat.ResultatCondorcet = resultatCondorcet; } return(resultat); }
public void IdentifyWinnerOnLatestTurn() { var scrutinBusiness = new VotingProcessModel { ClosingDate = new DateTime(2017, 11, 07), IsLastRound = true, Options = new List <OptionsModel> { new OptionsModel { Id = 23, Name = "Candidat 1", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 } } }, new OptionsModel { Id = 12, Name = "Candidat 2", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 }, new SuffrageModel { Value = 1 } } } } }; var resultat = _calculateur.CalculateResult(scrutinBusiness) as ResultatMajorityVotingProcessModel; var gagant = resultat.IndividualResults.First(); var perdant = resultat.IndividualResults.Last(); Check.That(gagant.Option.Id).IsEqualTo(12); Check.That(gagant.Option).IsEqualTo(resultat.Winner); Check.That(perdant.Option).Not.IsEqualTo(resultat.Winner); }
public void IdentifyWinnerWhenBlankVoteIsQualifiedAmongTwoCandidates() { var scrutinBusiness = new VotingProcessModel { ClosingDate = new DateTime(2017, 11, 07), IsLastRound = false, IsBlankVoteTakenIntoAccount = true, Options = new List <OptionsModel> { new OptionsModel { Id = 23, Name = "Vote blanc", IsBlankVote = true, Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 } } }, new OptionsModel { Id = 12, Name = "Candidat 2", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 }, new SuffrageModel { Value = 1 } } } } }; var resultat = _calculateur.CalculateResult(scrutinBusiness); Check.That(resultat.IsValidResult).IsTrue(); Check.That(resultat.Winner.Id).IsEqualTo(12); }
public void EndedVoteWhenBlankVoteWins() { var scrutinBusiness = new VotingProcessModel { ClosingDate = new DateTime(2017, 11, 07), IsLastRound = true, IsBlankVoteTakenIntoAccount = true, Options = new List <OptionsModel> { new OptionsModel { Id = 23, Name = "Vote blanc", IsBlankVote = true, Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 }, new SuffrageModel { Value = 1 } } }, new OptionsModel { Id = 12, Name = "Candidat 2", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 } } } } }; var resultat = _calculateur.CalculateResult(scrutinBusiness); Check.That(resultat.IsValidResult).IsFalse(); }
/// <summary> /// Maps the resultat model to resultat. /// </summary> /// <param name="scrutinModel">The scrutin model.</param> /// <param name="resultatModel">The resultat model.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"> /// scrutinModel /// or /// resultatModel /// </exception> public Result MapResultatModelToResultat(VotingProcessModel scrutinModel, IResultatModel resultatModel) { if (scrutinModel is null) { throw new ArgumentNullException(nameof(scrutinModel)); } if (resultatModel is null) { throw new ArgumentNullException(nameof(resultatModel)); } return(new Result { IdVotingProcess = scrutinModel.Id, IsValid = resultatModel.IsValidResult, NbVoters = resultatModel.Voters, IdWinningOption = resultatModel.Winner?.Id, ScoreDetail = JsonConvert.SerializeObject(GetScoreDetail(resultatModel)) }); }
public void EndedVoteInCaseOfEquality() { var scrutinBusiness = new VotingProcessModel { ClosingDate = new DateTime(2017, 11, 07), Options = new List <OptionsModel> { new OptionsModel { Id = 23, Name = "Candidat 1", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 } } }, new OptionsModel { Id = 12, Name = "Candidat 2", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 } } } } }; var resultat = _calculateur.CalculateResult(scrutinBusiness); Check.That(resultat.IsValidResult).IsFalse(); }
/// <summary> /// Maps the scrutin to scrutin model. /// </summary> /// <param name="scrutin">The scrutin.</param> /// <returns></returns> /// <exception cref="VoteIn.BL.Exceptions.VoteInException">Aucun scrutin à mapper</exception> public VotingProcessModel MapScrutinToScrutinModel(VotingProcess scrutin) { if (scrutin == null) { throw new VoteInException("Aucun scrutin à mapper"); } var model = new VotingProcessModel { Id = scrutin.Id, ClosingDate = scrutin.ClosingDate, IsLastRound = scrutin.IdPreviousVotingProcess.HasValue, Mode = scrutin.VotingProcessMode?.Code }; if (scrutin.VotingProcessMode != null) { var choiceModels = MapChoiceToChoiceModel(scrutin.VotingProcessMode.Choice.ToList()); model.PossibleChoices.AddRange(choiceModels); } if (scrutin.VotingProcessOption != null) { var optionsModels = MapOptionToOptionsModels(scrutin.VotingProcessOption.ToList(), model.PossibleChoices); model.Options.AddRange(optionsModels); } if (scrutin.Suffrage != null) { var bulletinModels = MapSuffrageToBulletin(scrutin.Suffrage.ToList()); model.Ballots.AddRange(bulletinModels); } model.IsBlankVoteTakenIntoAccount = model.Options.Any(o => o.IsBlankVote); return(model); }
public void VerifierScoresPourChaqueOption() { var scrutin = new VotingProcessModel { ClosingDate = new DateTime(2017, 11, 8), PossibleChoices = GetChoice(), Options = new List <OptionsModel>() { new OptionsModel { Name = "Candidat 1", Suffrages = new List <SuffrageModel>() { new SuffrageModel { Value = 5 }, new SuffrageModel { Value = 5 }, new SuffrageModel { Value = 4 }, new SuffrageModel { Value = 3 }, new SuffrageModel { Value = 3 }, new SuffrageModel { Value = 3 }, new SuffrageModel { Value = 6 }, new SuffrageModel { Value = 1 } } } }, IsLastRound = true }; var result = _calculateur.CalculateResult(scrutin) as ResultatMajoritaryJudgmentModel; Check.That(result.IndividualResults).IsNotNull(); Check.That(result.Voters).IsEqualTo(8); var gagnant = result.IndividualResults.First(); var scoreGagnant = gagnant.Scores; Check.That(scoreGagnant.First(s => s.Choices.Id == 1).Votes).IsEqualTo(2); Check.That(scoreGagnant.First(s => s.Choices.Id == 1).Percentage).IsEqualTo(25m); Check.That(scoreGagnant.First(s => s.Choices.Id == 2).Votes).IsEqualTo(1); Check.That(scoreGagnant.First(s => s.Choices.Id == 3).Votes).IsEqualTo(3); Check.That(scoreGagnant.First(s => s.Choices.Id == 4).Votes).IsEqualTo(1); Check.That(scoreGagnant.First(s => s.Choices.Id == 5).Votes).IsEqualTo(0); Check.That(scoreGagnant.First(s => s.Choices.Id == 6).Votes).IsEqualTo(1); Check.That(scoreGagnant.First(s => s.Choices.Id == 7).Votes).IsEqualTo(0); Check.That(result.IsValidResult).IsTrue(); }
public void MapJugementMajoritaireResultatModelToResultat() { var scrutinModel = new VotingProcessModel { Id = 52 }; var choice1 = new ChoiceModel { Id = 1, Value = 1 }; var choice2 = new ChoiceModel { Id = 2, Value = 2 }; var optionVainqueur = new OptionsModel { Id = 28, Name = "Winner" }; var optionPerdant = new OptionsModel { Id = 32, Name = "Loser" }; var resultatGagnant = new ResultatIndividualMajorityJudgmentModel { Option = optionVainqueur, Median = choice1, PercentageScoreInfMedian = 38m, PercentageScoreSupMedian = 42m }; var resultatPerdant = new ResultatIndividualMajorityJudgmentModel { Option = optionPerdant, Median = choice2, PercentageScoreInfMedian = 40m, PercentageScoreSupMedian = 36m }; var resultatModel = new ResultatMajoritaryJudgmentModel { Id = 96, IsValidResult = true, Voters = 4, Winner = optionVainqueur, IndividualResults = { resultatGagnant, resultatPerdant } }; var resultat = _mapper.MapResultatModelToResultat(scrutinModel, resultatModel); Check.That(resultat.IdVotingProcess).IsEqualTo(scrutinModel.Id); Check.That(resultat.IsValid).IsEqualTo(resultatModel.IsValidResult); Check.That(resultat.NbVoters).IsEqualTo(resultatModel.Voters); Check.That(resultat.IdWinningOption).IsEqualTo(resultatModel.Winner.Id); var scoreDetails = JsonConvert.DeserializeObject <List <ResultatIndividualMajorityJudgmentModel> >(resultat.ScoreDetail); Check.That(scoreDetails[0].PercentageScoreInfMedian).IsEqualTo(resultatGagnant.PercentageScoreInfMedian); Check.That(scoreDetails[0].PercentageScoreSupMedian).IsEqualTo(resultatGagnant.PercentageScoreSupMedian); Check.That(scoreDetails[0].Median.Id).IsEqualTo(resultatGagnant.Median.Id); Check.That(scoreDetails[0].Option.Id).IsEqualTo(resultatGagnant.Option.Id); Check.That(scoreDetails[1].PercentageScoreInfMedian).IsEqualTo(resultatPerdant.PercentageScoreInfMedian); Check.That(scoreDetails[1].PercentageScoreSupMedian).IsEqualTo(resultatPerdant.PercentageScoreSupMedian); Check.That(scoreDetails[1].Median.Id).IsEqualTo(resultatPerdant.Median.Id); Check.That(scoreDetails[1].Option.Id).IsEqualTo(resultatPerdant.Option.Id); }
public void ReturnOrdereredResults() { var scrutinBusiness = new VotingProcessModel { ClosingDate = new DateTime(2017, 11, 07), Options = new List <OptionsModel> { new OptionsModel { Id = 23, Name = "Candidat 1", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 }, new SuffrageModel { Value = 1 }, new SuffrageModel { Value = 1 } } }, new OptionsModel { Id = 12, Name = "Candidat 2", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 } } }, new OptionsModel { Id = 45, Name = "Candidat 3", Suffrages = new List <SuffrageModel> { new SuffrageModel { Value = 1 }, new SuffrageModel { Value = 1 } } } } }; var resultat = _calculateur.CalculateResult(scrutinBusiness) as ResultatMajorityVotingProcessModel; Check.That(resultat.IndividualResults).HasSize(3); var firstOption = resultat.IndividualResults.First(); Check.That(firstOption.Option.Id).IsEqualTo(23); Check.That(firstOption.Percentage).IsEqualTo(50); var secondOption = resultat.IndividualResults.ElementAt(1); Check.That(secondOption.Option.Id).IsEqualTo(45); Check.That(secondOption.Percentage).IsEqualTo(100 / 3m); var thirdOption = resultat.IndividualResults.Last(); Check.That(thirdOption.Option.Id).IsEqualTo(12); Check.That(thirdOption.Percentage).IsEqualTo(100 / 6m); }
/// <summary> /// Linears the solver loterie. /// </summary> /// <param name="duels">The duels.</param> /// <param name="scrutin">The scrutin.</param> /// <returns></returns> private Loterie linearSolverLoterie(IReadOnlyCollection <DuelCondorcet> duels, VotingProcessModel scrutin) { var solver = Solver.CreateSolver("LoterieSolver", "GLOP_LINEAR_PROGRAMMING"); var probas = new Dictionary <int, Variable>(); foreach (var option in scrutin.Options) { probas.Add(option.Id, solver.MakeNumVar(0, double.PositiveInfinity, option.Name)); } var normalDistrib = new Normal(0, 1); var objective = solver.Objective(); foreach (var proba in probas) { objective.SetCoefficient(proba.Value, normalDistrib.Sample()); } var sommeP = solver.MakeConstraint(1, 1, "Sum = 1"); foreach (var proba in probas) { sommeP.SetCoefficient(proba.Value, 1); var positif = solver.MakeConstraint(0, double.PositiveInfinity, proba.Value.Name() + " positive"); foreach (var proba2 in probas) { positif.SetCoefficient(proba2.Value, proba.Key == proba2.Key ? 1 : 0); } } foreach (var option in scrutin.Options) { var c = solver.MakeConstraint(0, double.PositiveInfinity); c.SetCoefficient(probas[option.Id], 0); foreach (var option2 in scrutin.Options) { if (option.Id != option2.Id) { var duel = duels.First(d => d.Option1.Id == option.Id && d.Option2.Id == option2.Id); var coeff = duel.PreferencesOption1 - duel.PreferencesOption2; if (coeff != 0) { coeff /= Math.Abs(coeff); } c.SetCoefficient(probas[option2.Id], coeff); } } } objective.SetMaximization(); solver.Solve(); var loterie = new Loterie { Probabilites = new List <Probabilite>() }; foreach (var proba in probas) { loterie.Probabilites.Add(new Probabilite() { Option = scrutin.Options.First(o => o.Id == proba.Key), Valeur = proba.Value.SolutionValue() }); } Console.Out.Write(solver.ExportModelAsLpFormat(false)); return(loterie); }
/// <summary> /// Calculates the result. /// </summary> /// <param name="votingProcess">The voting process.</param> /// <returns></returns> /// <exception cref="VoteInException">Impossible to calculate the results : The voting process is null</exception> public IResultatModel CalculateResult(VotingProcessModel votingProcess) { if (votingProcess == null) { throw new VoteInException("Impossible to calculate the results : The voting process is null"); } var resultat = new ResultatMajoritaryJudgmentModel(); var nbSuffrage = 0m; foreach (var option in votingProcess.Options) { var individualResults = new ResultatIndividualMajorityJudgmentModel { Option = option }; var suffrageOrderedByAscending = option.Suffrages.OrderBy(s => s.Value).ToList(); nbSuffrage = option.Suffrages.Count; var medianValue = GetMediane(suffrageOrderedByAscending, nbSuffrage); individualResults.Median = votingProcess.PossibleChoices.First(c => c.Value == medianValue); var pourcentageScoreInfMediane = (suffrageOrderedByAscending.Count(s => s.Value < medianValue) / nbSuffrage) * 100; individualResults.PercentageScoreInfMedian = Math.Round(pourcentageScoreInfMediane, 2); var pourcentageScoreSupMediane = (suffrageOrderedByAscending.Count(s => s.Value > medianValue) / nbSuffrage) * 100; individualResults.PercentageScoreSupMedian = Math.Round(pourcentageScoreSupMediane, 2); foreach (var choice in votingProcess.PossibleChoices) { decimal votes = suffrageOrderedByAscending.Count(s => s.Value == choice.Value); var percentage = (votes / nbSuffrage) * 100; var score = new ScoreModel { Votes = suffrageOrderedByAscending.Count(s => s.Value == choice.Value), Choices = choice, Percentage = Math.Round(percentage, 2) }; individualResults.Scores.Add(score); } resultat.IndividualResults.Add(individualResults); } resultat.IndividualResults = resultat.IndividualResults.OrderByDescending(r => r.Median.Value) .ThenBy(r => r.PercentageScoreInfMedian) .ThenByDescending(r => r.PercentageScoreSupMedian).ToList(); var winner = resultat.IndividualResults.First(); var perfectEquality = resultat.IndividualResults.Any(r => r.Median.Value == winner.Median.Value && r.PercentageScoreInfMedian == winner.PercentageScoreInfMedian && r.PercentageScoreSupMedian == winner.PercentageScoreSupMedian && r != winner); resultat.Voters = (int)nbSuffrage; if (!perfectEquality) { resultat.Winner = winner.Option; resultat.IsValidResult = true; } return(resultat); }
/// <summary> /// Saves the resultat. /// </summary> /// <param name="scrutin">The scrutin.</param> /// <param name="resultatModel">The resultat model.</param> private void SaveResultat(VotingProcessModel scrutin, IResultatModel resultatModel) { var resultat = MapperService.MapResultatModelToResultat(scrutin, resultatModel); ResultRepository.Add(resultat); }
/// <summary> /// Determines whether [is resultat valide] [the specified resultat]. /// </summary> /// <param name="resultat">The resultat.</param> /// <param name="votingProcess">The voting process.</param> /// <returns> /// <c>true</c> if [is resultat valide] [the specified resultat]; otherwise, <c>false</c>. /// </returns> private static bool IsResultatValide(ResultatMajorityVotingProcessModel resultat, VotingProcessModel votingProcess) { var first = resultat.IndividualResults.FirstOrDefault(); var second = resultat.IndividualResults.ElementAtOrDefault(1); var third = resultat.IndividualResults.ElementAtOrDefault(2); if (first == null || first.Option.IsBlankVote) { return(false); } if ((resultat.IndividualResults.Count == 2 || votingProcess.IsLastRound) && first.Votes == second.Votes) { return(false); } var isFirstRoundWithoutWinner = !votingProcess.IsLastRound && first.Percentage <= 50m; return(!isFirstRoundWithoutWinner || (second?.Votes != third?.Votes && !second.Option.IsBlankVote)); }
/// <summary> /// Calculates the result. /// </summary> /// <param name="votingProcess">The voting process.</param> /// <returns></returns> public IResultatModel CalculateResult(VotingProcessModel votingProcess) { var resultat = new AlternativeVoteResultatModel { Stages = new List <AlternativeStageVote>() }; var ballots = votingProcess.Ballots; var total = ballots.Count(); resultat.Voters = total; var rejets = new List <int>(); var victory = false; var conflict = false; while (!victory && !conflict && resultat.Stages.Count() < votingProcess.Options.Count()) { var stage = new AlternativeStageVote { Scores = new List <AlternativeScoreVote>() }; var preferences = ballots .Select(b => b.Acts.Where(a => rejets.All(r => r != a.IdOption))) .Select(actes => actes.First(a => a.Value == actes.Min(acte => acte.Value))); foreach (var option in votingProcess.Options) { var score = new AlternativeScoreVote { Option = option, Votes = preferences.Count(a => a.IdOption == option.Id && a.Value != null) }; stage.Scores.Add(score); if (score.Votes > total / 2.0) { victory = true; resultat.Winner = option; resultat.IsValidResult = true; } } if (!victory) { var scoresNotRejected = stage.Scores.Where(s => rejets.All(r => r != s.Option.Id)); var reject = scoresNotRejected.First(s => s.Votes == scoresNotRejected.Min(sc => sc.Votes)).Option; conflict = stage.Scores.Any(score => score.Votes == scoresNotRejected.Min(sc => sc.Votes) && score.Option.Id != reject.Id); if (!conflict) { rejets.Add(reject.Id); stage.RemovedOption = reject; } } resultat.Stages.Add(stage); } return(resultat); }