private static object Evaluate(string expression, IActivity activity, string condition, CalculatedFieldsRow calculatedFieldsRow) { expression = ParseExpression(expression, activity, condition, calculatedFieldsRow); //throw new Exception(expression); if (expression == "") { return null; } if (cacheEnabled && !expression.Contains("DATATRACK")) { if (expressionsCache.ContainsKey(expression)) { return expressionsCache[expression]; } } string tempModuleSource = ""; if (expression.Contains("DATATRACK")) { bool includePauses = false; bool onlyActive = false; if (expression.Contains("DATATRACKWITHPAUSES")) { includePauses = true; } if (expression.Contains("DATATRACKACTIVE")) { onlyActive = true; } List<DataTrackPoint> dataTrack = GetDataTrack(activity, onlyActive, includePauses); XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<DataTrackPoint>)); Stream fs = new FileStream(Environment.GetEnvironmentVariable("APPDATA") + "/CalculatedFieldsPlugin/TEMP/DataTrack.xml", FileMode.Create); XmlWriter xmlWriter = new XmlTextWriter(fs, Encoding.Unicode); xmlSerializer.Serialize(xmlWriter, dataTrack); xmlWriter.Close(); tempModuleSource = "namespace ns{" + "using System;using System.Text.RegularExpressions;" + "using System.Collections.Generic;using System.Xml;using System.Xml.Serialization;using System.IO;using System.Linq;" + "class CF{" + "public static object Evaluate(){"; tempModuleSource += "XmlSerializer xmlSerializer = new XmlSerializer(typeof(List<DataTrackPoint>));"; tempModuleSource += "FileStream fsRead = new FileStream(\"" + Environment.GetEnvironmentVariable("APPDATA").Escape() + "/CalculatedFieldsPlugin/TEMP/DataTrack.xml\", FileMode.Open);"; //tempModuleSource += "FileStream fsRead = new FileStream(\"C:/Users/Admin/AppData/Roaming/CalculatedFieldsPlugin/TEMP/DataTrack.xml\", FileMode.Open);"; tempModuleSource += "XmlReader xmlReader = XmlReader.Create(fsRead);"; if (includePauses) { tempModuleSource += "List<DataTrackPoint> DATATRACKWITHPAUSES = (List<DataTrackPoint>) xmlSerializer.Deserialize(xmlReader);"; } else if (onlyActive) { tempModuleSource += "List<DataTrackPoint> DATATRACKACTIVE = (List<DataTrackPoint>) xmlSerializer.Deserialize(xmlReader);"; } else { tempModuleSource += "List<DataTrackPoint> DATATRACK = (List<DataTrackPoint>) xmlSerializer.Deserialize(xmlReader);"; } tempModuleSource += "fsRead.Close();"; if (expression.Contains("@@DIRECT@@")) { tempModuleSource += expression.Replace("@@DIRECT@@", ""); } else { if (includePauses) { tempModuleSource += "if (DATATRACKWITHPAUSES"; } else if (onlyActive) { tempModuleSource += "if (DATATRACKACTIVE"; } else { tempModuleSource += "if (DATATRACK"; } tempModuleSource += ".Count() != 0) return " + expression + "; else return null;"; } tempModuleSource += "} }"; tempModuleSource += "public class DataTrackPoint {" + "int lapNumber;string lapNote;bool lapActive;float hr;float pace;float speed;float elevation;float grade;float cadence;float power;float elapsed;float distance;float climbSpeed;float verticalOscillation;float groundContact;bool pause;" + "public int LapNumber { get { return lapNumber; } set { lapNumber = value; } }" + "public string LapNote { get { return lapNote; } set { lapNote = value; } }" + "public bool LapActive { get { return lapActive; } set { lapActive = value; } }" + "public float Distance { get { return distance; } set { distance = value; } }" + "public float HR { get { return hr; } set { hr = value; } }" + "public float Pace { get { return pace; } set { pace = value; } }" + "public float Speed { get { return speed; } set { speed = value; } }" + "public float Elevation { get { return elevation; } set { elevation = value; } }" + "public float Grade { get { return grade; } set { grade = value; } }" + "public float Cadence { get { return cadence; } set { cadence = value; } }" + "public float Power { get { return power; } set { power = value; } }" + "public float Elapsed { get { return elapsed; } set { elapsed = value; } }" + "public float ClimbSpeed { get { return climbSpeed; } set { climbSpeed = value; } }" + "public float VerticalOscillation { get { return verticalOscillation; } set { verticalOscillation = value; } }" + "public float GroundContact { get { return groundContact; } set { groundContact = value; } }" + "public bool Pause { get { return pause; } set { pause = value; } }" + "public DataTrackPoint(){} }" + "}"; } else { tempModuleSource = "namespace ns{" + "using System;" + "using System.Text.RegularExpressions;" + "class CF{" + "public static object Evaluate(){"; if (expression.Contains("@@DIRECT@@")) { tempModuleSource += expression.Replace("@@DIRECT@@", ""); } else { tempModuleSource += "return " + expression + ";"; } tempModuleSource += "}} }"; } cp.OutputAssembly = Environment.GetEnvironmentVariable("APPDATA") + "/CalculatedFieldsPlugin/TEMP/" + Guid.NewGuid() + ".dll"; CompilerResults cr = provider.CompileAssemblyFromSource(cp, tempModuleSource); if (cr.Errors.Count > 0) { string errorText = "Expression: \"" + expression + "\" cannot be evaluated, please use a valid C# expression\n\n"; foreach (CompilerError error in cr.Errors) { if (!error.IsWarning) { errorText += "\"" + error.ErrorText + "\"" + "\n"; } } throw new Exception(expression + "\n\n" + errorText); } else { object result; MethodInfo methodInfo = cr.CompiledAssembly.GetType("ns.CF").GetMethod("Evaluate"); try { result = methodInfo.Invoke(null, null); } catch (Exception e) { throw new Exception(expression + "\n\n" + e.Message + "\n\n" + e.InnerException.InnerException.InnerException.Message); } if (cacheEnabled && !expression.Contains("DATATRACK")) { expressionsCache.Add(expression, result); } return result; } }
private static string ParseExpression(string expression, IActivity activity, string condition, CalculatedFieldsRow calculatedFieldsRow) { string field; string fieldValue = ""; string nestedExpressionsHistory = ""; Dictionary<string, List<ITrailResult>> trails = null; string history = ""; ActivityInfo activityInfoInstance = ActivityInfoCache.Instance.GetInfo(activity); //while (fieldPattern.IsMatch(expression)) while (FindField(expression) != "") { //field = fieldPattern.Match(expression).Value; field = FindField(expression); //field = bracketsPattern.Replace(field, ""); field = Regex.Replace(field, "^{", ""); field = Regex.Replace(field, "}$", ""); field = field.ToUpper(); if (fieldValue == "") { fieldValue = ActivityFields(activity, activityInfoInstance, field); } if (fieldValue == "") { fieldValue = SplitsFields(activity, activityInfoInstance, field); } if (fieldValue == "") { fieldValue = TrailsFields(activity, activityInfoInstance, field, trails); } if (fieldValue == "") { fieldValue = AthleteFields(activity, activityInfoInstance, field); } if (fieldValue == "") { fieldValue = CustomFields(activity, activityInfoInstance, field); } if (fieldValue == "") { fieldValue = NestedExpressions(field, nestedExpressionsHistory); } if (fieldValue == "") { fieldValue = Formulas(activity, activityInfoInstance, field); } if (fieldValue == "") { fieldValue = Zones(activity, activityInfoInstance, field); } if (fieldValue == "") { fieldValue = LastXDays(activity, activityInfoInstance, condition, field, calculatedFieldsRow); } if (fieldValue == "") { fieldValue = DataTrack(activity, activityInfoInstance, field); } if (fieldValue == "") { fieldValue = VirtualFields(field); } //if (fieldValue == "" || fieldValue == "NaN" || fieldValue == "Infinity") if (fieldValue == "NaN" || fieldValue == "Infinity") { //throw new Exception(expression); expression = ""; } //expression = fieldPattern.Replace(expression, fieldValue, 1); if (expression != "") { if (fieldValue != "") { expression = expression.Replace(FindField(expression), fieldValue); } else // to enabled {} in formulas { fieldValue = FindField(expression).Remove(0, 1); fieldValue = fieldValue.Remove(fieldValue.Length-1, 1); fieldValue = "/#/" + fieldValue + "/###/"; expression = expression.Replace(FindField(expression), fieldValue); } } history += expression + "-"; fieldValue = ""; } //throw new Exception(history); expression = expression.Replace("/#/", "{"); expression = expression.Replace("/###/", "}"); //throw new Exception(expression); return expression; }
private static void SmoothingSetTemporary(CalculatedFieldsRow calculatedFieldsRow) { var analysisSettings = CalculatedFields.GetApplication().SystemPreferences.AnalysisSettings; if (calculatedFieldsRow.SmoothingPace != 0) { analysisSettings.SpeedSmoothingSeconds = calculatedFieldsRow.SmoothingPace; } if (calculatedFieldsRow.SmoothingElevation != 0) { analysisSettings.ElevationSmoothingSeconds = calculatedFieldsRow.SmoothingElevation; } if (calculatedFieldsRow.SmoothingHR != 0) { analysisSettings.HeartRateSmoothingSeconds = calculatedFieldsRow.SmoothingHR; } if (calculatedFieldsRow.SmoothingCadence != 0) { analysisSettings.CadenceSmoothingSeconds = calculatedFieldsRow.SmoothingCadence; } if (calculatedFieldsRow.SmoothingPower != 0) { analysisSettings.PowerSmoothingSeconds = calculatedFieldsRow.SmoothingPower; } }
private static string LastXDays(IActivity activity, ActivityInfo activityInfo, string condition, string field, CalculatedFieldsRow calculatedFieldsRow) { string fieldValue = ""; if (!field.StartsWith("TRAIL")) { double result = 0; string aggField, aggOperation; int count = 0, days = 0; aggField = Regex.Match(field, ".*(?=\\()").Value; aggOperation = Regex.Match(field, "(?<=\\().*(?=,)").Value; if (aggOperation == "SUM" || aggOperation == "AVG" || aggOperation == "MIN" || aggOperation == "MAX" || aggOperation == "GET" || aggOperation == "COUNT") { field = ParseExpression(field, activity, "", null); days = Int32.Parse(Regex.Match(field, "(?<=,)[ 0-9]*(?=\\))").Value.Trim()); if (aggOperation == "GET") { days++; } DateTime actualActivityDate = (activity.StartTime.ToUniversalTime() + activity.TimeZoneUtcOffset).Date; foreach (var pastActivity in CalculatedFields.GetLogBook().Activities) { DateTime pastActivityDate = (pastActivity.StartTime.ToUniversalTime() + activity.TimeZoneUtcOffset).Date; if (pastActivityDate <= actualActivityDate) { if (actualActivityDate.Subtract(pastActivityDate).Days < days) { object conditionResult = "True"; if (condition != "") { conditionResult = Evaluate(condition, pastActivity, "", calculatedFieldsRow); } if (conditionResult.ToString() == "True") { //if (pastActivity.StartTime.Date.Day == 1) //{ // throw new Exception(pastActivity.StartTime.Date.ToString() + "-" + actualActivityDate.ToString() + "-" + activity.StartTime.ToString() + "-" + days.ToString() + "-" + actualActivityDate.Subtract(pastActivity.StartTime.Date).Days.ToString()); //} count++; switch (aggOperation) { case "GET": if (actualActivityDate.Subtract(pastActivityDate).Days == (days - 1)) { result = double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()); } break; case "SUM": result += double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()); break; case "AVG": result += double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()); break; case "MAX": if (result == 0) { result = double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()); } if ( double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()) > result) { result = double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()); } break; case "MIN": if (result == 0) { result = double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()); } if ( double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()) < result) { result = double.Parse( Evaluate("{" + aggField + "}", pastActivity, condition, calculatedFieldsRow).ToString()); } break; } } } } } switch (aggOperation) { case "AVG": if (count != 0) { result /= count; } else { result = 0; } break; case "COUNT": if (count != 0) { result = count; } break; } fieldValue = result.ToString(CultureInfo.InvariantCulture.NumberFormat); } } return fieldValue; }