use of org.olat.course.highscore.model.HighScoreRankingResults in project openolat by klemens.
the class HighScoreManager method processHistogramData.
/**
* Process histogram data.
*/
public HighScoreRankingResults processHistogramData(double[] scores, Float lowerBorder, Float upperBorder) {
try {
long classwidth;
// determine natural min, max and thus range
double max = Math.ceil(Arrays.stream(scores).max().getAsDouble());
double min = Math.floor(Arrays.stream(scores).min().getAsDouble());
double range = max - min;
// use original scores if range is too small else convert results to fit histogram
if (range <= 20 && range < 0) {
classwidth = 1;
return new HighScoreRankingResults(scores, classwidth, min);
} else {
if (lowerBorder == null) {
lowerBorder = 0f;
}
if (upperBorder == null) {
upperBorder = (float) max;
}
// decrease amount of possible classes to avoid overlapping of large numbers(condition) on x-axis
boolean largeNumbers = range > 100d || max >= 1000d;
int maxnumberofclasses = largeNumbers ? 12 : 20;
int minnumberofclasses = largeNumbers ? 4 : 5;
int numberofclasses = 10;
// primeRange increments range until a natural factor is found or upper/lower boundary is met
boolean primeRange = true;
// equalRangeExtend alternates between upper and lower boundary extension
int equalRangeExtend = 0;
// if true use it to calculate the class width
while (primeRange) {
for (int j = maxnumberofclasses; j > minnumberofclasses; j--) {
if (range % j == 0) {
numberofclasses = j;
primeRange = false;
break;
}
}
if (!primeRange || range <= 0 || equalRangeExtend > 10E3) {
break;
} else if (min - 1 > lowerBorder && equalRangeExtend % 2 == 0) {
min -= 1;
range = max - min;
equalRangeExtend++;
} else if (max + 1 < upperBorder && equalRangeExtend % 2 == 1) {
max += 1;
range = max - min;
equalRangeExtend++;
} else {
equalRangeExtend++;
}
// allow one extension if no borders are defined
primeRange = upperBorder - lowerBorder > 0;
}
// steps can only be natural numbersĀ
classwidth = Math.round(range / numberofclasses);
// modified scores are calculated and saved
double[] allScores = new double[scores.length];
for (int i = 0; i < scores.length; i++) {
// determine n-th class to fit the current score result
double n = Math.ceil((scores[i] - min) / classwidth);
// calculate higher score to fit the class width
double newscore = min + (n * classwidth);
allScores[i] = newscore;
}
return new HighScoreRankingResults(allScores, classwidth, min);
}
} catch (Exception e) {
log.error("", e);
return new HighScoreRankingResults(new double[] { 0, 1, 2, 3 }, 1L, 0D);
}
}
Aggregations