package com.metservice.kanban.charts.burnup;
import java.awt.Color;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYPointerAnnotation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.xy.XYDataset;
import org.joda.time.LocalDate;
import com.google.gson.internal.Pair;
import com.metservice.kanban.charts.KanbanDrawingSupplier;
import com.metservice.kanban.charts.cumulativeflow.CumulativeFlowChartBuilder;
import com.metservice.kanban.model.EstimatesProject;
import com.metservice.kanban.model.KanbanProject;
import com.metservice.kanban.model.WorkItem;
import com.metservice.kanban.model.WorkItemType;
public class DefaultBurnUpChartGenerator implements BurnUpChartGenerator {
private final ChartWriter chartWriter;
public DefaultBurnUpChartGenerator(ChartWriter chartWriter) {
this.chartWriter = chartWriter;
}
@Override
public void generateBurnUpChart(KanbanProject project, WorkItemType type, List<WorkItem> workItems,
LocalDate startDate, LocalDate currentDate, OutputStream outputStream)
throws IOException {
BurnUpDataModel model = new BurnUpDataModel(type, workItems, startDate, currentDate);
CategoryDataset dataset = new BurnUpDatasetGenerator().createDataset(model);
JFreeChart chart = createChart(dataset, project, startDate, currentDate);
chartWriter.writeChart(outputStream, chart, 800, 600);
}
private JFreeChart createChart(CategoryDataset dataset, KanbanProject project, LocalDate startDate,
LocalDate endDate) {
JFreeChart chart = ChartFactory.createStackedAreaChart(
"Burn-Up Chart", // chart title
"", // domain axis label
"", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true,
false
);
CategoryPlot plot = (CategoryPlot) chart.getPlot();
plot.setForegroundAlpha(1f);
plot.setBackgroundPaint(Color.WHITE);
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.GRAY);
plot.setRangeGridlinePaint(Color.GRAY);
plot.setDrawingSupplier(new KanbanDrawingSupplier(3));
CumulativeFlowChartBuilder.insertJournalEntries(dataset, project, plot, startDate, endDate);
CategoryAxis domainAxis = plot.getDomainAxis();
domainAxis.setLowerMargin(0.0);
domainAxis.setUpperMargin(0.0);
domainAxis.setCategoryLabelPositions(CategoryLabelPositions.UP_45);
// change the auto tick unit selection to integer units only...
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setUpperMargin(0.12);
return chart;
}
@Override
public void generateEstimatesBurnUpChart(EstimatesProject estimatesProject, List<WorkItem> workItems,
OutputStream outputStream) throws IOException {
EstimatesBurnDownDataModel model = new EstimatesBurnDownDataModel(workItems, estimatesProject);
XYDataset dataset = new EstimatesBurnDownDatasetGenerator().createDataset(model);
JFreeChart chart = createEstimatesChart(dataset, estimatesProject.getKanbanProject(), model);
chartWriter.writeChart(outputStream, chart, 800, 600);
}
private JFreeChart createEstimatesChart(XYDataset dataset, KanbanProject project, EstimatesBurnDownDataModel model) {
JFreeChart chart = ChartFactory.createXYLineChart(
"Estimates Burn-Down Chart", // chart title
"$ spent", // domain axis label
"feature points", // range axis label
dataset, // data
PlotOrientation.VERTICAL, // orientation
true, // include legend
true,
false
);
XYPlot plot = (XYPlot) chart.getPlot();
plot.setForegroundAlpha(1f);
plot.setBackgroundPaint(Color.WHITE);
plot.setDomainGridlinesVisible(true);
plot.setDomainGridlinePaint(Color.GRAY);
plot.setRangeGridlinePaint(Color.GRAY);
ValueAxis domainAxis = plot.getDomainAxis();
domainAxis.setLowerMargin(0.0);
domainAxis.setUpperMargin(0.1);
// change the auto tick unit selection to integer units only...
NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
rangeAxis.setUpperMargin(0.12);
XYPointerAnnotation annotation = new XYPointerAnnotation("Budget",
model.getBudget(), 0, -0.9);
annotation.setLabelOffset(10);
plot.addAnnotation(annotation);
Pair<Integer, LocalDate> lastBudgedEntry = model.getLastBudgedEntry();
if (lastBudgedEntry != null) {
annotation = new XYPointerAnnotation("Last budget entry",
lastBudgedEntry.first, model.getRemainingFeaturePointForBudget(lastBudgedEntry), -0.9);
annotation.setLabelOffset(10);
plot.addAnnotation(annotation);
}
annotation = new XYPointerAnnotation("Estimated budget",
model.getProjectedBudgetConsumed(), 0, -0.9);
annotation.setLabelOffset(10);
plot.addAnnotation(annotation);
annotation = new XYPointerAnnotation("Project start",
0, model.getAllFeaturePoints(), -0.5);
annotation.setLabelOffset(15);
plot.addAnnotation(annotation);
XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();
plot.setRenderer(renderer);
return chart;
}
}