Skip to content

Commit 9c535c5

Browse files
authored
Merge pull request #403 from BentoBoxWorld/copilot/fix-top-ten-order
Fix top ten ordering: replace LinkedHashMap with ConcurrentHashMap for thread safety
2 parents 6b986b8 + c5c6ef2 commit 9c535c5

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

src/main/java/world/bentobox/level/LevelsManager.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ private boolean addToTopTen(Island island, long lv) {
8282
&& hasTopTenPerm(island.getWorld(), island.getOwner())) {
8383
topTenLists.computeIfAbsent(island.getWorld(), k -> new TopTenData(island.getWorld())).getTopTen()
8484
.put(island.getUniqueId(), lv);
85+
// Invalidate the cache for this world because of the update
86+
cache.remove(island.getWorld());
8587
return true;
8688
}
8789
return false;

src/main/java/world/bentobox/level/objects/TopTenData.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package world.bentobox.level.objects;
22

3-
import java.util.LinkedHashMap;
43
import java.util.Locale;
54
import java.util.Map;
5+
import java.util.concurrent.ConcurrentHashMap;
66

77
import org.bukkit.World;
88

@@ -20,7 +20,7 @@ public class TopTenData {
2020
@Expose
2121
private String uniqueId = "";
2222
@Expose
23-
private Map<String, Long> topTen = new LinkedHashMap<>();
23+
private Map<String, Long> topTen = new ConcurrentHashMap<>();
2424

2525
public TopTenData(World k) {
2626
uniqueId = k.getName().toLowerCase(Locale.ENGLISH);

src/test/java/world/bentobox/level/LevelsManagerTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,43 @@ public void testSetIslandLevel() {
381381

382382
}
383383

384+
/**
385+
* Test method for
386+
* {@link world.bentobox.level.LevelsManager#getTopTen(org.bukkit.World, int)}.
387+
* Verifies that the top ten is sorted in descending order by level.
388+
*/
389+
@Test
390+
public void testGetTopTenSortOrder() {
391+
lm.createAndCleanRankings(world);
392+
Map<World, TopTenData> ttl = lm.getTopTenLists();
393+
Map<String, Long> tt = ttl.get(world).getTopTen();
394+
// Add islands in non-sorted order, mimicking the reported issue
395+
String island65 = UUID.randomUUID().toString();
396+
String island1065 = UUID.randomUUID().toString();
397+
String island500 = UUID.randomUUID().toString();
398+
String island200 = UUID.randomUUID().toString();
399+
// Insert in arbitrary order
400+
tt.put(island65, 65L);
401+
tt.put(island1065, 1065L);
402+
tt.put(island500, 500L);
403+
tt.put(island200, 200L);
404+
when(im.getIslandById(island65)).thenReturn(Optional.of(island));
405+
when(im.getIslandById(island1065)).thenReturn(Optional.of(island));
406+
when(im.getIslandById(island500)).thenReturn(Optional.of(island));
407+
when(im.getIslandById(island200)).thenReturn(Optional.of(island));
408+
409+
Map<String, Long> topTen = lm.getTopTen(world, Level.TEN);
410+
// Verify descending order
411+
long previousLevel = Long.MAX_VALUE;
412+
for (Long level : topTen.values()) {
413+
assertTrue("Top ten not in descending order: " + level + " should be <= " + previousLevel,
414+
level <= previousLevel);
415+
previousLevel = level;
416+
}
417+
// Verify highest is first
418+
assertEquals(1065L, topTen.values().iterator().next().longValue());
419+
}
420+
384421
/**
385422
* Test method for
386423
* {@link world.bentobox.level.LevelsManager#getRank(World, UUID)}

0 commit comments

Comments
 (0)