From 6968ef2b027d09f701abd4156f92686e17f1df41 Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Wed, 29 Mar 2017 10:18:35 +0200 Subject: [PATCH] OO-2657: implement the round robin algorithm with usage statistics --- .../nodes/gta/manager/GTAManagerImpl.java | 52 +++++++++++++------ .../nodes/gta/manager/GTAManagerTest.java | 35 ++++++++++++- 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java index bba5000030c..b1e4a902370 100644 --- a/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java +++ b/src/main/java/org/olat/course/nodes/gta/manager/GTAManagerImpl.java @@ -26,10 +26,12 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; import javax.persistence.LockModeType; import javax.persistence.Query; @@ -889,18 +891,6 @@ public class GTAManagerImpl implements GTAManager, DeletableGroupData { } protected String nextSlotRoundRobin(String[] slots, List<String> usedSlots) { - //remove previous rounds - Set<String> usedOnce = new HashSet<>(); - for(Iterator<String> usedSlotIt=usedSlots.iterator(); usedSlotIt.hasNext(); ) { - String usedSlot = usedSlotIt.next(); - if(usedOnce.contains(usedSlot)) { - usedSlotIt.remove(); - } else { - usedOnce.add(usedSlot); - } - } - - //usedSlots are cleaned and contains only current round String nextSlot = null; for(String slot:slots) { if(!usedSlots.contains(slot)) { @@ -909,11 +899,41 @@ public class GTAManagerImpl implements GTAManager, DeletableGroupData { } } + //not found an used slot if(nextSlot == null) { - //begin a new round - if (slots.length > 0) { - nextSlot = slots[0]; + //statistics + Map<String,AtomicInteger> usages = new HashMap<>(); + for(String usedSlot:usedSlots) { + if(usages.containsKey(usedSlot)) { + usages.get(usedSlot).incrementAndGet(); + } else { + usages.put(usedSlot, new AtomicInteger(1)); + } + } + + int minimum = Integer.MAX_VALUE; + for(AtomicInteger slotUsage:usages.values()) { + minimum = Math.min(minimum, slotUsage.get()); } + Set<String> slotsWithMinimalUsage = new HashSet<>(); + for(Map.Entry<String, AtomicInteger> slotUsage:usages.entrySet()) { + if(slotUsage.getValue().get() == minimum) { + slotsWithMinimalUsage.add(slotUsage.getKey()); + } + } + + //found the next slot with minimal usage + for(String slot:slots) { + if(slotsWithMinimalUsage.contains(slot)) { + nextSlot = slot; + break; + } + } + } + + //security + if(nextSlot == null && slots.length > 0) { + nextSlot = slots[0]; } return nextSlot; } diff --git a/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java b/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java index 91eb3470a00..f96e3b4394d 100644 --- a/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java +++ b/src/test/java/org/olat/course/nodes/gta/manager/GTAManagerTest.java @@ -600,7 +600,7 @@ public class GTAManagerTest extends OlatTestCase { } @Test - public void roundsRobin() { + public void roundRobin_oneRound() { String[] slots = new String[]{ "A", "B", "C" }; List<String> usedSlots = new ArrayList<>(); usedSlots.add("A"); @@ -608,7 +608,40 @@ public class GTAManagerTest extends OlatTestCase { usedSlots.add("C"); usedSlots.add("A"); + String nextSlot = gtaManager.nextSlotRoundRobin(slots, usedSlots); + Assert.assertEquals("B", nextSlot); + } + + @Test + public void roundRobin_randomRound() { + String[] slots = new String[]{ "A", "B", "C" }; + List<String> usedSlots = new ArrayList<>(); + usedSlots.add("A"); + usedSlots.add("B"); + usedSlots.add("B"); + usedSlots.add("B"); + usedSlots.add("C"); + usedSlots.add("C"); + usedSlots.add("A"); + String nextSlot = gtaManager.nextSlotRoundRobin(slots, usedSlots); Assert.assertEquals("A", nextSlot); } + + @Test + public void roundRobin_randomRoundAlt() { + String[] slots = new String[]{ "A", "B", "C" }; + List<String> usedSlots = new ArrayList<>(); + usedSlots.add("A"); + usedSlots.add("B"); + usedSlots.add("B"); + usedSlots.add("B"); + usedSlots.add("C"); + usedSlots.add("C"); + usedSlots.add("A"); + usedSlots.add("A"); + + String nextSlot = gtaManager.nextSlotRoundRobin(slots, usedSlots); + Assert.assertEquals("C", nextSlot); + } } -- GitLab