From 026a47f82f762b174316d271a91e750800db5f86 Mon Sep 17 00:00:00 2001
From: uhensler <urs.hensler@frentix.com>
Date: Fri, 17 Jan 2020 10:34:39 +0100
Subject: [PATCH] OO-4472: RS when trend diagram ha no data

---
 .../quality/analysis/MultiTrendSeries.java    | 35 +++++++++++++++-
 .../manager/StatisticsCalculator.java         | 40 +++++++++----------
 .../analysis/MultiTrendSeriesTest.java        | 16 +++++---
 .../manager/StatisticsCalculatorTest.java     | 18 +++++++++
 4 files changed, 82 insertions(+), 27 deletions(-)

diff --git a/src/main/java/org/olat/modules/quality/analysis/MultiTrendSeries.java b/src/main/java/org/olat/modules/quality/analysis/MultiTrendSeries.java
index 72c970e671d..6b56fca37e0 100644
--- a/src/main/java/org/olat/modules/quality/analysis/MultiTrendSeries.java
+++ b/src/main/java/org/olat/modules/quality/analysis/MultiTrendSeries.java
@@ -43,9 +43,11 @@ public class MultiTrendSeries<V> {
 		this.temporalKeys = Collections.emptyList();
 	}
 	
-	public MultiTrendSeries(TemporalGroupBy temporalGroupBy, TemporalKey min, TemporalKey max) {
+	public MultiTrendSeries(TemporalGroupBy temporalGroupBy, TemporalMinMaxKeys minMaxKeys) {
 		this.temporalGroupBy = temporalGroupBy;
 		this.temporalKeys = new ArrayList<>();
+		TemporalKey min = minMaxKeys.getMinKey();
+		TemporalKey max = minMaxKeys.getMaxKey();
 		if (!TemporalKey.none().equals(min) && !TemporalKey.none().equals(max)) {
 			generateTemporalKeys(temporalKeys, min, max);
 		}
@@ -92,6 +94,35 @@ public class MultiTrendSeries<V> {
 		}
 		return series;
 	}
-	
+
+	public static class TemporalMinMaxKeys {
+		
+		private static final TemporalMinMaxKeys NONES = new TemporalMinMaxKeys(TemporalKey.none(), TemporalKey.none());
+		
+		private final TemporalKey minKey;
+		private final TemporalKey maxKey;
+		
+		public static TemporalMinMaxKeys nones() {
+			return NONES;
+		}
+		
+		public static TemporalMinMaxKeys of(TemporalKey minKey, TemporalKey maxKey) {
+			return new TemporalMinMaxKeys(minKey, maxKey);
+		}
+		
+		private TemporalMinMaxKeys(TemporalKey minKey, TemporalKey maxKey) {
+			this.minKey = minKey;
+			this.maxKey = maxKey;
+		}
+
+		public TemporalKey getMinKey() {
+			return minKey;
+		}
+
+		public TemporalKey getMaxKey() {
+			return maxKey;
+		}
+		
+	}
 
 }
diff --git a/src/main/java/org/olat/modules/quality/analysis/manager/StatisticsCalculator.java b/src/main/java/org/olat/modules/quality/analysis/manager/StatisticsCalculator.java
index 8faba390c22..6ba36341c40 100644
--- a/src/main/java/org/olat/modules/quality/analysis/manager/StatisticsCalculator.java
+++ b/src/main/java/org/olat/modules/quality/analysis/manager/StatisticsCalculator.java
@@ -42,6 +42,7 @@ import org.olat.modules.quality.analysis.GroupedStatistics;
 import org.olat.modules.quality.analysis.HeatMapStatistic;
 import org.olat.modules.quality.analysis.MultiKey;
 import org.olat.modules.quality.analysis.MultiTrendSeries;
+import org.olat.modules.quality.analysis.MultiTrendSeries.TemporalMinMaxKeys;
 import org.olat.modules.quality.analysis.RawGroupedStatistic;
 import org.olat.modules.quality.analysis.TemporalGroupBy;
 import org.olat.modules.quality.analysis.TemporalKey;
@@ -236,18 +237,10 @@ public class StatisticsCalculator {
 
 
 	MultiTrendSeries<String> getTrendsByIdentifiers(GroupedStatistics<GroupedStatistic> statistics, TemporalGroupBy temporalGroupBy) {
-		Set<TemporalKey> temporalKeys = new HashSet<>();
-		for (GroupedStatisticKeys groupedStatistic : statistics.getStatistics()) {
-			temporalKeys.add(groupedStatistic.getTemporalKey());
-		}
-		List<TemporalKey> sortedTemporalKeys = new ArrayList<>(temporalKeys);
-		Collections.sort(sortedTemporalKeys);
-		TemporalKey minKey = sortedTemporalKeys.get(0);
-		TemporalKey maxKey = sortedTemporalKeys.get(sortedTemporalKeys.size() - 1);
-		
+		TemporalMinMaxKeys minMaxKeys = getTemporalMinMax(statistics);
 		Set<String> identifiers = statistics.getIdentifiers();
 		
-		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(temporalGroupBy, minKey, maxKey);
+		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(temporalGroupBy, minMaxKeys);
 		for (String identifier: identifiers) {
 			GroupedStatistic lastStatistic = null;
 			for (TemporalKey temporalKey: multiTrendSeries.getTemporalKeys()) {
@@ -266,18 +259,10 @@ public class StatisticsCalculator {
 	}
 	
 	MultiTrendSeries<MultiKey> getTrendsByMultiKey(GroupedStatistics<GroupedStatistic> statistics, TemporalGroupBy temporalGroupBy) {
-		Set<TemporalKey> temporalKeys = new HashSet<>();
-		for (GroupedStatisticKeys groupedStatistic : statistics.getStatistics()) {
-			temporalKeys.add(groupedStatistic.getTemporalKey());
-		}
-		List<TemporalKey> sortedTemporalKeys = new ArrayList<>(temporalKeys);
-		Collections.sort(sortedTemporalKeys);
-		TemporalKey minKey = sortedTemporalKeys.get(0);
-		TemporalKey maxKey = sortedTemporalKeys.get(sortedTemporalKeys.size() - 1);
-		
+		TemporalMinMaxKeys minMaxKeys = getTemporalMinMax(statistics);
 		Set<MultiKey> multiKeys = statistics.getMultiKeys();
 		
-		MultiTrendSeries<MultiKey> multiTrendSeries = new MultiTrendSeries<>(temporalGroupBy, minKey, maxKey);
+		MultiTrendSeries<MultiKey> multiTrendSeries = new MultiTrendSeries<>(temporalGroupBy, minMaxKeys);
 		for (MultiKey multiKey: multiKeys) {
 			GroupedStatistic lastStatistic = null;
 			for (TemporalKey temporalKey: multiTrendSeries.getTemporalKeys()) {
@@ -295,6 +280,21 @@ public class StatisticsCalculator {
 		return multiTrendSeries;
 	}
 	
+	private TemporalMinMaxKeys getTemporalMinMax(GroupedStatistics<GroupedStatistic> statistics) {
+		if (statistics.getStatistics().isEmpty()) return TemporalMinMaxKeys.nones();
+		
+		Set<TemporalKey> temporalKeys = new HashSet<>();
+		for (GroupedStatisticKeys groupedStatistic : statistics.getStatistics()) {
+			temporalKeys.add(groupedStatistic.getTemporalKey());
+		}
+		List<TemporalKey> sortedTemporalKeys = new ArrayList<>(temporalKeys);
+		Collections.sort(sortedTemporalKeys);
+		TemporalKey minKey = sortedTemporalKeys.get(0);
+		TemporalKey maxKey = sortedTemporalKeys.get(sortedTemporalKeys.size() - 1);
+		
+		return TemporalMinMaxKeys.of(minKey, maxKey);
+	}
+	
 	Double getAvgDiffAbsolute(GroupedStatistic prev, GroupedStatistic current) {
 		if (prev == null || prev.getAvg() == null || current == null || current.getAvg() == null) return null;
 		
diff --git a/src/test/java/org/olat/modules/quality/analysis/MultiTrendSeriesTest.java b/src/test/java/org/olat/modules/quality/analysis/MultiTrendSeriesTest.java
index e2456593e67..2b8ffba2de9 100644
--- a/src/test/java/org/olat/modules/quality/analysis/MultiTrendSeriesTest.java
+++ b/src/test/java/org/olat/modules/quality/analysis/MultiTrendSeriesTest.java
@@ -24,6 +24,7 @@ import static org.assertj.core.api.Assertions.assertThat;
 import java.util.List;
 
 import org.junit.Test;
+import org.olat.modules.quality.analysis.MultiTrendSeries.TemporalMinMaxKeys;
 import org.olat.modules.quality.analysis.model.TrendImpl;
 
 /**
@@ -40,16 +41,18 @@ public class MultiTrendSeriesTest {
 		TemporalKey tk2001 = TemporalKey.of(2001);
 		TemporalKey tk2002 = TemporalKey.of(2002);
 		TemporalKey tk2003 = TemporalKey.of(2003);
+		TemporalMinMaxKeys minMaxKeys = TemporalMinMaxKeys.of(tk2000, tk2003);
 
-		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, tk2000, tk2003);
+		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, minMaxKeys);
 		
 		assertThat(multiTrendSeries.getTemporalKeys()).containsExactly(tk2000, tk2001, tk2002, tk2003);
 	}
 	@Test
 	public void shouldGenerateTemporalKeysIfMinEqualsMax() {
 		TemporalKey tk2000 = TemporalKey.of(2000);
+		TemporalMinMaxKeys minMaxKeys = TemporalMinMaxKeys.of(tk2000, tk2000);
 
-		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, tk2000, tk2000);
+		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, minMaxKeys);
 		
 		assertThat(multiTrendSeries.getTemporalKeys()).containsExactly(tk2000);
 	}
@@ -59,8 +62,9 @@ public class MultiTrendSeriesTest {
 		String identifier = "1";
 		TemporalKey tk2000 = TemporalKey.of(2000);
 		TemporalKey tk2003 = TemporalKey.of(2003);
+		TemporalMinMaxKeys minMaxKeys = TemporalMinMaxKeys.of(tk2000, tk2003);
 
-		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, tk2000, tk2003);
+		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, minMaxKeys);
 		multiTrendSeries.put(identifier, tk2000, null);
 		
 		List<Trend> trendList = multiTrendSeries.getSeries(identifier).toList();
@@ -72,9 +76,10 @@ public class MultiTrendSeriesTest {
 		String identifier = "1";
 		TemporalKey tk2000 = TemporalKey.of(2000);
 		TemporalKey tk2003 = TemporalKey.of(2003);
+		TemporalMinMaxKeys minMaxKeys = TemporalMinMaxKeys.of(tk2000, tk2003);
 		Trend trend = new TrendImpl(null, null, null, null);
 
-		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, tk2000, tk2003);
+		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, minMaxKeys);
 		multiTrendSeries.put(identifier, tk2003, trend);
 		
 		List<Trend> trendList = multiTrendSeries.getSeries(identifier).toList();
@@ -86,8 +91,9 @@ public class MultiTrendSeriesTest {
 		String identifier = "1";
 		TemporalKey tk2000 = TemporalKey.of(2000);
 		TemporalKey tk2003 = TemporalKey.of(2003);
+		TemporalMinMaxKeys minMaxKeys = TemporalMinMaxKeys.of(tk2000, tk2003);
 
-		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, tk2000, tk2003);
+		MultiTrendSeries<String> multiTrendSeries = new MultiTrendSeries<>(TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR, minMaxKeys);
 		
 		List<Trend> trendList = multiTrendSeries.getSeries(identifier).toList();
 		assertThat(trendList).containsExactly(null, null, null, null);
diff --git a/src/test/java/org/olat/modules/quality/analysis/manager/StatisticsCalculatorTest.java b/src/test/java/org/olat/modules/quality/analysis/manager/StatisticsCalculatorTest.java
index d97883d2066..c266b18559b 100644
--- a/src/test/java/org/olat/modules/quality/analysis/manager/StatisticsCalculatorTest.java
+++ b/src/test/java/org/olat/modules/quality/analysis/manager/StatisticsCalculatorTest.java
@@ -326,6 +326,24 @@ public class StatisticsCalculatorTest {
 		assertThat(trend3.getDirection()).isEqualTo(DIRECTION.UP);
 	}
 	
+	@Test
+	public void shouldCalculateTrendsByMultiKeyWithoutData() {
+		GroupedStatistics<GroupedStatistic> statistics = new GroupedStatistics<>();
+		
+		MultiTrendSeries<MultiKey> multiTrendSeries = sut.getTrendsByMultiKey(statistics, TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR);
+		
+		assertThat(multiTrendSeries.getTemporalKeys()).hasSize(0);
+	}
+	
+	@Test
+	public void shouldCalculateTrendssByIdentifiersWithoutData() {
+		GroupedStatistics<GroupedStatistic> statistics = new GroupedStatistics<>();
+		
+		MultiTrendSeries<String> multiTrendSeries = sut.getTrendsByIdentifiers(statistics, TemporalGroupBy.DATA_COLLECTION_DEADLINE_YEAR);
+		
+		assertThat(multiTrendSeries.getTemporalKeys()).hasSize(0);
+	}
+	
 	@Test
 	public void shouldReduceIdentifier() {
 		// Rubric 1
-- 
GitLab