Ejemplo n.º 1
0
        private static void ComputeDetailedFileReport(Options options)
        {
            using (var stream = File.OpenRead(options.File))
            {
                var    parser = new FastParser(stream);
                var    laps   = new List <LapSummary>();
                double minimumHeartRateStandardDeviation = 4;

                var normalizedPowerCalculator      = new PowerStatisticsCalculator(FTP);
                var powerCurveCalculator           = new PowerCurveCalculator(new int[] { 1, 5, 10, 30, 60, 120, 240, 300, 600, 900 });
                var normalizedPowerCurveCalculator = new NormalizedPowerCurveCalculator(new int[] { 60, 120, 240, 300, 600, 900 });
                var heartRateVarianceCalculator    = new HeartRateVarianceCalculator(new int[] { 600, 1200, 2400, 3600 });
                var efficiencyFactorCalculator     = new EfficiencyFactorCalculator(new int[] { 600, 1200, 2400 }, minimumHeartRateStandardDeviation);

                var timer = new Stopwatch();
                timer.Start();

                foreach (var record in parser.GetMessages())
                {
                    if (record.GlobalMessageNumber != GlobalMessageDecls.Record)
                    {
                        // Dump the name of the record
                        Console.WriteLine(record.GlobalMessageNumber.ToString());
                    }
                    if (record.GlobalMessageNumber == GlobalMessageDecls.Record)
                    {
                        double power, heartRate;
                        bool   hasPower, hasHeartRate;

                        if (hasPower = record.TryGetField(RecordDef.Power, out power))
                        {
                            powerCurveCalculator.Add(power);
                            normalizedPowerCalculator.Add(power);
                            normalizedPowerCurveCalculator.Add(power);
                        }

                        if (hasHeartRate = record.TryGetField(RecordDef.HeartRate, out heartRate))
                        {
                            heartRateVarianceCalculator.Add(heartRate);
                        }

                        if (hasPower && hasHeartRate)
                        {
                            efficiencyFactorCalculator.Add(power, heartRate);
                        }
                    }
                    else if (record.IsStopTimerEvent())
                    {
                        normalizedPowerCalculator.Reset();
                        powerCurveCalculator.Reset();
                        normalizedPowerCurveCalculator.Reset();
                        heartRateVarianceCalculator.Reset();
                        efficiencyFactorCalculator.Reset();
                    }
                    else if (record.GlobalMessageNumber == GlobalMessageDecls.Lap)
                    {
                    }
                }

                timer.Stop();

                Console.WriteLine("Peak Average Power Curve:\n");
                for (int i = 0; i < powerCurveCalculator.Durations.Length; i++)
                {
                    Console.WriteLine("Duration: {0}s, Peak Average Power: {1:0}W",
                                      powerCurveCalculator.Durations[i],
                                      powerCurveCalculator.PeakAveragePowerForDuration[i]);
                }
                Console.WriteLine("\n");

                Console.WriteLine("Peak Normalized Power Curve:\n");
                for (int i = 0; i < normalizedPowerCurveCalculator.Durations.Length; i++)
                {
                    Console.WriteLine("Duration: {0}s, Peak Normalized Power: {1:0}W",
                                      normalizedPowerCurveCalculator.Durations[i],
                                      normalizedPowerCurveCalculator.PeakNormalizedPowerForDuration[i]);
                }
                Console.WriteLine("\n");

                Console.WriteLine("Minimum Heart Rate Variance:\n");
                for (int i = 0; i < heartRateVarianceCalculator.Durations.Length; i++)
                {
                    Console.WriteLine("Duration: {0}s, Average Heart Rate: {1:0}bpm +/- {2:0.0}",
                                      heartRateVarianceCalculator.Durations[i],
                                      heartRateVarianceCalculator.MeanHeartRateForDuration[i],
                                      heartRateVarianceCalculator.StandardDeviationForDuration[i]);
                }
                Console.WriteLine("\n");

                Console.WriteLine("Efficiency Factor:\n");
                for (int i = 0; i < efficiencyFactorCalculator.Durations.Length; i++)
                {
                    Console.WriteLine("Duration: {0}s, NP = {1:0}W, HR = {2:0.0}+/-{3:0.0}, EF = {4:0.000}",
                                      efficiencyFactorCalculator.Durations[i],
                                      efficiencyFactorCalculator.NormalizedPowerForDuration[i],
                                      efficiencyFactorCalculator.MeanHeartRateForDuration[i],
                                      efficiencyFactorCalculator.StandardDeviationForDuration[i],
                                      efficiencyFactorCalculator.EfficiencyFactorForDuration[i]);
                }
                Console.WriteLine("\n");

                Console.WriteLine("Summary statistics:\n");
                Console.WriteLine("Average Heart Rate: {0:0}bpm", heartRateVarianceCalculator.AverageHeartRate);
                Console.WriteLine("Average power: {0:0}W", powerCurveCalculator.AveragePower);
                Console.WriteLine("Normalized power: {0:0}W", normalizedPowerCalculator.NormalizedPower);
                Console.WriteLine("Intensity factor: {0:0.000}", normalizedPowerCalculator.IntensityFactor);
                Console.WriteLine("Variability index: {0:0.000}", normalizedPowerCalculator.VariabilityIndex);
                Console.WriteLine("Training Stress Score: {0:0}", normalizedPowerCalculator.TrainingStressScore);
                Console.WriteLine("Processing duration: {0}ms", timer.ElapsedMilliseconds);

                // Optional part to dump captured heart rate from efficiency calculator
                if (options.DumpHeartRateData)
                {
                    for (int i = 0; i < efficiencyFactorCalculator.StandardDeviationForDuration.Length; i++)
                    {
                        if (efficiencyFactorCalculator.StandardDeviationForDuration[i] > 0)
                        {
                            for (int j = 0; j < efficiencyFactorCalculator.CapturedHeartRateTraces[i].Length; j++)
                            {
                                Console.WriteLine(efficiencyFactorCalculator.CapturedHeartRateTraces[i][j]);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 2
0
        static void ComputeTrainingStressReport(Options options)
        {
            var files = Directory.GetFiles(options.Directory, "*.fit");
            var timer = new Stopwatch();

            timer.Start();

            var sb = new StringBuilder();
            Dictionary <int, Dictionary <int, double> > tssHistogram = new Dictionary <int, Dictionary <int, double> >();
            var calendar = System.Globalization.DateTimeFormatInfo.CurrentInfo.Calendar;

            foreach (var file in files)
            {
                using (var stream = File.OpenRead(file))
                {
                    var parser          = new FastParser(stream);
                    var powerCalculator = new PowerStatisticsCalculator(FTP);

                    bool     isFirstRecord = true, retrievedTimeStampOfFirstRecord = false;
                    DateTime timeStampOfFirstRecord = DateTime.MinValue;

                    foreach (var message in parser.GetMessages())
                    {
                        if (message.GlobalMessageNumber == GlobalMessageDecls.Record)
                        {
                            if (isFirstRecord)
                            {
                                retrievedTimeStampOfFirstRecord = message.TryGetField(RecordDef.TimeStamp, out timeStampOfFirstRecord);
                                isFirstRecord = false;
                            }

                            double power;
                            if (message.TryGetField(RecordDef.Power, out power))
                            {
                                powerCalculator.Add(power);
                            }
                        }
                    }

                    if (retrievedTimeStampOfFirstRecord)
                    {
                        int year = timeStampOfFirstRecord.Year;
                        int week = calendar.GetWeekOfYear(timeStampOfFirstRecord, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Monday);

                        if (!tssHistogram.ContainsKey(year))
                        {
                            tssHistogram[year] = new Dictionary <int, double>();
                        }

                        if (tssHistogram[year].ContainsKey(week))
                        {
                            tssHistogram[year][week] += powerCalculator.TrainingStressScore;
                        }
                        else
                        {
                            tssHistogram[year][week] = powerCalculator.TrainingStressScore;
                        }
                    }
                    else
                    {
                        sb.Append(String.Format("Unknown date for {0} TSS: {1:0}\n", file, powerCalculator.TrainingStressScore));
                    }
                }
            }

            // Generate Report
            foreach (int year in tssHistogram.Keys)
            {
                sb.Append(String.Format("\nYear {0}\n", year));
                foreach (int week in tssHistogram[year].Keys)
                {
                    sb.Append(String.Format("  Week {0} TSS = {1:0}\n", week, tssHistogram[year][week]));
                }
            }
            timer.Stop();
            Console.WriteLine(sb);
            Console.WriteLine("Total compute time: {0}ms", timer.ElapsedMilliseconds);
        }
Ejemplo n.º 3
0
        static void ComputeEfficiencyFactorReport(Options options)
        {
            // Parameters
            double standardDeviationThreshold = 7;
            double meanHeartRateLimit         = 142; // upper limit of Z2

            var files = Directory.GetFiles(options.Directory, "*.fit");

            var timer = new Stopwatch();

            timer.Start();

            var sb = new StringBuilder();

            foreach (var file in files)
            {
                using (var stream = File.OpenRead(file))
                {
                    var parser = new FastParser(stream);
                    var efficiencyFactorCalculator = new EfficiencyFactorCalculator(new int[] { 600 }, standardDeviationThreshold);

                    foreach (var record in parser.GetMessages())
                    {
                        if (record.GlobalMessageNumber == GlobalMessageDecls.Record)
                        {
                            double power, heartRate;
                            bool   hasPower     = record.TryGetField(RecordDef.Power, out power);
                            bool   hasHeartRate = record.TryGetField(RecordDef.HeartRate, out heartRate);
                            if (hasPower && hasHeartRate)
                            {
                                efficiencyFactorCalculator.Add(power, heartRate);
                            }
                        }
                        else if (record.IsStopTimerEvent())
                        {
                            efficiencyFactorCalculator.Reset();
                        }
                    }

                    if (!efficiencyFactorCalculator.HasData)
                    {
                        //Console.WriteLine("{0} has no HR data", Path.GetFileNameWithoutExtension(file));
                    }
                    else
                    {
                        for (int i = 0; i < efficiencyFactorCalculator.Durations.Length; i++)
                        {
                            if (efficiencyFactorCalculator.StandardDeviationForDuration[i] > 0 &&
                                efficiencyFactorCalculator.MeanHeartRateForDuration[i] < meanHeartRateLimit)
                            {
                                sb.AppendLine(String.Format("{0}, Duration {1}s, EF = {2:0.000}, NP = {3:0}, Avg HR = {4:0.0} +/- {5:0.0}",
                                                            Path.GetFileNameWithoutExtension(file),
                                                            efficiencyFactorCalculator.Durations[i],
                                                            efficiencyFactorCalculator.EfficiencyFactorForDuration[i],
                                                            efficiencyFactorCalculator.NormalizedPowerForDuration[i],
                                                            efficiencyFactorCalculator.MeanHeartRateForDuration[i],
                                                            efficiencyFactorCalculator.StandardDeviationForDuration[i]));
                            }
                        }
                    }
                }
            }

            timer.Stop();
            Console.WriteLine(sb);
            Console.WriteLine("Total compute time: {0}ms", timer.ElapsedMilliseconds);
        }