From 4592ca6d4e52318f1a0f735f18c3263bda344caa Mon Sep 17 00:00:00 2001
From: Michael Krisper <michael.krisper@tugraz.at>
Date: Fri, 12 Aug 2022 16:32:50 +0200
Subject: [PATCH] Gear Disabling Features for Engineering and Declaration
 HeavyLorry, SingleBus

---
 .../InputData/DeclarationInputData.cs         |  4 ++
 .../AbstractSimulationDataAdapter.cs          | 36 +++++++++++
 .../DeclarationDataAdapterHeavyLorry.cs       | 36 ++---------
 .../DeclarationDataAdapterSingleBus.cs        |  6 +-
 .../EngineeringDataAdapter.cs                 | 31 +++++----
 .../Models/Simulation/Data/VectoRunData.cs    | 12 ++--
 .../Integration/TorqueLimitsTest.cs           | 64 ++++++++++++++++++-
 7 files changed, 135 insertions(+), 54 deletions(-)

diff --git a/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs b/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs
index 87eb17253b..04f8ae8fa3 100644
--- a/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs
+++ b/VectoCommon/VectoCommon/InputData/DeclarationInputData.cs
@@ -124,6 +124,10 @@ namespace TUGraz.VectoCommon.InputData
 		///// </summary>
 		//string Rim { get; }  // deprecated
 
+		/// <summary>
+		/// P196, P197  TorqueLimits: Gear [-], MaxTorque [Nm]
+		/// cf. VECTO Input Parameters.xlsx
+		/// </summary>
 		IList<ITorqueLimitInputData> TorqueLimits { get; }
 
 		/// <summary>
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs
index 126c19ea45..8a8d0f6f87 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/AbstractSimulationDataAdapter.cs
@@ -37,6 +37,7 @@ using TUGraz.VectoCommon.InputData;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.InputData.Reader.ComponentData;
+using TUGraz.VectoCore.Models.Declaration;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
 using TUGraz.VectoCore.Models.SimulationComponent.Data.ElectricMotor;
 using TUGraz.VectoCore.Models.SimulationComponent.Data.Engine;
@@ -516,6 +517,41 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 			
 			return entries;
 		}
+
+		/// <summary>
+		/// Filters the gears based on disabling rule: Disable either the last 1 or 2 gears by setting their vehicle-level torque limit to 0.
+		/// </summary>
+		internal static IList<ITransmissionInputData> FilterDisabledGears(IList<ITorqueLimitInputData> torqueLimits, IGearboxDeclarationInputData gearboxData) {
+			if (torqueLimits == null || torqueLimits.Count == 0){
+				return gearboxData?.Gears ?? new List<ITransmissionInputData>();
+			}
+
+			if (gearboxData == null) {
+				return new List<ITransmissionInputData>();
+			}
+
+			var gearsInput = gearboxData.Gears;
+			var lastGearNumber = gearsInput.Max(g => g.Gear);
+			var toRemove = torqueLimits
+				.Where(tqLimit => tqLimit.MaxTorque.IsEqual(0))
+				.Select(tqLimit => gearsInput.FirstOrDefault(g => g.Gear == tqLimit.Gear))
+				.Where(g => g != default)
+				.OrderBy(g => g.Gear)
+				.ToList();
+			
+			if ((toRemove.Count == 1 && toRemove[0].Gear != lastGearNumber)
+				|| (toRemove.Count == 2 && (toRemove[0].Gear != lastGearNumber-1 || toRemove[1].Gear != lastGearNumber))
+				|| toRemove.Count > 2) {
+				throw new VectoException("Only the last 1 or 2 gears can be disabled. Disabling gear {0} for a {1}-speed gearbox is not allowed.", 
+					toRemove.Min(g => g.Gear), gearsInput.Count);
+			}
+
+			foreach (var entry in toRemove) {
+				gearsInput.Remove(entry);
+			}
+			
+			return gearsInput;
+		}
 	}
 }
 
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs
index e092f19436..6a4723df7f 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterHeavyLorry.cs
@@ -238,12 +238,14 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 
 			retVal.Inertia = DeclarationData.Engine.EngineInertia(retVal.Displacement, gearbox.Type);
 			retVal.EngineStartTime = DeclarationData.Engine.DefaultEngineStartTime;
+			
 			var limits = vehicle.TorqueLimits?.ToDictionary(e => e.Gear) ?? new Dictionary<int, ITorqueLimitInputData>();
-			var numGears = gearbox.Gears.Count;
+			var gears = FilterDisabledGears(vehicle.TorqueLimits, gearbox);
+			var numGears = gears.Count;
 			var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(numGears + 1);
 			fullLoadCurves[0] = FullLoadCurveReader.Create(mode.FullLoadCurve, true);
 			fullLoadCurves[0].EngineData = retVal;
-			foreach (var gear in gearbox.Gears) {
+			foreach (var gear in gears) {
 				var maxTorque = VectoMath.Min(
 					GbxMaxTorque(gear, numGears, fullLoadCurves[0].MaxTorque),
 					VehMaxTorque(gear, numGears, limits, fullLoadCurves[0].MaxTorque));
@@ -356,7 +358,7 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				throw new VectoSimulationException("Unsupported gearbox type: {0}!", retVal.Type);
 			}
 
-			var gearsInput = FilterDisabledGears(inputData, gearbox);
+			var gearsInput = FilterDisabledGears(inputData.TorqueLimits, gearbox);
 			
 			if (gearsInput.Count < 1) {
 				throw new VectoSimulationException(
@@ -431,34 +433,6 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
             return retVal;
 		}
 
-		/// <summary>
-		/// Filters the gears based on disabling rule: Disable either the last 1 or 2 gears by setting their vehicle-level torque limit to 0.
-		/// </summary>
-		private static IList<ITransmissionInputData> FilterDisabledGears(IVehicleDeclarationInputData inputData, IGearboxDeclarationInputData gearbox)
-		{
-			var gearsInput = gearbox.Gears;
-			var lastGearNumber = gearsInput.Max(g => g.Gear);
-
-			if (inputData.TorqueLimits != null) {
-				var toRemove = inputData.TorqueLimits
-					.Where(tqLimit => tqLimit.Gear >= lastGearNumber - 1 && tqLimit.MaxTorque.IsEqual(0))
-					.Select(tqLimit => gearsInput.FirstOrDefault(g => g.Gear == tqLimit.Gear))
-					.Where(g => g != default)
-					.ToList();
-				
-				if (toRemove.Count > 0 && toRemove.Min(g => g.Gear) <= gearsInput.Count - toRemove.Count) {
-					throw new VectoException("Only the last 1 or 2 gears can be disabled. Disabling gear {0} for a {1}-speed gearbox is not allowed.", 
-						toRemove.Min(), gearsInput.Count);
-				}
-
-				foreach (var entry in toRemove) {
-					gearsInput.Remove(entry);
-				}
-			}
-
-			return gearsInput;
-		}
-
 		protected virtual TorqueConverterData CreateTorqueConverterData(GearboxType gearboxType,
 			ITorqueConverterDeclarationInputData torqueConverter, double ratio,
 			CombustionEngineData componentsEngineInputData)
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs
index 5fd0766f12..1d41153479 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/DeclarationDataAdapterSingleBus.cs
@@ -91,11 +91,13 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 			retVal.Inertia = DeclarationData.Engine.EngineInertia(retVal.Displacement, gearbox.Type);
 			retVal.EngineStartTime = DeclarationData.Engine.DefaultEngineStartTime;
 			var limits = vehicle.TorqueLimits.ToDictionary(e => e.Gear);
-			var numGears = gearbox.Gears.Count;
+			var gears = FilterDisabledGears(vehicle.TorqueLimits, gearbox);
+			
+			var numGears = gears.Count;
 			var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(numGears + 1);
 			fullLoadCurves[0] = FullLoadCurveReader.Create(mode.FullLoadCurve, true);
 			fullLoadCurves[0].EngineData = retVal;
-			foreach (var gear in gearbox.Gears) {
+			foreach (var gear in gears) {
 				var maxTorque = VectoMath.Min(
 					GbxMaxTorque(gear, numGears, fullLoadCurves[0].MaxTorque),
 					VehMaxTorque(gear, numGears, limits, fullLoadCurves[0].MaxTorque));
diff --git a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
index cc5641aa7a..1b11643433 100644
--- a/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
+++ b/VectoCore/VectoCore/InputData/Reader/DataObjectAdapter/EngineeringDataAdapter.cs
@@ -188,7 +188,6 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 		{
 			var engine = vehicle.Components.EngineInputData;
 			var gbx = vehicle.Components.GearboxInputData;
-			var torqueLimits = vehicle.TorqueLimits;
 			var torqueConverter = vehicle.Components.TorqueConverterInputData;
 			var tankSystem = vehicle.TankSystem;
 			
@@ -213,16 +212,15 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 								? (gbx.Type == GearboxType.APTN || gbx.Type == GearboxType.IHPC ? 0.SI<KilogramSquareMeter>() : torqueConverter.Inertia)
 								: 0.SI<KilogramSquareMeter>());
 			retVal.EngineStartTime = engine.EngineStartTime ?? DeclarationData.Engine.DefaultEngineStartTime;
-			var limits = torqueLimits.ToDictionary(e => e.Gear);
-			var numGears = gbx?.Gears.Count ?? 0;
-			var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(numGears + 1);
+			var limits = vehicle.TorqueLimits.ToDictionary(e => e.Gear);
+
+			var gears = FilterDisabledGears(vehicle.TorqueLimits, gbx);
+			var fullLoadCurves = new Dictionary<uint, EngineFullLoadCurve>(gears.Count + 1);
 			fullLoadCurves[0] = FullLoadCurveReader.Create(engine.EngineModes.First().FullLoadCurve);
 			fullLoadCurves[0].EngineData = retVal;
-			if (gbx != null) {
-				foreach (var gear in gbx.Gears) {
-					var maxTorque = VectoMath.Min(gear.MaxTorque, limits.GetVECTOValueOrDefault(gear.Gear)?.MaxTorque);
-					fullLoadCurves[(uint)gear.Gear] = IntersectFullLoadCurves(fullLoadCurves[0], maxTorque);
-				}
+			foreach (var gear in gears) {
+				var maxTorque = VectoMath.Min(gear.MaxTorque, limits.GetVECTOValueOrDefault(gear.Gear)?.MaxTorque);
+				fullLoadCurves[(uint)gear.Gear] = IntersectFullLoadCurves(fullLoadCurves[0], maxTorque);
 			}
 
 			retVal.FullLoadCurves = fullLoadCurves;
@@ -326,17 +324,18 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 				return retVal;
 			}
 
-			//var gears = gearbox.Gears;
 			if (gearbox.Gears.Count < 2) {
 				throw new VectoSimulationException("At least two Gear-Entries must be defined in Gearbox!");
 			}
 
+			var gearsInput = FilterDisabledGears(inputData.JobInputData.Vehicle.TorqueLimits, gearbox);
+			
 			SetEngineeringData(gearbox, gearshiftData, retVal);
 
 			var hasTorqueConverter = retVal.Type.AutomaticTransmission() && retVal.Type != GearboxType.APTN && retVal.Type != GearboxType.IHPC;
 
-			var gearDifferenceRatio = hasTorqueConverter && gearbox.Gears.Count > 2
-				? gearbox.Gears[0].Ratio / gearbox.Gears[1].Ratio
+			var gearDifferenceRatio = hasTorqueConverter && gearsInput.Count > 2
+				? gearsInput[0].Ratio / gearsInput[1].Ratio
 				: 1.0;
 
 			var gears = new Dictionary<uint, GearData>();
@@ -346,8 +345,8 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 					? ShiftPolygonReader.Create(torqueConverter.ShiftPolygon)
 					: DeclarationData.TorqueConverter.ComputeShiftPolygon(engineData.FullLoadCurves[0]);
 			}
-			for (uint i = 0; i < gearbox.Gears.Count; i++) {
-				var gear = gearbox.Gears[(int)i];
+			for (uint i = 0; i < gearsInput.Count; i++) {
+				var gear = gearsInput[(int)i];
 				var lossMap = CreateGearLossMap(gear, i, true, VehicleCategory.Unknown, gearbox.Type);
 
 				ShiftPolygon shiftPolygon;
@@ -355,11 +354,11 @@ namespace TUGraz.VectoCore.InputData.Reader.DataObjectAdapter
 					shiftPolygon = ShiftPolygonReader.Create(gear.ShiftPolygon);
 				} else if (shiftPolygonCalc != null) {
 					shiftPolygon = shiftPolygonCalc.ComputeDeclarationShiftPolygon(gearbox.Type, (int)i,
-						engineData?.FullLoadCurves[i + 1], gearbox.Gears, engineData, axlegearRatio,
+						engineData?.FullLoadCurves[i + 1], gearsInput, engineData, axlegearRatio,
 						dynamicTyreRadius, runData.ElectricMachinesData?.FirstOrDefault()?.Item2);
 				} else {
 					shiftPolygon = DeclarationData.Gearbox.ComputeShiftPolygon(gearbox.Type, (int)i,
-						engineData?.FullLoadCurves[i + 1], gearbox.Gears, engineData, axlegearRatio,
+						engineData?.FullLoadCurves[i + 1], gearsInput, engineData, axlegearRatio,
 						dynamicTyreRadius, runData.ElectricMachinesData?.FirstOrDefault()?.Item2);
 				}
 
diff --git a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs
index 9dcc8106ab..1a83b0cd01 100644
--- a/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Data/VectoRunData.cs
@@ -42,6 +42,7 @@ using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.Configuration;
 using TUGraz.VectoCore.InputData.Reader.ComponentData;
+using TUGraz.VectoCore.InputData.Reader.DataObjectAdapter;
 using TUGraz.VectoCore.InputData.Reader.Impl;
 using TUGraz.VectoCore.Models.Declaration;
 using TUGraz.VectoCore.Models.SimulationComponent.Data;
@@ -252,7 +253,7 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 			return ValidationResult.Success;
 		}
 
-		private static ValidationResult CheckPowertrainLossMapsSizeConventionalPT(VectoRunData runData, GearboxData gearboxData,
+		private static ValidationResult CheckPowertrainLossMapsSizeConventionalPT(VectoRunData runData, GearboxData gearboxData, 
 			CombustionEngineData engineData)
 		{
 			
@@ -270,14 +271,17 @@ namespace TUGraz.VectoCore.Models.Simulation.Data
 								angledriveRatio * dynamicTyreRadius;
 			var maxSpeed = VectoMath.Min(vehicleMaxSpeed, (runData.VehicleDesignSpeed ?? 90.KMPHtoMeterPerSecond()) + (runData.DriverData?.OverSpeed?.OverSpeed ?? 0.KMPHtoMeterPerSecond()));
 
-			if (gearboxData.Gears.Count + 1 != engineData.FullLoadCurves.Count) {
+			var gearsInput = AbstractSimulationDataAdapter.FilterDisabledGears(runData.VehicleData.InputData.TorqueLimits, gearboxData.InputData);
+			var gears = gearboxData.Gears.Where(f => gearsInput.Any(g => f.Key == g.Gear)).ToList();
+			
+			if (gears.Count + 1 != engineData.FullLoadCurves.Count) {
 				return
 					new ValidationResult(
 						$"number of full-load curves in engine does not match gear count. " +
-						$"engine fld: {engineData.FullLoadCurves.Count}, gears: {gearboxData.Gears.Count}");
+						$"engine fld: {engineData.FullLoadCurves.Count}, gears: {gears.Count}");
 			}
 
-			foreach (var gear in gearboxData.Gears) {
+			foreach (var gear in gears) {
 				var maxEngineSpeed = VectoMath.Min(engineData.FullLoadCurves[gear.Key].RatedSpeed, gear.Value.MaxSpeed);
 				for (var angularVelocity = engineData.IdleSpeed;
 					angularVelocity < maxEngineSpeed;
diff --git a/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs b/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs
index bc38385e9c..f9b7123116 100644
--- a/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs
+++ b/VectoCore/VectoCoreTest/Integration/TorqueLimitsTest.cs
@@ -35,6 +35,7 @@ using System.IO;
 using System.Linq;
 using Ninject;
 using NUnit.Framework;
+using TUGraz.VectoCommon.Exceptions;
 using TUGraz.VectoCommon.Models;
 using TUGraz.VectoCommon.Utils;
 using TUGraz.VectoCore.InputData.FileIO.JSON;
@@ -43,6 +44,7 @@ using TUGraz.VectoCore.Models.Simulation.Impl;
 using TUGraz.VectoCore.Models.Simulation.Impl.SimulatorFactory;
 using TUGraz.VectoCore.OutputData;
 using TUGraz.VectoCore.OutputData.FileIO;
+using TUGraz.VectoCore.Tests.Utils;
 using Assert = NUnit.Framework.Assert;
 
 namespace TUGraz.VectoCore.Tests.Integration
@@ -311,6 +313,66 @@ namespace TUGraz.VectoCore.Tests.Integration
 			Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException)));
 		}
 
-		
+		[Category("LongRunning"),
+		TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6.vecto"),
+		TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and5.vecto")]
+		public void TestRunDisableGearsWithTorqueLimitSimulations(string file)
+		{
+			var fileWriter = new FileOutputWriter(file);
+			var sumData = new SummaryDataContainer(fileWriter);
+			var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file);
+			var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Declaration, inputDataProvider, fileWriter);
+			var jobContainer = new JobContainer(sumData);
+			jobContainer.AddRuns(factory);
+			jobContainer.Execute();
+			jobContainer.WaitFinished();
+			Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException)));
+		}
+
+		[TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear5invalid.vecto"),
+		 TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear4invalid.vecto"),
+		 TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and4invalid.vecto"),
+		 TestCase(@"Testdata\Integration\DeclarationMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear1invalid.vecto")]
+		public void TestRunDisableGearsInvalid(string file)
+		{
+			var fileWriter = new FileOutputWriter(file);
+			var sumData = new SummaryDataContainer(fileWriter);
+			var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file);
+			var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Declaration, inputDataProvider, fileWriter);
+			var jobContainer = new JobContainer(sumData);
+			AssertHelper.Exception<VectoException>(() => jobContainer.AddRuns(factory), messageContains: "Only the last 1 or 2 gears can be disabled. Disabling gear ");
+		}
+
+		[Category("LongRunning"),
+		TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6.vecto"),
+		TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and5.vecto")]
+		public void TestRunDisableGearsWithTorqueLimitSimulationsEngineering(string file)
+		{
+			var fileWriter = new FileOutputWriter(file);
+			var sumData = new SummaryDataContainer(fileWriter);
+			var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file);
+			var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Engineering, inputDataProvider, fileWriter);
+			var jobContainer = new JobContainer(sumData);
+			jobContainer.AddRuns(factory);
+			jobContainer.Execute();
+			jobContainer.WaitFinished();
+			Assert.IsTrue(jobContainer.Runs.All(r => r.Success), string.Concat(jobContainer.Runs.Select(r => r.ExecException)));
+		}
+
+		[TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear5invalid.vecto"),
+		 TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear4invalid.vecto"),
+		 TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear6and4invalid.vecto"),
+		 TestCase(@"Testdata\Integration\EngineeringMode\Class2_RigidTruck_4x2_VehTorqueLimits\Class2_RigidTruck_vehTqLimit-disableGear1invalid.vecto")]
+		public void TestRunDisableGearsInvalidEngineering(string file)
+		{
+			var fileWriter = new FileOutputWriter(file);
+			var sumData = new SummaryDataContainer(fileWriter);
+			var inputDataProvider = JSONInputDataFactory.ReadJsonJob(file);
+			var factory = SimulatorFactory.CreateSimulatorFactory(ExecutionMode.Engineering, inputDataProvider, fileWriter);
+			var jobContainer = new JobContainer(sumData);
+			AssertHelper.Exception<VectoException>(() => jobContainer.AddRuns(factory), messageContains: "Only the last 1 or 2 gears can be disabled. Disabling gear ");
+		}
+
+
 	}
 }
-- 
GitLab