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.
This commit is contained in:
tastybento 2023-11-24 09:33:16 -08:00
parent 9d1a5c7476
commit 117d15f3d0
4 changed files with 135 additions and 63 deletions

View File

@ -2,6 +2,7 @@ package world.bentobox.level;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
@ -293,6 +294,40 @@ public class LevelsManager {
return island == null ? "" : String.valueOf(getLevelsData(island).getPointsToNextLevel());
}
/**
* Get the weighted top ten for this world. Weighting is based on number of
* players per team.
*
* @param world - world requested
* @param size - size of the top ten
* @return sorted top ten map. The key is the island unique ID
*/
@NonNull
public Map<Island, Long> getWeightedTopTen(@NonNull World world, int size) {
createAndCleanRankings(world);
Map<Island, Long> weightedTopTen = topTenLists.get(world).getTopTen().entrySet().stream()
.map(en -> addon.getIslands().getIslandById(en.getKey()).map(island -> {
long value = (long) (en.getValue() / (double) Math.max(1, island.getMemberSet().size())); // Calculate
// weighted
// value
return new AbstractMap.SimpleEntry<>(island, value);
}).orElse(null)) // Handle islands that do not exist according to this ID - old deleted ones
.filter(Objects::nonNull) // Filter out null entries
.filter(en -> en.getValue() > 0) // Filter out entries with non-positive values
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())) // Sort in descending order of values
.limit(size) // Limit to the top 'size' entries
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, // In case of key
// collision, choose
// the first one
LinkedHashMap::new // Preserves the order of entries
));
// Return the unmodifiable map
return Collections.unmodifiableMap(weightedTopTen);
}
/**
* Get the top ten for this world. Returns offline players or players with the
* intopten permission.

View File

@ -2,7 +2,6 @@ package world.bentobox.level;
import java.util.Collections;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.UUID;
import java.util.stream.Collectors;
@ -66,19 +65,29 @@ public class PlaceholderManager {
final int rank = i;
// Name
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_name_" + i,
u -> getRankName(gm.getOverWorld(), rank));
u -> getRankName(gm.getOverWorld(), rank, false));
// Island Name
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_island_name_" + i,
u -> getRankIslandName(gm.getOverWorld(), rank));
u -> getRankIslandName(gm.getOverWorld(), rank, false));
// Members
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_members_" + i,
u -> getRankMembers(gm.getOverWorld(), rank));
u -> getRankMembers(gm.getOverWorld(), rank, false));
// Level
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_value_" + i,
u -> getRankLevel(gm.getOverWorld(), rank));
u -> getRankLevel(gm.getOverWorld(), rank, false));
// Weighted Level Name (Level / number of members)
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_weighted_name_" + i,
u -> getRankName(gm.getOverWorld(), rank, true));
// Weighted Island Name
bpm.registerPlaceholder(addon,
gm.getDescription().getName().toLowerCase() + "_top_weighted_island_name_" + i,
u -> getRankIslandName(gm.getOverWorld(), rank, true));
// Weighted Members
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_weighted_members_" + i,
u -> getRankMembers(gm.getOverWorld(), rank, true));
// Weighted Level (Level / number of members)
bpm.registerPlaceholder(addon, gm.getDescription().getName().toLowerCase() + "_top_weighted_value_" + i,
u -> getWeightedRankLevel(gm.getOverWorld(), rank));
u -> getRankLevel(gm.getOverWorld(), rank, true));
}
// Personal rank
@ -89,13 +98,18 @@ public class PlaceholderManager {
/**
* Get the name of the owner of the island who holds the rank in this world.
*
* @param world world
* @param rank rank 1 to 10
* @param world world
* @param rank rank 1 to 10
* @param weighted if true, then the weighted rank name is returned
* @return rank name
*/
String getRankName(World world, int rank) {
String getRankName(World world, int rank, boolean weighted) {
// Ensure rank is within bounds
rank = Math.max(1, Math.min(rank, Level.TEN));
if (weighted) {
return addon.getManager().getWeightedTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
.findFirst().map(Island::getOwner).map(addon.getPlayers()::getName).orElse("");
}
@Nullable
UUID owner = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
.findFirst().flatMap(addon.getIslands()::getIslandById).map(Island::getOwner).orElse(null);
@ -106,13 +120,18 @@ public class PlaceholderManager {
/**
* Get the island name for this rank
*
* @param world world
* @param rank rank 1 to 10
* @param world world
* @param rank rank 1 to 10
* @param weighted if true, then the weighted rank name is returned
* @return name of island or nothing if there isn't one
*/
String getRankIslandName(World world, int rank) {
String getRankIslandName(World world, int rank, boolean weighted) {
// Ensure rank is within bounds
rank = Math.max(1, Math.min(rank, Level.TEN));
if (weighted) {
return addon.getManager().getWeightedTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
.findFirst().map(Island::getName).orElse("");
}
return addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L).findFirst()
.flatMap(addon.getIslands()::getIslandById).map(Island::getName).orElse("");
}
@ -120,13 +139,23 @@ public class PlaceholderManager {
/**
* Gets a comma separated string of island member names
*
* @param world world
* @param rank rank to request
* @param world world
* @param rank rank to request
* @param weighted if true, then the weighted rank name is returned
* @return comma separated string of island member names
*/
String getRankMembers(World world, int rank) {
String getRankMembers(World world, int rank, boolean weighted) {
// Ensure rank is within bounds
rank = Math.max(1, Math.min(rank, Level.TEN));
if (weighted) {
return addon.getManager().getWeightedTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L).limit(1L)
.findFirst()
.map(is -> is.getMembers().entrySet().stream().filter(e -> e.getValue() >= RanksManager.MEMBER_RANK)
.sorted(Collections.reverseOrder(Map.Entry.comparingByValue())).map(Map.Entry::getKey)
.map(addon.getPlayers()::getName).collect(Collectors.joining(",")))
.orElse("");
}
Optional<Island> island = addon.getManager().getTopTen(world, Level.TEN).keySet().stream().skip(rank - 1L)
.limit(1L).findFirst().flatMap(addon.getIslands()::getIslandById);
@ -140,44 +169,20 @@ public class PlaceholderManager {
}
/**
* Gets the weighted level, which is the level / number of players
* Get the level for the rank requested
*
* @param world world
* @param rank level
* @return weighted level
* @param world world
* @param rank rank wanted
* @param weighted true if weighted (level/number of team members)
* @return level for the rank requested
*/
String getWeightedRankLevel(World world, int rank) {
String getRankLevel(World world, int rank, boolean weighted) {
// Ensure rank is within bounds
rank = Math.max(1, Math.min(rank, Level.TEN));
// Retrieve the top ten entries
Map<String, Long> topTen = addon.getManager().getTopTen(world, Level.TEN);
if (topTen.isEmpty()) {
return "";
if (weighted) {
return addon.getManager().formatLevel(addon.getManager().getWeightedTopTen(world, Level.TEN).values()
.stream().skip(rank - 1L).limit(1L).findFirst().orElse(null));
}
// Find the entry corresponding to the rank
Entry<String, Long> entry = topTen.entrySet().stream().skip(rank - 1).findFirst().orElse(null);
if (entry == null) {
return "";
}
// Calculate the score
Island island = addon.getIslands().getIslandById(entry.getKey()).orElse(null);
if (island == null || island.getMemberSet().isEmpty()) {
return "";
}
double score = (double) entry.getValue() / island.getMemberSet().size();
// Format and return the level
return addon.getManager().formatLevel((long) score);
}
String getRankLevel(World world, int rank) {
// Ensure rank is within bounds
rank = Math.max(1, Math.min(rank, Level.TEN));
return addon.getManager().formatLevel(addon.getManager().getTopTen(world, Level.TEN).values().stream()
.skip(rank - 1L).limit(1L).findFirst().orElse(null));
}

View File

@ -364,6 +364,19 @@ public class LevelsManagerTest {
assertEquals(1, lm.getTopTen(world, 1).size());
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#getWeightedTopTen(org.bukkit.World, int)}.
*/
@Test
public void testGetWeightedTopTen() {
testLoadTopTens();
Map<Island, Long> tt = lm.getWeightedTopTen(world, Level.TEN);
assertFalse(tt.isEmpty());
assertEquals(1, tt.size());
assertEquals(1, lm.getTopTen(world, 1).size());
}
/**
* Test method for
* {@link world.bentobox.level.LevelsManager#hasTopTenPerm(org.bukkit.World, java.util.UUID)}.

View File

@ -83,7 +83,8 @@ public class PlaceholderManagerTest {
names.put(UUID.randomUUID(), "vicky");
}
private Map<String, Island> islands = new HashMap<>();
private Map<String, Long> map = new HashMap<>();
private Map<String, Long> map = new LinkedHashMap<>();
private Map<Island, Long> map2 = new LinkedHashMap<>();
private @NonNull IslandLevels data;
@Mock
private PlayersManager pm;
@ -105,13 +106,14 @@ public class PlaceholderManagerTest {
int i = 0;
for (Entry<UUID, String> n : names.entrySet()) {
UUID uuid = UUID.randomUUID(); // Random island ID
map.put(uuid.toString(), (long)(100 - i++)); // level
Long value = (long)(100 - i++);
map.put(uuid.toString(), value); // level
Island is = new Island();
is.setUniqueId(uuid.toString());
is.setOwner(n.getKey());
is.setName(n.getValue() + "'s island");
islands.put(uuid.toString(), is);
map2.put(is, value);
}
// Sort
map = map.entrySet().stream()
@ -145,6 +147,7 @@ public class PlaceholderManagerTest {
when(lm.getPointsToNextString(any(), any())).thenReturn("1234567");
when(lm.getIslandMaxLevel(any(), any())).thenReturn(987654L);
when(lm.getTopTen(world, Level.TEN)).thenReturn(map);
when(lm.getWeightedTopTen(world, Level.TEN)).thenReturn(map2);
when(lm.formatLevel(any())).thenAnswer((Answer<String>) invocation -> invocation.getArgument(0, Long.class).toString());
data = new IslandLevels("uniqueId");
@ -206,12 +209,12 @@ public class PlaceholderManagerTest {
@Test
public void testGetRankName() {
// Test extremes
assertEquals("tasty", phm.getRankName(world, 0));
assertEquals("vicky", phm.getRankName(world, 100));
assertEquals("tasty", phm.getRankName(world, 0, false));
assertEquals("vicky", phm.getRankName(world, 100, false));
// Test the ranks
int rank = 1;
for (String name : names.values()) {
assertEquals(name, phm.getRankName(world, rank++));
assertEquals(name, phm.getRankName(world, rank++, false));
}
}
@ -223,12 +226,12 @@ public class PlaceholderManagerTest {
@Test
public void testGetRankIslandName() {
// Test extremes
assertEquals("tasty's island", phm.getRankIslandName(world, 0));
assertEquals("vicky's island", phm.getRankIslandName(world, 100));
assertEquals("tasty's island", phm.getRankIslandName(world, 0, false));
assertEquals("vicky's island", phm.getRankIslandName(world, 100, false));
// Test the ranks
int rank = 1;
for (String name : names.values()) {
assertEquals(name + "'s island", phm.getRankIslandName(world, rank++));
assertEquals(name + "'s island", phm.getRankIslandName(world, rank++, false));
}
}
@ -240,11 +243,11 @@ public class PlaceholderManagerTest {
@Test
public void testGetRankMembers() {
// Test extremes
check(1, phm.getRankMembers(world, 0));
check(2, phm.getRankMembers(world, 100));
check(1, phm.getRankMembers(world, 0, false));
check(2, phm.getRankMembers(world, 100, false));
// Test the ranks
for (int rank = 1; rank < 11; rank++) {
check(3, phm.getRankMembers(world, rank));
check(3, phm.getRankMembers(world, rank, false));
}
}
@ -261,11 +264,27 @@ public class PlaceholderManagerTest {
@Test
public void testGetRankLevel() {
// Test extremes
assertEquals("100", phm.getRankLevel(world, 0));
assertEquals("91", phm.getRankLevel(world, 100));
assertEquals("100", phm.getRankLevel(world, 0, false));
assertEquals("91", phm.getRankLevel(world, 100, false));
// Test the ranks
for (int rank = 1; rank < 11; rank++) {
assertEquals(String.valueOf(101 - rank), phm.getRankLevel(world, rank));
assertEquals(String.valueOf(101 - rank), phm.getRankLevel(world, rank, false));
}
}
/**
* Test method for
* {@link world.bentobox.level.PlaceholderManager#getRankLevel(org.bukkit.World, int)}.
*/
@Test
public void testGetWeightedRankLevel() {
// Test extremes
assertEquals("100", phm.getRankLevel(world, 0, true));
assertEquals("91", phm.getRankLevel(world, 100, true));
// Test the ranks
for (int rank = 1; rank < 11; rank++) {
assertEquals(String.valueOf(101 - rank), phm.getRankLevel(world, rank, true));
}
}