improvements
- split the 'sortby' select field into two fields - sort by average - legend shows plotted and total values in the date range - removed InlineDataSeries, because it was not used anymore
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
package org.lucares.pdbui.domain;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class DataSeriesStats {
|
||||
private final int values;
|
||||
private final long maxValue;
|
||||
private final double average;
|
||||
private final int plottedValues;
|
||||
|
||||
public DataSeriesStats(final int values, final int plottedValues, final long maxValue, final double average) {
|
||||
this.values = values;
|
||||
this.plottedValues = plottedValues;
|
||||
this.maxValue = maxValue;
|
||||
this.average = average;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of values in the date range, without applying the y-range.
|
||||
*
|
||||
* @return total number of values
|
||||
*/
|
||||
public int getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of values in the date range <em>and</em> the y-range.
|
||||
*
|
||||
* @return number of plotted values
|
||||
*/
|
||||
public int getPlottedValues() {
|
||||
return plottedValues;
|
||||
}
|
||||
|
||||
public long getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
public double getAverage() {
|
||||
return average;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[values=" + values + ", maxValue=" + maxValue + ", average=" + average + "]";
|
||||
}
|
||||
|
||||
public static double average(final Collection<DataSeriesStats> stats) {
|
||||
long n = 0;
|
||||
double average = 0;
|
||||
|
||||
for (final DataSeriesStats stat : stats) {
|
||||
final int newValues = stat.getValues();
|
||||
final double newAverage = stat.getAverage();
|
||||
if (newValues > 0) {
|
||||
average = (average * n + newAverage * newValues) / (n + newValues);
|
||||
n += newValues;
|
||||
}
|
||||
}
|
||||
|
||||
return average;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.lucares.pdbui.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.lucares.recommind.logs.DataSeries;
|
||||
@@ -9,14 +10,24 @@ public class PlotResponseStats {
|
||||
|
||||
private int values;
|
||||
|
||||
private double average;
|
||||
|
||||
private int plottedValues;
|
||||
|
||||
private List<DataSeriesStats> dataSeriesStats;
|
||||
|
||||
public PlotResponseStats() {
|
||||
super();
|
||||
}
|
||||
|
||||
public PlotResponseStats(final long maxValue, final int values) {
|
||||
public PlotResponseStats(final long maxValue, final int values, final int plottedValues, final double average,
|
||||
final List<DataSeriesStats> dataSeriesStats) {
|
||||
|
||||
this.maxValue = maxValue;
|
||||
this.values = values;
|
||||
this.plottedValues = plottedValues;
|
||||
this.average = average;
|
||||
this.dataSeriesStats = dataSeriesStats;
|
||||
}
|
||||
|
||||
public long getMaxValue() {
|
||||
@@ -35,21 +46,54 @@ public class PlotResponseStats {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
public int getPlottedValues() {
|
||||
return plottedValues;
|
||||
}
|
||||
|
||||
public void setPlottedValues(final int plottedValues) {
|
||||
this.plottedValues = plottedValues;
|
||||
}
|
||||
|
||||
public double getAverage() {
|
||||
return average;
|
||||
}
|
||||
|
||||
public void setAverage(final double average) {
|
||||
this.average = average;
|
||||
}
|
||||
|
||||
public List<DataSeriesStats> getDataSeriesStats() {
|
||||
return dataSeriesStats;
|
||||
}
|
||||
|
||||
public void setDataSeriesStats(final List<DataSeriesStats> dataSeriesStats) {
|
||||
this.dataSeriesStats = dataSeriesStats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "PlotResponseStats [maxValue=" + maxValue + ", values=" + values + "]";
|
||||
return "PlotResponseStats [maxValue=" + maxValue + ", values=" + values + ", average=" + average
|
||||
+ ", plottedValues=" + plottedValues + ", dataSeriesStats=" + dataSeriesStats + "]";
|
||||
}
|
||||
|
||||
public static PlotResponseStats fromDataSeries(final List<DataSeries> dataSeries) {
|
||||
|
||||
int values = 0;
|
||||
int plottedValues = 0;
|
||||
long maxValue = 0;
|
||||
final List<DataSeriesStats> dataSeriesStats = new ArrayList<>();
|
||||
|
||||
for (final DataSeries dataSerie : dataSeries) {
|
||||
values += dataSerie.getValues();
|
||||
plottedValues += dataSerie.getPlottedValues();
|
||||
maxValue = Math.max(maxValue, dataSerie.getMaxValue());
|
||||
|
||||
dataSeriesStats.add(new DataSeriesStats(dataSerie.getValues(), dataSerie.getPlottedValues(),
|
||||
dataSerie.getMaxValue(), dataSerie.getAverage()));
|
||||
}
|
||||
|
||||
return new PlotResponseStats(maxValue, values);
|
||||
final double average = DataSeriesStats.average(dataSeriesStats);
|
||||
|
||||
return new PlotResponseStats(maxValue, values, plottedValues, average, dataSeriesStats);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,10 +308,14 @@ Vue.component('navigation-bar-gallery', {
|
||||
<label for="gallerySortBy">Sort by:</label>
|
||||
<select id="gallerySortBy" name="gallerySortBy" v-model="gallery.sortBy" @change="sort">
|
||||
<option value="DEFAULT"></option>
|
||||
<option value="MAX_VALUE_DESC">max value desc</option>
|
||||
<option value="MAX_VALUE_ASC">max value asc</option>
|
||||
<option value="VALUES_DESC">#values desc</option>
|
||||
<option value="VALUES_ASC">#values asc</option>
|
||||
<option value="MAX_VALUE">max value</option>
|
||||
<option value="AVERAGE">average</option>
|
||||
<option value="VALUES">#values</option>
|
||||
<option value="PLOTTED_VALUES">#plotted values</option>
|
||||
</select>
|
||||
<select id="gallerySortOrder" name="gallerySortOrder" v-model="gallery.sortOrder" @change="sort">
|
||||
<option value="DESC">desc</option>
|
||||
<option value="ASC">asc</option>
|
||||
</select>
|
||||
</div>
|
||||
<!--
|
||||
@@ -603,6 +607,8 @@ Vue.component('search-bar', {
|
||||
'yRangeMax': data.searchBar.yRange.max,
|
||||
'yRangeUnit': data.searchBar.yRange.unit,
|
||||
'keyOutside': data.searchBar.keyOutside,
|
||||
'sortyBy': data.gallery.sortBy,
|
||||
'sortyOrder': data.gallery.sortOrder,
|
||||
};
|
||||
|
||||
var link = window.location.origin+ window.location.pathname + "?" + jQuery.param( params );
|
||||
@@ -833,7 +839,8 @@ var data = {
|
||||
tiles: [],
|
||||
toBeRendered: [],
|
||||
image: "",
|
||||
sortBy: "MAX_VALUE_DESC",
|
||||
sortBy: GetURLParameter('sortyBy','MAX_VALUE'),
|
||||
sortOrder: GetURLParameter('sortyOrder','DESC'),
|
||||
filter: "NONE",
|
||||
progress: {
|
||||
max: 0,
|
||||
@@ -1063,21 +1070,23 @@ function createGalleryItem(originalQuery, field, imageHeight, imageWidth)
|
||||
|
||||
function sortTiles() {
|
||||
|
||||
const orderFactor = data.gallery.sortOrder == 'ASC' ? 1 : -1;
|
||||
|
||||
switch (data.gallery.sortBy) {
|
||||
case "DEFAULT":
|
||||
data.gallery.tiles.sort(function(a, b){return a.fieldValue.localeCompare(b.fieldValue);});
|
||||
data.gallery.tiles.sort(function(a, b){return orderFactor*a.fieldValue.localeCompare(b.fieldValue);});
|
||||
break;
|
||||
case "VALUES_ASC":
|
||||
data.gallery.tiles.sort(function(a, b){return a.stats.values - b.stats.values;});
|
||||
case "VALUES":
|
||||
data.gallery.tiles.sort(function(a, b){return orderFactor*(a.stats.values - b.stats.values);});
|
||||
break;
|
||||
case "VALUES_DESC":
|
||||
data.gallery.tiles.sort(function(a, b){return b.stats.values - a.stats.values;});
|
||||
case "PLOTTED_VALUES":
|
||||
data.gallery.tiles.sort(function(a, b){return orderFactor*(a.stats.plottedValues - b.stats.plottedValues);});
|
||||
break;
|
||||
case "MAX_VALUE_ASC":
|
||||
data.gallery.tiles.sort(function(a, b){return a.stats.maxValue - b.stats.maxValue;});
|
||||
case "MAX_VALUE":
|
||||
data.gallery.tiles.sort(function(a, b){return orderFactor*(a.stats.maxValue - b.stats.maxValue);});
|
||||
break;
|
||||
case "MAX_VALUE_DESC":
|
||||
data.gallery.tiles.sort(function(a, b){return b.stats.maxValue - a.stats.maxValue;});
|
||||
case "AVERAGE":
|
||||
data.gallery.tiles.sort(function(a, b){return orderFactor*(a.stats.average - b.stats.average);});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
package org.lucares.pdbui.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@Test
|
||||
public class DataSeriesStatsTest {
|
||||
@DataProvider
|
||||
public Object[][] providerAverage() {
|
||||
final List<Object[]> result = new ArrayList<>();
|
||||
|
||||
{
|
||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||
new DataSeriesStats(10, 0, 0, 5.0)//
|
||||
);
|
||||
final double expected = 5.0;
|
||||
result.add(new Object[] { stats, expected });
|
||||
}
|
||||
{
|
||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||
new DataSeriesStats(0, 0, 0, 5.0)//
|
||||
);
|
||||
final double expected = 0.0; // no values
|
||||
result.add(new Object[] { stats, expected });
|
||||
}
|
||||
|
||||
{
|
||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||
new DataSeriesStats(10, 0, 0, 5.0), //
|
||||
new DataSeriesStats(40, 0, 0, 1.0)//
|
||||
);
|
||||
final double expected = 1.8; // 90 / 50
|
||||
result.add(new Object[] { stats, expected });
|
||||
}
|
||||
{
|
||||
final List<DataSeriesStats> stats = Arrays.asList(//
|
||||
new DataSeriesStats(5, 0, 0, 7.0), //
|
||||
new DataSeriesStats(0, 0, 0, 5.0), // // no values
|
||||
new DataSeriesStats(20, 0, 0, 2.0)//
|
||||
);
|
||||
final double expected = 3.0; // (35+40) / 25
|
||||
result.add(new Object[] { stats, expected });
|
||||
}
|
||||
|
||||
return result.toArray(new Object[0][]);
|
||||
}
|
||||
|
||||
@Test(dataProvider = "providerAverage")
|
||||
public void testAverage(final Collection<DataSeriesStats> stats, final double expected) {
|
||||
|
||||
final double actual = DataSeriesStats.average(stats);
|
||||
Assert.assertEquals(actual, expected, 0.01);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user