Revamp 'Estimation Accuracy' chart

FEA: ItEr76S15OrganizingPerProjectDashboard
This commit is contained in:
Diego Pino 2012-05-02 16:07:45 +02:00
parent 7b3ca0da29
commit 5dc4a59da2
4 changed files with 143 additions and 3 deletions

View file

@ -95,6 +95,7 @@ public class DashboardController extends GenericForwardComposer {
renderTasksSummary();
renderDeadlineViolation();
renderMarginWithDeadline();
renderEstimationAccuracy();
}
}
@ -172,6 +173,30 @@ public class DashboardController extends GenericForwardComposer {
renderChart(barChart, divId);
}
private void renderEstimationAccuracy() {
final String divId = "estimation-accuracy";
BarChart<Integer> barChart;
barChart = new BarChart<Integer>("Estimation Accuracy");
barChart.setFillZero(true);
barChart.setHighlightMouseDown(true);
barChart.setStackSeries(false);
barChart.setBarMargin(30);
barChart.addSeries(new Serie("Tasks"));
EstimationAccuracy estimationAccuracyData = EstimationAccuracy
.create(dashboardModel);
barChart.setTicks(estimationAccuracyData.getTicks());
barChart.addValues(estimationAccuracyData.getValues());
barChart.getAxes().getXaxis()
.setLabel(_("Number of Tasks / % Deviation"));
renderChart(barChart, divId);
}
private void renderTasksSummary() {
Map<TaskStatusEnum, Integer> taskStatus = dashboardModel
.calculateTaskStatus();
@ -407,4 +432,48 @@ public class DashboardController extends GenericForwardComposer {
}
/**
*
* @author Diego Pino García<dpino@igalia.com>
*
*/
static class EstimationAccuracy {
private final IDashboardModel dashboardModel;
private Map<Interval, Integer> estimationAccuracyData;
private EstimationAccuracy(IDashboardModel dashboardModel) {
this.dashboardModel = dashboardModel;
}
public static EstimationAccuracy create(IDashboardModel dashboardModel) {
return new EstimationAccuracy(dashboardModel);
}
private Map<Interval, Integer> getData() {
if (estimationAccuracyData == null) {
estimationAccuracyData = dashboardModel
.calculateEstimationAccuracy();
}
return estimationAccuracyData;
}
public String[] getTicks() {
Set<Interval> intervals = getData().keySet();
String[] result = new String[intervals.size()];
int i = 0;
for (Interval each : intervals) {
result[i++] = each.toString();
}
return result;
}
public Collection<Integer> getValues() {
return getData().values();
}
}
}

View file

@ -49,7 +49,7 @@ import org.springframework.stereotype.Component;
/**
* Model for UI operations related to Order Dashboard View
*
*
* @author Nacho Barrientos <nacho@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
*/
@ -383,9 +383,70 @@ public class DashboardModel implements IDashboardModel {
}
/**
*
* Calculates the estimation accuracy deviations for the current order
*
* All the deviations are groups in Interval.MAX_INTERVALS intervals of
* equal size. If the order contains just one single task then, the upper
* limit will be the deviation of the task + 30, and the lower limit will be
* deviation of the task - 20
*
* Each {@link Interval} contains the number of tasks that fit in that
* interval
*
* @return
*/
public Map<Interval, Integer> calculateEstimationAccuracy() {
final Integer one = Integer.valueOf(1);
Map<Interval, Integer> result = new LinkedHashMap<Interval, Integer>();
Double max, min;
// Get deviations of finished tasks, calculate max, min and delta
List<Double> deviations = getEstimationAccuracyDeviations();
if (deviations.isEmpty()) {
return result;
}
if (deviations.size() == 1) {
max = deviations.get(0).doubleValue() + 30;
min = deviations.get(0).doubleValue() - 20;
} else {
max = Collections.max(deviations);
min = Collections.min(deviations);
}
double delta = (max - min) / Interval.MAX_INTERVALS;
// Create MAX_INTERVALS
double from = min;
for (int i = 0; i < Interval.MAX_INTERVALS; i++) {
result.put(Interval.create(from, from + delta), Integer.valueOf(0));
from = from + delta;
}
// Construct map with number of tasks for each interval
final Set<Interval> intervals = result.keySet();
for (Double each : deviations) {
Interval interval = Interval.containingValue(intervals, each);
if (interval != null) {
Integer value = result.get(interval);
result.put(interval, value + one);
}
}
return result;
}
private List<Double> getEstimationAccuracyDeviations() {
if (this.getRootTask() == null) {
throw new RuntimeException("Root task is null");
}
CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor();
TaskElement rootTask = getRootTask();
rootTask.acceptVisitor(visitor);
return visitor.getDeviations();
}
/**
*
* @author Diego Pino García<dpino@igalia.com>
*
*
*/
static class Interval {

View file

@ -77,4 +77,6 @@ interface IDashboardModel {
Map<Interval, Integer> calculateTaskCompletation();
Map<Interval, Integer> calculateEstimationAccuracy();
}

View file

@ -106,6 +106,14 @@
</hbox>
</groupbox>
<!-- Resources -->
<groupbox closable="false">
<caption label="${i18n:_('Resources')}" />
<hbox>
<n:div id="estimation-accuracy" style="height:200px; width:580px;"></n:div>
</hbox>
</groupbox>
</div>
<div id="projectDashboardNoTasksWarningDiv" visible="false">