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); }
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; } }