private void AnalyzeTieGroup(ResultTie resultTie, List<Result> results) { AssertAtRuntime.That(results.Count != 0); resultTie.NumInTie = results.Count; resultTie.NumToElect = 0; resultTie.TieBreakRequired = false; var groupInTop = false; var groupInExtra = false; var groupInOther = false; foreach (var result in results) { switch (result.Section) { case ResultHelper.Section.Top: groupInTop = true; break; case ResultHelper.Section.Extra: groupInExtra = true; break; case ResultHelper.Section.Other: groupInOther = true; break; } } var groupOnlyInTop = groupInTop && !(groupInExtra || groupInOther); var groupOnlyInOther = groupInOther && !(groupInTop || groupInExtra); results.ForEach(delegate(Result r) { r.TieBreakRequired = !(groupOnlyInOther || groupOnlyInTop); r.IsTieResolved = r.TieBreakCount.AsInt() > 0 && !results.Any(r2 => r2.C_RowId != r.C_RowId && r2.TieBreakCount == r.TieBreakCount); }); if (groupInOther && (groupInTop || groupInExtra)) { results.Where(r => r.Section == ResultHelper.Section.Other) .ToList() .ForEach(r => r.ForceShowInOther = true); } if (groupInTop) { if (!groupOnlyInTop) { resultTie.NumToElect += results.Count(r => r.Section == ResultHelper.Section.Top); resultTie.TieBreakRequired = true; //resultTie.TieBreakRequired = results.Any(r => !r.IsTieResolved.AsBool()); } else { // default... tie-break not needed } } if (groupInExtra) { if (groupInTop && groupInOther || !groupInTop) { resultTie.NumToElect += results.Count(r => r.Section == ResultHelper.Section.Extra); resultTie.TieBreakRequired = true; //resultTie.TieBreakRequired = results.Any(r => !r.IsTieResolved.AsBool()); } } var foundBeforeDup = 0; if (resultTie.NumToElect > 0) { //results are in descending order already, so starting at 0 is starting at the "top" for (int i = 0, max = results.Count; i < max; i++) { var result = results[i]; if (!result.IsTieResolved.AsBoolean()) break; foundBeforeDup += result.TieBreakCount > 0 ? 1 : 0; } } if (foundBeforeDup < resultTie.NumToElect) { resultTie.IsResolved = false; results.ForEach(r => r.IsTieResolved = false); } else { resultTie.IsResolved = true; results.ForEach(r => r.IsTieResolved = true); } if (resultTie.NumInTie == resultTie.NumToElect) { resultTie.NumToElect--; } // conclusions //resultTie.Comments = resultTie.TieBreakRequired.AsBool() // ? "Tie-break required" // : "Tie-break not needed"; }
public ResultTie AddResultTie(ResultTie arg) { arg.C_RowId = ++_rowCounter; return arg; }
internal void AnalyzeForTies() { Result aboveResult = null; var nextTieBreakGroup = 1; foreach (var result in Results.OrderBy(r => r.Rank)) { result.IsTied = false; result.TieBreakGroup = null; if (aboveResult != null) { // compare this with the one 'above' it var numFewerVotesThanAboveResult = aboveResult.VoteCount - result.VoteCount; if (numFewerVotesThanAboveResult == 0) { aboveResult.IsTied = true; result.IsTied = true; if (aboveResult.TieBreakGroup.HasNoContent()) { aboveResult.TieBreakGroup = nextTieBreakGroup; nextTieBreakGroup++; } result.TieBreakGroup = aboveResult.TieBreakGroup; } // set CloseTo___ - if tied, then is also Close to var isClose = numFewerVotesThanAboveResult <= ThresholdForCloseVote; aboveResult.CloseToNext = isClose; result.CloseToPrev = isClose; } else { result.CloseToPrev = false; } aboveResult = result; } // last one if (aboveResult != null) { aboveResult.CloseToNext = false; } // pass 2 for (var groupCode = 1; groupCode < nextTieBreakGroup; groupCode++) { var code = groupCode; var resultTie = new ResultTie { ElectionGuid = TargetElection.ElectionGuid, TieBreakGroup = code }; ResultTies.Add(resultTie); AddResultTie(resultTie); AnalyzeTieGroup(resultTie, Results.Where(r => r.TieBreakGroup == code).OrderBy(r => r.Rank).ToList()); } }
public ResultTie RemoveResultTie(ResultTie arg) { throw new ApplicationException("Should not be called in tests!"); }