public void DefaultByPowerEfficiency()
        {
            tableGear     = new Dictionary <int, Dictionary <double, int> >();
            tableThrottle = new Dictionary <int, Dictionary <double, double> >();
            // Make sure there are 20 rpm steps, and 10 load steps
            for (int speed = 0; speed <= MaximumSpeed; speed += 1)
            {
                tableGear.Add(speed, new Dictionary <double, int>());
                tableThrottle.Add(speed, new Dictionary <double, double>());
                for (var load = 0.0; load <= 1.0; load += 0.1)
                {
                    tableThrottle[speed].Add(load, 1);
                    var gearSet            = false;
                    var bestFuelEfficiency = double.MinValue;
                    var bestFuelGear       = 0;

                    for (int gear = 0; gear < Drivetrain.Gears; gear++)
                    {
                        var calculatedRpm = Drivetrain.GearRatios[gear] * speed;

                        if (calculatedRpm < Drivetrain.StallRpm * 1.5)
                        {
                            continue;
                        }
                        if (calculatedRpm > Drivetrain.MaximumRpm)
                        {
                            continue;
                        }

                        var thr = (load < 0.05) ? 0.05 : load;

                        var pwr        = Drivetrain.CalculatePower(calculatedRpm, thr);
                        var fuel       = Drivetrain.CalculateFuelConsumption(calculatedRpm, thr);
                        var efficiency = pwr / fuel;

                        if (efficiency > bestFuelEfficiency)
                        {
                            bestFuelEfficiency = efficiency;
                            bestFuelGear       = gear;
                            gearSet            = true;
                        }
                    }
                    if (!gearSet)
                    {
                        if (Drivetrain is Ets2Drivetrain && Drivetrain.Gears >= 10)
                        {
                            tableGear[speed].Add(load, 3);
                        }
                        else
                        {
                            tableGear[speed].Add(load, 1);
                        }
                    }
                    else
                    {
                        if (Drivetrain is Ets2Drivetrain && Drivetrain.Gears >= 10)
                        {
                            bestFuelGear = Math.Max(2, bestFuelGear);
                        }
                        tableGear[speed].Add(load, bestFuelGear + 1);
                    }
                }
            }
        }
        private void DefaultByPowerEfficiency2()
        {
            tableGear     = new Dictionary <int, Dictionary <double, int> >();
            tableThrottle = new Dictionary <int, Dictionary <double, double> >();

            if (Drivetrain.Gears == 0)
            {
                return;
            }
            // Make sure there are 20 rpm steps, and 10 load steps
            for (int speed = 0; speed <= MaximumSpeed; speed += 1)
            {
                tableGear.Add(speed, new Dictionary <double, int>());
                tableThrottle.Add(speed, new Dictionary <double, double>());

                Dictionary <int, float> pwrPerGear = new Dictionary <int, float>();

                // Populate:
                for (int gear = 0; gear < Drivetrain.Gears; gear++)
                {
                    var calculatedRpm = Drivetrain.GearRatios[gear] * speed;
                    var power         = (float)Drivetrain.CalculatePower(calculatedRpm, 1);
                    pwrPerGear.Add(gear, power);
                }

                var maxPwrAvailable = pwrPerGear.Values.Max() * 0.85;

                for (var load = 0.0; load <= 1.0; load += 0.1)
                {
                    Dictionary <int, float> efficiencyPerGear = new Dictionary <int, float>();
                    var highestGearBeforeStalling             = 0;

                    for (int gear = 0; gear < Drivetrain.Gears; gear++)
                    {
                        var calculatedRpm = Drivetrain.GearRatios[gear] * speed;
                        if (calculatedRpm > Drivetrain.StallRpm)
                        {
                            highestGearBeforeStalling = gear;
                        }
                        var power = (float)Drivetrain.CalculatePower(calculatedRpm, 1);
                        var fuel  = (float)Drivetrain.CalculateFuelConsumption(calculatedRpm, Math.Max(0.05, load));
                        efficiencyPerGear.Add(gear, fuel / power);
                    }
                    var bestGear  = highestGearBeforeStalling;
                    var bestGearV = 100.0f;
                    foreach (var kvp in efficiencyPerGear)
                    {
                        if (kvp.Value < bestGearV && kvp.Value > 0)
                        {
                            bestGearV = kvp.Value;
                            bestGear  = kvp.Key;
                        }
                    }
                    var actualRpm = Drivetrain.GearRatios[bestGear] * speed;

                    var reqThr   = Drivetrain.CalculateThrottleByPower(actualRpm, load * maxPwrAvailable);
                    var thrScale = reqThr / Math.Max(load, 0.1);
                    if (thrScale > 1.5)
                    {
                        thrScale = 1.5;
                    }
                    tableGear[speed].Add(load, bestGear + 1);
                    tableThrottle[speed].Add(load, thrScale);
                }
            }
        }
        public void DefaultByPowerEconomy()
        {
            var maxPwr = Drivetrain.CalculateMaxPower() * 0.75;

            maxPwr        = 500;
            tableGear     = new Dictionary <int, Dictionary <double, int> >();
            tableThrottle = new Dictionary <int, Dictionary <double, double> >();
            // Make sure there are 20 rpm steps, and 10 load steps
            for (int speed = 0; speed <= MaximumSpeed; speed += 1)
            {
                tableGear.Add(speed, new Dictionary <double, int>());
                tableThrottle.Add(speed, new Dictionary <double, double>());
                for (var load = 0.0; load <= 1.0; load += 0.1)
                {
                    tableThrottle[speed].Add(load, 1);
                    var    gearSet = false;
                    double req     = Math.Max(25, load * maxPwr);

                    var bestFuelEfficiency = double.MaxValue;
                    var bestFuelGear       = 0;
                    var highestValidGear   = 11;

                    for (int gear = 0; gear < Drivetrain.Gears; gear++)
                    {
                        var calculatedRpm = Drivetrain.GearRatios[gear] * speed;

                        if (calculatedRpm <= Drivetrain.StallRpm * 1.033333)
                        {
                            highestValidGear = 0;
                            continue;
                        }
                        if (calculatedRpm >= Drivetrain.MaximumRpm)
                        {
                            continue;
                        }

                        var thr = Drivetrain.CalculateThrottleByPower(calculatedRpm, req);

                        if (thr > 1)
                        {
                            continue;
                        }
                        if (thr < 0)
                        {
                            continue;
                        }

                        if (double.IsNaN(thr) || double.IsInfinity(thr))
                        {
                            continue;
                        }

                        var fuel = Drivetrain.CalculateFuelConsumption(calculatedRpm, thr);

                        if (bestFuelEfficiency >= fuel)
                        {
                            bestFuelEfficiency = fuel;
                            bestFuelGear       = gear;
                            gearSet            = true;
                        }
                    }
                    if (!gearSet)
                    {
                        if (Drivetrain is Ets2Drivetrain)
                        {
                            highestValidGear = Math.Max(2, highestValidGear);
                        }
                        tableGear[speed].Add(load, 1 + highestValidGear);
                    }
                    else
                    {
                        bestFuelGear = Math.Max(2, bestFuelGear);
                        if (Drivetrain is Ets2Drivetrain)
                        {
                            highestValidGear = Math.Max(2, bestFuelGear);
                        }
                        tableGear[speed].Add(load, bestFuelGear + 1);
                    }
                }
            }
        }