Skip to content

Commit 117d15f

Browse files
committed
Added more placeholders. #296
Refactored how the top ten maps are structured. In the future, it may be best to have the key be the island.
1 parent 9d1a5c7 commit 117d15f

File tree

4 files changed

+135
-63
lines changed

4 files changed

+135
-63
lines changed

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

+35
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.math.BigInteger;
44
import java.text.DecimalFormat;
5+
import java.util.AbstractMap;
56
import java.util.Collections;
67
import java.util.HashMap;
78
import java.util.LinkedHashMap;
@@ -293,6 +294,40 @@ public String getPointsToNextString(@NonNull World world, @Nullable UUID targetP
293294
return island == null ? "" : String.valueOf(getLevelsData(island).getPointsToNextLevel());
294295
}
295296

297+
/**
298+
* Get the weighted top ten for this world. Weighting is based on number of
299+
* players per team.
300+
*
301+
* @param world - world requested
302+
* @param size - size of the top ten
303+
* @return sorted top ten map. The key is the island unique ID
304+
*/
305+
@NonNull
306+
public Map<Island, Long> getWeightedTopTen(@NonNull World world, int size) {
307+
createAndCleanRankings(world);
308+
Map<Island, Long> weightedTopTen = topTenLists.get(world).getTopTen().entrySet().stream()
309+
.map(en -> addon.getIslands().getIslandById(en.getKey()).map(island -> {
310+
311+
long value = (long) (en.getValue() / (double) Math.max(1, island.getMemberSet().size())); // Calculate
312+
// weighted
313+
// value
314+
return new AbstractMap.SimpleEntry<>(island, value);
315+
}).orElse(null)) // Handle islands that do not exist according to this ID - old deleted ones
316+
.filter(Objects::nonNull) // Filter out null entries
317+
.filter(en -> en.getValue() > 0) // Filter out entries with non-positive values
318+
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) // Sort in descending order of values
319+
.limit(size) // Limit to the top 'size' entries
320+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, // In case of key
321+
// collision, choose
322+
// the first one
323+
LinkedHashMap::new // Preserves the order of entries
324+
));
325+
326+
// Return the unmodifiable map
327+
return Collections.unmodifiableMap(weightedTopTen);
328+
329+
}
330+
296331
/**
297332
* Get the top ten for this world. Returns offline players or players with the
298333
* intopten permission.

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

+53-48
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.util.Collections;
44
import java.util.Map;
5-
import java.util.Map.Entry;
65
import java.util.Optional;
76
import java.util.UUID;
87
import java.util.stream.Collectors;
@@ -66,19 +65,29 @@ protected void registerPlaceholders(GameModeAddon gm) {
6665
final int rank = i;
6766
// Name
6867
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_name_" + i,
69-
u -> getRankName(gm.getOverWorld(), rank));
68+
u -> getRankName(gm.getOverWorld(), rank, false));
7069
// Island Name
7170
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_island_name_" + i,
72-
u -> getRankIslandName(gm.getOverWorld(), rank));
71+
u -> getRankIslandName(gm.getOverWorld(), rank, false));
7372
// Members
7473
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_members_" + i,
75-
u -> getRankMembers(gm.getOverWorld(), rank));
74+
u -> getRankMembers(gm.getOverWorld(), rank, false));
7675
// Level
7776
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_value_" + i,
78-
u -> getRankLevel(gm.getOverWorld(), rank));
77+
u -> getRankLevel(gm.getOverWorld(), rank, false));
78+
// Weighted Level Name (Level / number of members)
79+
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_weighted_name_" + i,
80+
u -> getRankName(gm.getOverWorld(), rank, true));
81+
// Weighted Island Name
82+
bpm.registerPlaceholder(addon,
83+
gm.getDescription().getName().toLowerCase() + "_top_weighted_island_name_" + i,
84+
u -> getRankIslandName(gm.getOverWorld(), rank, true));
85+
// Weighted Members
86+
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_weighted_members_" + i,
87+
u -> getRankMembers(gm.getOverWorld(), rank, true));
7988
// Weighted Level (Level / number of members)
8089
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_weighted_value_" + i,
81-
u -> getWeightedRankLevel(gm.getOverWorld(), rank));
90+
u -> getRankLevel(gm.getOverWorld(), rank, true));
8291
}
8392

8493
// Personal rank
@@ -89,13 +98,18 @@ protected void registerPlaceholders(GameModeAddon gm) {
8998
/**
9099
* Get the name of the owner of the island who holds the rank in this world.
91100
*
92-
* @param world world
93-
* @param rank rank 1 to 10
101+
* @param world world
102+
* @param rank rank 1 to 10
103+
* @param weighted if true, then the weighted rank name is returned
94104
* @return rank name
95105
*/
96-
String getRankName(World world, int rank) {
106+
String getRankName(World world, int rank, boolean weighted) {
97107
// Ensure rank is within bounds
98108
rank = Math.max(1, Math.min(rank, Level.TEN));
109+
if (weighted) {
110+
return addon.getManager().getWeightedTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
111+
.findFirst().map(Island::getOwner).map(addon.getPlayers()::getName).orElse("");
112+
}
99113
@Nullable
100114
UUID owner = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
101115
.findFirst().flatMap(addon.getIslands()::getIslandById).map(Island::getOwner).orElse(null);
@@ -106,27 +120,42 @@ String getRankName(World world, int rank) {
106120
/**
107121
* Get the island name for this rank
108122
*
109-
* @param world world
110-
* @param rank rank 1 to 10
123+
* @param world world
124+
* @param rank rank 1 to 10
125+
* @param weighted if true, then the weighted rank name is returned
111126
* @return name of island or nothing if there isn't one
112127
*/
113-
String getRankIslandName(World world, int rank) {
128+
String getRankIslandName(World world, int rank, boolean weighted) {
114129
// Ensure rank is within bounds
115130
rank = Math.max(1, Math.min(rank, Level.TEN));
131+
if (weighted) {
132+
return addon.getManager().getWeightedTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
133+
.findFirst().map(Island::getName).orElse("");
134+
}
116135
return addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L).findFirst()
117136
.flatMap(addon.getIslands()::getIslandById).map(Island::getName).orElse("");
118137
}
119138

120139
/**
121140
* Gets a comma separated string of island member names
122141
*
123-
* @param world world
124-
* @param rank rank to request
142+
* @param world world
143+
* @param rank rank to request
144+
* @param weighted if true, then the weighted rank name is returned
125145
* @return comma separated string of island member names
126146
*/
127-
String getRankMembers(World world, int rank) {
147+
String getRankMembers(World world, int rank, boolean weighted) {
128148
// Ensure rank is within bounds
129149
rank = Math.max(1, Math.min(rank, Level.TEN));
150+
if (weighted) {
151+
return addon.getManager().getWeightedTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
152+
.findFirst()
153+
.map(is -> is.getMembers().entrySet().stream().filter(e -> e.getValue() >= RanksManager.MEMBER_RANK)
154+
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).map(Map.Entry::getKey)
155+
.map(addon.getPlayers()::getName).collect(Collectors.joining(",")))
156+
.orElse("");
157+
}
158+
130159
Optional<Island> island = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L)
131160
.limit(1L).findFirst().flatMap(addon.getIslands()::getIslandById);
132161

@@ -140,44 +169,20 @@ String getRankMembers(World world, int rank) {
140169
}
141170

142171
/**
143-
* Gets the weighted level, which is the level / number of players
172+
* Get the level for the rank requested
144173
*
145-
* @param world world
146-
* @param rank level
147-
* @return weighted level
174+
* @param world world
175+
* @param rank rank wanted
176+
* @param weighted true if weighted (level/number of team members)
177+
* @return level for the rank requested
148178
*/
149-
String getWeightedRankLevel(World world, int rank) {
179+
String getRankLevel(World world, int rank, boolean weighted) {
150180
// Ensure rank is within bounds
151181
rank = Math.max(1, Math.min(rank, Level.TEN));
152-
153-
// Retrieve the top ten entries
154-
Map<String, Long> topTen = addon.getManager().getTopTen(world, Level.TEN);
155-
if (topTen.isEmpty()) {
156-
return "";
182+
if (weighted) {
183+
return addon.getManager().formatLevel(addon.getManager().getWeightedTopTen(world, Level.TEN).values()
184+
.stream().skip(rank - 1L).limit(1L).findFirst().orElse(null));
157185
}
158-
159-
// Find the entry corresponding to the rank
160-
Entry<String, Long> entry = topTen.entrySet().stream().skip(rank - 1).findFirst().orElse(null);
161-
if (entry == null) {
162-
return "";
163-
}
164-
165-
// Calculate the score
166-
Island island = addon.getIslands().getIslandById(entry.getKey()).orElse(null);
167-
if (island == null || island.getMemberSet().isEmpty()) {
168-
return "";
169-
}
170-
171-
double score = (double) entry.getValue() / island.getMemberSet().size();
172-
173-
// Format and return the level
174-
return addon.getManager().formatLevel((long) score);
175-
176-
}
177-
178-
String getRankLevel(World world, int rank) {
179-
// Ensure rank is within bounds
180-
rank = Math.max(1, Math.min(rank, Level.TEN));
181186
return addon.getManager().formatLevel(addon.getManager().getTopTen(world, Level.TEN).values().stream()
182187
.skip(rank - 1L).limit(1L).findFirst().orElse(null));
183188
}

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

+13
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,19 @@ public void testGetTopTen() {
364364
assertEquals(1, lm.getTopTen(world, 1).size());
365365
}
366366

367+
/**
368+
* Test method for
369+
* {@link world.bentobox.level.LevelsManager#getWeightedTopTen(org.bukkit.World, int)}.
370+
*/
371+
@Test
372+
public void testGetWeightedTopTen() {
373+
testLoadTopTens();
374+
Map<Island, Long> tt = lm.getWeightedTopTen(world, Level.TEN);
375+
assertFalse(tt.isEmpty());
376+
assertEquals(1, tt.size());
377+
assertEquals(1, lm.getTopTen(world, 1).size());
378+
}
379+
367380
/**
368381
* Test method for
369382
* {@link world.bentobox.level.LevelsManager#hasTopTenPerm(org.bukkit.World, java.util.UUID)}.

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

+34-15
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@ public class PlaceholderManagerTest {
8383
names.put(UUID.randomUUID(), "vicky");
8484
}
8585
private Map<String, Island> islands = new HashMap<>();
86-
private Map<String, Long> map = new HashMap<>();
86+
private Map<String, Long> map = new LinkedHashMap<>();
87+
private Map<Island, Long> map2 = new LinkedHashMap<>();
8788
private @NonNull IslandLevels data;
8889
@Mock
8990
private PlayersManager pm;
@@ -105,13 +106,14 @@ public void setUp() throws Exception {
105106
int i = 0;
106107
for (Entry<UUID, String> n : names.entrySet()) {
107108
UUID uuid = UUID.randomUUID(); // Random island ID
108-
map.put(uuid.toString(), (long)(100 - i++)); // level
109+
Long value = (long)(100 - i++);
110+
map.put(uuid.toString(), value); // level
109111
Island is = new Island();
110112
is.setUniqueId(uuid.toString());
111113
is.setOwner(n.getKey());
112114
is.setName(n.getValue() + "'s island");
113115
islands.put(uuid.toString(), is);
114-
116+
map2.put(is, value);
115117
}
116118
// Sort
117119
map = map.entrySet().stream()
@@ -145,6 +147,7 @@ public void setUp() throws Exception {
145147
when(lm.getPointsToNextString(any(), any())).thenReturn("1234567");
146148
when(lm.getIslandMaxLevel(any(), any())).thenReturn(987654L);
147149
when(lm.getTopTen(world, Level.TEN)).thenReturn(map);
150+
when(lm.getWeightedTopTen(world, Level.TEN)).thenReturn(map2);
148151
when(lm.formatLevel(any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, Long.class).toString());
149152

150153
data = new IslandLevels("uniqueId");
@@ -206,12 +209,12 @@ public void testRegisterPlaceholders() {
206209
@Test
207210
public void testGetRankName() {
208211
// Test extremes
209-
assertEquals("tasty", phm.getRankName(world, 0));
210-
assertEquals("vicky", phm.getRankName(world, 100));
212+
assertEquals("tasty", phm.getRankName(world, 0, false));
213+
assertEquals("vicky", phm.getRankName(world, 100, false));
211214
// Test the ranks
212215
int rank = 1;
213216
for (String name : names.values()) {
214-
assertEquals(name, phm.getRankName(world, rank++));
217+
assertEquals(name, phm.getRankName(world, rank++, false));
215218
}
216219

217220
}
@@ -223,12 +226,12 @@ public void testGetRankName() {
223226
@Test
224227
public void testGetRankIslandName() {
225228
// Test extremes
226-
assertEquals("tasty's island", phm.getRankIslandName(world, 0));
227-
assertEquals("vicky's island", phm.getRankIslandName(world, 100));
229+
assertEquals("tasty's island", phm.getRankIslandName(world, 0, false));
230+
assertEquals("vicky's island", phm.getRankIslandName(world, 100, false));
228231
// Test the ranks
229232
int rank = 1;
230233
for (String name : names.values()) {
231-
assertEquals(name + "'s island", phm.getRankIslandName(world, rank++));
234+
assertEquals(name + "'s island", phm.getRankIslandName(world, rank++, false));
232235
}
233236

234237
}
@@ -240,11 +243,11 @@ public void testGetRankIslandName() {
240243
@Test
241244
public void testGetRankMembers() {
242245
// Test extremes
243-
check(1, phm.getRankMembers(world, 0));
244-
check(2, phm.getRankMembers(world, 100));
246+
check(1, phm.getRankMembers(world, 0, false));
247+
check(2, phm.getRankMembers(world, 100, false));
245248
// Test the ranks
246249
for (int rank = 1; rank < 11; rank++) {
247-
check(3, phm.getRankMembers(world, rank));
250+
check(3, phm.getRankMembers(world, rank, false));
248251
}
249252
}
250253

@@ -261,11 +264,27 @@ void check(int indicator, String list) {
261264
@Test
262265
public void testGetRankLevel() {
263266
// Test extremes
264-
assertEquals("100", phm.getRankLevel(world, 0));
265-
assertEquals("91", phm.getRankLevel(world, 100));
267+
assertEquals("100", phm.getRankLevel(world, 0, false));
268+
assertEquals("91", phm.getRankLevel(world, 100, false));
266269
// Test the ranks
267270
for (int rank = 1; rank < 11; rank++) {
268-
assertEquals(String.valueOf(101 - rank), phm.getRankLevel(world, rank));
271+
assertEquals(String.valueOf(101 - rank), phm.getRankLevel(world, rank, false));
272+
}
273+
274+
}
275+
276+
/**
277+
* Test method for
278+
* {@link world.bentobox.level.PlaceholderManager#getRankLevel(org.bukkit.World, int)}.
279+
*/
280+
@Test
281+
public void testGetWeightedRankLevel() {
282+
// Test extremes
283+
assertEquals("100", phm.getRankLevel(world, 0, true));
284+
assertEquals("91", phm.getRankLevel(world, 100, true));
285+
// Test the ranks
286+
for (int rank = 1; rank < 11; rank++) {
287+
assertEquals(String.valueOf(101 - rank), phm.getRankLevel(world, rank, true));
269288
}
270289

271290
}

0 commit comments

Comments
 (0)