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)); }
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)); }
protected override ContentRepairSuggestion GetObsoletableAspect(CarObject car, DataWrapper data) { if ((car.SpecsWeight?.IndexOf("*", StringComparison.Ordinal) ?? 0) != -1) { return(null); } var uiWeight = car.GetWidthValue() ?? 0d; if (uiWeight <= 1d) { return(null); } var withDriver = data.GetIniFile(@"car.ini")["BASIC"].GetFloat("TOTALMASS", -1f); if (withDriver <= 0f) { return(null); } var weight = withDriver - CommonAcConsts.DriverWeight; var driverWeight = withDriver - uiWeight; if (driverWeight > CommonAcConsts.DriverWeight - OptionAllowedPadding) { return(null); } var valueStr = Math.Abs(driverWeight) < 0.1 ? "nothing" : driverWeight < 1 ? $"{driverWeight} kg" : $"only {driverWeight} kg"; return(new CommonErrorSuggestion("Invalid weight", $"In car.ini, TOTALMASS should include driver weight (+{CommonAcConsts.DriverWeight} kg) as well, " + $"but according to these TOTALMASS and mass in UI file, driver weights {valueStr}. Could be a mistake.\n\nIf you want to specify weight with driver in UI, add “*”.", (p, c) => FixAsync(car, p, c)) { AffectsData = true, FixCaption = "Fix data" }.AlternateFix("Fix UI", (progress, token) => { car.SpecsWeight = SelectedAcObjectViewModel.SpecsFormat(AppStrings.CarSpecs_Weight_FormatTooltip, weight.ToString(@"F0", CultureInfo.InvariantCulture)); return Task.FromResult(true); }, false).AlternateFix("Add “*”", (progress, token) => { car.SpecsWeight = SelectedAcObjectViewModel.SpecsFormat(AppStrings.CarSpecs_Weight_FormatTooltip, withDriver.ToString(@"F0", CultureInfo.InvariantCulture)) + "*"; return Task.FromResult(true); }, false)); }