package org.dicadeveloper.weplantaforest.planting.plantbag; import java.util.HashMap; import org.dicadeveloper.weplantaforest.common.support.PriceHelper; import org.dicadeveloper.weplantaforest.planting.plantbag.PlantBag.ProjectData; import org.dicadeveloper.weplantaforest.planting.plantbag.PlantBag.ProjectData.PlantItem; import org.dicadeveloper.weplantaforest.projects.Project; import org.dicadeveloper.weplantaforest.projects.ProjectArticle; import org.dicadeveloper.weplantaforest.projects.ProjectArticleRepository; import org.dicadeveloper.weplantaforest.projects.ProjectRepository; import org.dicadeveloper.weplantaforest.trees.TreeRepository; import org.dicadeveloper.weplantaforest.treetypes.TreeTypeRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Component; @Component public class PlantBagHelper extends AbstractPlantBagHelper { private PlantBag plantPageData; @Autowired private PlantBagHelper(ProjectRepository projectRepository, ProjectArticleRepository projectArticleRepository, TreeTypeRepository treeTypeRepository, TreeRepository treeRepository) { super(projectRepository, projectArticleRepository, treeTypeRepository, treeRepository); } public PlantBag createPlantProposalForTargetPrice(long targetedPrice) { initialize(targetedPrice); ProjectArticle articleWithHighestMarge = findProjectArticleWithHighestMarge(); double targetPriceAsDouble = PriceHelper.fromCentsToEuro(targetedPrice); double targetedPriceForHighestMarge = targetPriceAsDouble * 0.7; increaseAmountOfPlantItemTillPriceReached(articleWithHighestMarge, targetedPriceForHighestMarge); double targetedPriceForOtherTrees = targetPriceAsDouble - PriceHelper.fromCentsToEuro(plantPageData.getActualPrice()); targetedPriceForOtherTrees = addFurtherPlantItems(targetedPriceForOtherTrees); increaseAmountOfPlantItemTillPriceReached(articleWithHighestMarge, targetedPriceForOtherTrees); return plantPageData; } private void initialize(long targetedPrice) { plantPageData = new PlantBag(); addActiveProjectsToPlantPageData(); plantPageData.setTargetPrice(targetedPrice); projectArticles = createListOfAllAvailableProjectArticles(); initializePlantItems(); } private void initializePlantItems() { for (ProjectArticle article : projectArticles) { initialisePlantItem(article); } } private void addActiveProjectsToPlantPageData() { HashMap<String, ProjectData> projectMap = new HashMap<>(); plantPageData.setProjects(projectMap); for (Project project : _projectRepository.active(new PageRequest(0, 5))) { ProjectData projectData = new ProjectData(); String projectName = project.getName(); plantPageData.projects.put(projectName, projectData); HashMap<String, PlantItem> plantItemMap = new HashMap<>(); plantPageData.projects.get(projectName) .setPlantItems(plantItemMap); } } private void increaseAmountOfPlantItemTillPriceReached(ProjectArticle article, double targetedPrice) { boolean treeCouldBeAdded = false; do { treeCouldBeAdded = false; double treePrice = article.getPrice() .getAmount() .doubleValue(); // check, if it's possible to add 1 tree without // exceeding the targeted price if (targetedPrice > 0 && isLowerOrEqualThanTargetedPrice(treePrice, targetedPrice)) { // if yes, increase the amount of this article by one, if there // are enough remaining trees if (increasePlantItemAmountByOneIfEnoughTreesRemaining(article)) { // targeted price lowered by price of one tree targetedPrice = targetedPrice - treePrice; treeCouldBeAdded = true; } } else { // do Nothing } } // if at least 1 tree could be added, iterate over all articles again while (treeCouldBeAdded); } private double addFurtherPlantItems(double targetedPrice) { boolean treeCouldBeAdded = false; do { treeCouldBeAdded = false; for (ProjectArticle article : projectArticles) { double treePrice = article.getPrice() .getAmount() .doubleValue(); // check, if it's possible to add 1 tree without // exceeding the targeted price and if there are remaining trees // by // this article if (targetedPrice > 0 && isLowerOrEqualThanTargetedPrice(treePrice, targetedPrice)) { // if yes, increase the amount of this article by one if (increasePlantItemAmountByOneIfEnoughTreesRemaining(article)) { // targeted price lowered by price of one tree targetedPrice = targetedPrice - treePrice; treeCouldBeAdded = true; } } else { // do Nothing } } } // if at least 1 tree could be added, iterate over all articles again while (treeCouldBeAdded); return targetedPrice; } private void initialisePlantItem(ProjectArticle article) { String projectName = article.getProject() .getName(); String treeTypeName = article.getTreeType() .getName(); long treePrice = PriceHelper.fromBigDecimalToLong(article.getPrice() .getAmount()); PlantItem plantItem = new PlantItem(); plantItem.setAmount(0); plantItem.setTreePrice(treePrice); plantPageData.getProjects() .get(projectName) .getPlantItems() .put(treeTypeName, plantItem); } private boolean increasePlantItemAmountByOneIfEnoughTreesRemaining(ProjectArticle article) { String projectName = article.getProject() .getName(); String treeTypeName = article.getTreeType() .getName(); int amountNow = plantPageData.getProjects() .get(projectName) .getPlantItems() .get(treeTypeName) .getAmount(); if ((amountNow + 1) <= countTreesRemainingByThisArticle(article)) { long treePrice = PriceHelper.fromBigDecimalToLong(article.getPrice() .getAmount()); long actualPriceNow = plantPageData.getActualPrice() + treePrice; plantPageData.setActualPrice(actualPriceNow); plantPageData.getProjects() .get(projectName) .getPlantItems() .get(treeTypeName) .setAmount(amountNow + 1); return true; } else { return false; } } }