private static double CalculateSolutionValue(List <List <int> > solution)
        {
            //double cashEarned = 0;
            //foreach(List<int> contractsIDs in solution)
            //{
            //    foreach(int contractID in contractsIDs)
            //    {
            //        foreach(City city in World.Cities)
            //        {
            //            DelieveryContract contract = city.GetDelieveryContractByID(contractID);
            //            if(contract != null)
            //            {
            //                cashEarned += contract.Payment;
            //            }
            //        }
            //    }
            //}

            Locomotive.EvalCash(SolutionType.New);
            //Console.WriteLine("\n\tThis solution value is: " + Locomotive.NewCash);

            return(Locomotive.NewCash);
        }
        private static List <List <int> > GenerateNextContractSet(List <List <int> > contractSet, List <int> cityRoute)
        {
            List <List <int> > newContractsSet = new List <List <int> >(contractSet);

            Locomotive.NewFlowingStatusList      = new List <Status>(Locomotive.BetterFlowingStatusList);
            Locomotive.NewFlowingContractsList   = new List <List <DelieveryContract> >(Locomotive.BetterFlowingContractsList);
            Locomotive.NewCompleatedContractsIDs = new List <int>();

            #region Removing Contracts

            foreach (List <int> contractsList in newContractsSet) // we decide if we want ro remove any currently taken contracts
            {
                if (contractsList.Count < 1)
                {
                    continue;
                }                                                                           // checking if any contracts are available

                int contractToRemoveIndex = _random.Next(0, (contractsList.Count - 1) * 2); // we decide if we want to remove anything
                // and if yes then what is the index of it
                if (contractToRemoveIndex > contractsList.Count - 1)
                {
                    continue;
                }

                foreach (List <DelieveryContract> contracts in Locomotive.NewFlowingContractsList)
                {
                    contracts.RemoveAll(contract => contract.ID == contractsList[contractToRemoveIndex]);
                }                                                             // wywalamy z flowing lista
                Locomotive.NewCompleatedContractsIDs.RemoveAll(id => id == contractsList[contractToRemoveIndex]);
                contractsList.Remove(contractsList[contractToRemoveIndex]);   // we remove chosen element
                Locomotive.EvalStatusList();
            }

            #endregion

            #region Adding Contracts

            List <DelieveryContract> possibleContracts = new List <DelieveryContract>();

            for (int currentCityIndex = 0; currentCityIndex < cityRoute.LastIndex(); currentCityIndex++) // przechodzimy przez wszystkie miasta w wektorze
            {
                Locomotive.CompleateContractsInCityIndex(cityIndex: currentCityIndex, cityID: cityRoute[currentCityIndex]);

                #region Finding possible contracts

                possibleContracts = new List <DelieveryContract>();

                foreach (DelieveryContract contract in World.GetCityByID(cityRoute[currentCityIndex]).DelieveryContracts) // przechodzimy przez wszystkie kontrakty w każdym mieście
                {
                    //if(newContractsSet[currentCityIndex].Count < 1) { continue; } // this might speed up algorithm by a bit

                    if (newContractsSet[currentCityIndex].Exists(id => id == contract.ID) == false &&                                        // sprawdzamy czy kontrakt jest już podpisany w rozwiązaniu
                        Locomotive.NewFlowingContractsList.Exists(cityIndex => cityIndex.Exists(cont => cont.ID == contract.ID)) == false && // sprawdzamy czy kontrakt jest już podpisany w flowing contracts list
                        cityRoute.FindIndex(cityId => cityId == contract.TargetCityID) > currentCityIndex                                    // sprawdzamy czy dotrzemy do celu tego kontraktu jeszcze kiedyś
                        )
                    {
                        possibleContracts.Add(contract); // jeśli nie jest już na liście i będziemy w kolejnych krokach przejeżdżali przez target city to dodajemy do listy potencalnych kontraktów
                    }
                }

                #endregion

                if (possibleContracts.Count < 1)
                {
                    continue;
                }                                                                                                                                                     // checking if there is at least one contract to sign in list of potential contracts

                int contractToAddIndex = _random.Next(0, possibleContracts.Count - 1);                                                                                // randomly choosing contract to add from the list of available ones

                if (Locomotive.MaxWeight >= (Locomotive.NewFlowingStatusList[currentCityIndex].Weight + possibleContracts[contractToAddIndex].TotalWeight) &&         // we check if we wont exceed the max weight!
                    Locomotive.MaxWaggonCount >= (Locomotive.NewFlowingStatusList[currentCityIndex].WaggonCount + possibleContracts[contractToAddIndex].WaggonCount)) // we check if we wont exceed the max waggon count :)
                {
                    newContractsSet[currentCityIndex].Add(possibleContracts[contractToAddIndex].ID);
                    Locomotive.SignContract(possibleContracts[contractToAddIndex], currentCityIndex);
                    //Locomotive.ShowFlowingContractsList();
                }
                //Locomotive.ShowFlowingContractsList();
                Locomotive.MoveContractsForward(currentCityIndex);
                Locomotive.EvalStatusList();
            }
            Locomotive.CompleateContractsInCityIndex(cityIndex: cityRoute.LastIndex(), cityID: cityRoute.Last()); // we complete contracts in last city
            Locomotive.EvalStatusList();
            //Locomotive.ShowFlowingContractsList();

            #endregion

            return(newContractsSet);
        }
        private static List <List <int> > GenerateTemplateContractSet(List <int> cityRoute)
        {
            #region Reseting lists

            List <List <int> > templateContractSet = new List <List <int> >();

            Locomotive.NewCompleatedContractsIDs = new List <int>();
            Locomotive.NewFlowingContractsList   = new List <List <DelieveryContract> >();
            Locomotive.NewFlowingStatusList      = new List <Status>();

            for (int i = 0; i <= MaxCityVisited; i++)
            {
                Locomotive.NewFlowingContractsList.Add(new List <DelieveryContract>());
                Locomotive.NewFlowingStatusList.Add(new Status(0, 0));
            }

            #endregion

            #region Adding Contracts

            // generating lists of contracts that will be signed up in each city
            for (int currentCityIndex = 0; currentCityIndex < cityRoute.LastIndex(); currentCityIndex++)   // iterating through cities in current city route
            {
                templateContractSet.Add(new List <int>());

                Locomotive.CompleateContractsInCityIndex(cityIndex: currentCityIndex, cityID: cityRoute[currentCityIndex]); // compleating contracts

                #region Finding contracts that are possible to realize

                City currentCity = World.GetCityByID(cityRoute[currentCityIndex]);  // current city
                List <DelieveryContract> possibleContracts = new List <DelieveryContract>();

                foreach (DelieveryContract contract in currentCity.DelieveryContracts)  // iterating through the contracts of each city in current route
                {
                    if (cityRoute.
                        GetRange(currentCityIndex + 1, cityRoute.Count - currentCityIndex - 1). //todo I feel like it might go out of bounds, but it does not >:[
                        Exists(cityID => cityID == contract.TargetCityID))                      // generating the list of contracts that have their target city futher in the cities to visit list
                    {
                        possibleContracts.Add(contract);
                    }
                }

                #endregion

                #region Adding conntracts to Lists

                int maxContractsWeWantToAdd = _random.Next(0, possibleContracts.Count); // we decide for the max number of contracts we want to add
                for (int i = 0; i < maxContractsWeWantToAdd; i++)                       // and here we try to add contracts //todo need to add bounds with max weight and max waggon count
                {
                    if (possibleContracts.Count > 0)
                    {
                        int chosenContractIndex = _random.Next(0, possibleContracts.Count - 1);                                                                                  // randomly choosing contract from available ones

                        if (Locomotive.BetterFlowingContractsList.Exists(hop => hop.Exists(contract => contract.ID == possibleContracts[chosenContractIndex].ID)) == false &&    // we check if we havent taken that contract already
                            Locomotive.MaxWeight >= (Locomotive.BetterFlowingStatusList[currentCityIndex].Weight + possibleContracts[chosenContractIndex].TotalWeight) &&        // we check if we wont exceed the max weight!
                            Locomotive.MaxWaggonCount >= (Locomotive.BetterFlowingStatusList[currentCityIndex].WaggonCount + possibleContracts[chosenContractIndex].WaggonCount) // we check if we wont exceed the max waggon count :)
                            )                                                                                                                                                    // checking the bounds, if the contract we possibly want to add meets the requirements
                        {
                            Locomotive.SignContract(possibleContracts[chosenContractIndex], currentCityIndex);                                                                   // adding contracts to list of contracts we take

                            templateContractSet[currentCityIndex].Add(possibleContracts[chosenContractIndex].ID);                                                                // adding contracts to list of contracts we take in station
                            possibleContracts.Remove(possibleContracts[chosenContractIndex]);                                                                                    // removing from possibleContracts so we wont try to add the same contract twice
                        }
                    }
                }

                #endregion

                Locomotive.BetterCompleatedContractsIDs = new List <int>(Locomotive.NewCompleatedContractsIDs);
                Locomotive.BetterFlowingContractsList   = new List <List <DelieveryContract> >(Locomotive.NewFlowingContractsList);
                Locomotive.BetterFlowingStatusList      = new List <Status>(Locomotive.NewFlowingStatusList);

                //Locomotive.ShowFlowingContractsList();
                Locomotive.MoveContractsForward(currentCityIndex);
                Locomotive.EvalStatusList();
            }

            #endregion

            Locomotive.CompleateContractsInCityIndex(cityIndex: cityRoute.LastIndex(), cityID: cityRoute.Last()); // we complete contracts in last city
            Locomotive.EvalStatusList();
            //Locomotive.ShowFlowingContractsList();

            return(templateContractSet);
        }