private WorkshopValidatedItem TestCarSpecAcceleration() { return(TestSpec("Car top speed", Target.SpecsAcceleration, () => { var actualValue = FlexibleParser.TryParseDouble(Target.SpecsAcceleration) ?? 0d; return Target.SpecsAcceleration?.IndexOf("--") >= 0 || actualValue < 0.1 ? "-- s 0–100" : $"{actualValue.Round(0.1)} s 0–100"; }, v => Target.SpecsAcceleration = v)); }
private WorkshopValidatedItem TestCarSpecTopSpeed() { return(TestSpec("Car top speed", Target.SpecsTopSpeed, () => { var actualValue = FlexibleParser.TryParseDouble(Target.SpecsTopSpeed) ?? 0d; return Target.SpecsTopSpeed?.IndexOf("--") >= 0 || actualValue < 0.1 ? "-- km/h" : $"{actualValue.Round()} km/h"; }, v => Target.SpecsTopSpeed = v)); }
private static void Finish(Lut values, string data, int index, int line, ref double key, ref int started, ref int malformed) { if (started != -1) { if (double.IsNaN(key)) { if (malformed == -1) { AcToolsLogging.Write($@"Key is NaN at {line}"); malformed = line; } } else { if (FlexibleParser.TryParseDouble(data.Substring(started, index - started), out var value)) { values.Add(new LutPoint(key, value)); } else { if (malformed == -1) { AcToolsLogging.Write($@"Failed to parse key “{data.Substring(started, index - started)}” at {line}"); malformed = line; } } key = double.NaN; } started = -1; } else if (!double.IsNaN(key)) { key = double.NaN; } }
public static bool ToMeters([CanBeNull] string value, out double meters) { if (value == null) { meters = 0d; return(false); } if (!FlexibleParser.TryParseDouble(value, out meters)) { return(false); } if (value.IndexOf("km", StringComparison.InvariantCultureIgnoreCase) != -1 || value.IndexOf("κμ", StringComparison.InvariantCultureIgnoreCase) != -1) { meters *= 1e3; } if (value.IndexOf("mm", StringComparison.InvariantCultureIgnoreCase) != -1 || value.IndexOf("μμ", StringComparison.InvariantCultureIgnoreCase) != -1) { meters /= 1e2; } return(true); }
private void FixValue(TextBox textBox) { var mask = GetTextBoxMask(textBox); if (mask == null) { return; } var text = textBox.Text; if (Equals(textBox, AccelerationInput)) { text = text.Replace(@"0-100", ""); } double value; if (!FlexibleParser.TryParseDouble(text, out value)) { return; } textBox.Text = Format(mask, value.ToString(CultureInfo.InvariantCulture)); }
private static ITestEntry CreateNumericTestEntry(Operator op, string key, string value) { if (value.IndexOf(':') != -1) { return(CreateTimeSpanTestEntry(op, value)); } var point = value.IndexOf('.'); if (point != -1 && value.IndexOf('.', point + 1) != -1 || value.IndexOf('/') != -1 || value.IndexOf('-') > 0) { return(CreateDateTimeTestEntry(op, value)); } if (DistanceTestEntry.IsDistanceKey(key) || DistanceTestEntry.IsDistanceValue(value)) { double num; return(DistanceTestEntry.ToMeters(value, out num) ? new DistanceTestEntry(op, num) : (ITestEntry) new ConstTestEntry(false)); } if (point != -1 || value.IndexOf(',') != -1) { double num; return(FlexibleParser.TryParseDouble(value, out num) ? new NumberTestEntry(op, num) : (ITestEntry) new ConstTestEntry(false)); } else { int num; return(FlexibleParser.TryParseInt(value, out num) ? new IntTestEntry(op, num) : (ITestEntry) new ConstTestEntry(false)); } }
private void RecalculateAndScaleCurves(object sender, RoutedEventArgs e) { double maxPower, maxTorque; if (!FlexibleParser.TryParseDouble(PowerInput.Text, out maxPower) || !FlexibleParser.TryParseDouble(TorqueInput.Text, out maxTorque)) { NonfatalError.Notify(ToolsStrings.Common_CannotDo_Title, AppStrings.CarSpecs_SpecifyPowerAndTorqueFirst); return; } var data = Car.AcdData; if (data == null) { NonfatalError.Notify(ToolsStrings.Common_CannotDo_Title, "Data is damaged"); return; } Lut torque; try { torque = TorquePhysicUtils.LoadCarTorque(data); } catch (Exception ex) { NonfatalError.Notify(ToolsStrings.Common_CannotDo_Title, ex); return; } torque.ScaleToSelf(maxTorque); TorqueGraph = new GraphData(torque); torque.TransformSelf(x => x.X * x.Y); torque.ScaleToSelf(maxPower); PowerGraph = new GraphData(torque); }
private static void Finish(Lut values, string data, int index, int line, ref double key, ref int started, ref int malformed) { if (started != -1) { if (double.IsNaN(key)) { if (malformed == -1) { malformed = line; } } else { double value; if (FlexibleParser.TryParseDouble(data.Substring(started, index - started), out value)) { values.Add(new LutPoint(key, value)); } else { if (malformed == -1) { malformed = line; } } key = double.NaN; } started = -1; } else if (!double.IsNaN(key)) { key = double.NaN; } }
private float[] GetVectorF([NotNull, LocalizationRequired(false)] string key, int size) { var result = new float[size]; var line = GetNonEmpty(key); if (line == null) { return(result); } var s = line.Split(','); if (s.Length != size) { return(result); } for (var i = 0; i < result.Length; i++) { if (FlexibleParser.TryParseDouble(s[i], out double f)) { result[i] = (float)f; } } return(result); }
private WorkshopValidatedItem TestCarSpecPwRatio() { return(TestSpec("Car P/W ratio", Target.SpecsPwRatio, () => { var carPower = FlexibleParser.TryParseDouble(Target.SpecsBhp) ?? 0d; var carWeight = GetSpecsWeight(out _); return carPower < 0.01 || carWeight == null ? "-- kg/hp" : $"{(carWeight.Value / carPower).ToString("F2", CultureInfo.InvariantCulture)} kg/hp"; }, v => Target.SpecsPwRatio = v)); }
protected override ContentRepairSuggestion GetObsoletableAspect(CarObject car, DataWrapper data) { // doesn’t work with KERS if (!data.GetIniFile("ers.ini").IsEmptyOrDamaged() || !data.GetIniFile("ctrl_ers_0.ini").IsEmptyOrDamaged()) { return(null); } if ((car.SpecsBhp?.IndexOf("*", StringComparison.Ordinal) ?? 0) != -1 || (car.SpecsBhp?.IndexOf("whp", StringComparison.OrdinalIgnoreCase) ?? 0) != -1 || (car.SpecsTorque?.IndexOf("*", StringComparison.Ordinal) ?? 0) != -1 || !FlexibleParser.TryParseDouble(car.SpecsTorque, out var maxUiTorque)) { return(null); } Lut torque; try { torque = TorquePhysicUtils.LoadCarTorque(data); } catch (Exception e) { Logging.Warning(e); return(null); } var loss = 1d - torque.MaxY / maxUiTorque; if (loss > 0.01) { return(null); } var actual = loss.Abs() < 0.002 ? "same" : loss > 0 ? $"{loss * 100:F1}% smaller" : $"{-loss * 100:F1}% bigger"; return(new CommonErrorSuggestion("Suspiciously low transmission power loss", $"Usually, in UI torque & power are taken from crankshaft, but data should contain torque at wheels, which is about 10–20% smaller. " + $"Here, although, it’s {actual}. It might be a mistake.\n\nIf you want to specify power at the wheels in UI, add “*”.", (p, c) => FixAsync(car, p, c)) { AffectsData = false, ShowProgressDialog = false, FixCaption = "Fix UI" }.AlternateFix("Add “*”", (progress, token) => { if (FlexibleParser.TryParseDouble(car.SpecsBhp, out var uiBhp)) { car.SpecsBhp = SelectedAcObjectViewModel.SpecsFormat(AppStrings.CarSpecs_PowerAtWheels_FormatTooltip, uiBhp.ToString(@"F0", CultureInfo.InvariantCulture)); } if (FlexibleParser.TryParseDouble(car.SpecsTorque, out var uiTorque)) { car.SpecsTorque = SelectedAcObjectViewModel.SpecsFormat(AppStrings.CarSpecs_Torque_FormatTooltip, uiTorque.ToString(@"F0", CultureInfo.InvariantCulture)) + "*"; } return Task.FromResult(true); }, false)); }
public double GetDoubleParam(int index, double defaultValue) { if (DoubleParams == null) { DoubleParams = Params.Select(x => FlexibleParser.TryParseDouble(x)).ToArray(); } return(index < Params.Length ? DoubleParams[index] ?? defaultValue : defaultValue); }
private WorkshopValidatedItem TestCarSpecTorque() { return(TestSpec("Car torque", Target.SpecsTorque, () => { var actualValue = FlexibleParser.TryParseDouble(Target.SpecsTorque) ?? 0d; var showRaw = Target.SpecsBhp?.IndexOf('*') > 0; return Target.SpecsTorque?.IndexOf("--") >= 0 || actualValue < 0.1 ? "-- Nm" : showRaw ? $"{actualValue.Round()} Nm*" : $"{actualValue.Round()} Nm"; }, v => Target.SpecsTorque = v)); }
private static bool ToTimeSpan([CanBeNull] string value, [CanBeNull] string defaultPostfix, out TimeSpan timeSpan, out bool strict) { if (value == null) { timeSpan = default; strict = false; return(false); } var postfix = TestEntryFactory.GetPostfix(value, 2) ?? (value.IndexOf(':') == -1 ? defaultPostfix?.Substring(0, Math.Min(defaultPostfix.Length, 2)) : null); var fromPostfix = GetTimeSpanPostfix(FlexibleParser.TryParseDouble(value) ?? 1d, postfix); if (fromPostfix.HasValue) { strict = false; timeSpan = fromPostfix.Value; return(true); } var p = value.Split(':'); double?result; switch (p.Length) { case 2: result = FlexibleParser.TryParseDouble(p[0]) * 60 + FlexibleParser.TryParseDouble(p[1]); break; case 3: result = (FlexibleParser.TryParseDouble(p[0]) * 60 + FlexibleParser.TryParseDouble(p[1])) * 60 + FlexibleParser.TryParseDouble(p[2]); break; case 4: result = ((FlexibleParser.TryParseDouble(p[0]) * 24 + FlexibleParser.TryParseDouble(p[1])) * 60 + FlexibleParser.TryParseDouble(p[2])) * 60 + FlexibleParser.TryParseDouble(p[3]); break; default: timeSpan = default; strict = false; return(false); } if (!result.HasValue) { timeSpan = default; strict = false; return(false); } timeSpan = TimeSpan.FromSeconds(result.Value); strict = value.IndexOf('.') != -1 || value.IndexOf(',') != -1; return(true); }
public bool Test(string value) { if (value == null) { return(false); } double val; return(FlexibleParser.TryParseDouble(value, out val) && Test(val)); }
private FontObjectBitmap(BitmapSource font, byte[] fontData) { _fontBitmapImage = font; try { _fontList = fontData.ToUtf8String().Split('\n').Select(line => FlexibleParser.TryParseDouble(line) ?? 0d).ToList(); } catch (Exception e) { Logging.Warning("File damaged: " + e); } }
protected override void Fix(CarObject car, DataWrapper data) { double uiWeight; if ((car.SpecsWeight?.IndexOf("*", StringComparison.Ordinal) ?? 0) != -1 || !FlexibleParser.TryParseDouble(car.SpecsWeight, out uiWeight)) { return; } data.GetIniFile(@"car.ini")["BASIC"].Set("TOTALMASS", uiWeight + CommonAcConsts.DriverWeight); }
public bool Test(string value) { if (_override != null) { return(_override.Test(value)); } if (value == null) { return(false); } return(FlexibleParser.TryParseDouble(value, out var val) && Test(val)); }
private WorkshopValidatedItem TestCarSpecPower() { return(TestSpec("Car power", Target.SpecsBhp, () => { var actualValue = FlexibleParser.TryParseDouble(Target.SpecsBhp) ?? 0d; if (Target.SpecsBhp?.IndexOf("--") >= 0 || actualValue < 0.1) { return "-- bhp"; } var showRaw = Target.SpecsBhp?.IndexOf('*') > 0 || Regex.IsMatch(Target.SpecsBhp ?? "", @"\bw?hp\b"); return showRaw ? $"{actualValue.Round()} whp" : $"{actualValue.Round()} bhp"; }, v => Target.SpecsBhp = v)); }
private void RecalculatePwRatio() { double power, weight; if (!FlexibleParser.TryParseDouble(PowerInput.Text, out power) || !FlexibleParser.TryParseDouble(WeightInput.Text, out weight)) { return; } var ratio = weight / power; PwRatioInput.Text = Format(AppStrings.CarSpecs_PwRatio_FormatTooltip, ratio.Round(0.01)); }
private void ScaleCurves(object sender, RoutedEventArgs e) { double power, torque; if (!FlexibleParser.TryParseDouble(PowerInput.Text, out power) || !FlexibleParser.TryParseDouble(TorqueInput.Text, out torque)) { ShowMessage(AppStrings.CarSpecs_SpecifyPowerAndTorqueFirst, ToolsStrings.Common_CannotDo_Title, MessageBoxButton.OK); return; } TorqueGraph = new GraphData(TorqueGraph.ToLut().ScaleTo(torque)); PowerGraph = new GraphData(PowerGraph.ToLut().ScaleTo(power)); }
private double?GetSpecsLengthValue([CanBeNull] string original, bool dotFix) { if (original == null) { return(null); } double value; if (!double.TryParse(original, NumberStyles.Float | NumberStyles.Integer, CultureInfo.InvariantCulture, out value)) { var m = SpecsLengthFix.Match(original); if (m.Success) { var n = m.Groups[1].Value; if (n.IndexOf(',') != -1) { n = n.Replace(',', '.'); } if (!FlexibleParser.TryParseDouble(n, out value)) { return(null); } if (m.Groups[2].Success) { value *= 1e3; } else if (m.Groups[3].Success) { value *= 1.6e3; } } else if (!FlexibleParser.TryParseDouble(original, out value)) { return(null); } } if (dotFix && value < 100 && SpecsDotFixTest.IsMatch(original)) { // For those lost and misguided souls who use “.” as a thousands separator or “,” as decimal separators. value *= 1e3; } return(value); }
private void LoadExtended(IniFile ini) { var clouds = ini["CLOUDS"]; CloudsCover = clouds.GetDouble("COVER", 0.9); CloudsCutoff = clouds.GetDouble("CUTOFF", 0.5); CloudsColor = clouds.GetDouble("COLOR", 0.7); CloudsWidth = clouds.GetDouble("WIDTH", 9); CloudsHeight = clouds.GetDouble("HEIGHT", 4); CloudsRadius = clouds.GetDouble("RADIUS", 6); CloudsNumber = clouds.GetInt("NUMBER", 40); CloudsSpeedMultipler = clouds.GetDouble("BASE_SPEED_MULT", 0.0015) * 100d; var fog = ini["FOG"]; var color = fog.GetStrings("COLOR").Select(x => FlexibleParser.TryParseDouble(x) ?? 1d).ToArray(); if (color.Length == 3) { var maxValue = color.Max(); if (Equals(maxValue, 0d)) { FogColor = Colors.Black; FogColorMultipler = 100; } else { maxValue *= 1.2; if (maxValue >= 0d && maxValue < 1d) { maxValue = 1d; } else if (maxValue < 0d && maxValue > -1d) { maxValue = -1d; } FogColor = Color.FromRgb((255 * color[0] / maxValue).ClampToByte(), (255 * color[1] / maxValue).ClampToByte(), (255 * color[2] / maxValue).ClampToByte()); FogColorMultipler = maxValue; } } FogBlend = fog.GetDouble("BLEND", 0.85); FogDistance = fog.GetDouble("DISTANCE", 9000); ForceCarLights = ini["CAR_LIGHTS"].GetBool("FORCE_ON", false); }
protected override void ParseString(string data) { Clear(); foreach (var line in data.Split('\n')) { var sep = line.LastIndexOf('|'); if (sep == -1) { continue; } if (FlexibleParser.TryParseDouble(line.Substring(sep + 1), out var value)) { Values[line.Substring(0, sep).Replace("//", "/")] = value; } } }
public TestEntryFactory([NotNull] TestEntryFactoryPostfixMultiplier convertation, int maxPostfixLength = 4) { _convertation = (string value, out double valueToCompareWith) => { if (value == null) { valueToCompareWith = 0d; return(false); } if (!FlexibleParser.TryParseDouble(value, out valueToCompareWith)) { return(false); } valueToCompareWith *= convertation(GetPostfix(value, maxPostfixLength)); return(true); }; }
private void FixFormat(string key) { var format = GetFormat(key); var value = GetSpecsValue(key); if (value == null) { return; } value = FixAccelerationRegex.Replace(value, ""); double actualValue; var replacement = FlexibleParser.TryParseDouble(value, out actualValue) ? actualValue.Round(0.01).ToInvariantString() : @"--"; value = SpecsFormat(format, replacement); SetSpecsValue(key, value); }
private static Lut ConvertToValues(JArray obj) { var values = new Lut(); if (obj == null) { return(values); } foreach (var entry in obj.OfType <JArray>().Where(x => x.Count == 2)) { if (FlexibleParser.TryParseDouble(Convert.ToString(entry[0], CultureInfo.InvariantCulture), out var x) && FlexibleParser.TryParseDouble(Convert.ToString(entry[1], CultureInfo.InvariantCulture), out var y)) { values.Add(new LutPoint(x, y)); } } return(values); }
private double?GetSpecsWeight(out bool showRaw) { showRaw = Target.SpecsWeight?.IndexOf('*') > 0; var actualValue = FlexibleParser.TryParseDouble(Target.SpecsWeight) ?? 0d; var dataWeight = Target.AcdData?.GetIniFile("car.ini")["BASIC"].GetDouble("TOTALMASS", 0) ?? 0d; if (Target.SpecsWeight?.IndexOf("--") >= 0 || actualValue < 1 && dataWeight < 80) { showRaw = false; return(null); } if (dataWeight < 80) { showRaw = false; return(actualValue.Round()); } if (showRaw) { return(dataWeight.Round()); } return((Math.Abs(actualValue - (dataWeight - 75)) <= 50d ? actualValue : dataWeight - 75d).Round()); }
private static Func <double, bool> GetTest([NotNull] string extra) { if (extra.Length < 1) { return(null); } var v = FlexibleParser.TryParseDouble(extra.Substring(1)) ?? 0d; switch (extra[0]) { case '=': return(c => c == v); case '≠': return(c => c != v); case '<': return(c => c < v); case '>': return(c => c > v); case '≤': return(c => c <= v); case '≥': return(c => c >= v); } return(null); }
private static ITestEntry CreateTimeSpanTestEntry(Operator op, string value) { var p = value.Split(':'); double?result; switch (p.Length) { case 0: result = null; break; case 1: result = FlexibleParser.TryParseDouble(p[0]); break; case 2: result = FlexibleParser.TryParseDouble(p[0]) * 60 + FlexibleParser.TryParseDouble(p[1]); break; case 3: result = (FlexibleParser.TryParseDouble(p[0]) * 60 + FlexibleParser.TryParseDouble(p[1])) * 60 + FlexibleParser.TryParseDouble(p[2]); break; default: result = ((FlexibleParser.TryParseDouble(p[0]) * 24 + FlexibleParser.TryParseDouble(p[1])) * 60 + FlexibleParser.TryParseDouble(p[2])) * 60 + FlexibleParser.TryParseDouble(p[3]); break; } if (!result.HasValue) { return(new ConstTestEntry(false)); } return(new TimeSpanTestEntry(op, TimeSpan.FromSeconds(result.Value), value.IndexOf('.') != -1 || value.IndexOf(',') != -1)); }