Added median issue age feature.

This commit is contained in:
Christian P. MOMON 2021-05-05 04:25:02 +02:00
parent 4c28fe2dc7
commit 10bc11baf4
6 changed files with 153 additions and 3 deletions

View file

@ -198,6 +198,42 @@ public class AgirStatoolUtils
return result; return result;
} }
/**
* Builds the week median ages.
*
* @param project
* the project
* @param start
* the start
* @param end
* the end
* @return the string list
*/
public static StringList buildWeekMedianAges(final Project project, final LocalDate start, final LocalDate end)
{
StringList result;
result = new StringList();
if (start != null)
{
LocalDate date = AgirStatoolUtils.normaliseWeekDate(start);
LocalDate normalizedEnd = AgirStatoolUtils.normaliseWeekDate(end);
while (date.isBefore(normalizedEnd) || date.isEqual(normalizedEnd))
{
double stat = project.issues().extractActivedAt(date).computeMedian(date);
result.add(String.valueOf(stat));
//
date = date.plusWeeks(1);
}
}
//
return result;
}
/** /**
* Builds the week min ages. * Builds the week min ages.
* *

View file

@ -47,6 +47,30 @@ public class Issues extends ArrayList<Issue>
super(capacity); super(capacity);
} }
/**
* Compute median.
*
* @param date
* the date
* @return the double
*/
public double computeMedian(final LocalDate date)
{
double result;
LongList values = new LongList();
for (Issue issue : this)
{
int age = issue.getAgeInDays(date);
values.add(Long.valueOf(age));
}
result = values.median();
//
return result;
}
/** /**
* Compute stat. * Compute stat.
* *

View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 Christian Pierre MOMON <christian.momon@devinsy.fr>
*
* This file is part of AgirStatool, simple key value database.
*
* AgirStatool is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* AgirStatool is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with AgirStatool. If not, see <http://www.gnu.org/licenses/>.
*/
package org.april.agirstatool.core;
import java.util.ArrayList;
import java.util.Collections;
/**
* The Class LongList.
*/
public class LongList extends ArrayList<Long>
{
private static final long serialVersionUID = 2724688980125113107L;
/**
* Instantiates a new stat.
*/
public LongList()
{
super();
}
/**
* Median.
*
* @return the double
*/
public double median()
{
double result;
sort();
if (this.isEmpty())
{
result = 0;
}
else if (this.size() % 2 == 0)
{
long a = get(this.size() / 2 - 1);
long b = get(this.size() / 2);
result = (a + b) / 2;
}
else
{
result = get(this.size() / 2);
}
//
return result;
}
/**
* Sort.
*/
public void sort()
{
Collections.sort(this);
}
}

View file

@ -78,6 +78,9 @@ public class IssueAgeChartView
values = AgirStatoolUtils.buildWeekMaxAges(project, start, end); values = AgirStatoolUtils.buildWeekMaxAges(project, start, end);
code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values)); code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
values = AgirStatoolUtils.buildWeekMedianAges(project, start, end);
code = code.replaceAll("data : \\[.*\\]", "data: " + AgirStatoolUtils.toJSonNumbers(labels, values));
result = code.toString(); result = code.toString();
} }
else else

View file

@ -38,12 +38,23 @@ var myChart = new Chart(ctx,
backgroundColor: 'rgba(75, 192, 192, 0.2)', backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)', borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1, borderWidth: 1,
fill: +2, fill: +3,
cubicInterpolationMode: 'monotone', cubicInterpolationMode: 'monotone',
lineTension: 0, lineTension: 0,
pointBorderWidth: 0.00000001, pointBorderWidth: 0.00000001,
data : [1, 5, 9, 13, 15, 22], data : [1, 5, 9, 13, 15, 22],
}, },
{
label: 'median',
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1,
fill: false,
cubicInterpolationMode: 'monotone',
lineTension: 0,
pointBorderWidth: 0.00000001,
data : [1, 5, 9, 13, 15, 22],
},
{ {
label: 'max', label: 'max',
backgroundColor: 'rgba(153, 102, 255, 0.2)', backgroundColor: 'rgba(153, 102, 255, 0.2)',
@ -55,7 +66,7 @@ var myChart = new Chart(ctx,
pointBorderWidth: 0.00000001, pointBorderWidth: 0.00000001,
data : [1, 5, 9, 13, 15, 22], data : [1, 5, 9, 13, 15, 22],
} }
] ]
}, },
options: options:
{ {

View file

@ -81,7 +81,7 @@
<div id="unassignedGroupedChart" style="width: 360px; height: 200px; display: none;"></div> <div id="unassignedGroupedChart" style="width: 360px; height: 200px; display: none;"></div>
<div id="createdClosedChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED/CLOSED CHART MINI</div> <div id="createdClosedChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED/CLOSED CHART MINI</div>
<div id="created-ClosedChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED-CLOSED CHART MINI</div> <div id="created-ClosedChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED-CLOSED CHART MINI</div>
<div id="ageChartMini" style="width: 250px; height: 200px; display: inline-block;">CREATED-CLOSED MONTHS CHART MINI</div> <div id="ageChartMini" style="width: 220px; height: 200px; display: inline-block;">CREATED-CLOSED MONTHS CHART MINI</div>
</div> </div>
<br/> <br/>
<div id="tableView"> <div id="tableView">