public void F3KRoundScoringAlgo_ScoreRound_VerifyPenaltyIsApplied()
        {
            // Create a single round.
            var timeSheets = ScoringTestHelpers.GenerateValidTimeSheets(2, "Test Contest", 1, 120);

            // Set the first the be the highest score so we can calculate.
            timeSheets[0].TimeGates = new List <TimeGate> {
                new TimeGate(TimeSpan.FromSeconds(121), 0, TimeGateType.Task)
            };

            // Set a known time on the #2 and add a penalty of 100pts
            var totalPenalty = 100;

            timeSheets[1].TimeGates = new List <TimeGate> {
                new TimeGate(TimeSpan.FromSeconds(110), 0, TimeGateType.Task)
            };
            timeSheets[1].TotalPenalties = totalPenalty;
            var expectedEndScoreWithPenaltyApplied = 809;

            mockTaskBase.Setup(x => x.ValidateTask(It.IsAny <RoundScoreBase>())).Returns(true);
            mockTaskBase.Setup(x => x.ScoreTask(It.IsAny <RoundScoreBase>())).Returns <RoundScoreBase>(y => y.TimeGates.Sum(x => x.Time.TotalSeconds));

            var f3KRoundScoringAlgo = new RoundScoringAlgo();

            f3KRoundScoringAlgo.ScoreRound(timeSheets, mockTaskBase.Object);
            timeSheets.Sort();

            // Verify the penalty is applied
            Assert.AreEqual(expectedEndScoreWithPenaltyApplied, timeSheets[1].Score);
            Assert.AreEqual(totalPenalty, timeSheets[1].TotalPenalties);
        }
        public void F3KRoundScoringAlgo_ScoreRound_HappyPath()
        {
            var timeSheets = ScoringTestHelpers.GenerateValidTimeSheets(10);

            // Mock out the validation to return true every time.
            mockTaskBase.Setup(x => x.ValidateTask(It.IsAny <RoundScoreBase>())).Returns(true);

            // Just mock a task scorer that adds up all the seconds to get a total score (essentially what every F3K task does).
            mockTaskBase.Setup(x => x.ScoreTask(It.IsAny <RoundScoreBase>())).Returns <RoundScoreBase>(y => y.TimeGates.Sum(x => x.Time.TotalSeconds));

            var f3KRoundScoringAlgo = new RoundScoringAlgo();

            f3KRoundScoringAlgo.ScoreRound(timeSheets, mockTaskBase.Object);
            timeSheets.Sort();

            // Verify the all come back.
            Assert.AreEqual(10, timeSheets.Count());

            // Verify the first is the granny.
            Assert.AreEqual(1000, timeSheets.First().Score);

            // Verify sort order is descending.
            // Loop through each and make sure each is less that the previous (they can be the same though).
            var previousScore = timeSheets.First().Score;

            foreach (var score in timeSheets)
            {
                Assert.IsFalse(score.Score > previousScore);
            }
        }
        public void F3KRoundScoringAlgo_ScoreRound_BadTimeGateParam_NegativePenalty()
        {
            var timeSheets = ScoringTestHelpers.GenerateValidTimeSheets(10);

            timeSheets[4].TotalPenalties = -100;

            mockTaskBase.Setup(x => x.ScoreTask(It.IsAny <RoundScoreBase>())).Returns <RoundScoreBase>(y => y.TimeGates.Sum(x => x.Time.TotalSeconds));
            var f3KRoundScoringAlgo = new RoundScoringAlgo();

            f3KRoundScoringAlgo.ScoreRound(timeSheets, mockTaskBase.Object);
        }
        public void F3KRoundScoringAlgo_ScoreRound_BadPilotIdParam()
        {
            var timeSheets = ScoringTestHelpers.GenerateValidTimeSheets(10);

            timeSheets[3].PilotId = null;

            var taskG = new TaskG_FiveTwos();
            var f3KRoundScoringAlgo = new RoundScoringAlgo();

            f3KRoundScoringAlgo.ScoreRound(timeSheets, taskG);
        }
        public void F3KRoundScoringAlgo_ScoreRound_BadTimeGateParam_PracticeTimeIncluded()
        {
            var timeSheets = ScoringTestHelpers.GenerateValidTimeSheets(10);

            timeSheets[2].TimeGates = new List <TimeGate> {
                new TimeGate(new TimeSpan(0, 0, -34), timeSheets[3].RoundOrdinal, TimeGateType.Practice)
            };

            mockTaskBase.Setup(x => x.ScoreTask(It.IsAny <RoundScoreBase>())).Returns <RoundScoreBase>(y => y.TimeGates.Sum(x => x.Time.TotalSeconds));
            var f3KRoundScoringAlgo = new RoundScoringAlgo();

            f3KRoundScoringAlgo.ScoreRound(timeSheets, mockTaskBase.Object);
        }
        /// <summary>
        /// Generates valid time sheets.
        /// </summary>
        /// <param name="numberOfPilots">The number to create.</param>
        /// <param name="contestId">The contest identifier.</param>
        /// <param name="numberOfRounds">The number of rounds.</param>
        /// <param name="maxTimeGateTimeInSeconds">The maximum time gate time in seconds.</param>
        /// <param name="multipleFlightGroups">if set to <c>true</c> [multiple flight groups].</param>
        /// <param name="generateScores">if set to <c>true</c> [generate scores].</param>
        /// <returns></returns>
        public static List <TimeSheet> GenerateValidTimeSheets(int numberOfPilots,
                                                               string contestId             = "SASS August 2017",
                                                               int numberOfRounds           = 1,
                                                               int maxTimeGateTimeInSeconds = 120,
                                                               bool multipleFlightGroups    = false,
                                                               bool generateScores          = false)
        {
            var validScoresToReturn = new List <TimeSheet>();
            var validScoresForRound = new List <TimeSheet>();
            var TaskA = new TaskA_LastFlightSevenMin();

            if (numberOfPilots == 0)
            {
                return(validScoresToReturn);
            }
            var rnd = new Random();

            // Set up a mock task to validate and score the rounds if required.
            var mockTask = new Mock <TaskBase>();

            mockTask.Setup(x => x.ValidateTask(It.IsAny <RoundScoreBase>())).Returns(true);
            mockTask.Setup(x => x.ScoreTask(It.IsAny <RoundScoreBase>())).Returns <RoundScoreBase>(y => y.TimeGates.Sum(x => x.Time.TotalSeconds));
            var f3kRoundScoreAlgo = new RoundScoringAlgo();

            for (var i = 0; i < numberOfRounds; ++i)
            {
                // Reset
                validScoresForRound = new List <TimeSheet>();

                for (var j = 0; j < numberOfPilots; ++j)
                {
                    var flightGroup = FlightGroup.A;

                    // Generate 2 flight groups
                    if (multipleFlightGroups)
                    {
                        flightGroup = (j % 2) != 0 ? FlightGroup.A : FlightGroup.B;
                    }

                    var timeGates = new List <TimeGate> {
                        new TimeGate(TimeSpan.FromSeconds(rnd.Next(45, maxTimeGateTimeInSeconds)), j, TimeGateType.Task)
                    };
                    var roundScore = new TimeSheet
                    {
                        RoundOrdinal = i,
                        TimeGates    = timeGates,
                        PilotId      = $"pilot{j}",
                        ContestId    = contestId,
                        TaskId       = TaskA.Id,
                        FlightGroup  = FlightGroup.A
                    };

                    // Generate the scores if needed.
                    if (generateScores)
                    {
                    }

                    validScoresForRound.Add(roundScore);
                }

                if (generateScores)
                {
                    f3kRoundScoreAlgo.ScoreRound(validScoresForRound, mockTask.Object);
                }

                validScoresToReturn.AddRange(validScoresForRound);
            }

            return(validScoresToReturn);
        }