コード例 #1
0
        private static float HillinessMovementDifficultyOffset(Hilliness hilliness)
        {
            float result;

            switch (hilliness)
            {
            case Hilliness.Flat:
                result = 0f;
                break;

            case Hilliness.SmallHills:
                result = 0.5f;
                break;

            case Hilliness.LargeHills:
                result = 1.5f;
                break;

            case Hilliness.Mountainous:
                result = 3f;
                break;

            case Hilliness.Impassable:
                result = 1000f;
                break;

            default:
                result = 0f;
                break;
            }
            return(result);
        }
コード例 #2
0
        public static string GetLabel(this Hilliness h)
        {
            string result;

            switch (h)
            {
            case Hilliness.Flat:
                result = "Hilliness_Flat".Translate();
                break;

            case Hilliness.SmallHills:
                result = "Hilliness_SmallHills".Translate();
                break;

            case Hilliness.LargeHills:
                result = "Hilliness_LargeHills".Translate();
                break;

            case Hilliness.Mountainous:
                result = "Hilliness_Mountainous".Translate();
                break;

            case Hilliness.Impassable:
                result = "Hilliness_Impassable".Translate();
                break;

            default:
                Log.ErrorOnce("Hilliness label unknown: " + h.ToString(), 694362, false);
                result = h.ToString();
                break;
            }
            return(result);
        }
 static void Postfix(ref float __result, Hilliness hilliness)
 {
     if (hilliness == Hilliness.Impassable)
     {
         __result = Settings.MovementDifficulty;
     }
 }
コード例 #4
0
ファイル: Preset.cs プロジェクト: AzureFox4/PrepareLanding
        private static void SaveHilliness(XContainer xRoot, string entryName, Hilliness hilliness)
        {
            if (hilliness == Hilliness.Undefined)
            {
                return;
            }

            xRoot.Add(new XElement(entryName, hilliness.ToString()));
        }
コード例 #5
0
        public static bool ImpassableAllowed(int tile, RoadDef roadDef)
        {
            DefModExtension_RotR_RoadDef RoadDefMod = roadDef.GetModExtension <DefModExtension_RotR_RoadDef>();
            Hilliness hillinnessHere = Find.WorldGrid.tiles[tile].hilliness;

            if (RoadDefMod.canBuildOnImpassable && hillinnessHere == Hilliness.Impassable)
            {
                return(true);
            }
            return(hillinnessHere != Hilliness.Impassable);
        }
コード例 #6
0
 private static float HillinessMovementDifficultyOffset(Hilliness hilliness)
 {
     return(hilliness switch
     {
         Hilliness.Flat => 0f,
         Hilliness.SmallHills => 0.5f,
         Hilliness.LargeHills => 1.5f,
         Hilliness.Mountainous => 3f,
         Hilliness.Impassable => 1000f,
         _ => 0f,
     });
コード例 #7
0
ファイル: WarUtility.cs プロジェクト: SwimUp/moreevents
        public static float GetMultiplierFor(Hilliness hilliness)
        {
            switch (hilliness)
            {
            case Hilliness.SmallHills:
                return(1.04f);

            case Hilliness.Mountainous:
                return(1.06f);

            case Hilliness.LargeHills:
                return(1.1f);

            default:
                return(1f);
            }
        }
コード例 #8
0
		public static string GetLabel(this Hilliness h)
		{
			switch (h)
			{
			case Hilliness.Flat:
				return "Hilliness_Flat".Translate();
			case Hilliness.SmallHills:
				return "Hilliness_SmallHills".Translate();
			case Hilliness.LargeHills:
				return "Hilliness_LargeHills".Translate();
			case Hilliness.Mountainous:
				return "Hilliness_Mountainous".Translate();
			case Hilliness.Impassable:
				return "Hilliness_Impassable".Translate();
			default:
				Log.ErrorOnce("Hilliness label unknown: " + h.ToString(), 694362);
				return h.ToString();
			}
		}
コード例 #9
0
        private static float HillinessMovementDifficultyOffset(Hilliness hilliness)
        {
            switch (hilliness)
            {
            case Hilliness.Flat:
                return(0f);

            case Hilliness.SmallHills:
                return(0.5f);

            case Hilliness.LargeHills:
                return(1.5f);

            case Hilliness.Mountainous:
                return(3f);

            case Hilliness.Impassable:
                return(1000f);

            default:
                return(0f);
            }
        }
コード例 #10
0
 public static float FactorFromHilliness(Hilliness hilliness)
 {
     if (hilliness == Hilliness.Flat)
     {
         return(0.2f);
     }
     else if (hilliness == Hilliness.SmallHills)
     {
         return(0.12f);
     }
     else if (hilliness == Hilliness.LargeHills)
     {
         return(0.1f);
     }
     else if (hilliness == Hilliness.Mountainous)
     {
         return(0.05f);
     }
     else
     {
         return(0.05f);
     }
 }
コード例 #11
0
        private static int CostFromTileHilliness(Hilliness hilliness)
        {
            switch (hilliness)
            {
            case Hilliness.Flat:
                return(0);

            case Hilliness.SmallHills:
                return(2000);

            case Hilliness.LargeHills:
                return(6000);

            case Hilliness.Mountainous:
                return(30000);

            case Hilliness.Impassable:
                return(30000);

            default:
                return(0);
            }
        }
コード例 #12
0
        private static IEnumerable<KeyValuePair<int, int>> GetSpeedToWaggonsValues(Train train,
            int numLocomotives,
                                                                                   Waggon waggon,
                                                                                   int cargoFactor,
                                                                                   int slopePercentage,
                                                                                   Hilliness selectedHilliness,
                                                                                   int tilesBetweenSlopes,
                                                                                   bool useStaticFriction)
        {
            // Create speed values from 0 to 200 km/h in 5 km/h steps.
            IEnumerable<int> speedValues = Enumerable.Range(0, 42).Select(value => value * 5).ToList();

            // Compute waggon weight based on cargo factor
            int waggonMass = waggon.MassEmpty + (waggon.MassFull - waggon.MassEmpty) * cargoFactor;

            // Calculate the tractive effort at each speed step and cap at TE max.
            IEnumerable<int> numWaggonsPerSpeed = speedValues.Select(
                speed =>
                {
                    var tractiveEffort = (int)((train.Power * numLocomotives) / (speed / 3.6));
                    tractiveEffort = ((speed > train.MaxSpeed) || (speed > waggon.MaxSpeed)) ? 0 : tractiveEffort;
                    tractiveEffort = Math.Min((train.MaxTractiveEffort * numLocomotives), tractiveEffort);
                    tractiveEffort = (speed == 0 ? (train.MaxTractiveEffort * numLocomotives) : tractiveEffort);

                    double tonnage = (tractiveEffort * 1000.0) / (useStaticFriction ? 27.0 : 17.0);
                    tonnage = Math.Max(0.0, tonnage - (train.Mass * numLocomotives));

                    var maxNumWaggons = (int)(tonnage / waggonMass);

                    IEnumerable<int> numberOfWaggons = Enumerable.Range(0, maxNumWaggons + 1);

                    IEnumerable<KeyValuePair<int, double>> numWaggonsToTeValue = numberOfWaggons.Select(
                        numWaggons =>
                        {
                            double numWaggonsOnSlope = 0;

                            switch (selectedHilliness)
                            {
                                case Hilliness.OneSlope:
                                {
                                    numWaggonsOnSlope = Math.Min(numWaggons, 1.0 / waggon.Length);
                                }
                                    break;

                                case Hilliness.MultipleSlopes:
                                {
                                    double trainTileLength = numWaggons * waggon.Length;
                                    double tilesWithWaggons = Math.Ceiling(trainTileLength / (tilesBetweenSlopes + 1));

                                    numWaggonsOnSlope = Math.Min(numWaggons, tilesWithWaggons / waggon.Length);
                                }
                                    break;
                            }

                            // 1/10 is Short for 9.81 / 100. It just works and is very close to the correct
                            // trigonometry based values for small slope percentages.
                            double teSlopeResistance = (numWaggonsOnSlope * waggonMass * slopePercentage) / 10.0;

                            // Compute rolling resistance efforts
                            double trainTonnage = (numWaggons * waggonMass + (train.Mass * numLocomotives));

                            double teRollingRestistance = (trainTonnage * (useStaticFriction ? 27.0 : 17.0)) / 1000.0;

                            double teTotal = (teSlopeResistance + teRollingRestistance);

                            return new KeyValuePair<int, double>(numWaggons, teTotal);
                        });

                    int numPossibleWaggons = numWaggonsToTeValue.LastOrDefault(pair => pair.Value <= tractiveEffort).Key;

                    return numPossibleWaggons;
                });

            return speedValues.Zip(
                numWaggonsPerSpeed,
                (speed, numWaggons) => new KeyValuePair<int, int>(speed, numWaggons));
        }
コード例 #13
0
ファイル: InGameEditor.cs プロジェクト: SwimUp/worldedit
        public override void DoWindowContents(Rect inRect)
        {
            Text.Font = GameFont.Small;

            WidgetRow row = new WidgetRow(0, 0, UIDirection.RightThenDown, 580);

            if (row.ButtonText(Translator.Translate("UpdateAllTiles"), Translator.Translate("UpdateAllTilesInfo")))
            {
                WorldUpdater.UpdateMap();
            }
            if (row.ButtonText(Translator.Translate("UpdateCustomLayer"), Translator.Translate("UpdateCustomLayerInfo")))
            {
                layersWindow.Show();
            }
            if (updateImmediately)
            {
                if (row.ButtonText(Translator.Translate("UpdateImmediatelyON"), Translator.Translate("UpdateImmediatelyInfo")))
                {
                    updateImmediately = false;
                }
            }
            else
            {
                if (row.ButtonText(Translator.Translate("UpdateImmediatelyOFF"), Translator.Translate("UpdateImmediatelyInfo")))
                {
                    updateImmediately = true;
                }
            }
            if (row.ButtonText(Translator.Translate("Utilities")))
            {
                Find.WindowStack.Add(new UtilsMenu());
            }
            if (row.ButtonText(Translator.Translate("SaveWorldTemplate")))
            {
                Find.WindowStack.Add(new WorldTemplateManager());
            }

            int  size               = 900;
            Rect mainScrollRect     = new Rect(0, 25, 600, 600);
            Rect mainScrollVertRect = new Rect(0, 0, mainScrollRect.x, size);

            Widgets.BeginScrollView(mainScrollRect, ref mainScrollPosition, mainScrollVertRect);

            Rect group1 = new Rect(0, 20, inRect.width / 2, size);

            GUI.BeginGroup(group1);
            Widgets.Label(new Rect(0, 5, 50, 20), Translator.Translate("Biome"));
            int   biomeDefSize   = avaliableBiomes.Count * 25;
            float group1Height   = inRect.height - 360;
            Rect  scrollRect     = new Rect(0, 25, 250, group1Height);
            Rect  scrollVertRect = new Rect(0, 0, scrollRect.x, biomeDefSize);

            Widgets.BeginScrollView(scrollRect, ref scrollPosition, scrollVertRect);
            int yButtonPos = 5;

            Text.Font = GameFont.Small;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 230, 20), Translator.Translate("NoText")))
            {
                selectedBiome = null;
                Messages.Message($"Biome: none", MessageTypeDefOf.NeutralEvent, false);
            }
            yButtonPos += 25;
            foreach (BiomeDef def in avaliableBiomes)
            {
                if (Widgets.ButtonText(new Rect(0, yButtonPos, 230, 20), def.label))
                {
                    selectedBiome = def;
                    Messages.Message($"Biome: {selectedBiome.defName}", MessageTypeDefOf.NeutralEvent, false);
                }
                yButtonPos += 22;
            }
            Widgets.EndScrollView();

            yButtonPos = 265;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("ClearAllHillnses")))
            {
                ClearAllHillnes();
            }

            yButtonPos = 290;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("SetTileToAllMap")))
            {
                SetBiomeToAllTiles();
            }
            yButtonPos = 315;
            if (Widgets.RadioButtonLabeled(new Rect(0, yButtonPos, 250, 20), Translator.Translate("SenOceanToo"), setOceanToo))
            {
                setOceanToo = !setOceanToo;
            }

            yButtonPos = 340;
            foreach (Hilliness hillnes in Enum.GetValues(typeof(Hilliness)))
            {
                if (Widgets.RadioButtonLabeled(new Rect(0, yButtonPos, 250, 20), hillnes.ToString(), hillnes == selectedHillness))
                {
                    selectedHillness = hillnes;
                }
                yButtonPos += 20;
            }
            yButtonPos += 10;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("SetHillnesToAllMap")))
            {
                SetHillnesToAllMap();
            }
            yButtonPos += 30;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("SetHillnesToAllBiome")))
            {
                SetHillnesToAllBiome();
            }

            GUI.EndGroup();

            float group2Width = 270;
            Rect  group2      = new Rect(group2Width, 20, inRect.width / 2, inRect.height);

            GUI.BeginGroup(group2);
            yButtonPos = 25;
            if (Widgets.RadioButtonLabeled(new Rect(0, yButtonPos, 250, 20), $"{Translator.Translate("BrushEnable")} - {brushRadius.max}", brushEnabled))
            {
                brushEnabled = !brushEnabled;
            }
            yButtonPos += 25;
            Widgets.IntRange(new Rect(0, yButtonPos, 250, 20), 3424354, ref brushRadius, 0, 3, Translator.Translate("BrushSettings"));
            yButtonPos += 50;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("TemperatureMenuTitle")))
            {
                Find.WindowStack.Add(new TileParametersMenu(this));
            }
            yButtonPos += 50;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("FactionEditor")))
            {
                factionEditor.Show();
            }
            Widgets.Label(new Rect(255, yButtonPos, 35, 20), $"{Settings.FactionHotKey}");

            yButtonPos += 25;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("FactionDiagramm")))
            {
                Find.WindowStack.Add(new Dialog_FactionDuringLanding());
            }

            yButtonPos += 35;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("RoadAndRiverEditor")))
            {
                Find.WindowStack.Add(new RoadAndRiversEditor());
            }
            Widgets.Label(new Rect(255, yButtonPos, 35, 20), $"{Settings.RiversAndRoadsHotKey}");

            yButtonPos += 35;
            if (Widgets.ButtonText(new Rect(0, yButtonPos, 250, 20), Translator.Translate("WorldFeaturesEditor")))
            {
                worldObjectsEditor.Show();
            }
            Widgets.Label(new Rect(255, yButtonPos, 35, 20), $"{Settings.WorldObjectHotKey}");

            GUI.EndGroup();

            Widgets.EndScrollView();
        }
コード例 #14
0
 public static string GetLabelCap(this Hilliness h)
 {
     return(h.GetLabel().CapitalizeFirst());
 }
コード例 #15
0
        private static IEnumerable<KeyValuePair<int, int>> GetWaggonsToSpeedValues(Train train,
            int numLocomotives,
                                                                                   Waggon waggon,
                                                                                   int cargoFactor,
                                                                                   int slopePercentage,
                                                                                   Hilliness selectedHilliness,
                                                                                   int tilesBetweenSlopes,
                                                                                   bool useStaticFriction)
        {
            // Create waggon numbers from 1 to 19.
            IEnumerable<int> waggonNumbers = Enumerable.Range(1, 19).ToList();

            // Compute waggon weight based on cargo factor
            int waggonMass = waggon.MassEmpty + (waggon.MassFull - waggon.MassEmpty) * cargoFactor;

            // Compute total tonnages.
            IEnumerable<double> tonnages =
                waggonNumbers.Select(numWaggons => (double)(numWaggons * waggonMass) + (train.Mass * numLocomotives));

            // Compute rolling resistance efforts
            IEnumerable<double> tractiveEfforts =
                tonnages.Select(tonnage => (tonnage * (useStaticFriction ? 27.0 : 17.0)) / 1000.0);

            // Compute slope resistance efforts
            IEnumerable<double> slopeTractiveEfforts = waggonNumbers.Select(
                numWaggons =>
                {
                    double numWaggonsOnSlope = 0;

                    switch (selectedHilliness)
                    {
                        case Hilliness.OneSlope:
                        {
                            numWaggonsOnSlope = Math.Min(numWaggons, 1.0 / waggon.Length);
                        }
                            break;

                        case Hilliness.MultipleSlopes:
                        {
                            double trainTileLength = numWaggons * waggon.Length;
                            double tilesWithWaggons = Math.Ceiling(trainTileLength / (tilesBetweenSlopes + 1));

                            numWaggonsOnSlope = Math.Min(numWaggons, tilesWithWaggons / waggon.Length);
                        }
                            break;
                    }

                    // 1/10 is Short for 9.81 / 100. It just works and is very close to the correct
                    // trigonometry based values for small slope percentages.
                    double teSlopeResistance = (numWaggonsOnSlope * waggonMass * slopePercentage) / 10.0;

                    return teSlopeResistance;
                });

            // Compute total tractive efforts
            IEnumerable<double> totalTractiveEfforts = tractiveEfforts.Zip(
                slopeTractiveEfforts,
                (resistanceTe, slopeTe) => resistanceTe + slopeTe);

            // Compute the speed for each tonnage.
            IEnumerable<double> speeds =
                totalTractiveEfforts.Select(
                    tractiveEffort => (tractiveEffort > (train.MaxTractiveEffort * numLocomotives)) ? 0 : ((train.Power * numLocomotives) / tractiveEffort));

            // Convert to km/h.
            speeds = speeds.Select(speed => (speed * 3.6));

            // Cap at max speed.
            int maxSpeed = Math.Min(train.MaxSpeed, waggon.MaxSpeed);

            speeds = speeds.Select(speed => Math.Min(maxSpeed, speed));

            // Zip them together.
            IEnumerable<KeyValuePair<int, int>> values = waggonNumbers.Zip(
                speeds,
                (numWaggons, speed) => new KeyValuePair<int, int>(numWaggons, (int)speed));

            return values;
        }
コード例 #16
0
        private static IEnumerable <KeyValuePair <int, int> > GetWaggonsToSpeedValues(Train train,
                                                                                      int numLocomotives,
                                                                                      Waggon waggon,
                                                                                      int cargoFactor,
                                                                                      int slopePercentage,
                                                                                      Hilliness selectedHilliness,
                                                                                      int tilesBetweenSlopes,
                                                                                      bool useStaticFriction)
        {
            // Create waggon numbers from 1 to 19.
            IEnumerable <int> waggonNumbers = Enumerable.Range(1, 19).ToList();

            // Compute waggon weight based on cargo factor
            int waggonMass = waggon.MassEmpty + (waggon.MassFull - waggon.MassEmpty) * cargoFactor;

            // Compute total tonnages.
            IEnumerable <double> tonnages =
                waggonNumbers.Select(numWaggons => (double)(numWaggons * waggonMass) + (train.Mass * numLocomotives));

            // Compute rolling resistance efforts
            IEnumerable <double> tractiveEfforts =
                tonnages.Select(tonnage => (tonnage * (useStaticFriction ? 27.0 : 17.0)) / 1000.0);

            // Compute slope resistance efforts
            IEnumerable <double> slopeTractiveEfforts = waggonNumbers.Select(
                numWaggons =>
            {
                double numWaggonsOnSlope = 0;

                switch (selectedHilliness)
                {
                case Hilliness.OneSlope:
                    {
                        numWaggonsOnSlope = Math.Min(numWaggons, 1.0 / waggon.Length);
                    }
                    break;

                case Hilliness.MultipleSlopes:
                    {
                        double trainTileLength  = numWaggons * waggon.Length;
                        double tilesWithWaggons = Math.Ceiling(trainTileLength / (tilesBetweenSlopes + 1));

                        numWaggonsOnSlope = Math.Min(numWaggons, tilesWithWaggons / waggon.Length);
                    }
                    break;
                }

                // 1/10 is Short for 9.81 / 100. It just works and is very close to the correct
                // trigonometry based values for small slope percentages.
                double teSlopeResistance = (numWaggonsOnSlope * waggonMass * slopePercentage) / 10.0;

                return(teSlopeResistance);
            });

            // Compute total tractive efforts
            IEnumerable <double> totalTractiveEfforts = tractiveEfforts.Zip(
                slopeTractiveEfforts,
                (resistanceTe, slopeTe) => resistanceTe + slopeTe);

            // Compute the speed for each tonnage.
            IEnumerable <double> speeds =
                totalTractiveEfforts.Select(
                    tractiveEffort => (tractiveEffort > (train.MaxTractiveEffort * numLocomotives)) ? 0 : ((train.Power * numLocomotives) / tractiveEffort));

            // Convert to km/h.
            speeds = speeds.Select(speed => (speed * 3.6));

            // Cap at max speed.
            int maxSpeed = Math.Min(train.MaxSpeed, waggon.MaxSpeed);

            speeds = speeds.Select(speed => Math.Min(maxSpeed, speed));

            // Zip them together.
            IEnumerable <KeyValuePair <int, int> > values = waggonNumbers.Zip(
                speeds,
                (numWaggons, speed) => new KeyValuePair <int, int>(numWaggons, (int)speed));

            return(values);
        }
コード例 #17
0
        private static IEnumerable <KeyValuePair <int, int> > GetSpeedToWaggonsValues(Train train,
                                                                                      int numLocomotives,
                                                                                      Waggon waggon,
                                                                                      int cargoFactor,
                                                                                      int slopePercentage,
                                                                                      Hilliness selectedHilliness,
                                                                                      int tilesBetweenSlopes,
                                                                                      bool useStaticFriction)
        {
            // Create speed values from 0 to 200 km/h in 5 km/h steps.
            IEnumerable <int> speedValues = Enumerable.Range(0, 42).Select(value => value * 5).ToList();

            // Compute waggon weight based on cargo factor
            int waggonMass = waggon.MassEmpty + (waggon.MassFull - waggon.MassEmpty) * cargoFactor;

            // Calculate the tractive effort at each speed step and cap at TE max.
            IEnumerable <int> numWaggonsPerSpeed = speedValues.Select(
                speed =>
            {
                var tractiveEffort = (int)((train.Power * numLocomotives) / (speed / 3.6));
                tractiveEffort     = ((speed > train.MaxSpeed) || (speed > waggon.MaxSpeed)) ? 0 : tractiveEffort;
                tractiveEffort     = Math.Min((train.MaxTractiveEffort * numLocomotives), tractiveEffort);
                tractiveEffort     = (speed == 0 ? (train.MaxTractiveEffort * numLocomotives) : tractiveEffort);

                double tonnage = (tractiveEffort * 1000.0) / (useStaticFriction ? 27.0 : 17.0);
                tonnage        = Math.Max(0.0, tonnage - (train.Mass * numLocomotives));

                var maxNumWaggons = (int)(tonnage / waggonMass);

                IEnumerable <int> numberOfWaggons = Enumerable.Range(0, maxNumWaggons + 1);

                IEnumerable <KeyValuePair <int, double> > numWaggonsToTeValue = numberOfWaggons.Select(
                    numWaggons =>
                {
                    double numWaggonsOnSlope = 0;

                    switch (selectedHilliness)
                    {
                    case Hilliness.OneSlope:
                        {
                            numWaggonsOnSlope = Math.Min(numWaggons, 1.0 / waggon.Length);
                        }
                        break;

                    case Hilliness.MultipleSlopes:
                        {
                            double trainTileLength  = numWaggons * waggon.Length;
                            double tilesWithWaggons = Math.Ceiling(trainTileLength / (tilesBetweenSlopes + 1));

                            numWaggonsOnSlope = Math.Min(numWaggons, tilesWithWaggons / waggon.Length);
                        }
                        break;
                    }

                    // 1/10 is Short for 9.81 / 100. It just works and is very close to the correct
                    // trigonometry based values for small slope percentages.
                    double teSlopeResistance = (numWaggonsOnSlope * waggonMass * slopePercentage) / 10.0;

                    // Compute rolling resistance efforts
                    double trainTonnage = (numWaggons * waggonMass + (train.Mass * numLocomotives));

                    double teRollingRestistance = (trainTonnage * (useStaticFriction ? 27.0 : 17.0)) / 1000.0;

                    double teTotal = (teSlopeResistance + teRollingRestistance);

                    return(new KeyValuePair <int, double>(numWaggons, teTotal));
                });

                int numPossibleWaggons = numWaggonsToTeValue.LastOrDefault(pair => pair.Value <= tractiveEffort).Key;

                return(numPossibleWaggons);
            });

            return(speedValues.Zip(
                       numWaggonsPerSpeed,
                       (speed, numWaggons) => new KeyValuePair <int, int>(speed, numWaggons)));
        }