示例#1
0
 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));
 }
示例#2
0
 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));
 }
示例#3
0
 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;
     }
 }
示例#4
0
        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);
        }
示例#5
0
        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));
        }
示例#6
0
        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));
            }
        }
示例#7
0
        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);
        }
示例#8
0
 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;
     }
 }
示例#9
0
        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);
        }
示例#10
0
 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));
 }
示例#11
0
        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));
        }
示例#12
0
            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);
            }
示例#13
0
 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));
 }
示例#14
0
        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);
        }
示例#15
0
        public bool Test(string value)
        {
            if (value == null)
            {
                return(false);
            }
            double val;

            return(FlexibleParser.TryParseDouble(value, out val) && Test(val));
        }
示例#16
0
        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);
            }
        }
示例#17
0
        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);
        }
示例#18
0
 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));
 }
示例#19
0
        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));
        }
示例#20
0
        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));
        }
示例#21
0
        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));
        }
示例#22
0
        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);
        }
示例#23
0
        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);
        }
示例#24
0
        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;
                }
            }
        }
示例#25
0
        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);
            };
        }
示例#26
0
            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);
            }
示例#27
0
        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);
        }
示例#28
0
        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());
        }
示例#29
0
        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);
        }
示例#30
0
        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));
        }