From 39de2b9cc8494de4f134c8ac859b90dbea1978c2 Mon Sep 17 00:00:00 2001 From: tastybento Date: Thu, 8 Aug 2019 17:12:12 -0700 Subject: [PATCH] Adds shorthand level presentation for large level values. https://github.com/BentoBoxWorld/Level/issues/52 --- src/main/java/world/bentobox/level/Level.java | 15 ++++-- .../world/bentobox/level/LevelPresenter.java | 46 +++++++++++++++++-- .../java/world/bentobox/level/TopTen.java | 4 +- .../world/bentobox/level/config/Settings.java | 6 +++ .../level/placeholders/LevelPlaceholder.java | 5 +- .../placeholders/TopTenNamePlaceholder.java | 3 -- .../level/placeholders/TopTenPlaceholder.java | 3 -- src/main/resources/config.yml | 4 ++ .../bentobox/level/LevelPresenterTest.java | 38 +++++++++++++-- .../java/world/bentobox/level/TopTenTest.java | 23 ++++++---- 10 files changed, 116 insertions(+), 31 deletions(-) diff --git a/src/main/java/world/bentobox/level/Level.java b/src/main/java/world/bentobox/level/Level.java index fba0fc6..181faf5 100644 --- a/src/main/java/world/bentobox/level/Level.java +++ b/src/main/java/world/bentobox/level/Level.java @@ -47,7 +47,7 @@ public class Level extends Addon { private TopTen topTen; // Level calculator - private LevelPresenter levelCalc; + private LevelPresenter levelPresenter; /** * Calculates a user's island @@ -56,7 +56,7 @@ public class Level extends Addon { * @param playerUUID - the target island member's UUID */ public void calculateIslandLevel(World world, @Nullable User user, UUID playerUUID) { - levelCalc.calculateIslandLevel(world, user, playerUUID); + levelPresenter.calculateIslandLevel(world, user, playerUUID); } /** @@ -86,7 +86,7 @@ public class Level extends Addon { /** * @return the settings */ - public final Settings getSettings() { + public Settings getSettings() { return settings; } @@ -94,6 +94,13 @@ public class Level extends Addon { return topTen; } + /** + * @return the levelPresenter + */ + public LevelPresenter getLevelPresenter() { + return levelPresenter; + } + @Override public void onDisable(){ // Save the cache @@ -116,7 +123,7 @@ public class Level extends Addon { // Initialize the cache levelsCache = new HashMap<>(); // Load the calculator - levelCalc = new LevelPresenter(this, this.getPlugin()); + levelPresenter = new LevelPresenter(this, this.getPlugin()); // Start the top ten and register it for clicks topTen = new TopTen(this); registerListener(topTen); diff --git a/src/main/java/world/bentobox/level/LevelPresenter.java b/src/main/java/world/bentobox/level/LevelPresenter.java index 480e842..c4a5bd3 100644 --- a/src/main/java/world/bentobox/level/LevelPresenter.java +++ b/src/main/java/world/bentobox/level/LevelPresenter.java @@ -1,7 +1,11 @@ package world.bentobox.level; +import java.math.BigInteger; +import java.text.DecimalFormat; import java.util.Calendar; import java.util.HashMap; +import java.util.Map; +import java.util.TreeMap; import java.util.UUID; import org.bukkit.World; @@ -10,7 +14,18 @@ import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.api.user.User; import world.bentobox.level.calculators.PlayerLevel; -class LevelPresenter { +public class LevelPresenter { + + private static final BigInteger THOUSAND = BigInteger.valueOf(1000); + private static final TreeMap LEVELS; + static { + LEVELS = new TreeMap<>(); + + LEVELS.put(THOUSAND, "k"); + LEVELS.put(THOUSAND.pow(2), "M"); + LEVELS.put(THOUSAND.pow(3), "G"); + LEVELS.put(THOUSAND.pow(4), "T"); + } private int levelWait; private final Level addon; @@ -60,11 +75,36 @@ class LevelPresenter { } } else { - // Asking for the level of another player - sender.sendMessage("island.level.island-level-is","[level]", String.valueOf(addon.getIslandLevel(world, targetPlayer))); + long lvl = addon.getIslandLevel(world, targetPlayer); + + sender.sendMessage("island.level.island-level-is","[level]", getLevelString(lvl)); } } + /** + * Get the string representation of the level. May be converted to shorthand notation, e.g., 104556 -> 10.5k + * @param lvl - long value to represent + * @return string of the level. + */ + public String getLevelString(long lvl) { + String level = String.valueOf(lvl); + // Asking for the level of another player + if(addon.getSettings().isShortHand()) { + BigInteger levelValue = BigInteger.valueOf(lvl); + + Map.Entry stage = LEVELS.floorEntry(levelValue); + + if (stage != null) { // level > 1000 + // 1 052 -> 1.0k + // 1 527 314 -> 1.5M + // 3 874 130 021 -> 3.8G + // 4 002 317 889 -> 4.0T + level = new DecimalFormat("#.#").format(levelValue.divide(stage.getKey().divide(THOUSAND)).doubleValue()/1000.0) + stage.getValue(); + } + } + return level; + } + /** * Sets cool down for the level command * diff --git a/src/main/java/world/bentobox/level/TopTen.java b/src/main/java/world/bentobox/level/TopTen.java index 9648e4d..157375b 100644 --- a/src/main/java/world/bentobox/level/TopTen.java +++ b/src/main/java/world/bentobox/level/TopTen.java @@ -125,12 +125,12 @@ public class TopTen implements Listener { * @param asker - the asker of the top ten * @return PanelItem */ - private PanelItem getHead(int rank, Long level, UUID playerUUID, User asker, World world) { + private PanelItem getHead(int rank, long level, UUID playerUUID, User asker, World world) { final String name = addon.getPlayers().getName(playerUUID); List description = new ArrayList<>(); if (name != null) { description.add(asker.getTranslation("island.top.gui-heading", "[name]", name, "[rank]", String.valueOf(rank))); - description.add(asker.getTranslation("island.top.island-level","[level]", String.valueOf(level))); + description.add(asker.getTranslation("island.top.island-level","[level]", addon.getLevelPresenter().getLevelString(level))); if (addon.getIslands().inTeam(world, playerUUID)) { List memberList = new ArrayList<>(); for (UUID members : addon.getIslands().getMembers(world, playerUUID)) { diff --git a/src/main/java/world/bentobox/level/config/Settings.java b/src/main/java/world/bentobox/level/config/Settings.java index 7158283..5a16783 100644 --- a/src/main/java/world/bentobox/level/config/Settings.java +++ b/src/main/java/world/bentobox/level/config/Settings.java @@ -212,4 +212,10 @@ public class Settings { return level.getConfig().getBoolean("login"); } + /** + * @return true if levels should be shown in shorthand notation, e.g., 10,234 -> 10k + */ + public boolean isShortHand() { + return level.getConfig().getBoolean("shorthand"); + } } diff --git a/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java b/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java index da61bf0..4bf27ee 100644 --- a/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java +++ b/src/main/java/world/bentobox/level/placeholders/LevelPlaceholder.java @@ -1,6 +1,3 @@ -/** - * - */ package world.bentobox.level.placeholders; import world.bentobox.bentobox.api.addons.GameModeAddon; @@ -32,7 +29,7 @@ public class LevelPlaceholder implements PlaceholderReplacer { */ @Override public String onReplace(User user) { - return String.valueOf(addon.getIslandLevel(gm.getOverWorld(), user.getUniqueId())); + return addon.getLevelPresenter().getLevelString(addon.getIslandLevel(gm.getOverWorld(), user.getUniqueId())); } } diff --git a/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java b/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java index 593b18d..b0e7c67 100644 --- a/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java +++ b/src/main/java/world/bentobox/level/placeholders/TopTenNamePlaceholder.java @@ -1,6 +1,3 @@ -/** - * - */ package world.bentobox.level.placeholders; import java.util.Collection; diff --git a/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java b/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java index 27849e4..0da18d3 100644 --- a/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java +++ b/src/main/java/world/bentobox/level/placeholders/TopTenPlaceholder.java @@ -1,6 +1,3 @@ -/** - * - */ package world.bentobox.level.placeholders; import java.util.Collection; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index cd0fffe..3651de6 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -50,6 +50,10 @@ deathpenalty: 100 sumteamdeaths: false # For other death related settings, see the GameModeAddon's config.yml settings. +# Shorthand island level +# Shows large level values rounded down, e.g., 10,345 -> 10k +shorthand: false + # This section lists the limits for any particular block. Blocks over this amount # are not counted. # Format: diff --git a/src/test/java/world/bentobox/level/LevelPresenterTest.java b/src/test/java/world/bentobox/level/LevelPresenterTest.java index e701c72..01e33e6 100644 --- a/src/test/java/world/bentobox/level/LevelPresenterTest.java +++ b/src/test/java/world/bentobox/level/LevelPresenterTest.java @@ -1,5 +1,6 @@ package world.bentobox.level; +import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -10,6 +11,7 @@ import org.bukkit.World; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PrepareForTest; @@ -20,6 +22,7 @@ import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.level.calculators.PlayerLevel; +import world.bentobox.level.config.Settings; /** * @author tastybento @@ -29,14 +32,17 @@ import world.bentobox.level.calculators.PlayerLevel; @PrepareForTest({Bukkit.class, LevelPresenter.class}) public class LevelPresenterTest { + @Mock private BentoBox plugin; + @Mock private Level addon; + @Mock private PlayerLevel pl; + @Mock + private Settings settings; @Before public void setUp() throws Exception { - plugin = mock(BentoBox.class); - addon = mock(Level.class); IslandWorldManager iwm = mock(IslandWorldManager.class); when(plugin.getIWM()).thenReturn(iwm); when(iwm.getPermissionPrefix(Mockito.any())).thenReturn("world"); @@ -49,9 +55,11 @@ public class LevelPresenterTest { // team leader when(im.getOwner(Mockito.any(), Mockito.any())).thenReturn(UUID.randomUUID()); - pl = mock(PlayerLevel.class); + // Player level PowerMockito.whenNew(PlayerLevel.class).withAnyArguments().thenReturn(pl); + // Settings + when(addon.getSettings()).thenReturn(settings); } /** @@ -76,4 +84,28 @@ public class LevelPresenterTest { Mockito.verify(sender).sendMessage("island.level.calculating"); } + /** + * Test method for {@link LevelPresenter#getLevelString(long)}. + */ + @Test + public void testGetLevelStringLong() { + LevelPresenter lp = new LevelPresenter(addon, plugin); + assertEquals("123456789", lp.getLevelString(123456789L)); + + } + + /** + * Test method for {@link LevelPresenter#getLevelString(long)}. + */ + @Test + public void testGetLevelStringLongShorthand() { + when(settings.isShortHand()).thenReturn(true); + LevelPresenter lp = new LevelPresenter(addon, plugin); + assertEquals("123.5M", lp.getLevelString(123456789L)); + assertEquals("1.2k", lp.getLevelString(1234L)); + assertEquals("123.5G", lp.getLevelString(123456789352L)); + assertEquals("1.2T", lp.getLevelString(1234567893524L)); + assertEquals("12345.7T", lp.getLevelString(12345678345345349L)); + + } } diff --git a/src/test/java/world/bentobox/level/TopTenTest.java b/src/test/java/world/bentobox/level/TopTenTest.java index 47cee5c..8dd3807 100644 --- a/src/test/java/world/bentobox/level/TopTenTest.java +++ b/src/test/java/world/bentobox/level/TopTenTest.java @@ -3,10 +3,11 @@ package world.bentobox.level; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyInt; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -23,7 +24,6 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemFactory; import org.bukkit.inventory.meta.ItemMeta; -import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -44,6 +44,7 @@ import world.bentobox.bentobox.database.DatabaseSetup; import world.bentobox.bentobox.managers.IslandWorldManager; import world.bentobox.bentobox.managers.IslandsManager; import world.bentobox.bentobox.managers.PlayersManager; +import world.bentobox.level.config.Settings; import world.bentobox.level.objects.TopTenData; @RunWith(PowerMockRunner.class) @@ -71,6 +72,11 @@ public class TopTenTest { private PlayersManager pm; @Mock private Inventory inv; + @Mock + private LevelPresenter lp; + @Mock + private Settings settings; + @SuppressWarnings("unchecked") @BeforeClass @@ -87,7 +93,6 @@ public class TopTenTest { @Before public void setUp() throws Exception { - plugin = mock(BentoBox.class); Whitebox.setInternalState(BentoBox.class, "instance", plugin); when(addon.getPlugin()).thenReturn(plugin); @@ -142,10 +147,10 @@ public class TopTenTest { // Inventory GUI when(Bukkit.createInventory(any(), anyInt(), anyString())).thenReturn(inv); - } - @After - public void tearDown() throws Exception { + // Level presenter + when(addon.getLevelPresenter()).thenReturn(lp); + when(lp.getLevelString(anyLong())).thenAnswer((Answer) invocation -> String.valueOf(invocation.getArgument(0, Long.class))); } @Test