コード例 #1
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);
        }
コード例 #2
0
ファイル: CarTorqueRepair.cs プロジェクト: windygu/actools
        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));
        }
コード例 #3
0
ファイル: CarTorqueRepair.cs プロジェクト: windygu/actools
        protected override Task <bool> FixAsync(CarObject car, IProgress <AsyncProgressEntry> progress = null,
                                                CancellationToken cancellation = default(CancellationToken))
        {
            progress?.Report(AsyncProgressEntry.FromStringIndetermitate("Fixing car…"));

            var data = car.AcdData;

            if (data == null || data.IsEmpty)
            {
                return(Task.FromResult(false));
            }

            Lut torque, power;

            try {
                torque = TorquePhysicUtils.LoadCarTorque(data);
                power  = TorquePhysicUtils.TorqueToPower(torque);
            } catch (Exception e) {
                Logging.Error(e);
                return(Task.FromResult(false));
            }

            var multipler = ActionExtension.InvokeInMainThread(() => {
                var dlg = new CarTransmissionLossSelector(car, torque.MaxY, power.MaxY);
                dlg.ShowDialog();
                return(dlg.IsResultOk ? dlg.Multipler : (double?)null);
            });

            if (!multipler.HasValue)
            {
                return(Task.FromResult(false));
            }

            torque.TransformSelf(x => x.Y * multipler.Value);
            power.TransformSelf(x => x.Y * multipler.Value);

            if (car.SpecsTorqueCurve != null)
            {
                var torqueUi = new Lut(car.SpecsTorqueCurve.Points);
                torqueUi.TransformSelf(x => x.Y * multipler.Value);
                car.SpecsTorqueCurve = new GraphData(torqueUi);
            }

            if (car.SpecsPowerCurve != null)
            {
                var powerUi = new Lut(car.SpecsPowerCurve.Points);
                powerUi.TransformSelf(x => x.Y * multipler.Value);
                car.SpecsPowerCurve = new GraphData(powerUi);
            }

            car.SpecsTorque = SelectedAcObjectViewModel.SpecsFormat(AppStrings.CarSpecs_Torque_FormatTooltip,
                                                                    torque.MaxY.ToString(@"F0", CultureInfo.InvariantCulture)) + (multipler.Value == 1d ? "*" : "");
            car.SpecsBhp = SelectedAcObjectViewModel.SpecsFormat(multipler.Value == 1d ? AppStrings.CarSpecs_PowerAtWheels_FormatTooltip
                    : AppStrings.CarSpecs_Power_FormatTooltip, power.MaxY.ToString(@"F0", CultureInfo.InvariantCulture));
            return(Task.FromResult(true));
        }
コード例 #4
0
        public void NegativePoint()
        {
            var data = new DataDirectoryWrapper(Path.Combine(TestDir, "physics", "negative_point"));

            var powerLutPointsOnly = TorquePhysicUtils.LoadCarTorque(data);

            Assert.AreEqual(100, powerLutPointsOnly.InterpolateLinear(-100d), 0.1);
            Assert.AreEqual(100d, powerLutPointsOnly.InterpolateLinear(0d), 0.1);
            Assert.AreEqual(200d, powerLutPointsOnly.InterpolateLinear(5000d), 0.1);
        }
コード例 #5
0
        public void TurboTest()
        {
            var data   = new DataDirectoryWrapper(Path.Combine(TestDir, "physics", "turbo_test"));
            var torque = TorquePhysicUtils.LoadCarTorque(data);

            Assert.AreEqual(100d, torque.InterpolateLinear(0d), 0.1);
            Assert.AreEqual(125d, torque.InterpolateLinear(1500d), 0.1);
            Assert.AreEqual(150d, torque.InterpolateLinear(3000d), 0.1);
            Assert.AreEqual(150d, torque.InterpolateLinear(4000d), 0.1);
            Assert.AreEqual(150d, torque.InterpolateLinear(5000d), 0.1);
        }
コード例 #6
0
        private void RecalculateCurves(object sender, RoutedEventArgs e)
        {
            var o = Car;

            var data = o.AcdData;

            if (data == null)
            {
                NonfatalError.Notify(ToolsStrings.Common_CannotDo_Title, "Data is damaged");
                return;
            }

            Lut torque, power;

            try {
                torque = TorquePhysicUtils.LoadCarTorque(data);
                power  = TorquePhysicUtils.TorqueToPower(torque);
            } catch (Exception ex) {
                NonfatalError.Notify(ToolsStrings.Common_CannotDo_Title, ex);
                return;
            }

            var dlg = new CarTransmissionLossSelector(o, torque.MaxY, power.MaxY);

            dlg.ShowDialog();
            if (!dlg.IsResultOk)
            {
                return;
            }

            torque.TransformSelf(x => x.Y * dlg.Multipler);
            power.TransformSelf(x => x.Y * dlg.Multipler);

            o.SpecsTorqueCurve = new GraphData(torque);
            o.SpecsPowerCurve  = new GraphData(power);

            if (ShowMessage(AppStrings.CarSpecs_CopyNewPowerAndTorque, AppStrings.Common_OneMoreThing, MessageBoxButton.YesNo, "copyNewPowerAndTorque") ==
                MessageBoxResult.Yes)
            {
                // MaxY values were updated while creating new GraphData instances above
                var postfix = dlg.Multipler == 1d ? "*" : "";
                TorqueInput.Text = Format(AppStrings.CarSpecs_Torque_FormatTooltip, torque.MaxY.ToString(@"F0", CultureInfo.InvariantCulture)) + postfix;
                PowerInput.Text  = Format(AppStrings.CarSpecs_Power_FormatTooltip, power.MaxY.ToString(@"F0", CultureInfo.InvariantCulture)) + postfix;
            }
        }
コード例 #7
0
        public void InterpolationMode()
        {
            var data = new DataDirectoryWrapper(Path.Combine(TestDir, "physics", "two_points"));

            var powerLutPointsOnly = TorquePhysicUtils.LoadCarTorque(data, false, 0);

            Assert.AreEqual(100d, powerLutPointsOnly.InterpolateLinear(0d), 0.1);
            Assert.AreEqual(125d, powerLutPointsOnly.InterpolateLinear(1250d), 0.1);
            Assert.AreEqual(150d, powerLutPointsOnly.InterpolateLinear(2500d), 0.1);
            Assert.AreEqual(200d, powerLutPointsOnly.InterpolateLinear(5000d), 0.1);

            var detailedMode = TorquePhysicUtils.LoadCarTorque(data, false);

            Assert.AreEqual(100d, detailedMode.InterpolateLinear(0d), 0.1);
            Assert.AreEqual(109.8d, detailedMode.InterpolateLinear(1250d), 0.1);
            Assert.AreEqual(139.2d, detailedMode.InterpolateLinear(2500d), 0.1);
            Assert.AreEqual(164.2, detailedMode.InterpolateLinear(3200d), 0.1);
            Assert.AreEqual(200d, detailedMode.InterpolateLinear(4000d), 0.1);
            Assert.AreEqual(200d, detailedMode.InterpolateLinear(5000d), 0.1);
        }
コード例 #8
0
        public void ConsiderLimiterMode()
        {
            var data = new DataDirectoryWrapper(Path.Combine(TestDir, "physics", "two_points"));

            var notConsider = TorquePhysicUtils.LoadCarTorque(data, false, 0);

            Assert.AreEqual(160, notConsider.InterpolateLinear(3000d), 0.1);
            Assert.AreEqual(200d, notConsider.InterpolateLinear(5000d), 0.1);

            var consider = TorquePhysicUtils.LoadCarTorque(data, true, 0);

            Assert.AreEqual(156.3d, consider.InterpolateLinear(3000d), 0.1);
            Assert.AreEqual(156.3d, consider.InterpolateLinear(5000d), 0.1);

            var notConsiderDetailed = TorquePhysicUtils.LoadCarTorque(data, false);

            Assert.AreEqual(156.3d, notConsiderDetailed.InterpolateLinear(3000d), 0.1);
            Assert.AreEqual(200d, notConsiderDetailed.InterpolateLinear(5000d), 0.1);

            var considerDetailed = TorquePhysicUtils.LoadCarTorque(data);

            Assert.AreEqual(156.3d, considerDetailed.InterpolateLinear(3000d), 0.1);
            Assert.AreEqual(156.3d, considerDetailed.InterpolateLinear(5000d), 0.1);
        }