public List<DetectedInterval> DetectIntervals(SessionDto session)
        {
            var sessionData = session.SessionData;
            var interval = session.Interval;
            var potentialIntervalStart = new SessionDataDto();
            var detectedIntervalEnd = new SessionDataDto();
            var detectedIntervals = new List<DetectedInterval>();

            for (var x = 0; x < sessionData.Count; x++)
            {
                bool potentialIntervalDetected = false;
                bool intervalDetected = false;

                for (var p = x; p < sessionData.Count; p++)
                {
                    // get average of proceeding 14 seconds of powers - time taken for rider to reach maximum power
                    var currentPowers = new List<double>();
                    var proceedingPowers = new List<double>();

                    for (var i = 0; i < 14; i++)
                    {
                        if (p + (i + 1) < sessionData.Count)
                        {
                            if (sessionData[p + i].Power == 0) // rider must be applying power for next 14 seconds
                            {
                                break;
                            }
                            currentPowers.Add(sessionData[p + i].Power); // get power for the next 14 seconds
                            proceedingPowers.Add(sessionData[(p + 1) + i].Power); // get power for the next 14 seconds starting at current power +1
                        }
                    }

                    if (currentPowers.Count == 0) // no powers added to the last - last detected power was 0
                    {
                        break;
                    }

                    var currentPowersAverage = currentPowers.Average();
                    var proceedingPowersAverage = proceedingPowers.Average();

                    // check for potential interval
                    if (currentPowersAverage < proceedingPowersAverage)
                    {
                        if (!potentialIntervalDetected)
                        {
                            potentialIntervalStart = sessionData[p];
                            potentialIntervalDetected = true;
                        }
                    }
                    else // possible that cyclist built up speed and reached interval speed to maintain
                    {
                        var potentialIntervalPowerToMaintain = sessionData[p].Power;

                        var percentage = ((potentialIntervalPowerToMaintain * 40) / 100);
                        var minimumPowerRange = potentialIntervalPowerToMaintain - percentage;
                        var maximumPowerRange = potentialIntervalPowerToMaintain + percentage;
                        var minimumIntervalDuration = 10; // interval power must be maintained for atleast 10 seconds

                        var timer = 0;
                        var counter = 1;
                        for (var q = p; q < sessionData.Count; q++)
                        {
                            if (sessionData[q].Power > minimumPowerRange && sessionData[q].Power < maximumPowerRange)
                            {
                                timer += interval * counter;
                            }
                            else
                            {
                                if (timer > minimumIntervalDuration)
                                {
                                    intervalDetected = true;
                                    detectedIntervalEnd = sessionData[q];

                                    var startTime = potentialIntervalStart.Row * interval;
                                    var finishTime = detectedIntervalEnd.Row * interval;

                                    var intervalData = GetSessionDataSubset(new SessionDataSubsetDto() // get interval summary
                                    {
                                        MinimumSecond = startTime,
                                        MaximumSecond = finishTime,
                                        Unit = 0,
                                        SessionId = session.Id
                                    });
                                    
                                    detectedIntervals.Add(new DetectedInterval(startTime, finishTime, intervalData.AveragePower, true));
                                }
                                break;
                            }
                        }
                    }

                    if (intervalDetected)
                    {
                        x = detectedIntervalEnd.Row * interval; // start detecting new interval at the end of the detected interval
                        potentialIntervalStart = sessionData[detectedIntervalEnd.Row];
                        break;
                    }
                }
            }

            // detect workout and rest periods
            var totalCount = sessionData.Count();
            var totalPower = sessionData.Sum(s => s.Power);
            var averagePower =  Math.Round(totalPower / totalCount, 2, MidpointRounding.AwayFromZero);
            var minimumIntervalPower = ((averagePower * 80) / 100); // workout periods must be greater than 30% of average session power

            for (var f = 0; f < detectedIntervals.Count; f ++)
            {
                detectedIntervals[f].IsRest = detectedIntervals[f].AveragePower < minimumIntervalPower;
            }

            return detectedIntervals;
        }
        public void DateTimeDaysForSessionHeaderRowsShouldBeCalculatedByInterval()
        {
            var interval = 1;
            var startDate = new DateTime(2016, 05, 10, 23, 59, 59, 1); // hh:mm:s:ms - 09:30:5:100

            var sessionRow1 = new SessionDataDto() { Row = 0 };
            var sessionRow2 = new SessionDataDto() { Row = 1 };
            var sessionRow3 = new SessionDataDto() { Row = 2 };

            // calculate seconds for each session header row
            sessionRow1.Date = DateFormat.CalculateSessionDataRowDate(startDate, interval, sessionRow1.Row);
            sessionRow2.Date = DateFormat.CalculateSessionDataRowDate(startDate, interval, sessionRow2.Row);
            sessionRow3.Date = DateFormat.CalculateSessionDataRowDate(startDate, interval, sessionRow3.Row);

            // assert seconds
            Assert.AreEqual(59, sessionRow1.Date.Second);
            Assert.AreEqual(0, sessionRow2.Date.Second);
            Assert.AreEqual(1, sessionRow3.Date.Second);

            // assert minutes
            Assert.AreEqual(10, sessionRow1.Date.Day);
            Assert.AreEqual(11, sessionRow2.Date.Day);
            Assert.AreEqual(11, sessionRow3.Date.Day);
        }