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!");
 }