package com.metservice.kanban.charts.burnup; import java.util.ArrayList; import java.util.List; import org.joda.time.LocalDate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.gson.internal.Pair; import com.metservice.kanban.model.EstimatesProject; import com.metservice.kanban.model.WorkItem; public class EstimatesBurnDownDataModel { private static final Logger LOGGER = LoggerFactory.getLogger(EstimatesBurnDownDataModel.class); private final List<WorkItem> workItems; private final EstimatesProject estimatesProject; private final int allFeaturePoints; private final List<Pair<Integer, LocalDate>> budgetEntries; private final int projectedBudgedConsumed; public EstimatesBurnDownDataModel(List<WorkItem> workItems, EstimatesProject estimatesProject) { this.workItems = removeExcludedWorkItems(workItems); this.estimatesProject = estimatesProject; this.allFeaturePoints = computeAllFeaturePoints(); this.budgetEntries = computeBudgetEntries(); this.projectedBudgedConsumed = computeProjectedBudgedConsumed(); } private static List<WorkItem> removeExcludedWorkItems(List<WorkItem> workItemList) { List<WorkItem> list = new ArrayList<WorkItem>(); for (WorkItem item : workItemList) { if (!item.isExcluded()) { list.add(item); } } return list; } public List<Pair<Integer, LocalDate>> getBudgetEntries() { return budgetEntries; } List<Pair<Integer, LocalDate>> computeBudgetEntries() { List<Pair<Integer, LocalDate>> result = new ArrayList<Pair<Integer, LocalDate>>(); int currentBudget = 0; for (LocalDate day : estimatesProject.getDayCosts().keySet()) { Integer integer = estimatesProject.getDayCosts().get(day); currentBudget += integer; result.add(new Pair<Integer, LocalDate>(currentBudget, day)); } return result; } public int getAllFeaturePoints() { return allFeaturePoints; } int computeAllFeaturePoints() { int points = 0; for (WorkItem wi : workItems) { points += wi.getAverageCaseEstimate(); } return points; } public int getRemainingFeaturePointForBudget(Pair<Integer, LocalDate> budgetEntry) { int points = getAllFeaturePoints(); for (WorkItem wi : workItems) { if (wi.isCompleted() && !wi.getDate(wi.getCurrentPhase()).isAfter(budgetEntry.second)) { points -= wi.getAverageCaseEstimate(); } } return points; } public Pair<Integer, LocalDate> getLastBudgedEntry() { if (budgetEntries == null || budgetEntries.size() == 0) { return null; } return budgetEntries.get(budgetEntries.size() - 1); } public int getProjectedBudgetConsumed() { return projectedBudgedConsumed; } int computeProjectedBudgedConsumed() { Pair<Integer, LocalDate> lastBudgedEntry = getLastBudgedEntry(); if (lastBudgedEntry == null) { LOGGER.info("Trying to getProjectedBudget with no budget recorded, should return infinity"); // just some large value to indicate that sth is wrong return getBudget() * 5; } int remainingFeaturePointForBudget = getRemainingFeaturePointForBudget(lastBudgedEntry); if (allFeaturePoints - remainingFeaturePointForBudget != 0) { return lastBudgedEntry.first * allFeaturePoints / (allFeaturePoints - remainingFeaturePointForBudget); } else { LOGGER.info("Trying to getProjectedBudget with no finished work items, should return infinity"); // just some large value to indicate that sth is wrong return getBudget() * 5; } } public int getBudget() { return estimatesProject.getBudget(); } }