Example #1
0
        public override string GetText(object element, TreeList.Column column)
        {
            Data.TrailResult row = (element as TrailResultWrapper).Result;

            //Some special for Summary
            if (row is SummaryTrailResult)
            {
                switch (column.Id)
                {
                case TrailResultColumnIds.AveragePowerBalance:
                case TrailResultColumnIds.AverageTemperature:
                case TrailResultColumnIds.AverageGroundContactTime:
                case TrailResultColumnIds.AverageVerticalOscillation:
                case TrailResultColumnIds.AverageSaturatedHemoglobin:
                case TrailResultColumnIds.AverageTotalHemoglobinConcentration:
                    //No implementation, ignore
                    return(null);

                default:
                    if (!Controller.TrailController.Instance.ExplicitSelection &&
                        TrailResultColumnIds.ClimbFields.Contains(column.Id) && !row.ClimbCalculated)
                    {
                        //Potentially many selections (of Ascent etc), no value set
                        return(null);
                    }
                    break;
                }

                if (TrailsPlugin.Data.Settings.ResultSummaryStdDev)
                {
                    SummaryTrailResult row2 = row as SummaryTrailResult;
                    if (!row2.IsTotal && row2.Results.Count > 1)
                    {
                        switch (column.Id)
                        {
                        case TrailResultColumnIds.StartTime:
                            //Not interesting to average time when only one activity. Other multi may be interesting.
                            if (row2.Activities.Count <= 1)
                            {
                                return(null);
                            }
                            //Only time of day, averaged
                            return(row.StartTime.ToLocalTime().ToString("T"));

                        case TrailResultColumnIds.Duration:
                        {
                            SummaryValue <TimeSpan> a = row2.DurationStdDev();
                            return(UnitUtil.Time.ToString(a.Value, "") + " σ" + UnitUtil.Time.ToString(a.StdDev, ""));
                        }

                        case TrailResultColumnIds.Distance:
                        {
                            SummaryValue <double> a = row2.DistanceStdDev();
                            string d;
                            if (row.PoolLengthInfo != null)
                            {
                                d = UnitUtil.Distance.ToString(a.Value, row.PoolLengthInfo.DistanceUnits, "F0");
                            }
                            else
                            {
                                d = UnitUtil.Distance.ToString(a.Value, Controller.TrailController.Instance.ReferenceActivity, "");
                            }
                            return(d + " σ" + UnitUtil.Elevation.ToString(a.StdDev, Controller.TrailController.Instance.ReferenceActivity, ""));
                        }

                        case TrailResultColumnIds.AvgPace:
                        {
                            SummaryValue <double> a = row2.AvgPaceStdDev();
                            return(UnitUtil.Pace.ToString(a.Value, Controller.TrailController.Instance.ReferenceActivity, "") + " σ" + UnitUtil.Pace.ToString(a.StdDev, Controller.TrailController.Instance.ReferenceActivity, ""));
                        }

                        case TrailResultColumnIds.AvgSpeed:
                        {
                            SummaryValue <double> a = row2.AvgSpeedStdDev();
                            return(UnitUtil.Speed.ToString(a.Value, Controller.TrailController.Instance.ReferenceActivity, "") + " σ" + UnitUtil.Speed.ToString(a.StdDev, Controller.TrailController.Instance.ReferenceActivity, ""));
                        }

                        case TrailResultColumnIds.AvgSpeedPace:
                        {
                            SummaryValue <double> a;
                            if (UnitUtil.PaceOrSpeed.IsPace(Controller.TrailController.Instance.ReferenceActivity))
                            {
                                a = row2.AvgPaceStdDev();
                                return(UnitUtil.Pace.ToString(a.Value, Controller.TrailController.Instance.ReferenceActivity, "") + " σ" + UnitUtil.Pace.ToString(a.StdDev, Controller.TrailController.Instance.ReferenceActivity, ""));
                            }
                            else
                            {
                                a = row2.AvgSpeedStdDev();
                                return(UnitUtil.Speed.ToString(a.Value, Controller.TrailController.Instance.ReferenceActivity, "") + " σ" + UnitUtil.Speed.ToString(a.StdDev, Controller.TrailController.Instance.ReferenceActivity, ""));
                            }
                        }

                        //case TrailResultColumnIds.GradeRunAdjustedTime:
                        //    {
                        //        SummaryValue<double> a = row2.GradeRunAdjustedTimeStdDev();
                        //        return UnitUtil.Time.ToString(a.Value, "") + " σ" + UnitUtil.Time.ToString(a.StdDev, "");
                        //    }
                        //case TrailResultColumnIds.GradeRunAdjustedPace:
                        //    {
                        //        SummaryValue<TimeSpan> a = row2.GradeRunAdjustedPaceStdDev();
                        //        return UnitUtil.Pace.ToString(a.Value, Controller.TrailController.Instance.ReferenceActivity, "") + " σ" + UnitUtil.Pace.ToString(a.StdDev, Controller.TrailController.Instance.ReferenceActivity, "");
                        //    }
                        //case TrailResultColumnIds.Diff:
                        //    {
                        //        SummaryValue<double> a = row2.DiffStdDev();
                        //        return UnitUtil.Elevation.ToString(a.Value, Controller.TrailController.Instance.ReferenceActivity, "") + " σ" + UnitUtil.Elevation.ToString(a.StdDev, Controller.TrailController.Instance.ReferenceActivity, "");
                        //    }
                        default:
                            break;
                        }
                    }
                }
            }

            if (row is PausedChildTrailResult)
            {
                switch (column.Id)
                {
                //Some paused fields should not be visible
                case TrailResultColumnIds.Order:
                    return(null);

                default:
                    break;
                }
            }

            if (row is SubChildTrailResult)
            {
                switch (column.Id)
                {
                //Ignore wildly inaccurate data, few points for Pool swimming, can be lower than Avg
                //(not always good on lap level too)
                case TrailResultColumnIds.FastestSpeed:
                case TrailResultColumnIds.FastestPace:
                    return(null);

                default:
                    break;
                }
            }

            switch (column.Id)
            {
            case TrailResultColumnIds.ResultColor:
                return(null);

            //String output without formatting
            case TrailResultColumnIds.Order:
            case TrailResultColumnIds.Name:
            case TrailResultColumnIds.TrailName:
                return(base.GetText(row, column));

            case TrailResultColumnIds.StartTime:
                if (row.Activity == null)
                {
                    return(null);
                }
                string date = "";
                if (m_multiple)
                {
                    date = row.StartTime.ToLocalTime().ToShortDateString() + " ";
                }
                return(date + row.StartTime.ToLocalTime().ToString("T"));

            case TrailResultColumnIds.StartDistance:
                if (row.PoolLengthInfo != null)
                {
                    return(UnitUtil.Distance.ToString(row.StartDistance, row.PoolLengthInfo.DistanceUnits, "F0u"));
                }
                else
                {
                    return(UnitUtil.Distance.ToString(row.StartDistance, Controller.TrailController.Instance.ReferenceActivity, ""));
                }

            case TrailResultColumnIds.EndTime:
                if (row.Activity == null)
                {
                    return(null);
                }
                return(row.EndTime.ToLocalTime().ToString("T"));

            case TrailResultColumnIds.Duration:
                return(UnitUtil.Time.ToString(row.Duration, ""));

            case TrailResultColumnIds.Distance:
                if (row.PoolLengthInfo != null)
                {
                    return(UnitUtil.Distance.ToString(row.Distance, row.PoolLengthInfo.DistanceUnits, "F0u"));
                }
                else
                {
                    return(UnitUtil.Distance.ToString(row.Distance, Controller.TrailController.Instance.ReferenceActivity, ""));
                }

            case TrailResultColumnIds.AvgCadence:
                return(UnitUtil.Cadence.ToString(row.AvgCadence));

            case TrailResultColumnIds.AvgHR:
                return(UnitUtil.HeartRate.ToString(row.AvgHR));

            case TrailResultColumnIds.MaxHR:
                return(UnitUtil.HeartRate.ToString(row.MaxHR));

            case TrailResultColumnIds.Ascent:
                return(UnitUtil.Elevation.ToString(row.Ascent));

            case TrailResultColumnIds.Descent:
                return(UnitUtil.Elevation.ToString(row.Descent));

            case TrailResultColumnIds.ElevChg:
                return((row.ElevChg > 0 ? "+" : "") + UnitUtil.Elevation.ToString(row.ElevChg, ""));

            case TrailResultColumnIds.AvgPower:
                return(UnitUtil.Power.ToString(row.AvgPower));

            case TrailResultColumnIds.AscAvgGrade:
                return((row.AscAvgGrade).ToString("0.0%"));

            case TrailResultColumnIds.AscMaxAvgGrade:
                return((row.AscMaxAvgGrade).ToString("0.0%"));

            case TrailResultColumnIds.DescAvgGrade:
                return((row.DescAvgGrade).ToString("0.0%"));

            case TrailResultColumnIds.AvgSpeed:
                return(UnitUtil.Speed.ToString(row.AvgSpeed, Controller.TrailController.Instance.ReferenceActivity, ""));

            case TrailResultColumnIds.FastestSpeed:
                return(UnitUtil.Speed.ToString(row.FastestSpeed, Controller.TrailController.Instance.ReferenceActivity, ""));

            case TrailResultColumnIds.AvgPace:
                return(UnitUtil.Pace.ToString(row.AvgSpeed, Controller.TrailController.Instance.ReferenceActivity, ""));

            case TrailResultColumnIds.FastestPace:
                return(UnitUtil.Pace.ToString(row.FastestSpeed, Controller.TrailController.Instance.ReferenceActivity, ""));

            case TrailResultColumnIds.AvgSpeedPace:
                return(UnitUtil.PaceOrSpeed.ToString(row.AvgSpeed, Controller.TrailController.Instance.ReferenceActivity, ""));

            case TrailResultColumnIds.FastestSpeedPace:
                return(UnitUtil.PaceOrSpeed.ToString(row.FastestSpeed, Controller.TrailController.Instance.ReferenceActivity, ""));

            case TrailResultColumnIds.PredictDistance:
                return(UnitUtil.Time.ToString(row.PredictDistance, ""));

            case TrailResultColumnIds.IdealTime:
                return(UnitUtil.Time.ToString(row.IdealTime, ""));

            case TrailResultColumnIds.GradeRunAdjustedTime:
                return(UnitUtil.Time.ToString(row.GradeRunAdjustedTime, ""));

            case TrailResultColumnIds.GradeRunAdjustedPace:
                return(UnitUtil.Pace.ToString(row.GradeRunAdjustedSpeed, Controller.TrailController.Instance.ReferenceActivity, ""));

            case TrailResultColumnIds.Diff:
                return(UnitUtil.Elevation.ToString(row.Diff, ""));

            case TrailResultColumnIds.AscendingSpeed_VAM:
                return(UnitUtil.Elevation.ToString(row.AscendingSpeed_VAM, ""));

            case TrailResultColumnIds.AveragePowerBalance:
                return((row.AveragePowerBalance / 100).ToString("0.0%"));

            case TrailResultColumnIds.AverageTemperature:
                return((row.AverageTemperature).ToString("0.0"));

            case TrailResultColumnIds.AverageGroundContactTime:
                return((row.AverageGroundContactTime).ToString("0"));

            case TrailResultColumnIds.AverageVerticalOscillation:
                return((row.AverageVerticalOscillation).ToString("0.0"));

            case TrailResultColumnIds.AverageSaturatedHemoglobin:
                return((row.AverageSaturatedHemoglobin / 100).ToString("0.0%"));

            case TrailResultColumnIds.AverageTotalHemoglobinConcentration:
                return((row.AverageTotalHemoglobinConcentration).ToString("0.0"));

            default:

                if (TrailResultColumns.IsLapField(column.Id))
                {
                    ILapInfo lap = row.LapInfo;
                    if (lap != null)
                    {
                        //The column Id is faked to not clash with the internal ids
                        TreeList.Column c = new TreeList.Column(TrailResultColumns.LapId(column.Id));
                        return(base.GetText(lap, c));
                    }
                    //Not Splits trail
                    return(null);
                }
                else if (TrailResultColumns.IsSwimLapField(column.Id))
                {
                    IPoolLengthInfo lap = row.PoolLengthInfo;
                    if (lap != null)
                    {
                        //The column Id is faked to not clash with the internal ids
                        TreeList.Column c = new TreeList.Column(TrailResultColumns.SwimLapId(column.Id));
                        return(base.GetText(lap, c));
                    }
                    //Not Splits trail
                    return(null);
                }
                else if (TrailResultColumns.IsActivityField(column.Id))
                {
                    if (row is ParentTrailResult)
                    {
                        if (row.Activity == null)
                        {
                            return(null);
                        }
                        if (column.Id == TrailResultColumnIds.MetaData_Source)
                        {
                            return(row.Activity.Metadata.Source);
                        }
                        return(base.GetText(row.Activity, column));
                    }
                    return(null);
                }
                else
                {
                    if (row.Activity == null)
                    {
                        return(null);
                    }
                    ICustomDataFieldDefinition cust = TrailResultColumns.CustomDef(column.Id);
                    if (cust != null)
                    {
                        if (row is ParentTrailResult)
                        {
                            return(row.Activity.GetCustomDataValue(TrailResultColumns.CustomDef(column.Id)).ToString());
                        }
                        return(null);
                    }
                }

                System.Diagnostics.Debug.Assert(false, string.Format("No label info for id {0}", column.Id));
                return(null);
            }
        }
Example #2
0
        public static int Compare(TrailResult x, TrailResult y)
        {
            if (x == null)
            {
                return(1);
            }
            if (y == null)
            {
                return(-1);
            }

            //Summary results are not supposed to be sorted, this should not be used
            if (x is SummaryTrailResult)
            {
                if ((x as SummaryTrailResult).IsTotal || !(y is SummaryTrailResult))
                {
                    return(1);
                }
            }
            if (y is SummaryTrailResult)
            {
                return(-1);
            }

            int result = 0;

            {
                //Paused results handling
                //Keep the paused result close to the unpaused result by using the normal resul
                //If two results to sort relate to the same normal result, use the start time to sort them
                TrailResult x0 = x;
                TrailResult y0 = y;
                if (x is PausedChildTrailResult)
                {
                    x = (x as PausedChildTrailResult).RelatedChildResult;
                }
                if (y is PausedChildTrailResult)
                {
                    y = (y as PausedChildTrailResult).RelatedChildResult;
                }

                if (x == y)
                {
                    result = x0.StartTime.CompareTo(y0.StartTime);
                    if (TrailsPlugin.Data.Settings.SummaryViewSortColumns.Count > 0 && TrailsPlugin.Data.Settings.SummaryViewSortColumns[0].Equals(TrailResultColumnIds.StartTime))
                    {
                        //Switch order when sorting on start time only
                        result *= (TrailsPlugin.Data.Settings.SummaryViewSortDirection == ListSortDirection.Ascending ? 1 : -1);
                    }
                    return(result);
                }
            }

            const string GradeRunAdjustedPace_Field = "GradeRunAdjustedSpeed";

            foreach (string id0 in TrailsPlugin.Data.Settings.SummaryViewSortColumns)
            {
                bool   reverseSortOrder = false;
                string id = id0;
                //Sort Pace and speed the same
                switch (id)
                {
                case TrailResultColumnIds.AvgPace:
                case TrailResultColumnIds.AvgSpeedPace:
                    id = TrailResultColumnIds.AvgSpeed;
                    break;

                case TrailResultColumnIds.FastestPace:
                case TrailResultColumnIds.FastestSpeedPace:
                    id = TrailResultColumnIds.FastestSpeed;
                    break;

                case TrailResultColumnIds.GradeRunAdjustedPace:
                    reverseSortOrder = true;
                    id = GradeRunAdjustedPace_Field;
                    break;
                }

                //Limit "automatic" calculations in some situations
                if (TrailsPlugin.Controller.TrailController.Instance.AutomaticUpdate)
                {
                    if (id == TrailResultColumnIds.GradeRunAdjustedTime ||
                        id == TrailResultColumnIds.PredictDistance ||
                        id == TrailResultColumnIds.IdealTime)
                    {
                        id = TrailResultColumnIds.Duration;
                    }
                    if (id == GradeRunAdjustedPace_Field)
                    {
                        id = TrailResultColumnIds.AvgPace;
                    }
                }
                if (TrailResultColumnIds.ClimbFields.Contains(id) && (!x.ClimbCalculated || !y.ClimbCalculated))
                {
                    continue;
                }

                try
                {
                    Boolean fieldFound = false;
                    if (id == TrailResultColumnIds.MetaData_Source)
                    {
                        //Special handling, sub object
                        fieldFound = true;
                        if (x is ParentTrailResult && x.Activity != null && y.Activity != null)
                        {
                            result = x.Activity.Metadata.Source.CompareTo(y.Activity.Metadata.Source);
                        }
                    }

                    {
                        //Dont bother with reflection CompareTo, few types, just complicates TrailResult/Lap
                        //If not parent result, there is no difference
                        ICustomDataFieldDefinition cust = TrailResultColumns.CustomDef(id);
                        if (cust != null)
                        {
                            fieldFound = true;
                            if (x is ParentTrailResult && x.Activity != null && y.Activity != null)
                            {
                                object xoc = x.Activity.GetCustomDataValue(cust);
                                object yoc = y.Activity.GetCustomDataValue(cust);
                                if (xoc == null)
                                {
                                    result = 1;
                                }
                                else if (yoc == null)
                                {
                                    result = -1;
                                }
                                else if (cust.DataType.Id.Equals(new System.Guid("{6e0f7115-6aa3-49ea-a855-966ce17317a1}")))
                                {
                                    //numeric
                                    result = ((System.Double)xoc).CompareTo((System.Double)yoc);
                                }
                                else
                                {
                                    //date or string
                                    result = ((string)xoc).CompareTo((string)yoc);
                                }
                            }
                        }
                    }
                    if (!fieldFound)
                    {
                        //Use reflection to get values and compare routines
                        //This is very slightly slower than hardcoded access.
                        //Profiling on the simple Duration field, it takes 129 ms vs 150ms for 64000/57000(?) operations (Splits, 2400 activities, sorted twice)
                        //(Total sort is 300/400 ms though)
                        //An attempt to cache method gave 180ms 82000(?), this was removed
                        //For most fields, this is not measurable, getting data is much slower
                        object xo;
                        object yo;

                        if (IsLapField(id))
                        {
                            //Note: Some lap/poolinfo fields are read using TrailResult properties
                            id = LapId(id);
                            xo = x.LapInfo;
                            yo = y.LapInfo;
                        }
                        else if (IsSwimLapField(id))
                        {
                            id = SwimLapId(id);
                            xo = x.PoolLengthInfo;
                            yo = y.PoolLengthInfo;
                        }
                        else if (IsActivityField(id))
                        {
                            xo = x.Activity;
                            yo = y.Activity;
                        }
                        else
                        {
                            xo = x;
                            yo = y;
                        }

                        if (xo != null && yo != null)
                        {
                            //Only Properties, no fields searched
                            PropertyInfo xf = xo.GetType().GetProperty(id);
                            PropertyInfo yf = yo.GetType().GetProperty(id);
                            if (xf == null)
                            {
                                Debug.Assert(false, string.Format("No property info for id {0} for x {1}", id, xo));
                                result = 1;
                            }
                            else if (yf == null)
                            {
                                Debug.Assert(false, string.Format("No property info for id {0} for y {1}", id, yo));
                                result = -1;
                            }

                            object xv = xf.GetValue(xo, null);
                            object yv = yf.GetValue(yo, null);
                            if (xv == null)
                            {
                                //Debug.Assert(false, string.Format("No value for id {0} for x {1}", id, xo));
                                if (yv == null)
                                {
                                    result = 1;
                                }
                            }
                            else if (yv == null)
                            {
                                Debug.Assert(false, string.Format("No value for id {0} for y {1}", id, yo));
                                if (xv == null)
                                {
                                    result = -1;
                                }
                            }
                            else
                            {
                                //Get the CompareTo method using reflection
                                MethodInfo cmp = null;
                                //Specialized version of generic (not applicable for .Net2)
                                // from http://stackoverflow.com/questions/4035719/getmethod-for-generic-method
                                foreach (MethodInfo methodInfo in xv.GetType().GetMember("CompareTo",
                                                                                         MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance))
                                {
                                    // Check that the parameter counts and types match,
                                    // with 'loose' matching on generic parameters
                                    ParameterInfo[] parameterInfos = methodInfo.GetParameters();
                                    if (parameterInfos.Length == 1)
                                    {
                                        if (parameterInfos[0].ParameterType.Equals(yv) || parameterInfos[0].ParameterType.Equals(typeof(object)))
                                        {
                                            cmp = methodInfo;
                                            break;
                                        }
                                    }
                                }
                                if (cmp != null)
                                {
                                    result = (int)cmp.Invoke(xv, new object[1] {
                                        yv
                                    });
                                }
                                else
                                {
                                    Debug.Assert(false, string.Format("No CompareTo for id {0} for x {1}", id, xo));
                                }
                            }
                        }
                        else if (xo == null)
                        {
                            result = 1;
                        }
                        else if (y == null)
                        {
                            result = -1;
                        }
                    }
                }

                catch (System.Exception e)
                {
                    Debug.Assert(false, string.Format("Exception when finding properties for id {0} for x {1}, y {2}: {3}", id, x, y, e));
                }

                if (result != 0)
                {
                    if (reverseSortOrder)
                    {
                        result *= -1;
                    }
                    break;
                }
            }
            if (result == 0)
            {
                //Fallback sorting
                result = x.StartTime.CompareTo(y.StartTime);
            }
            result *= (TrailsPlugin.Data.Settings.SummaryViewSortDirection == ListSortDirection.Ascending ? 1 : -1);
            return(result);
        }