diff --git a/VectoCommon/VectoCommon/Models/IResponse.cs b/VectoCommon/VectoCommon/Models/IResponse.cs
index 497c6a51490be0aead411f18403c7ab63ff5c0c0..c3ddf1fdcb9ea4abaa71509b36a6a5dbc591cd23 100644
--- a/VectoCommon/VectoCommon/Models/IResponse.cs
+++ b/VectoCommon/VectoCommon/Models/IResponse.cs
@@ -166,6 +166,7 @@ namespace TUGraz.VectoCommon.Models
 		public NewtonMeter InertiaTorque { get; set; }
 		public PerSecond AvgDrivetrainSpeed { get; set; }
 		public NewtonMeter MaxDriveTorqueEM { get; set; }
+		public NewtonMeter MaxRecuperationTorqueEM { get; set; }
 		public NewtonMeter TorqueRequestEmMap { get; set; }
 	}
 
diff --git a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
index 031243119acc527d46102f117a22560324a66427..03638744c9eb9f43b1cd3bb09b8950dc73850882 100644
--- a/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
+++ b/VectoCore/VectoCore/Models/Simulation/Data/ShiftStrategyParameters.cs
@@ -8,6 +8,11 @@ using TUGraz.VectoCore.Models.SimulationComponent.Data.ShiftStrategy;
 namespace TUGraz.VectoCore.Models.Simulation.Data {
 	public class ShiftStrategyParameters
 	{
+		public ShiftStrategyParameters()
+		{
+			TargetSpeedBrakeNorm = 0.7;
+		}
+
 		public MeterPerSecond StartVelocity { get; internal set; }
 
 		//public MeterPerSquareSecond StartAcceleration { get; internal set; }
@@ -101,5 +106,6 @@ namespace TUGraz.VectoCore.Models.Simulation.Data {
 		public double[] LoadStageThresoldsUp { get; set; }
 		public double[] LoadStageThresoldsDown { get; set; }
 		public double[][] ShiftSpeedsTCToLocked { get; set; }
+		public double TargetSpeedBrakeNorm { get; set; }
 	}
 }
\ No newline at end of file
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
index 7cb5c059f39ae174e9985880736df1846edb2049..264ba3812fb05d5533c19fd1edd1574fc1ecfaf6 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/ElectricMotor.cs
@@ -341,6 +341,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			retVal.ElectricMotor.MaxDriveTorque = maxDriveTorqueDt;
 			retVal.ElectricMotor.MaxDriveTorqueEM = maxDriveTorqueEm;
 			retVal.ElectricMotor.MaxRecuperationTorque = maxRecuperationTorqueDt;
+			retVal.ElectricMotor.MaxRecuperationTorqueEM = maxRecuperationTorqueEm;
 			retVal.ElectricMotor.AngularVelocity = avgEmSpeed;
 			retVal.ElectricMotor.AvgDrivetrainSpeed = avgDtSpeed;
 
diff --git a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs
index fe8a3b6c9a90f89e083f7cae79a48a445e163265..bdaaa0702b2f886f650348cd32a8c8a655ff7bc4 100644
--- a/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs
+++ b/VectoCore/VectoCore/Models/SimulationComponent/Impl/PEVAMTShiftStrategy.cs
@@ -29,6 +29,581 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		protected Gearbox _gearbox;
 		protected GearshiftPosition _nextGear;
 
+		private ShiftStrategyParameters shiftStrategyParameters;
+		protected readonly VelocityRollingLookup VelocityDropData = new VelocityRollingLookup();
+		private SimplePowertrainContainer TestContainer;
+		private Gearbox TestContainerGbx;
+
+		private VoltageLevelData VoltageLevels;
+		private SI TransmissionRatio;
+		private ShiftStrategyParameters GearshiftParams;
+		private GearList GearList;
+
+
+		public static string Name => "AMT - EffShift (BEV)";
+
+
+		protected bool DriveOffStandstill { get; set; }
+
+		public PEVAMTShiftStrategy(IVehicleContainer dataBus)
+		{
+			var runData = dataBus.RunData;
+			if (runData.VehicleData == null) {
+				return;
+			}
+			GearboxModelData = dataBus.RunData.GearboxData;
+			GearshiftParams = dataBus.RunData.GearshiftParameters;
+			GearList = GearboxModelData.GearList;
+			MaxStartGear = GearList.Reverse().First();
+
+			VoltageLevels = dataBus.RunData.ElectricMachinesData
+				.FirstOrDefault(x => x.Item1 == PowertrainPosition.BatteryElectricE2)?.Item2.EfficiencyData;
+
+			DataBus = dataBus;
+
+			TransmissionRatio = runData.AxleGearData.AxleGear.Ratio *
+									(runData.AngledriveData?.Angledrive.Ratio ?? 1.0) /
+									runData.VehicleData.DynamicTyreRadius;
+			//var minEngineSpeed = (runData.EngineData.FullLoadCurves[0].RatedSpeed - runData.EngineData.IdleSpeed) *
+			//	Constants.SimulationSettings.ClutchClosingSpeedNorm + runData.EngineData.IdleSpeed;
+
+			shiftStrategyParameters = runData.GearshiftParameters;
+			
+			if (shiftStrategyParameters == null) {
+				throw new VectoException("Parameters for shift strategy missing!");
+			}
+			SetupVelocityDropPreprocessor(dataBus);
+		}
+
+		private void SetupVelocityDropPreprocessor(IVehicleContainer dataBus)
+		{
+			var runData = dataBus.RunData;
+			// MQ: 2019-11-29 - fuel used here has no effect as this is the modDatacontainer for the test-powertrain only!
+			var modData = new ModalDataContainer(runData, null, null);
+			var builder = new PowertrainBuilder(modData);
+			TestContainer = new SimplePowertrainContainer(runData);
+			builder.BuildSimplePowertrainE2(runData, TestContainer);
+			TestContainerGbx = TestContainer.GearboxCtl as Gearbox;
+			if (TestContainerGbx == null) {
+				throw new VectoException("Unknown gearboxtype: {0}", TestContainer.GearboxCtl.GetType().FullName);
+			}
+
+			// register pre-processors
+			var maxG = runData.Cycle.Entries.Max(x => Math.Abs(x.RoadGradientPercent.Value())) + 1;
+			var grad = Convert.ToInt32(maxG / 2) * 2;
+			if (grad == 0) {
+				grad = 2;
+			}
+
+			dataBus.AddPreprocessor(
+				new VelocitySpeedGearshiftPreprocessorE2(VelocityDropData, runData.GearboxData.TractionInterruption, TestContainer, -grad, grad, 2));
+
+		}
+
+		#region Implementation of IShiftPolygonCalculator
+
+		public ShiftPolygon ComputeDeclarationShiftPolygon(GearboxType gearboxType, int i, EngineFullLoadCurve engineDataFullLoadCurve,
+			IList<ITransmissionInputData> gearboxGears, CombustionEngineData engineData, double axlegearRatio, Meter dynamicTyreRadius,
+			ElectricMotorData electricMotorData = null)
+		{
+			return DeclarationData.Gearbox.ComputeElectricMotorShiftPolygon(i, electricMotorData.EfficiencyData.VoltageLevels.First().FullLoadCurve, electricMotorData.RatioADC, gearboxGears, axlegearRatio, dynamicTyreRadius);
+		}
+
+		#endregion
+
+		#region Implementation of IShiftStrategy
+
+		public bool ShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque,
+			PerSecond inAngularVelocity, GearshiftPosition gear, Second lastShiftTime, IResponse response)
+		{
+			CheckGearshiftRequired = true;
+			var retVal = DoCheckShiftRequired(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity,
+				gear, lastShiftTime, response);
+			CheckGearshiftRequired = false;
+			return retVal;
+		}
+
+		private bool DoCheckShiftRequired(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition gear, Second lastShiftTime, IResponse response)
+		{
+			// no shift when vehicle stands
+			if (DataBus.VehicleInfo.VehicleStopped) {
+				return false;
+			}
+
+			if (DriveOffStandstill &&
+				DataBus.VehicleInfo.VehicleSpeed.IsGreaterOrEqual(DataBus.DrivingCycleInfo.TargetSpeed)) {
+				DriveOffStandstill = false;
+			}
+			if (DriveOffStandstill && response.ElectricMotor.AngularVelocity.IsGreater(VoltageLevels.VoltageLevels.First().FullLoadCurve.NP80low)) {
+				DriveOffStandstill = false;
+			}
+
+			if (DriveOffStandstill && response.ElectricMotor.TorqueRequestEmMap != null &&
+				response.ElectricMotor.TorqueRequestEmMap.IsEqual(response.ElectricMotor.MaxDriveTorqueEM)) {
+				DriveOffStandstill = false;
+			}
+
+			// emergency shift to not stall the engine ------------------------
+			while (GearList.HasSuccessor(_nextGear) &&
+					SpeedTooHighForEngine(_nextGear, inAngularVelocity / GearboxModelData.Gears[gear.Gear].Ratio)) {
+				_nextGear = GearList.Successor(_nextGear);
+			}
+			if (_nextGear != gear) {
+				return true;
+			}
+			if (DriveOffStandstill) {
+				return false;
+			}
+
+			// normal shift when all requirements are fullfilled ------------------
+			var minimumShiftTimePassed = (lastShiftTime + GearshiftParams.TimeBetweenGearshifts).IsSmallerOrEqual(absTime);
+			if (!minimumShiftTimePassed) {
+				return false;
+			}
+
+			_nextGear = CheckDownshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear, response);
+			if (_nextGear != gear) {
+				return true;
+			}
+
+			_nextGear = CheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, gear, response);
+
+			//if ((ModelData.Gears[_nextGear].Ratio * outAngularVelocity - DataBus.EngineIdleSpeed) /
+			//	(DataBus.EngineRatedSpeed - DataBus.EngineIdleSpeed) <
+			//	Constants.SimulationSettings.ClutchClosingSpeedNorm && _nextGear > 1) {
+			//	_nextGear--;
+			//}
+
+			return _nextGear != gear;
+		}
+
+		private GearshiftPosition CheckUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response)
+		{
+			// if the driver's intention is _not_ to accelerate or drive along then don't upshift
+			if (DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Accelerating && DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Driving) {
+				return currentGear;
+			}
+			if ((absTime - _gearbox.LastDownshift).IsSmaller(GearshiftParams.UpshiftAfterDownshiftDelay)) {
+				return currentGear;
+			}
+			var nextGear = DoCheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response);
+			if (!nextGear.Equals(currentGear)) {
+				return nextGear;
+			}
+
+			// early up shift to higher gear ---------------------------------------
+			if (GearList.HasSuccessor(currentGear)) {
+				nextGear = CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response);
+			}
+
+			return nextGear;
+		}
+
+		protected virtual GearshiftPosition DoCheckUpshift(Second absTime, Second dt, NewtonMeter outTorque,
+			PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity,
+			GearshiftPosition currentGear, IResponse r)
+		{
+			var nextGear = currentGear;
+			// upshift
+			if (IsAboveUpShiftCurve(currentGear, inTorque, inAngularVelocity)) {
+				nextGear = GearList.Successor(currentGear);
+
+				while (GearList.HasSuccessor(nextGear)) {
+					// check skip gears
+					nextGear = GearList.Successor(nextGear);
+					var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, nextGear);
+
+					inAngularVelocity = response.ElectricMotor.AngularVelocity;
+					inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity;
+
+					var maxTorque = VectoMath.Min(-response.ElectricMotor.MaxDriveTorque,
+						!nextGear.Equals(GearList.First())
+							? GearboxModelData.Gears[nextGear.Gear].ShiftPolygon
+								.InterpolateDownshift(response.Engine.EngineSpeed)
+							: double.MaxValue.SI<NewtonMeter>());
+					var reserve = 1 - inTorque / maxTorque;
+
+					if (reserve >= 0 /*ModelData.TorqueReserve */ &&
+						IsAboveDownShiftCurve(nextGear, inTorque, inAngularVelocity)) {
+						continue;
+					}
+
+					nextGear = GearList.Predecessor(nextGear);
+					break;
+				}
+			}
+
+			return nextGear;
+		}
+
+		protected virtual GearshiftPosition CheckEarlyUpshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1)
+		{
+			var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>());
+			if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) {
+				return currentGear;
+			}
+
+			var vDrop = DataBus.VehicleInfo.VehicleSpeed - estimatedVelocityPostShift;
+			var vehicleSpeedPostShift = DataBus.VehicleInfo.VehicleSpeed - vDrop * shiftStrategyParameters.VelocityDropFactor;
+
+			var totalTransmissionRatio = DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).ElectricMotorSpeed / DataBus.VehicleInfo.VehicleSpeed;
+			
+			var results = new List<Tuple<GearshiftPosition, double>>();
+			foreach (var tryNextGear in GearList.IterateGears(GearList.Successor(currentGear), GearList.Successor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) {
+				var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear);
+
+				var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity;
+				var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity;
+
+				if (IsBelowDownShiftCurve(tryNextGear, inTorque, inAngularVelocity)) {
+					continue;
+				}
+
+				var estimatedEngineSpeed = (vehicleSpeedPostShift * (totalTransmissionRatio / GearboxModelData.Gears[currentGear.Gear].Ratio * GearboxModelData.Gears[tryNextGear.Gear].Ratio)).Cast<PerSecond>();
+				if (estimatedEngineSpeed.IsSmaller(shiftStrategyParameters.MinEngineSpeedPostUpshift)) {
+					continue;
+				}
+
+				var fullLoadPower = -response.ElectricMotor.MaxDriveTorque * response.ElectricMotor.AngularVelocity;
+				var reserve = 1 - response.ElectricMotor.PowerRequest / fullLoadPower;
+				if (reserve < 0) {
+					continue;
+				}
+
+				var fcNext = GetFCRating(response);
+				results.Add(Tuple.Create(tryNextGear, fcNext));
+
+			}
+
+			if (results.Count == 0) {
+				return currentGear;
+			}
+
+			var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear);
+			var fcCurrent = GetFCRating(responseCurrent);
+
+			var minFc = results.MinBy(x => x.Item2);
+
+			var ratingFactor = outTorque < 0
+				? 1 / shiftStrategyParameters.RatingFactorCurrentGear
+				: shiftStrategyParameters.RatingFactorCurrentGear;
+
+			if (minFc.Item2.IsGreater(fcCurrent * ratingFactor)) {
+				return minFc.Item1;
+			}
+
+			return currentGear;
+			//return fcUpshiftPossible
+			//	? currentGear
+			//	: base.CheckEarlyUpshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response1);
+		}
+
+
+		private GearshiftPosition CheckDownshift(Second absTime, Second dt, NewtonMeter outTorque,
+			PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity,
+			GearshiftPosition currentGear, IResponse response)
+		{
+			if ((absTime - _gearbox.LastUpshift).IsSmaller(GearshiftParams.DownshiftAfterUpshiftDelay)) {
+				return currentGear;
+			}
+
+			if (!GearList.HasPredecessor(currentGear)) {
+				return currentGear;
+			}
+
+			// check with shiftline
+			if (response.ElectricMotor.TorqueRequestEmMap != null && IsBelowDownShiftCurve(currentGear,
+				response.ElectricMotor.TorqueRequestEmMap,
+				response.ElectricMotor.AngularVelocity)) {
+
+				if (DataBus.DriverInfo.DriverBehavior == DrivingBehavior.Braking) {
+					var brakingGear = SelectBrakingGear(currentGear, response);
+					return brakingGear;
+				}
+
+				var nextGear = GearList.Predecessor(currentGear);
+				return nextGear;
+			}
+
+			if (response.ElectricMotor.TorqueRequestEmMap != null && response.ElectricMotor.TorqueRequestEmMap.IsEqual(
+				response.ElectricMotor.MaxRecuperationTorqueEM,
+				response.ElectricMotor.MaxRecuperationTorqueEM * 0.1)) {
+				// no early downshift when close to max recuperation line
+				return currentGear;
+			}
+
+			// check early downshift
+			return CheckEarlyDownshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response);
+		}
+
+		private GearshiftPosition SelectBrakingGear(GearshiftPosition currentGear, IResponse response)
+		{
+			var tmpGear = new GearshiftPosition(currentGear.Gear, currentGear.TorqueConverterLocked);
+			var candidates = new Dictionary<GearshiftPosition, PerSecond>();
+			var gbxOutSpeed = response.Engine.EngineSpeed /
+							GearboxModelData.Gears[tmpGear.Gear].Ratio;
+			var firstGear = GearList.Predecessor(currentGear, 1);
+			var lastGear = GearList.Predecessor(currentGear, (uint)GearshiftParams.AllowedGearRangeFC);
+			foreach (var gear in GearList.IterateGears(firstGear, lastGear)) {
+				var ratio = gear.IsLockedGear()
+					? GearboxModelData.Gears[gear.Gear].Ratio
+					: GearboxModelData.Gears[gear.Gear].TorqueConverterRatio;
+				candidates[gear] = gbxOutSpeed * ratio;
+			}
+
+			var ratedSpeed = VoltageLevels.VoltageLevels.First().FullLoadCurve.RatedSpeed;
+			var maxSpeedNorm = VoltageLevels.MaxSpeed / ratedSpeed;
+			var targetMotor = (shiftStrategyParameters.TargetSpeedBrakeNorm * (maxSpeedNorm - 1) + 1) * ratedSpeed;
+
+			if (candidates.Any(x => x.Value > targetMotor && x.Value < VoltageLevels.MaxSpeed)) {
+				var best = candidates.Where(x => x.Value > targetMotor && x.Value < VoltageLevels.MaxSpeed)
+					.OrderBy(x => x.Value).First();
+				return best.Key;
+			}
+
+			var retVal = candidates.Where(x => x.Value < VoltageLevels.MaxSpeed).MaxBy(x => x.Value).Key;
+			return retVal;
+		}
+
+		protected virtual GearshiftPosition CheckEarlyDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition currentGear, IResponse response1)
+		{
+			var estimatedVelocityPostShift = VelocityDropData.Interpolate(DataBus.VehicleInfo.VehicleSpeed, DataBus.DrivingCycleInfo.RoadGradient ?? 0.SI<Radian>());
+			if (!estimatedVelocityPostShift.IsGreater(DeclarationData.GearboxTCU.MIN_SPEED_AFTER_TRACTION_INTERRUPTION)) {
+				return currentGear;
+			}
+
+			var results = new List<Tuple<GearshiftPosition, double>>();
+			foreach (var tryNextGear in GearList.IterateGears(GearList.Predecessor(currentGear), GearList.Predecessor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) {
+
+				var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear);
+				var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity;
+				var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity;
+
+				if (IsAboveUpShiftCurve(tryNextGear, inTorque, inAngularVelocity)) {
+					continue;
+				}
+
+				var fcNext = GetFCRating(response);
+				results.Add(Tuple.Create(tryNextGear, fcNext));
+			}
+
+			if (results.Count == 0) {
+				return currentGear;
+			}
+
+			var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear);
+			var fcCurrent = GetFCRating(responseCurrent);
+			var minFc = results.MinBy(x => x.Item2);
+			var ratingFactor = outTorque < 0
+				? 1 / shiftStrategyParameters.RatingFactorCurrentGear
+				: shiftStrategyParameters.RatingFactorCurrentGear;
+
+			if (minFc.Item2.IsGreater(fcCurrent * ratingFactor)) {
+					return minFc.Item1;
+			}
+
+			return currentGear;
+		}
+
+
+		protected double GetFCRating(ResponseDryRun response)//PerSecond engineSpeed, NewtonMeter tqCurrent)
+		{
+			var currentGear = response.Gearbox.Gear;
+
+			var maxGenTorque = VectoMath.Min(GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxRecuperationTorque);
+			var maxDriveTorque = GearboxModelData.Gears[currentGear.Gear].MaxTorque != null
+				? VectoMath.Max(-GearboxModelData.Gears[currentGear.Gear].MaxTorque, response.ElectricMotor.MaxDriveTorque)
+				: response.ElectricMotor.MaxDriveTorque;
+
+			var tqCurrent = (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricMotor.AngularVelocity);
+			if (!tqCurrent.IsBetween(maxDriveTorque, maxGenTorque)) {
+				return double.NaN;
+			}
+			var engineSpeed = response.ElectricMotor.AngularVelocity;
+
+
+			var fcCurRes = VoltageLevels.LookupElectricPower(DataBus.BatteryInfo.InternalVoltage, engineSpeed, tqCurrent, true);
+			if (fcCurRes.Extrapolated) {
+				Log.Warn(
+					"EffShift Strategy: Extrapolation of power consumption for current gear! n: {0}, Tq: {1}",
+					engineSpeed, tqCurrent);
+			}
+			return fcCurRes.ElectricalPower.Value();
+		}
+
+		protected ResponseDryRun RequestDryRunWithGear(
+			Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, GearshiftPosition tryNextGear)
+		{
+			LogEnabled = false;
+			TestContainerGbx.Disengaged = false;
+			TestContainerGbx.Gear = tryNextGear;
+
+			TestContainer.GearboxOutPort.Initialize(outTorque, outAngularVelocity);
+			var response = (ResponseDryRun)TestContainer.GearboxOutPort.Request(
+				0.SI<Second>(), dt, outTorque, outAngularVelocity, true);
+			LogEnabled = true;
+			return response;
+		}
+
+
+		public GearshiftPosition InitGear(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{
+			if (DataBus.VehicleInfo.VehicleSpeed.IsEqual(0)) {
+				return InitStartGear(absTime, outTorque, outAngularVelocity);
+			}
+
+			foreach (var gear in GearList.Reverse()) {
+				//for (var gear = (uint)GearboxModelData.Gears.Count; gear > 1; gear--) {
+				var response = _gearbox.Initialize(absTime, gear, outTorque, outAngularVelocity);
+
+				var inAngularSpeed = outAngularVelocity * GearboxModelData.Gears[gear.Gear].Ratio;
+				var inTorque = response.ElectricMotor.PowerRequest / inAngularSpeed;
+
+				// if in shift curve and torque reserve is provided: return the current gear
+				if (!IsBelowDownShiftCurve(gear, inTorque, inAngularSpeed) && !IsAboveUpShiftCurve(gear, inTorque, inAngularSpeed)) {
+					_nextGear = gear;
+					return gear;
+				}
+			}
+			// fallback: return first gear
+			_nextGear = GearList.First();
+			return _nextGear;
+		}
+
+		private GearshiftPosition InitStartGear(Second absTime, NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{
+			DriveOffStandstill = true;
+
+			var emSpeeds = new Dictionary<GearshiftPosition, Tuple<PerSecond, PerSecond, double>>();
+
+			foreach (var gear in GearList.Reverse()) {
+				//for (var gear = (uint)GearboxModelData.Gears.Count; gear >= 1; gear--) {
+				var inAngularSpeed = outAngularVelocity * GearboxModelData.Gears[gear.Gear].Ratio;
+
+				var ratedSpeed = VoltageLevels.MaxSpeed * 0.9;
+				if (inAngularSpeed > ratedSpeed || inAngularSpeed.IsEqual(0)) {
+					continue;
+				}
+
+				var response = _gearbox.Initialize(absTime, gear, outTorque, outAngularVelocity);
+
+				var fullLoadPower = -(response.ElectricMotor.MaxDriveTorque * response.ElectricMotor.AngularVelocity);
+				//.DynamicFullLoadPower; //EnginePowerRequest - response.DeltaFullLoad;
+				var reserve = 1 - response.ElectricMotor.TorqueRequestEmMap / response.ElectricMotor.MaxDriveTorqueEM;
+
+				var isBelowDownshift = gear.Gear > 1 &&
+										IsBelowDownshiftCurve(GearboxModelData.Gears[gear.Gear].ShiftPolygon, response.ElectricMotor.TorqueRequest,
+											response.ElectricMotor.AngularVelocity);
+
+				if (reserve >= GearshiftParams.StartTorqueReserve && !isBelowDownshift) {
+					//_nextGear = gear;
+					//return gear;
+					emSpeeds[gear] = Tuple.Create(response.ElectricMotor.AngularVelocity,
+						(GearshiftParams.StartSpeed * TransmissionRatio * GearboxModelData.Gears[gear.Gear].Ratio)
+						.Cast<PerSecond>(), (response.ElectricMotor.ElectricMotorPowerMech / response.ElectricSystem.RESSPowerDemand).Value());
+				}
+			}
+
+			if (emSpeeds.Any()) {
+				var optimum = emSpeeds.MaxBy(x => x.Key.Gear); //x => VectoMath.Abs(x.Value.Item2 - FullLoadCurve.MaxSpeed * 0.5));
+				_nextGear = optimum.Key;
+				return _nextGear;
+			}
+			_nextGear = GearList.First();
+			return _nextGear;
+		}
+
+
+		protected bool IsBelowDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
+		{
+			if (!GearList.HasPredecessor(gear)) {
+				return false;
+			}
+			return IsBelowDownshiftCurve(GearboxModelData.Gears[gear.Gear].ShiftPolygon, inTorque, inEngineSpeed);
+		}
+
+		protected bool IsAboveDownShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
+		{
+			if (!GearList.HasPredecessor(gear)) {
+				return true;
+			}
+			return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveDownshiftCurve(inTorque, inEngineSpeed);
+		}
+
+		protected bool IsAboveUpShiftCurve(GearshiftPosition gear, NewtonMeter inTorque, PerSecond inEngineSpeed)
+		{
+			if (!GearList.HasSuccessor(gear)) {
+				return false;
+			}
+			return GearboxModelData.Gears[gear.Gear].ShiftPolygon.IsAboveUpshiftCurve(inTorque, inEngineSpeed);
+		}
+
+		protected bool IsBelowDownshiftCurve(ShiftPolygon shiftPolygon, NewtonMeter emTorque, PerSecond emSpeed)
+		{
+			foreach (var entry in shiftPolygon.Downshift.Pairwise(Tuple.Create)) {
+				if (!emTorque.IsBetween(entry.Item1.Torque, entry.Item2.Torque)) {
+					continue;
+				}
+
+				if (ShiftPolygon.IsLeftOf(emSpeed, emTorque, entry)) {
+
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		public GearshiftPosition Engage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{
+			while (GearList.HasSuccessor(_nextGear) && SpeedTooHighForEngine(_nextGear, outAngularVelocity)) {
+				_nextGear = GearList.Successor(_nextGear);
+			}
+
+			return _nextGear;
+		}
+
+		protected bool SpeedTooHighForEngine(GearshiftPosition gear, PerSecond outAngularSpeed)
+		{
+			return
+				(outAngularSpeed * GearboxModelData.Gears[gear.Gear].Ratio).IsGreaterOrEqual(VectoMath.Min(GearboxModelData.Gears[gear.Gear].MaxSpeed,
+					DataBus.ElectricMotorInfo(PowertrainPosition.BatteryElectricE2).MaxSpeed));
+		}
+
+		public void Disengage(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { }
+
+		public IGearbox Gearbox {
+			get => _gearbox;
+			set {
+				var myGearbox = value as Gearbox;
+				if (myGearbox == null) {
+					throw new VectoException("This shift strategy can't handle gearbox of type {0}", value.GetType());
+				}
+				_gearbox = myGearbox;
+			}
+		}
+
+		public GearshiftPosition NextGear => _nextGear;
+		public bool CheckGearshiftRequired { get; protected set; }
+		public GearshiftPosition MaxStartGear { get; }
+		public void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { }
+
+		public void WriteModalResults(IModalDataContainer container) { }
+
+		#endregion
+	}
+
+
+	// ##########################
+
+	public class PEVAMTShiftStrategy_OLD : LoggingObject, IShiftStrategy
+	{
+		protected readonly IDataBus DataBus;
+		protected readonly GearboxData GearboxModelData;
+
+		protected Gearbox _gearbox;
+		protected GearshiftPosition _nextGear;
+
 		private ShiftStrategyParameters shiftStrategyParameters;
 		protected readonly VelocityRollingLookup VelocityDropData = new VelocityRollingLookup();
 		private SimplePowertrainContainer TestContainer;
@@ -45,8 +620,23 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		public static string Name => "AMT - EffShift (BEV)";
 
+		public enum GearshiftTrigger
+		{
+			NoShift = 0,
+			GearshiftBlockedTimeDelay = -2,
+			GearshiftBlockedNotAccelerating = -4,
+			AboveUpshiftLine = 10,
+			BelowDownshiftLine = -10,
+			EfficiencyShift = 5,
+			EmergencyShift = 2
+		}
+
+		public GearshiftTrigger ShiftTrigger;
+		private Second ShiftDecisionTstmp = -double.MaxValue.SI<Second>();
 
-		public PEVAMTShiftStrategy(IVehicleContainer dataBus)
+		protected bool DriveOffStandstill = false;
+
+		public PEVAMTShiftStrategy_OLD(IVehicleContainer dataBus)
 		{
 			var runData = dataBus.RunData;
 			if (runData.VehicleData == null) {
@@ -124,18 +714,37 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				return false;
 			}
 
+			if (DriveOffStandstill &&
+				DataBus.VehicleInfo.VehicleSpeed.IsGreaterOrEqual(DataBus.DrivingCycleInfo.TargetSpeed)) {
+				DriveOffStandstill = false;
+			}
+			if (DriveOffStandstill && response.ElectricMotor.AngularVelocity.IsGreater(VoltageLevels.VoltageLevels.First().FullLoadCurve.NP80low)) {
+				DriveOffStandstill = false;
+			}
+
+			if (DriveOffStandstill && response.ElectricMotor.TorqueRequestEmMap != null &&
+				response.ElectricMotor.TorqueRequestEmMap.IsEqual(response.ElectricMotor.MaxDriveTorqueEM)) {
+				DriveOffStandstill = false;
+			}
+
 			// emergency shift to not stall the engine ------------------------
 			while (GearList.HasSuccessor(_nextGear) &&
 					SpeedTooHighForEngine(_nextGear, inAngularVelocity / GearboxModelData.Gears[gear.Gear].Ratio)) {
 				_nextGear = GearList.Successor(_nextGear);
 			}
 			if (_nextGear != gear) {
+				SetShiftDecision(GearshiftTrigger.EmergencyShift, absTime);
 				return true;
 			}
 
+			if (DriveOffStandstill) {
+				return false;
+			}
+
 			// normal shift when all requirements are fullfilled ------------------
 			var minimumShiftTimePassed = (lastShiftTime + GearshiftParams.TimeBetweenGearshifts).IsSmallerOrEqual(absTime);
 			if (!minimumShiftTimePassed) {
+				SetShiftDecision(GearshiftTrigger.GearshiftBlockedTimeDelay, absTime);
 				return false;
 			}
 
@@ -159,9 +768,11 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		{
 			// if the driver's intention is _not_ to accelerate or drive along then don't upshift
 			if (DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Accelerating && DataBus.DriverInfo.DriverBehavior != DrivingBehavior.Driving) {
+				SetShiftDecision(GearshiftTrigger.GearshiftBlockedNotAccelerating, absTime);
 				return currentGear;
 			}
 			if ((absTime - _gearbox.LastDownshift).IsSmaller(GearshiftParams.UpshiftAfterDownshiftDelay)) {
+				SetShiftDecision(GearshiftTrigger.GearshiftBlockedTimeDelay, absTime);
 				return currentGear;
 			}
 			var nextGear = DoCheckUpshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response);
@@ -411,6 +1022,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		protected virtual GearshiftPosition CheckDownshift(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity, NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response)
 		{
 			if ((absTime - _gearbox.LastUpshift).IsSmaller(GearshiftParams.DownshiftAfterUpshiftDelay)) {
+				SetShiftDecision(GearshiftTrigger.GearshiftBlockedTimeDelay, absTime);
 				return currentGear;
 			}
 			return DoCheckDownshift(absTime, dt, outTorque, outAngularVelocity, inTorque, inAngularVelocity, currentGear, response);
@@ -425,6 +1037,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 			if (nextGear.Equals(currentGear) && !currentGear.Equals(GearList.First())) {
 				nextGear = CheckEarlyDownshift(absTime, dt, outTorque, outAngularVelocity, currentGear, response);
+				if (nextGear != currentGear) {
+					SetShiftDecision(GearshiftTrigger.EfficiencyShift, absTime);
+				}
 			}
 			return nextGear;
 		}
@@ -433,8 +1048,13 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			NewtonMeter inTorque, PerSecond inAngularVelocity, GearshiftPosition currentGear, IResponse response)
 		{
 			// down shift
+			if (response.ElectricMotor.TorqueRequestEmMap == null) {
+				// em is off - no need to shift
+				return currentGear;
+			}
 			if (IsBelowDownShiftCurve(currentGear, response.ElectricMotor.TorqueRequestEmMap, response.ElectricMotor.AngularVelocity)) {
 				currentGear = GearList.Predecessor(currentGear);
+				SetShiftDecision(GearshiftTrigger.BelowDownshiftLine, absTime);
 				//while (SkipGears && currentGear > 1) {
 				//	currentGear--;
 				//	var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear);
@@ -476,14 +1096,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 			var results = new List<Tuple<GearshiftPosition, double>>();
 			foreach (var tryNextGear in GearList.IterateGears(GearList.Predecessor(currentGear), GearList.Predecessor(currentGear, (uint)shiftStrategyParameters.AllowedGearRangeFC))) {
 				
-				//if (tryNextGear < 1 /*|| !(ModelData.Gears[tryNextGear].Ratio <= shiftStrategyParameters.RatioEarlyDownshiftFC)*/) {
-				//	continue;
-				//}
-
 				var response = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, tryNextGear);
 
-				//var response = RequestDryRunWithGear(absTime, dt, DataBus.VehicleSpeed, DataBus.DriverAcceleration, tryNextGear);
-
 				var inAngularVelocity = GearboxModelData.Gears[tryNextGear.Gear].Ratio * outAngularVelocity;
 				var inTorque = response.ElectricMotor.PowerRequest / inAngularVelocity;
 
@@ -491,22 +1105,9 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 					continue;
 				}
 
-				//if (double.IsNaN(fcCurrent)) {
-				//	var responseCurrent = RequestDryRunWithGear(absTime, dt, outTorque, outAngularVelocity, currentGear);
-
-				//	//var responseCurrent = RequestDryRunWithGear(absTime, dt, DataBus.VehicleSpeed, DataBus.DriverAcceleration, currentGear);
-				//	fcCurrent = GetFCRating(responseCurrent);
-				//}
 				var fcNext = GetFCRating(response);
 				results.Add(Tuple.Create(tryNextGear,fcNext));
 
-				//if (!fcNext.IsGreater(fcCurrent * shiftStrategyParameters.RatingFactorCurrentGear) ||
-				//	!fcNext.IsGreater(minFc)) {
-				//	continue;
-				//}
-
-				//minFcGear = tryNextGear;
-				//minFc = fcNext;
 			}
 
 			if (results.Count == 0) {
@@ -557,6 +1158,8 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 
 		private GearshiftPosition InitStartGear(Second absTime, NewtonMeter outTorque, PerSecond outAngularVelocity)
 		{
+			DriveOffStandstill = true;
+
 			var emSpeeds = new Dictionary<GearshiftPosition, Tuple<PerSecond, PerSecond, double>>();
 
 			foreach (var gear in GearList.Reverse()) {
@@ -604,6 +1207,7 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 				}
 
 				if (ShiftPolygon.IsLeftOf(emSpeed, emTorque, entry)) {
+
 					return true;
 				}
 			}
@@ -672,7 +1276,19 @@ namespace TUGraz.VectoCore.Models.SimulationComponent.Impl
 		public bool CheckGearshiftRequired { get; protected set; }
 		public GearshiftPosition MaxStartGear { get; }
 
-		public void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity) { }
+		public void Request(Second absTime, Second dt, NewtonMeter outTorque, PerSecond outAngularVelocity)
+		{
+			if (!absTime.IsEqual(ShiftDecisionTstmp)) {
+				ShiftTrigger = GearshiftTrigger.NoShift;
+			}
+
+			ShiftDecisionTstmp = absTime;
+		}
+
+		protected void SetShiftDecision(GearshiftTrigger trigger, Second absTime)
+		{
+			ShiftTrigger = trigger;
+		}
 
 		public void WriteModalResults(IModalDataContainer container) { }