public RequiredProductFlattenerResponse GetFlattenedInventory(RequiredProductFlattenerRequest requiredProductFlattenerRequest)
 {
     _productTypes = requiredProductFlattenerRequest.ProductTypes;
     _cityStorage = requiredProductFlattenerRequest.CityStorage == null ? new CityStorage
     {
         CurrentInventory = new Product[0]
     } : requiredProductFlattenerRequest.CityStorage.Clone();
     //            var flattenedList = RequiredProductFlattenerRequest.Products.SelectMany(upgrade => GetFlattenedInventory(upgrade.Products)).ToArray();
     var flattenedList = GetFlattenedInventory(requiredProductFlattenerRequest.Products);
     return new RequiredProductFlattenerResponse
     {
         Products = flattenedList
     };
 }
        private static int? GetQuantityToManufacture(Product item, CityStorage storage)
        {
            var storageProduct = storage.CurrentInventory.FirstOrDefault(x => x.ProductTypeId == item.ProductTypeId);
            if (storageProduct == null)
                return item.Quantity;
            var newStorage = storageProduct.Quantity - item.Quantity;
            if (newStorage <= 0)
            {
                storageProduct.Quantity = 0;
                return -1 * newStorage;

            }
            storageProduct.Quantity = newStorage;
            return 0;
        }
 private void SubtractChildProductsFromCityStorage(ICollection<Domain.Product> requiredProducts, CityStorage cityStorage)
 {
     foreach (var prd in requiredProducts)
     {
         var cityStorageProduct =
             cityStorage.CurrentInventory.FirstOrDefault(x => x.ProductTypeId == prd.ProductTypeId);
         if (cityStorageProduct == null)
             continue;
         cityStorageProduct.Quantity -= prd.Quantity;
         if (cityStorageProduct.Quantity < 0)
             cityStorageProduct.Quantity = 0;
         var requiredProductType = _productTypes.FirstOrDefault(x => x.Id == prd.ProductTypeId);
         if (requiredProductType == null ||  requiredProductType.RequiredProducts == null)
             continue;
     //                SubtractChildProductsFromCityStorage(requiredProductType.RequiredProducts, cityStorage);
     }
 }
 private void AddTopLevelProductToCityStorage(Product updateProduct, CityStorage cityStorage)
 {
     if (updateProduct.Quantity == 0)
         return;
     var prodType = _productTypes.FirstOrDefault(x => x.Id == updateProduct.ProductTypeId);
     var currentCityStorageProduct =
         cityStorage.CurrentInventory.FirstOrDefault(x => x.ProductTypeId == updateProduct.ProductTypeId);
     if (currentCityStorageProduct == null)
         return;
     //Add top level amount
     currentCityStorageProduct.Quantity += updateProduct.Quantity;
     if (prodType == null)
         return;
     //now subtract the required products it took to create the top level product.
     for (int i = 0; i < updateProduct.Quantity; i++)
     {
         SubtractChildProductsFromCityStorage(prodType.RequiredProducts, cityStorage);
     }
 }
 private List<Product> GetAvailableStorageList(CityStorage cityStorage, IEnumerable<Product> combinedProductList)
 {
     var ret = new List<Product>();
     foreach (var item in cityStorage.CurrentInventory)
     {
         var availableProduct = item.Clone();
         if (availableProduct.Quantity > 0)
         {
             // ReSharper disable once PossibleMultipleEnumeration
             var requireProduct = combinedProductList.FirstOrDefault(x => x.ProductTypeId == item.ProductTypeId);
             if (requireProduct != null)
             {
                 availableProduct.Quantity = availableProduct.Quantity - requireProduct.Quantity;
                 if (availableProduct.Quantity < 0) availableProduct.Quantity = 0;
             }
         }
         if (availableProduct.Quantity > 0)
             ret.Add(availableProduct);
     }
     return ret;
 }
        /// <summary>
        /// Recurses through required products and calculates the total time required to produce the product 
        ///     based on product type duration and quanity of child products required. If city storage  
        ///     is specified then the amount in storage is subrtacted from the total durations and the
        ///     quantity of items in storage is decremented to reflect the use of the required products. 
        /// </summary>
        /// <param name="productType"></param>
        /// <param name="typesAlreadyAdded"></param>
        /// <param name="includeRequiredTypes"></param>
        /// <param name="cityStorage">If included then duration is decreased by what's in storage.</param>
        /// <param name="productsToUpdate"></param>
        /// <returns></returns>
        private int CalculateInventoryItemDurationByType(ProductType productType, ICollection<int> typesAlreadyAdded, bool includeRequiredTypes, CityStorage cityStorage, Product[] productsToUpdate)
        {
            // if we have one in storage then we consider the duration already having been elapsed.
            var cityStorageSpecified = cityStorage != null;
            var cityStorageDecremented = DecrementCityStorageByProductType(productType, cityStorage);
            if (cityStorageDecremented)
                return 0;

            var productTypeTotalDuration = CalculateTimeToManufacture(productType, typesAlreadyAdded);

            if (!includeRequiredTypes)
                return productTypeTotalDuration;

            foreach (var prod in productsToUpdate)
            {
                var productTotalDuration = 0;

                //product types should always have any product type.
                var requiredProductType = _productTypes.First(x => x.Id == prod.ProductTypeId);
                if (prod.RequiredProducts == null)
                    prod.RequiredProducts = requiredProductType.RequiredProducts.Select(x => x.Clone()).ToArray();
                for (var a = 0; a < prod.Quantity; a++)
                {
                    productTotalDuration += CalculateInventoryItemDurationByType(requiredProductType, typesAlreadyAdded, true, cityStorage, prod.RequiredProducts);
                }

                //if city storage is not null then set remaining time
                if (cityStorageSpecified)
                {
                    if (!prod.RemainingDuration.HasValue)
                        prod.RemainingDuration = 0;
                    prod.RemainingDuration += productTotalDuration;
                }
                else
                {
                    if (!prod.TotalDuration.HasValue)
                        prod.TotalDuration = 0;
                    prod.TotalDuration += productTotalDuration;
                }
                productTypeTotalDuration += productTotalDuration;

            }
            return productTypeTotalDuration;
        }
        /// <summary>
        /// Calculates the specified products duration based on the product types duration and quantity. 
        /// </summary>
        /// <param name="item"></param>
        /// <param name="parallelTypesAlreadyAdded"></param>
        /// <param name="includeRequiredProducts"></param>
        /// <param name="cityStorage"></param>
        /// <returns></returns>
        private int CalculateInventoryItemDuration(Product item, ICollection<int> parallelTypesAlreadyAdded, bool includeRequiredProducts, CityStorage cityStorage)
        {
            if (item.Quantity < 1)
                return 0;
            var productType = GetProductType(item);
            if (productType == null)
                return 0;

            var duration = 0;
            var quantity = item.Quantity.HasValue ? item.Quantity.Value < 0 ? 0 : item.Quantity.Value : 0;
            if (item.RequiredProducts == null)
                item.RequiredProducts = productType.RequiredProducts.Select(x => x.Clone()).ToArray();
            for (var a = 0; a < quantity; a++)
            {
                duration += CalculateInventoryItemDurationByType(productType, parallelTypesAlreadyAdded, includeRequiredProducts, cityStorage, item.RequiredProducts);
            }

            if (cityStorage == null)
            {
                item.TotalDuration += duration;
            }
            else
            {
                item.RemainingDuration += duration;
            }
            return duration;
        }
        private static bool DecrementCityStorageByProductType(ProductType productType, CityStorage cityStorage)
        {
            if (cityStorage==null) return false;
            var storageProduct = cityStorage.CurrentInventory.FirstOrDefault(x => x.ProductTypeId == productType.Id);
            if (storageProduct == null || storageProduct.Quantity <= 0) return false;

            storageProduct.Quantity -= 1;
            return true;
        }
 private List<Product> GetRequiredInStorageList(CityStorage cityStorage, IEnumerable<Product> combinedProductList)
 {
     var ret = new List<Product>();
     foreach (var product in combinedProductList)
     {
         var storedProduct = cityStorage.CurrentInventory.FirstOrDefault(x => x.ProductTypeId == product.ProductTypeId);
         if (storedProduct != null && storedProduct.Quantity >= product.Quantity)
         {
             ret.Add(product);
         }
     }
     return ret;
 }
 private RequiredProductFlattenerResponse GetFlattenedProductRequirementList(BuildingUpgradeProductConsoldatorRequest request, CityStorage cityStorage)
 {
     var inventoryFlattenerRequest = new RequiredProductFlattenerRequest
     {
         Products = request.BuildingUpgrades.Where(x=>x.CalculateInBuildingUpgrades).SelectMany(x=>x.Products).ToArray(),
         ProductTypes = _productTypes,
         CityStorage = cityStorage
     };
     return _requiredProductFlattener.GetFlattenedInventory(inventoryFlattenerRequest);
 }
Example #11
0
 private void UpdateCityStorage(CityStorage currentCityStorage)
 {
     var reporequest = new RepositoryRequest<Product>
     {
         Expression = GetCityStorageExpression()
     };
     var storageProductsResponse = _cityUpdateUnitOfWork
                                                 .ProductRepository
                                                 .Get(reporequest);
     foreach (var product in currentCityStorage.CurrentInventory)
     {
         var cityStorageProduct = storageProductsResponse
                                     .FirstOrDefault(x=>x.ProductTypeId == product.ProductTypeId);
         if (cityStorageProduct == null)
         {
             cityStorageProduct = new Product
             {
                 // ReSharper disable once PossibleInvalidOperationException
                 ProductTypeId = product.ProductTypeId.Value,
                 IsCityStorage = true
             };
             _cityUpdateUnitOfWork.ProductRepository.Add(cityStorageProduct);
         }
         cityStorageProduct.Quantity = product.Quantity ?? 0;
     }
 }