Started working on top statistic (#1)

This commit is contained in:
Artemis-the-gr8 2022-05-11 13:40:08 +02:00
parent 17a7d10a4c
commit e21d44e119
7 changed files with 177 additions and 104 deletions

View File

@ -18,13 +18,13 @@ public class Main extends JavaPlugin {
ConfigHandler config = new ConfigHandler(this);
EnumHandler enumHandler = new EnumHandler();
OutputFormatter outputFormatter = new OutputFormatter(config);
OutputFormatter outputFormatter = new OutputFormatter(config, this);
StatManager statManager = new StatManager(enumHandler, this);
this.getCommand("statistic").setExecutor(new StatCommand(outputFormatter, statManager, this));
this.getCommand("statistic").setTabCompleter(new TabCompleter(
enumHandler, statManager,this));
this.getCommand("statisticreload").setExecutor(new ReloadCommand(config, outputFormatter));
this.getCommand("statisticreload").setExecutor(new ReloadCommand(config, outputFormatter, this));
Bukkit.getPluginManager().registerEvents(new JoinListener(), this);
this.getLogger().info("Enabled PlayerStats!");
@ -45,4 +45,8 @@ public class Main extends JavaPlugin {
}
}
public long logTimeTaken(String className, long previousTime, int lineNumber) {
getLogger().info(className + " " + lineNumber + ": " + (System.currentTimeMillis() - previousTime));
return System.currentTimeMillis();
}
}

View File

@ -7,9 +7,7 @@ import org.bukkit.OfflinePlayer;
import org.bukkit.Statistic;
import org.bukkit.entity.EntityType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
public class StatManager {
@ -48,38 +46,32 @@ public class StatManager {
OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(playerName);
plugin.getLogger().info("StatManager 51: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatManager", time, 49);
if (player == null) throw new NullPointerException("No player called " + playerName + " was found!");
Statistic stat = getStatistic(statName);
plugin.getLogger().info("StatManager 56: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatManager", time, 53);
if (stat != null) {
switch (stat.getType()) {
case UNTYPED -> {
plugin.getLogger().info("StatManager 62: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatManager", time, 58);
return player.getStatistic(stat);
}
case BLOCK -> {
plugin.getLogger().info("StatManager 67: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatManager", time, 62);
Material block = enumHandler.getBlock(subStatEntryName);
if (block == null) throw new NullPointerException(subStatEntryName + " is not a valid block name!");
return player.getStatistic(stat, block);
}
case ENTITY -> {
plugin.getLogger().info("StatManager 74: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatManager", time, 68);
EntityType entity = enumHandler.getEntityType(subStatEntryName);
if (entity == null) throw new NullPointerException(subStatEntryName + " is not a valid entity name!");
return player.getStatistic(stat, entity);
}
case ITEM -> {
plugin.getLogger().info("StatManager 81: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatManager", time, 74);
Material item = enumHandler.getItem(subStatEntryName);
if (item == null) throw new NullPointerException(subStatEntryName + " is not a valid item name!");
return player.getStatistic(stat, item);
@ -89,15 +81,62 @@ public class StatManager {
throw new NullPointerException(statName + " is not a valid statistic name!");
}
//returns the statistic enum constant, or null if non-existent (param: statName, not case sensitive)
private Statistic getStatistic(String statName) {
try {
return Statistic.valueOf(statName.toUpperCase());
public LinkedHashMap<String, Integer> getTopStatistics(String statistic) {
return getTopStatistics(statistic, null);
}
public LinkedHashMap<String, Integer> getTopStatistics(String statName, String subStatEntry) {
long time = System.currentTimeMillis();
HashMap<String, Integer> playerStats = new HashMap<>((int) (offlinePlayerHandler.getOfflinePlayerCount() * 1.05));
time = plugin.logTimeTaken("StatManager", time, 91);
Statistic stat = getStatistic(statName);
time = plugin.logTimeTaken("StatManager", time, 94);
if (stat != null) {
switch (stat.getType()) {
case UNTYPED -> {
time = plugin.logTimeTaken("StatManager", time, 99);
for (String playerName : offlinePlayerHandler.getAllOfflinePlayerNames()) {
OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(playerName);
if (player != null) {
playerStats.put(playerName, player.getStatistic(stat));
}
}
}
}
time = plugin.logTimeTaken("StatManager", time, 109);
LinkedHashMap<String, Integer> topStats = playerStats.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(10).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
time = plugin.logTimeTaken("StatManager", time, 113);
plugin.getLogger().info("Top 10: " + topStats);
time = plugin.logTimeTaken("StatManager", time, 116);
HashMap<String, Integer> playerStats2 = new HashMap<>((int) (offlinePlayerHandler.getOfflinePlayerCount() * 1.05));
offlinePlayerHandler.getAllOfflinePlayerNames().stream().forEach(playerName -> {
OfflinePlayer player = offlinePlayerHandler.getOfflinePlayer(playerName);
if (player != null) playerStats2.put(playerName, player.getStatistic(stat));
});
time = plugin.logTimeTaken("StatManager", time, 124);
LinkedHashMap<String, Integer> topStats2 = playerStats2.entrySet().stream()
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.limit(10).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1, LinkedHashMap::new));
time = plugin.logTimeTaken("StatManager", time, 129);
plugin.getLogger().info("Top 10: " + topStats2);
time = plugin.logTimeTaken("StatManager", time, 131);
return topStats;
}
catch (IllegalArgumentException | NullPointerException exception) {
plugin.logStatRelatedExceptions(exception);
return null;
}
//checks if string is a valid statistic (param: statName, not case sensitive)
public boolean isStatistic(String statName) {
return statNames.contains(statName.toLowerCase());
}
//gets the type of the statistic from the string, otherwise returns null (param: statName, not case sensitive)
@ -111,17 +150,17 @@ public class StatManager {
}
}
//checks if string is a valid statistic (param: statName, not case sensitive)
public boolean isStatistic(String statName) {
return statNames.contains(statName.toLowerCase());
//returns the names of all general statistics in lowercase
public List<String> getStatNames() {
return statNames;
}
//checks if string is a valid substatistic dealing with entities (param: statName, not case sensitive)
public boolean isStatEntityType(String statName) {
return entityStatNames.contains(statName.toLowerCase());
//returns all statistics that have type entities, in lowercase
public List<String> getEntityStatNames() {
return entityStatNames;
}
//checks in the most general sense if this statistic is a substatistic (param: statName, not case sensitive)
//checks if this statistic is a subStatEntry, meaning it is a block, item or entity (param: statName, not case sensitive)
public boolean isSubStatEntry(String statName) {
return subStatEntryNames.contains(statName.toLowerCase());
}
@ -148,18 +187,14 @@ public class StatManager {
return false;
}
//returns the names of all general statistics in lowercase
public List<String> getStatNames() {
return statNames;
//returns the statistic enum constant, or null if non-existent (param: statName, not case sensitive)
private Statistic getStatistic(String statName) {
try {
return Statistic.valueOf(statName.toUpperCase());
}
//returns all statistics that have type entities, in lowercase
public List<String> getEntityTypeNames() {
return entityStatNames;
catch (IllegalArgumentException | NullPointerException exception) {
plugin.logStatRelatedExceptions(exception);
return null;
}
//returns all substatnames in lowercase
public List<String> getSubStatEntryNames() {
return subStatEntryNames;
}
}

View File

@ -1,6 +1,8 @@
package com.gmail.artemis.the.gr8.playerstats.commands;
import com.gmail.artemis.the.gr8.playerstats.ConfigHandler;
import com.gmail.artemis.the.gr8.playerstats.Main;
import com.gmail.artemis.the.gr8.playerstats.utils.OfflinePlayerHandler;
import com.gmail.artemis.the.gr8.playerstats.utils.OutputFormatter;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
@ -11,18 +13,30 @@ import org.jetbrains.annotations.NotNull;
public class ReloadCommand implements CommandExecutor {
private final ConfigHandler config;
private final OfflinePlayerHandler offlinePlayerHandler;
private final OutputFormatter outputFormatter;
private final Main plugin;
public ReloadCommand(ConfigHandler c, OutputFormatter o) {
public ReloadCommand(ConfigHandler c, OutputFormatter o, Main p) {
outputFormatter = o;
offlinePlayerHandler = OfflinePlayerHandler.getInstance();
config = c;
plugin = p;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
if (config.reloadConfig()) {
long time = System.currentTimeMillis();
outputFormatter.updateOutputColors();
time = plugin.logTimeTaken("ReloadCommand", time, 33);
offlinePlayerHandler.updateOfflinePlayers();
time = plugin.logTimeTaken("ReloadCommand", time, 36);
sender.sendMessage(ChatColor.GREEN + "Config reloaded!");
time = plugin.logTimeTaken("ReloadCommand", time, 39);
return true;
}
return false;

View File

@ -10,6 +10,8 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashMap;
public class StatCommand implements CommandExecutor {
@ -37,74 +39,75 @@ public class StatCommand implements CommandExecutor {
String subStatEntry = null;
String playerName = null;
boolean playerFlag = false;
boolean topFlag = false;
plugin.getLogger().info("onCommand 40: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 44);
//all args are in lowercase
for (String arg : args) {
if (statManager.isStatistic(arg)) {
statName = (statName == null) ? arg : statName;
plugin.getLogger().info("onCommand 48: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 50);
}
else if (statManager.isSubStatEntry(arg)) {
if (arg.equalsIgnoreCase("player")) {
if (!playerFlag) {
subStatEntry = (subStatEntry == null) ? arg : subStatEntry;
playerFlag = true;
plugin.getLogger().info("onCommand 56: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 57);
}
}
else {
subStatEntry = (subStatEntry == null || playerFlag) ? arg : subStatEntry;
plugin.getLogger().info("onCommand 62: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 62);
}
}
else if (arg.equalsIgnoreCase("top")) {
topFlag = true;
}
else if (arg.equalsIgnoreCase("me") && sender instanceof Player) {
playerName = sender.getName();
plugin.getLogger().info("onCommand 69: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 71);
}
else if (offlinePlayerHandler.isOfflinePlayerName(arg)) {
playerName = (playerName == null) ? arg : playerName;
plugin.getLogger().info("onCommand 74: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 75);
}
}
if (playerName != null && statName != null) {
plugin.getLogger().info("onCommand 79: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
if (statName != null) {
time = plugin.logTimeTaken("StatCommand", time, 79);
subStatEntry = statManager.isMatchingSubStatEntry(statName, subStatEntry) ? subStatEntry : null;
plugin.getLogger().info("onCommand 82: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 82);
if (topFlag) {
LinkedHashMap<String, Integer> topStats = statManager.getTopStatistics(statName, subStatEntry);
return true;
}
else if (playerName != null) {
try {
plugin.getLogger().info("onCommand 85: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 91);
int stat = statManager.getStatistic(statName, subStatEntry, playerName);
plugin.getLogger().info("onCommand 89: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 94);
String msg = outputFormatter.formatPlayerStat(playerName, statName, subStatEntry, stat);
plugin.getLogger().info("onCommand 93: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 97);
sender.sendMessage(msg);
plugin.getLogger().info("onCommand 97: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("StatCommand", time, 100);
}
catch (Exception e) {
sender.sendMessage(e.toString());
}
}
}
plugin.getLogger().info("onCommand 106: " + (System.currentTimeMillis() - time));
}
time = plugin.logTimeTaken("StatCommand", time, 108);
plugin.getLogger().info("Total time elapsed: " + (System.currentTimeMillis() - startTime));
return true;
}
}

View File

@ -66,7 +66,7 @@ public class TabCompleter implements org.bukkit.command.TabCompleter {
//if previous arg = "player", suggest playerNames
else if (args[args.length-2].equalsIgnoreCase("player")) {
if (args.length >= 3 && statManager.getEntityTypeNames().contains(args[args.length-3].toLowerCase())) {
if (args.length >= 3 && statManager.getEntityStatNames().contains(args[args.length-3].toLowerCase())) {
tabSuggestions = commandOptions;
}

View File

@ -4,14 +4,13 @@ import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.util.*;
import java.util.stream.Collectors;
public class OfflinePlayerHandler {
private static OfflinePlayerHandler instance;
private List<OfflinePlayer> offlinePlayers;
private List<String> offlinePlayerNames;
private HashMap<String, OfflinePlayer> offlinePlayerMap;
private List<String> offlinePlayerNames;
private int totalOfflinePlayers;
private OfflinePlayerHandler() {
updateOfflinePlayers();
@ -30,25 +29,45 @@ public class OfflinePlayerHandler {
public OfflinePlayer getOfflinePlayer(String playerName) {
long time = System.currentTimeMillis();
OfflinePlayer player = offlinePlayerMap.get(playerName);
System.out.println(("OfflinePlayerHandler 35: " + (System.currentTimeMillis() - time)));
return player;
return offlinePlayerMap.get(playerName);
}
public List<OfflinePlayer> getAllOfflinePlayers() {
return offlinePlayers;
public int getOfflinePlayerCount() {
return totalOfflinePlayers > 0 ? totalOfflinePlayers : 1;
}
public List<String> getAllOfflinePlayerNames() {
return offlinePlayerNames;
}
//stores a private HashMap with keys:playerName and values:OfflinePlayer, and a private list of the names for easy access
public void updateOfflinePlayers() {
offlinePlayerMap = new HashMap<>();
offlinePlayers = Arrays.stream(Bukkit.getOfflinePlayers()).filter(offlinePlayer ->
offlinePlayer.getName() != null && offlinePlayer.hasPlayedBefore()).collect(Collectors.toList());
offlinePlayerNames = offlinePlayers.stream().map(OfflinePlayer::getName).collect(Collectors.toList());
offlinePlayers.forEach(offlinePlayer -> offlinePlayerMap.put(offlinePlayer.getName(), offlinePlayer));
long totalTime = System.currentTimeMillis();
long time = System.currentTimeMillis();
if (offlinePlayerMap == null) offlinePlayerMap = new HashMap<>();
else if (!offlinePlayerMap.isEmpty()) {
offlinePlayerMap.clear();
}
if (offlinePlayerNames == null) offlinePlayerNames = new ArrayList<>();
else if (!offlinePlayerNames.isEmpty()) {
offlinePlayerNames.clear();
}
Arrays.stream(Bukkit.getOfflinePlayers()).filter(offlinePlayer ->
offlinePlayer.getName() != null && offlinePlayer.hasPlayedBefore()).forEach(offlinePlayer -> {
offlinePlayerNames.add(offlinePlayer.getName());
offlinePlayerMap.put(offlinePlayer.getName(), offlinePlayer);
});
System.out.println("OfflinePlayerHandler, making the HashMap and ArrayList: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
totalOfflinePlayers = offlinePlayerMap.size();
System.out.println("OfflinePlayerHandler, counting the HashMap: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
totalOfflinePlayers = offlinePlayerNames.size();
System.out.println("OfflinePlayerHandler, counting the ArrayList: " + (System.currentTimeMillis() - time));
System.out.println("updateOfflinePlayers total time: " + (System.currentTimeMillis() - totalTime));
}
}

View File

@ -15,10 +15,12 @@ public class OutputFormatter {
//subStatNames(Ranked)
//numbers(Ranked)
private final ConfigHandler config;
private final Main plugin;
private HashMap<String, ChatColor> chatColors;
public OutputFormatter(ConfigHandler c) {
public OutputFormatter(ConfigHandler c, Main p) {
config = c;
plugin = p;
updateOutputColors();
}
@ -32,19 +34,15 @@ public class OutputFormatter {
public String formatPlayerStat(String playerName, String statName, String subStatEntryName, int stat) {
long time = System.currentTimeMillis();
System.out.println("OutputFormatter 33: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("OutputFormatter", time, 37);
String subStat = subStatEntryName != null ?
chatColors.get("subStatNames") + " (" + subStatEntryName.toLowerCase().replace("_", " ") + ")" : "";
System.out.println("OutputFormatter 39: " + (System.currentTimeMillis() - time));
time = System.currentTimeMillis();
time = plugin.logTimeTaken("OutputFormatter", time, 41);
String msg = chatColors.get("playerNames") + playerName + chatColors.get("numbers") + ": " + stat + " " +
chatColors.get("statNames") + statName.toLowerCase().replace("_", " ") + subStat;
System.out.println("OutputFormatter 45: " + (System.currentTimeMillis() - time));
time = plugin.logTimeTaken("OutputFormatter", time, 45);
return msg;
}