use of org.olat.course.highscore.model.HighScoreRankingResults in project OpenOLAT by OpenOLAT.
the class HighScoreManager method sortRankByScore.
/**
* Sort rank by score, then by id and last alphabetically,
* determine rank of each member dependent on score,
* decide whether there is a second table or not
*/
public HighScoreRankingResults sortRankByScore(List<AssessmentEntry> assessEntries, List<HighScoreTableEntry> allMembers, List<HighScoreTableEntry> ownIdMembers, List<List<HighScoreTableEntry>> allPodium, List<Integer> ownIdIndices, int tableSize, Identity ownIdentity) {
HighScoreTableEntry ownTableEntry = null;
for (AssessmentEntry assessmentEntry : assessEntries) {
float score = assessmentEntry.getScore() == null ? 0f : assessmentEntry.getScore().floatValue();
HighScoreTableEntry tableEntry = new HighScoreTableEntry(score, userManager.getUserDisplayName(assessmentEntry.getIdentity()), assessmentEntry.getIdentity());
if (tableEntry.getIdentity().equals(ownIdentity)) {
ownTableEntry = tableEntry;
}
allMembers.add(tableEntry);
}
assessEntries.clear();
// 3 step comparator, sorts by score then own Identity comes first, last alphabetically
Collections.sort(allMembers, new HighscoreComparator(ownIdentity));
float buffer = -1;
int index = 0;
// int rank = 1;
double[] allScores = new double[allMembers.size()];
for (int j = 0; j < allMembers.size(); j++) {
HighScoreTableEntry member = allMembers.get(j);
if (member.getScore() < buffer) {
index++;
// rank = j + 1;
}
// first three position are put in separate lists, exclude zero scorers
if (index < 3 && member.getScore() > 0) {
allPodium.get(index).add(member);
}
// finding position rank for own id
if (member.getIdentity().equals(ownIdentity)) {
ownIdIndices.add(j);
}
// setting rank for each member
member.setRank(index + 1);
buffer = member.getScore();
// adding scores for histogram
allScores[j] = buffer;
}
// only getting member with own id for 2nd table
ownIdMembers.addAll(allMembers.stream().skip(tableSize).filter(a -> a.getIdentity().equals(ownIdentity)).collect(Collectors.toList()));
if (ownIdMembers.size() > 0) {
log.audit("2nd Highscore Table established");
}
return new HighScoreRankingResults(allScores, ownTableEntry);
}
use of org.olat.course.highscore.model.HighScoreRankingResults in project OpenOLAT by OpenOLAT.
the class HighScoreRunController method initForm.
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
VelocityContainer mainVC = this.flc.getFormItemComponent();
mainVC.put("loadd3js", new StatisticsComponent("d3loader"));
if (viewHistogram) {
VelocityContainer scoreHistogramVC = createVelocityContainer("histogram_score");
// transfer all scores to velocity container as base data for histogram
HighScoreRankingResults modifiedData = highScoreManager.processHistogramData(allScores, lowerBorder, upperBorder);
allScores = modifiedData.getModifiedScores();
scoreHistogramVC.contextPut("datas", BarSeries.datasToString(allScores));
// histogram marker for own position
scoreHistogramVC.contextPut("cutValue", ownIdIndices.size() > 0 ? highScoreManager.calculateHistogramCutvalue(allMembers.get(ownIdIndices.get(0)).getScore(), modifiedData.getClasswidth(), modifiedData.getMin()) : -1000);
// classwidth to correctly display the histogram
long classwidth = modifiedData.getClasswidth();
scoreHistogramVC.contextPut("step", classwidth);
// find path for ownID image to display in histogram
UserAvatarMapper mapper = new UserAvatarMapper(false);
String mapperPath = registerMapper(ureq, mapper);
String identityMapperPath = mapper.createPathFor(mapperPath, ownIdentity);
scoreHistogramVC.contextPut("mapperUrl", identityMapperPath);
mainVC.put("scoreHistogram", scoreHistogramVC);
}
if (viewPodium) {
String[] localizer = { "first", "second", "third" };
// for clarity and space reasons do not show any portraits if one position has more than 6 persons
int maxPerson = 6;
boolean showPortraits = !anonymous && allPodium.get(0).size() <= maxPerson && allPodium.get(1).size() <= maxPerson && allPodium.get(2).size() <= maxPerson;
for (int i = 0; i < localizer.length; i++) {
int sizePerPos = allPodium.get(i).size();
StringBuilder sb = new StringBuilder();
if (sizePerPos > 2) {
int reduce = 0;
// create link if podium has more than 2 entries per rank, entries can be displayed as anonymous
if (allPodium.get(i).get(0).getIdentity().equals(ownIdentity)) {
sb.append(userManager.getUserDisplayName(ownIdentity));
++reduce;
}
if (sizePerPos > 6 || anonymous) {
mainVC.contextPut("further" + (i + 1), (sizePerPos - reduce) + " " + (reduce == 1 ? translate("highscore.further") : translate("highscore.total")));
} else {
links[i] = LinkFactory.createLink(null, "link" + (i + 1), "cmd", (sizePerPos - reduce) + " " + (reduce == 1 ? translate("highscore.further") : translate("highscore.total")), getTranslator(), mainVC, this, 16);
}
} else {
for (HighScoreTableEntry te : allPodium.get(i)) {
if (!anonymous || te.getIdentity().equals(ownIdentity)) {
sb.append(userManager.getUserDisplayName(te.getIdentity()));
sb.append("<br/>");
}
}
}
mainVC.contextPut(localizer[i], sizePerPos > 0 ? sb.toString() : translate("highscore.unavail"));
mainVC.contextPut("score" + (i + 1), sizePerPos > 0 ? allPodium.get(i).get(0).getScore() : null);
if (sizePerPos > 0 && showPortraits) {
// decide whether or not to display id portrait
mainVC.contextPut("number" + (i + 1), sizePerPos);
for (int j = 0; j < sizePerPos; j++) {
Identity currentID = allPodium.get(i).get(j).getIdentity();
boolean choosePortrait = !anonymous || ownIdentity.equals(currentID);
DisplayPortraitController portrait = new DisplayPortraitController(ureq, getWindowControl(), currentID, false, choosePortrait, !choosePortrait);
listenTo(portrait);
Component portraitComponent = portrait.getInitialComponent();
mainVC.put("portrait" + (i + 1) + "-" + (j + 1), portraitComponent);
}
} else {
// if amount of people per rank is too large, own id portrait can still be displayed
for (int j = 0; j < sizePerPos; j++) {
Identity currentID = allPodium.get(i).get(j).getIdentity();
if (ownIdentity.equals(currentID)) {
DisplayPortraitController portrait = new DisplayPortraitController(ureq, getWindowControl(), currentID, true, true, false);
listenTo(portrait);
mainVC.put("portrait" + (i + 1), portrait.getInitialComponent());
}
}
}
}
}
if (viewTable) {
FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("highscore.table.header1", HighScoreTableEntry.RANK));
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("highscore.table.header2", HighScoreTableEntry.SCORE));
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("highscore.table.header3", HighScoreTableEntry.NAME));
// trim to tableSize
if (tableSize < allMembers.size()) {
allMembers.subList(tableSize, allMembers.size()).clear();
}
tableDataModel = new FlexiTableDataModelImpl<HighScoreTableEntry>(new HighScoreFlexiTableModel(allMembers, anonymous, translate("highscore.anonymous"), ownIdentity), tableColumnModel);
FlexiTableElement topTenTable = uifactory.addTableElement(getWindowControl(), "table", tableDataModel, getTranslator(), formLayout);
topTenTable.setNumOfRowsEnabled(false);
topTenTable.setCustomizeColumns(false);
topTenTable.setCssDelegate(new MarkedMemberCssDelegate(false));
// establish a 2nd table if ownID position is greater than first table's size setting
if (!ownIdMembers.isEmpty()) {
tableDataModel2 = new FlexiTableDataModelImpl<HighScoreTableEntry>(new HighScoreFlexiTableModel(ownIdMembers, anonymous, translate("highscore.anonymous"), ownIdentity), tableColumnModel);
FlexiTableElement tableElement = uifactory.addTableElement(getWindowControl(), "table2", tableDataModel2, getTranslator(), formLayout);
tableElement.setNumOfRowsEnabled(false);
tableElement.setCustomizeColumns(false);
tableElement.setCssDelegate(new MarkedMemberCssDelegate(true));
}
}
if (viewPosition && ownIdIndices.size() > 0) {
int amountWorse = allScores.length - ownIdIndices.get(0) - 1;
if (amountWorse > 0) {
mainVC.contextPut("relposition", translate("highscore.position.inrelation", new String[] { String.valueOf(amountWorse) }));
}
int ownRank = highscoreDataModel.getOwnTableEntry().getRank();
mainVC.contextPut("position", translate("highscore.position.yourposition", new String[] { String.valueOf(ownRank) }));
}
}
use of org.olat.course.highscore.model.HighScoreRankingResults in project openolat by klemens.
the class HighScoreManager method sortRankByScore.
/**
* Sort rank by score, then by id and last alphabetically,
* determine rank of each member dependent on score,
* decide whether there is a second table or not
*/
public HighScoreRankingResults sortRankByScore(List<AssessmentEntry> assessEntries, List<HighScoreTableEntry> allMembers, List<HighScoreTableEntry> ownIdMembers, List<List<HighScoreTableEntry>> allPodium, List<Integer> ownIdIndices, int tableSize, Identity ownIdentity) {
HighScoreTableEntry ownTableEntry = null;
for (AssessmentEntry assessmentEntry : assessEntries) {
float score = assessmentEntry.getScore() == null ? 0f : assessmentEntry.getScore().floatValue();
HighScoreTableEntry tableEntry = new HighScoreTableEntry(score, userManager.getUserDisplayName(assessmentEntry.getIdentity()), assessmentEntry.getIdentity());
if (tableEntry.getIdentity().equals(ownIdentity)) {
ownTableEntry = tableEntry;
}
allMembers.add(tableEntry);
}
assessEntries.clear();
// 3 step comparator, sorts by score then own Identity comes first, last alphabetically
Collections.sort(allMembers, new HighscoreComparator(ownIdentity));
float buffer = -1;
int index = 0;
// int rank = 1;
double[] allScores = new double[allMembers.size()];
for (int j = 0; j < allMembers.size(); j++) {
HighScoreTableEntry member = allMembers.get(j);
if (member.getScore() < buffer) {
index++;
// rank = j + 1;
}
// first three position are put in separate lists, exclude zero scorers
if (index < 3 && member.getScore() > 0) {
allPodium.get(index).add(member);
}
// finding position rank for own id
if (member.getIdentity().equals(ownIdentity)) {
ownIdIndices.add(j);
}
// setting rank for each member
member.setRank(index + 1);
buffer = member.getScore();
// adding scores for histogram
allScores[j] = buffer;
}
// only getting member with own id for 2nd table
ownIdMembers.addAll(allMembers.stream().skip(tableSize).filter(a -> a.getIdentity().equals(ownIdentity)).collect(Collectors.toList()));
if (ownIdMembers.size() > 0) {
log.audit("2nd Highscore Table established");
}
return new HighScoreRankingResults(allScores, ownTableEntry);
}
use of org.olat.course.highscore.model.HighScoreRankingResults in project openolat by klemens.
the class HighScoreRunController method initForm.
@Override
protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) {
VelocityContainer mainVC = this.flc.getFormItemComponent();
mainVC.put("loadd3js", new StatisticsComponent("d3loader"));
if (viewHistogram) {
VelocityContainer scoreHistogramVC = createVelocityContainer("histogram_score");
// transfer all scores to velocity container as base data for histogram
HighScoreRankingResults modifiedData = highScoreManager.processHistogramData(allScores, lowerBorder, upperBorder);
allScores = modifiedData.getModifiedScores();
scoreHistogramVC.contextPut("datas", BarSeries.datasToString(allScores));
// histogram marker for own position
scoreHistogramVC.contextPut("cutValue", ownIdIndices.size() > 0 ? highScoreManager.calculateHistogramCutvalue(allMembers.get(ownIdIndices.get(0)).getScore(), modifiedData.getClasswidth(), modifiedData.getMin()) : -1000);
// classwidth to correctly display the histogram
long classwidth = modifiedData.getClasswidth();
scoreHistogramVC.contextPut("step", classwidth);
// find path for ownID image to display in histogram
UserAvatarMapper mapper = new UserAvatarMapper(false);
String mapperPath = registerMapper(ureq, mapper);
String identityMapperPath = mapper.createPathFor(mapperPath, ownIdentity);
scoreHistogramVC.contextPut("mapperUrl", identityMapperPath);
mainVC.put("scoreHistogram", scoreHistogramVC);
}
if (viewPodium) {
String[] localizer = { "first", "second", "third" };
// for clarity and space reasons do not show any portraits if one position has more than 6 persons
int maxPerson = 6;
boolean showPortraits = !anonymous && allPodium.get(0).size() <= maxPerson && allPodium.get(1).size() <= maxPerson && allPodium.get(2).size() <= maxPerson;
for (int i = 0; i < localizer.length; i++) {
int sizePerPos = allPodium.get(i).size();
StringBuilder sb = new StringBuilder();
if (sizePerPos > 2) {
int reduce = 0;
// create link if podium has more than 2 entries per rank, entries can be displayed as anonymous
if (allPodium.get(i).get(0).getIdentity().equals(ownIdentity)) {
sb.append(userManager.getUserDisplayName(ownIdentity));
++reduce;
}
if (sizePerPos > 6 || anonymous) {
mainVC.contextPut("further" + (i + 1), (sizePerPos - reduce) + " " + (reduce == 1 ? translate("highscore.further") : translate("highscore.total")));
} else {
links[i] = LinkFactory.createLink(null, "link" + (i + 1), "cmd", (sizePerPos - reduce) + " " + (reduce == 1 ? translate("highscore.further") : translate("highscore.total")), getTranslator(), mainVC, this, 16);
}
} else {
for (HighScoreTableEntry te : allPodium.get(i)) {
if (!anonymous || te.getIdentity().equals(ownIdentity)) {
sb.append(userManager.getUserDisplayName(te.getIdentity()));
sb.append("<br/>");
}
}
}
mainVC.contextPut(localizer[i], sizePerPos > 0 ? sb.toString() : translate("highscore.unavail"));
mainVC.contextPut("score" + (i + 1), sizePerPos > 0 ? allPodium.get(i).get(0).getScore() : null);
if (sizePerPos > 0 && showPortraits) {
// decide whether or not to display id portrait
mainVC.contextPut("number" + (i + 1), sizePerPos);
for (int j = 0; j < sizePerPos; j++) {
Identity currentID = allPodium.get(i).get(j).getIdentity();
boolean choosePortrait = !anonymous || ownIdentity.equals(currentID);
DisplayPortraitController portrait = new DisplayPortraitController(ureq, getWindowControl(), currentID, false, choosePortrait, !choosePortrait);
listenTo(portrait);
Component portraitComponent = portrait.getInitialComponent();
mainVC.put("portrait" + (i + 1) + "-" + (j + 1), portraitComponent);
}
} else {
// if amount of people per rank is too large, own id portrait can still be displayed
for (int j = 0; j < sizePerPos; j++) {
Identity currentID = allPodium.get(i).get(j).getIdentity();
if (ownIdentity.equals(currentID)) {
DisplayPortraitController portrait = new DisplayPortraitController(ureq, getWindowControl(), currentID, true, true, false);
listenTo(portrait);
mainVC.put("portrait" + (i + 1), portrait.getInitialComponent());
}
}
}
}
}
if (viewTable) {
FlexiTableColumnModel tableColumnModel = FlexiTableDataModelFactory.createFlexiTableColumnModel();
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("highscore.table.header1", HighScoreTableEntry.RANK));
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("highscore.table.header2", HighScoreTableEntry.SCORE));
tableColumnModel.addFlexiColumnModel(new DefaultFlexiColumnModel("highscore.table.header3", HighScoreTableEntry.NAME));
// trim to tableSize
if (tableSize < allMembers.size()) {
allMembers.subList(tableSize, allMembers.size()).clear();
}
tableDataModel = new FlexiTableDataModelImpl<HighScoreTableEntry>(new HighScoreFlexiTableModel(allMembers, anonymous, translate("highscore.anonymous"), ownIdentity), tableColumnModel);
FlexiTableElement topTenTable = uifactory.addTableElement(getWindowControl(), "table", tableDataModel, getTranslator(), formLayout);
topTenTable.setNumOfRowsEnabled(false);
topTenTable.setCustomizeColumns(false);
topTenTable.setCssDelegate(new MarkedMemberCssDelegate(false));
// establish a 2nd table if ownID position is greater than first table's size setting
if (!ownIdMembers.isEmpty()) {
tableDataModel2 = new FlexiTableDataModelImpl<HighScoreTableEntry>(new HighScoreFlexiTableModel(ownIdMembers, anonymous, translate("highscore.anonymous"), ownIdentity), tableColumnModel);
FlexiTableElement tableElement = uifactory.addTableElement(getWindowControl(), "table2", tableDataModel2, getTranslator(), formLayout);
tableElement.setNumOfRowsEnabled(false);
tableElement.setCustomizeColumns(false);
tableElement.setCssDelegate(new MarkedMemberCssDelegate(true));
}
}
if (viewPosition && ownIdIndices.size() > 0) {
int amountWorse = allScores.length - ownIdIndices.get(0) - 1;
if (amountWorse > 0) {
mainVC.contextPut("relposition", translate("highscore.position.inrelation", new String[] { String.valueOf(amountWorse) }));
}
int ownRank = highscoreDataModel.getOwnTableEntry().getRank();
mainVC.contextPut("position", translate("highscore.position.yourposition", new String[] { String.valueOf(ownRank) }));
}
}
use of org.olat.course.highscore.model.HighScoreRankingResults in project OpenOLAT by OpenOLAT.
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