/** * Calculate the maximal factor for a ware that can be produced based on avalable material. * @param storage from which to take the required ware * @param requiredWare that's availability is to be checked * @param producableWare output product * @return factor that has to be applied to the maximal producable amount. */ @VisibleForTesting double calculateProducableAmountFactor(ProductionStorage storage, IWare requiredWare, IWare producableWare) { double stored = storage.getStored(requiredWare); double requiredForFullProduction = productionChain.getRequiredAmount(producableWare, requiredWare) * ONE_DAY_OF_WEEK; return Math.min(1.0, stored / requiredForFullProduction); } }
/** * Calculate the cost of wares that are consumed in one days production. * The ware is removed from storage in the process. * @param producedWare the ware that is produced. * @param storage where the ware is stored. * @param requiredWareFactor adjustment factor considering, that there may not be a full production due to * missing wares or under staffing. * @param ware that is required for the production * @return the average price of the consumed ware, with the amount taken into account. */ @VisibleForTesting double calculateWareCost(IWare producedWare, ProductionStorage storage, double requiredWareFactor, IWare ware) { double requiredForFullProduction = productionChain.getRequiredAmount(producedWare, ware) * ONE_DAY_OF_WEEK; double remove = -requiredForFullProduction * requiredWareFactor; double price = storage.getAvgPrice(ware); double moved = -storage.transfer(ware, remove, price); return moved * price; }
} else { return (int)(workShops.stream() .filter(workshop -> productionChain.getRequiredAmount(workshop.getProducableWare(), ware) > 0) .mapToInt(workshop -> (int)Math.ceil(productionChain.getRequiredAmount(workshop.getProducableWare(), ware))) .sum() * 0.5); .filter(workshop -> productionChain.getRequiredAmount(workshop.getProducableWare(), ware) > 0) .mapToInt(workshop -> (int)Math.ceil(productionChain.getRequiredAmount(workshop.getProducableWare(), ware))) .sum(); default:
@VisibleForTesting int calculateBuyAmount(IWare ware, ICity city, IAIPlayer player, ETradeReason tradeReason, List<IWorkShop> workShops) { switch (tradeReason) { case REQUIRE_FOR_PRODUCTION: // one week supply return workShops.stream() .filter(workshop -> productionChain.getRequiredWares(workshop.getProducableWare()).contains(ware)) .mapToInt(workshop -> (int)Math.ceil(productionChain.getRequiredAmount(workshop.getProducableWare(), ware))) .sum(); case PRODUCED_WARE_IN_CITY: // if needed in city or city is central storage, buy higher amount int baseAmount; if (ware.isBarrelSizedWare()) { baseAmount = 20; } else { baseAmount = 5; } if (tradeService.getBasicNeeds().contains(ware) || hasCentralStorageStrategy(city, player)) { baseAmount *= 2; } return baseAmount; default: throw new IllegalStateException("Unhandled buy trade reason: "+tradeReason); } }
public Map<IWare, Double> calculateConsumptionByProductionChain(ICity city) { List<IWare> wares = collectProducableWares(city); Map<IWare, Double> requireWares = new HashMap<>(); for (IWare ware : wares) { double adjustmentFactor = 1; if (!isEffectiveProduction(city, ware)) { adjustmentFactor = inefficiencyFactor; } if (city.getImported().contains(ware)) { if (isEffectiveProduction(city, ware)) { adjustmentFactor = inefficiencyFactor; } else { continue; } } int population = city.getPopulationBinding().get(); int amountWorkshops = population / populationAmountPerWorkshop + 1; List<IWare> required = productionChain.getRequiredWares(ware); for (IWare requiredWare : required) { double requiredAmount = productionChain.getRequiredAmount(ware, requiredWare) * amountWorkshops * adjustmentFactor; if (requireWares.containsKey(requiredWare)) { double update = requireWares.get(requiredWare) + requiredAmount; requireWares.put(requiredWare, update); } else { requireWares.put(requiredWare, requiredAmount); } } } return requireWares; }
double minProducableAmount = theoreticalProducableAmount; for (IWare requiredWare : requiredWares) { double requiredAmount = productionChain.getRequiredAmount(ware, requiredWare) * amountWorkshops * adjustmentFactor; double storedAmount = storage.getStored(requiredWare); if (storedAmount >= requiredAmount) {
private void prepareForProductionNextWeekAndMakeAvailable(ICity city, IWare ware) { double producedAmount = getExactOutputCurrentWeek(ware, city); int makeAvailableAmount = (int) Math.floor(producedAmount); double remainingAmount = producedAmount - makeAvailableAmount; ProductionStorage storage = cityProductionStorage.getStorage(city); storage.transfer(ware, remainingAmount, 0); if (storage.getStored(ware) > 1) { int fromStorage = (int) Math.floor(storage.getStored(ware)); storage.transfer(ware, -fromStorage, 0); makeAvailableAmount += fromStorage; } city.move(ware, makeAvailableAmount, null); List<IWare> requiredWares = productionChain.getRequiredWares(ware); double adjustmentFactor = 1; if (!isEffectiveProduction(city, ware) || city.getImported().contains(ware)) { adjustmentFactor = inefficiencyFactor; } int population = city.getPopulationBinding().get(); int amountWorkshops = population / populationAmountPerWorkshop + 1; for (IWare requiredWare : requiredWares) { double requiredAmount = productionChain.getRequiredAmount(ware, requiredWare) * amountWorkshops * adjustmentFactor; double storedAmount = storage.getStored(requiredWare); double removeAmount = Math.min(requiredAmount, storedAmount); storage.transfer(requiredWare, -removeAmount, 0); } } }
ProductionStorage storage = workshop.getStorage(); for (IWare ware : required) { double requiredAmount = productionChain.getRequiredAmount(producedWare, ware) * ONE_DAY_OF_WEEK; if (storage.getStored(ware) < requiredAmount) {