mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-21 23:51:29 +01:00
[2.6.0-RELEASE] PlanLite features, Analysis tabs, final bugfixes
- Fixed DB removeall method. more here: https://www.spigotmc.org/resources/plan-player-analytics.32536/update?update=146125
This commit is contained in:
parent
f0daeb91c4
commit
091e3eb1c5
@ -49,6 +49,12 @@
|
||||
<version>2.10.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.palmergames</groupId>
|
||||
<artifactId>towny</artifactId>
|
||||
<version>0.91.4.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- -->
|
||||
<dependency>
|
||||
<groupId>com.googlecode.charts4j</groupId>
|
||||
|
@ -35,6 +35,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import main.java.com.djrapitops.plan.api.API;
|
||||
import main.java.com.djrapitops.plan.command.PlanCommand;
|
||||
import main.java.com.djrapitops.plan.data.additional.HookHandler;
|
||||
import main.java.com.djrapitops.plan.data.cache.*;
|
||||
import main.java.com.djrapitops.plan.data.listeners.*;
|
||||
import main.java.com.djrapitops.plan.database.Database;
|
||||
@ -56,16 +57,12 @@ Play session length
|
||||
- Playtime month
|
||||
- Playtime week
|
||||
Location Analysis to view meaningful locations on Dynmap (Investigate dynmap api)
|
||||
Integrate PlanLite features to Plan and discontinue PlanLite
|
||||
- Towny hook
|
||||
- Text interface
|
||||
Text interface
|
||||
Database Cleaning of useless data
|
||||
Sortable player table.
|
||||
- Players page
|
||||
- Navigation (Security req)
|
||||
Add -n argument for nickname search.
|
||||
Location saving & getting seperately
|
||||
Fix any bugs that come up
|
||||
Random security code generation
|
||||
*/
|
||||
/**
|
||||
*
|
||||
@ -80,6 +77,7 @@ public class Plan extends JavaPlugin {
|
||||
private Database db;
|
||||
private HashSet<Database> databases;
|
||||
private WebSocketServer uiServer;
|
||||
private HookHandler hookHandler;
|
||||
|
||||
private int bootAnalysisTaskID;
|
||||
|
||||
@ -146,6 +144,7 @@ public class Plan extends JavaPlugin {
|
||||
consoleSender.sendMessage(Phrase.NOTIFY_EMPTY_IP + "");
|
||||
}
|
||||
|
||||
hookHandler = new HookHandler(this);
|
||||
log(Phrase.ENABLED + "");
|
||||
}
|
||||
|
||||
@ -241,7 +240,7 @@ public class Plan extends JavaPlugin {
|
||||
pluginManager.registerEvents(new PlanCommandPreprocessListener(this), this);
|
||||
pluginManager.registerEvents(new PlanDeathEventListener(this), this);
|
||||
if (Settings.GATHERLOCATIONS.isTrue()) {
|
||||
// pluginManager.registerEvents(new PlanPlayerMoveListener(this), this);
|
||||
pluginManager.registerEvents(new PlanPlayerMoveListener(this), this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,6 +336,10 @@ public class Plan extends JavaPlugin {
|
||||
return uiServer;
|
||||
}
|
||||
|
||||
public HookHandler getHookHandler() {
|
||||
return hookHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Set containing SqLite & MySQL classes.
|
||||
*/
|
||||
|
@ -82,11 +82,6 @@ public class ManageBackupCommand extends SubCommand {
|
||||
SQLiteDB backupDB = new SQLiteDB(plugin,
|
||||
args[0] + "-backup-" + now.toString().substring(4, 10).replaceAll(" ", "-").replaceAll(":", "-"));
|
||||
|
||||
if (!backupDB.init()) {
|
||||
sender.sendMessage(Phrase.MANAGE_DATABASE_FAILURE + "");
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(Phrase.MANAGE_PROCESS_START.parse());
|
||||
backupDB.removeAllData();
|
||||
Set<UUID> uuids = copyFromDB.getSavedUUIDs();
|
||||
|
@ -1,10 +0,0 @@
|
||||
|
||||
package main.java.com.djrapitops.plan.data;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class AdditionalData {
|
||||
|
||||
}
|
@ -43,7 +43,6 @@ public class UserData {
|
||||
|
||||
private SessionData currentSession;
|
||||
private List<SessionData> sessions;
|
||||
private AdditionalData additionalData;
|
||||
|
||||
public UserData(Player player, DemographicsData demData) {
|
||||
accessing = 0;
|
||||
@ -71,7 +70,6 @@ public class UserData {
|
||||
sessions = new ArrayList<>();
|
||||
lastNick = "";
|
||||
playerKills = new ArrayList<>();
|
||||
additionalData = new AdditionalData();
|
||||
}
|
||||
|
||||
public UserData(OfflinePlayer player, DemographicsData demData) {
|
||||
@ -98,12 +96,8 @@ public class UserData {
|
||||
sessions = new ArrayList<>();
|
||||
lastNick = "";
|
||||
playerKills = new ArrayList<>();
|
||||
additionalData = new AdditionalData();
|
||||
}
|
||||
|
||||
public AdditionalData getAdditionalData() {
|
||||
return additionalData;
|
||||
}
|
||||
|
||||
public void addIpAddress(InetAddress ip) {
|
||||
if (!ips.contains(ip)) {
|
||||
|
@ -22,13 +22,13 @@ public class AdvancedAchievementsHook extends Hook {
|
||||
* @param plugin
|
||||
*/
|
||||
public AdvancedAchievementsHook(Plan plugin) {
|
||||
super(AdvancedAchievements.class);
|
||||
super("com.hm.achievement.AdvancedAchievements");
|
||||
this.plugin = plugin;
|
||||
if (isEnabled()) {
|
||||
if (super.isEnabled()) {
|
||||
try {
|
||||
totalAchievements = calcTotalAchievements();
|
||||
} catch (Exception | NoClassDefFoundError e) {
|
||||
setEnabled(false);
|
||||
super.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -21,11 +22,15 @@ public class EssentialsHook extends Hook {
|
||||
|
||||
/**
|
||||
* Hooks to Essentials plugin
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
public EssentialsHook(Plan plugin) {
|
||||
super(Essentials.class);
|
||||
this.plugin = plugin;
|
||||
super("com.earth2me.essentials.Essentials");
|
||||
this.plugin = plugin;
|
||||
if (super.isEnabled()) {
|
||||
ess = getPlugin(Essentials.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,21 +38,24 @@ public class EssentialsHook extends Hook {
|
||||
* isEnabled() should be called before this method.
|
||||
*
|
||||
* @param uuid UUID of player
|
||||
* @return HashMap with boolean, int and string values: JAILED boolean, MUTED
|
||||
* boolean, AFK boolean, GOD boolean, JAILTIMEOUT
|
||||
* @return HashMap with boolean, int and string values: JAILED boolean,
|
||||
* MUTED boolean
|
||||
*/
|
||||
public HashMap<String, Serializable> getEssentialsData(UUID uuid) {
|
||||
HashMap<String, Serializable> essData = new HashMap<>();
|
||||
User user = ess.getUser(uuid);
|
||||
essData.put("JAILED", user.isJailed());
|
||||
essData.put("MUTED", user.isMuted());
|
||||
essData.put("AFK", user.isAfk());
|
||||
essData.put("GOD", user.isGodModeEnabled());
|
||||
User user = ess.getUser(uuid);
|
||||
if (user != null) {
|
||||
essData.put("JAILED", user.isJailed());
|
||||
essData.put("MUTED", user.isMuted());
|
||||
} else {
|
||||
essData.put("JAILED", false);
|
||||
essData.put("MUTED", false);
|
||||
}
|
||||
return essData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
* @return Warp list
|
||||
*/
|
||||
public List<String> getWarps() {
|
||||
return (ArrayList<String>) ess.getWarps().getList();
|
||||
|
@ -28,7 +28,7 @@ public class FactionsHook extends Hook {
|
||||
* @param plugin
|
||||
*/
|
||||
public FactionsHook(Plan plugin) {
|
||||
super(Factions.class);
|
||||
super("com.massivecraft.factions.Factions");
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@ -61,24 +61,31 @@ public class FactionsHook extends Hook {
|
||||
info.put("LAND", faction.getPower());
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab power of player. isEnabled() should be called before this
|
||||
* method.
|
||||
* @param uuid UUID of player
|
||||
* @return Faction power of player
|
||||
*/
|
||||
public double getPower(UUID uuid) {
|
||||
return MPlayer.get(uuid).getPower();
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab Max power of player. isEnabled() should be called before this
|
||||
* Grab info about a Player. isEnabled() should be called before this
|
||||
* method.
|
||||
* @param uuid UUID of player
|
||||
* @return Faction Max power of player
|
||||
*
|
||||
* @param uuid UUID of the player
|
||||
* @return HashMap containing boolean, number & string: POWER int, MAXPOWER
|
||||
* int, FACTION String
|
||||
*/
|
||||
public double getMaxPower(UUID uuid) {
|
||||
return MPlayer.get(uuid).getPowerMax();
|
||||
public HashMap<String, Serializable> getPlayerInfo(UUID uuid) {
|
||||
HashMap<String, Serializable> info = new HashMap<>();
|
||||
MPlayer mPlayer = MPlayer.get(uuid);
|
||||
if (mPlayer != null) {
|
||||
info.put("POWER", mPlayer.getPower());
|
||||
info.put("MAXPOWER", mPlayer.getPowerMax());
|
||||
if (mPlayer.hasFaction()) {
|
||||
info.put("FACTION", mPlayer.getFactionName());
|
||||
} else {
|
||||
info.put("FACTION", "Not in faction");
|
||||
}
|
||||
} else {
|
||||
info.put("POWER",0);
|
||||
info.put("MAXPOWER", 0);
|
||||
info.put("FACTION", "Not in faction");
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,10 @@ public abstract class Hook {
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
public Hook(Class<? extends JavaPlugin> plugin) {
|
||||
JavaPlugin hookedPlugin = getPlugin(plugin);
|
||||
public Hook(String plugin) {
|
||||
try {
|
||||
Class<? extends JavaPlugin> pluginClass = (Class<? extends JavaPlugin>) Class.forName(plugin);
|
||||
JavaPlugin hookedPlugin = getPlugin(pluginClass);
|
||||
enabled = hookedPlugin.isEnabled();
|
||||
} catch (Exception | NoClassDefFoundError e) {
|
||||
enabled = false;
|
||||
|
@ -1,34 +1,45 @@
|
||||
package main.java.com.djrapitops.plan.data.additional;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.ui.tables.SortableFactionsTableCreator;
|
||||
import main.java.com.djrapitops.plan.ui.tables.SortableTownTableCreator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class HookHandler {
|
||||
|
||||
private Plan plan;
|
||||
private AdvancedAchievementsHook advancedAchievementsHook;
|
||||
private EssentialsHook essentialsHook;
|
||||
private SuperbVoteHook superbVoteHook;
|
||||
private FactionsHook factionsHook;
|
||||
private OnTimeHook onTimeHook;
|
||||
private TownyHook townyHook;
|
||||
|
||||
public HookHandler(Plan plan) {
|
||||
this.plan = plan;
|
||||
hook();
|
||||
}
|
||||
|
||||
|
||||
public void reloadHooks() {
|
||||
hook();
|
||||
}
|
||||
|
||||
|
||||
private void hook() {
|
||||
advancedAchievementsHook = new AdvancedAchievementsHook(plan);
|
||||
essentialsHook = new EssentialsHook(plan);
|
||||
superbVoteHook = new SuperbVoteHook(plan);
|
||||
factionsHook = new FactionsHook(plan);
|
||||
townyHook = new TownyHook(plan);
|
||||
onTimeHook = new OnTimeHook(plan);
|
||||
}
|
||||
|
||||
|
||||
public AdvancedAchievementsHook getAdvancedAchievementsHook() {
|
||||
return advancedAchievementsHook;
|
||||
}
|
||||
@ -44,6 +55,57 @@ public class HookHandler {
|
||||
public FactionsHook getFactionsHook() {
|
||||
return factionsHook;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public TownyHook getTownyHook() {
|
||||
return townyHook;
|
||||
}
|
||||
|
||||
public OnTimeHook getOnTimeHook() {
|
||||
return onTimeHook;
|
||||
}
|
||||
|
||||
public Map<String, String> getAdditionalAnalysisReplaceRules() {
|
||||
Map<String, String> addReplace = new HashMap<>();
|
||||
AdvancedAchievementsHook aH = advancedAchievementsHook;
|
||||
EssentialsHook eH = essentialsHook;
|
||||
SuperbVoteHook sH = superbVoteHook;
|
||||
FactionsHook fH = factionsHook;
|
||||
TownyHook tH = townyHook;
|
||||
addReplace.put("%towntable%", tH.isEnabled() ? SortableTownTableCreator.createSortableTownsTable(tH.getTopTowns(), tH) : "");
|
||||
addReplace.put("%factionstable%", fH.isEnabled() ? SortableFactionsTableCreator.createSortableFactionsTable(fH.getTopFactions(), fH) : "");
|
||||
addReplace.put("%essentialswarps%", eH.isEnabled() ? "<br/>Warps: "+eH.getWarps().toString() : "");
|
||||
return addReplace;
|
||||
}
|
||||
|
||||
public Map<String, String> getAdditionalInspectReplaceRules(UUID uuid) {
|
||||
Map<String, String> addReplace = new HashMap<>();
|
||||
AdvancedAchievementsHook aH = advancedAchievementsHook;
|
||||
EssentialsHook eH = essentialsHook;
|
||||
SuperbVoteHook sH = superbVoteHook;
|
||||
FactionsHook fH = factionsHook;
|
||||
TownyHook tH = townyHook;
|
||||
addReplace.put("%achievements%", (aH.isEnabled() ? "<br/>Achievements: " + aH.getPlayerAchievements(uuid) + "/" + aH.getTotalAchievements() : ""));
|
||||
if (eH.isEnabled()) {
|
||||
HashMap<String, Serializable> essData = eH.getEssentialsData(uuid);
|
||||
addReplace.put("%essentials%", ((boolean) essData.get("JAILED") ? "| Jailed" : "")
|
||||
+ " " + ((boolean) essData.get("MUTED") ? "| Muted" : ""));
|
||||
} else {
|
||||
addReplace.put("%essentials%", "");
|
||||
}
|
||||
|
||||
addReplace.put("%votes%", sH.isEnabled() ? "<br/>Has voted " + sH.getVotes(uuid) + "times" : "");
|
||||
if (fH.isEnabled()) {
|
||||
HashMap<String, Serializable> facInfo = fH.getPlayerInfo(uuid);
|
||||
addReplace.put("%faction%", "<br/>Faction: " + facInfo.get("FACTION") + " | Power: " + facInfo.get("POWER") + "/" + facInfo.get("MAXPOWER"));
|
||||
} else {
|
||||
addReplace.put("%faction%", "");
|
||||
}
|
||||
if (tH.isEnabled()) {
|
||||
HashMap<String, Serializable> townInfo = tH.getPlayerInfo(uuid);
|
||||
addReplace.put("%town%", "<br/>Town: " + townInfo.get("TOWN"));
|
||||
} else {
|
||||
addReplace.put("%town%", "");
|
||||
}
|
||||
return addReplace;
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public class OnTimeHook extends Hook {
|
||||
* @param plugin
|
||||
*/
|
||||
public OnTimeHook(Plan plugin) {
|
||||
super(OnTime.class);
|
||||
super("me.edge209.OnTime.OnTime");
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,7 @@ public class SuperbVoteHook extends Hook {
|
||||
* @param plugin
|
||||
*/
|
||||
public SuperbVoteHook(Plan plugin) {
|
||||
super(SuperbVote.class);
|
||||
super("io.minimum.minecraft.superbvote.SuperbVote");
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,92 @@
|
||||
package main.java.com.djrapitops.plan.data.additional;
|
||||
|
||||
import com.palmergames.bukkit.towny.Towny;
|
||||
import com.palmergames.bukkit.towny.exceptions.NotRegisteredException;
|
||||
import com.palmergames.bukkit.towny.object.Resident;
|
||||
import com.palmergames.bukkit.towny.object.Town;
|
||||
import com.palmergames.bukkit.towny.object.TownyUniverse;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.TownComparator;
|
||||
import static org.bukkit.Bukkit.getOfflinePlayer;
|
||||
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TownyHook extends Hook {
|
||||
|
||||
private final Plan plugin;
|
||||
private final Towny towny;
|
||||
|
||||
/**
|
||||
* Hooks to Factions plugin
|
||||
*
|
||||
* @param plugin
|
||||
*/
|
||||
public TownyHook(Plan plugin) {
|
||||
super("com.palmergames.bukkit.towny.Towny");
|
||||
this.plugin = plugin;
|
||||
this.towny = getPlugin(Towny.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return List of Faction names sorted by power
|
||||
*/
|
||||
public List<String> getTopTowns() {
|
||||
List<Town> topTowns = TownyUniverse.getDataSource().getTowns();
|
||||
Collections.sort(topTowns, new TownComparator());
|
||||
List<String> townNames = topTowns.stream()
|
||||
.map(town -> town.getName())
|
||||
.collect(Collectors.toList());
|
||||
return townNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab basic info about Town. isEnabled() should be called before this
|
||||
* method.
|
||||
*
|
||||
* @param townName Name of the town.
|
||||
* @return HashMap containing boolean, number & string: RESIDENTS int, MAYOR string, LAND int
|
||||
*/
|
||||
public HashMap<String, Serializable> getTownInfo(String townName) {
|
||||
HashMap<String, Serializable> info = new HashMap<>();
|
||||
try {
|
||||
Town town = TownyUniverse.getDataSource().getTown(townName);
|
||||
info.put("RESIDENTS", town.getNumResidents());
|
||||
info.put("MAYOR", town.getMayor().getName());
|
||||
info.put("LAND", town.getPurchasedBlocks());
|
||||
} catch (NotRegisteredException ex) {
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grab basic info about Player. isEnabled() should be called before this
|
||||
* method.
|
||||
*
|
||||
* @param uuid UUID of player
|
||||
* @return HashMap containing boolean, number & string: TOWN string, Friends string
|
||||
*/
|
||||
public HashMap<String, Serializable> getPlayerInfo(UUID uuid) {
|
||||
HashMap<String, Serializable> info = new HashMap<>();
|
||||
String name = getOfflinePlayer(uuid).getName();
|
||||
try {
|
||||
Resident res = TownyUniverse.getDataSource().getResident(name);
|
||||
if (res.hasTown()) {
|
||||
info.put("TOWN", res.getTown().getName());
|
||||
} else {
|
||||
info.put("TOWN", "Not in town");
|
||||
}
|
||||
info.put("FRIENDS", res.getFriends().toString());
|
||||
} catch (NotRegisteredException ex) {
|
||||
}
|
||||
return info;
|
||||
}
|
||||
}
|
@ -1,8 +1,11 @@
|
||||
package main.java.com.djrapitops.plan.data.handlers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.data.UserData;
|
||||
import org.bukkit.Location;
|
||||
|
||||
/**
|
||||
@ -12,6 +15,7 @@ import org.bukkit.Location;
|
||||
public class LocationHandler {
|
||||
|
||||
private Plan plugin;
|
||||
private HashMap<UUID, List<Location>> locations;
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
@ -20,31 +24,43 @@ public class LocationHandler {
|
||||
*/
|
||||
public LocationHandler(Plan plugin) {
|
||||
this.plugin = plugin;
|
||||
locations = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds location to the UserData if it is not being saved.
|
||||
*
|
||||
* @param data UserData of player
|
||||
* @param uuid UUID of player
|
||||
* @param loc Location from the MoveEvent listener.
|
||||
*/
|
||||
public void addLocation(UserData data, Location loc) {
|
||||
if (!data.isAccessed()) {
|
||||
data.addLocation(loc);
|
||||
} else {
|
||||
// TODO: Location scheduler
|
||||
public void addLocation(UUID uuid, Location loc) {
|
||||
if (!locations.containsKey(uuid)) {
|
||||
locations.put(uuid, new ArrayList<>());
|
||||
}
|
||||
locations.get(uuid).add(loc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple locaitons to the UserData.
|
||||
*
|
||||
* @param data Userdata of Player
|
||||
* @param uuid UUID of player
|
||||
* @param locs The Locations that are added.
|
||||
*/
|
||||
public void addLocations(UserData data, Collection<Location> locs) {
|
||||
if (!data.isAccessed()) {
|
||||
data.addLocations(locs);
|
||||
public void addLocations(UUID uuid, Collection<Location> locs) {
|
||||
if (!locations.containsKey(uuid)) {
|
||||
locations.put(uuid, new ArrayList<>());
|
||||
}
|
||||
locations.get(uuid).addAll(locs);
|
||||
}
|
||||
|
||||
public List<Location> getLocationsForSaving(UUID uuid) {
|
||||
if (!locations.containsKey(uuid)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return locations.get(uuid);
|
||||
}
|
||||
|
||||
public void clearLocations(UUID uuid) {
|
||||
locations.remove(uuid);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ public class PlanPlayerListener implements Listener {
|
||||
private final GamemodeTimesHandler gmTimesH;
|
||||
private final DemographicsHandler demographicH;
|
||||
private final RuleBreakingHandler rulebreakH;
|
||||
private final LocationHandler locationH;
|
||||
|
||||
/**
|
||||
* Class Constructor.
|
||||
@ -45,6 +46,7 @@ public class PlanPlayerListener implements Listener {
|
||||
gmTimesH = handler.getGamemodeTimesHandler();
|
||||
demographicH = handler.getDemographicsHandler();
|
||||
rulebreakH = handler.getRuleBreakingHandler();
|
||||
locationH = handler.getLocationHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,7 +96,9 @@ public class PlanPlayerListener implements Listener {
|
||||
public void process(UserData data) {
|
||||
activityH.handleLogOut(data);
|
||||
gmTimesH.handleLogOut(player.getGameMode(), data);
|
||||
data.addLocations(locationH.getLocationsForSaving(uuid));
|
||||
handler.saveCachedData(uuid);
|
||||
locationH.clearLocations(uuid);
|
||||
}
|
||||
};
|
||||
handler.getUserDataForProcessing(logoutProcessor, uuid);
|
||||
@ -117,7 +121,9 @@ public class PlanPlayerListener implements Listener {
|
||||
@Override
|
||||
public void process(UserData data) {
|
||||
rulebreakH.handleKick(data);
|
||||
data.addLocations(locationH.getLocationsForSaving(uuid));
|
||||
handler.saveCachedData(uuid);
|
||||
locationH.clearLocations(uuid);
|
||||
handler.clearFromCache(uuid);
|
||||
}
|
||||
};
|
||||
|
@ -1,10 +1,12 @@
|
||||
package main.java.com.djrapitops.plan.data.listeners;
|
||||
|
||||
import java.util.UUID;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.data.UserData;
|
||||
import main.java.com.djrapitops.plan.data.cache.DBCallableProcessor;
|
||||
import main.java.com.djrapitops.plan.data.cache.DataCacheHandler;
|
||||
import main.java.com.djrapitops.plan.data.handlers.LocationHandler;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
@ -48,8 +50,8 @@ public class PlanPlayerMoveListener implements Listener {
|
||||
if (from.getBlockX() == to.getBlockX() && from.getBlockZ() == to.getBlockZ()) {
|
||||
return;
|
||||
}
|
||||
Player p = event.getPlayer();
|
||||
UUID uuid = event.getPlayer().getUniqueId();
|
||||
Location savedLocation = to.getBlock().getLocation();
|
||||
// locationH.addLocation(uData, savedLocation);
|
||||
locationH.addLocation(uuid, savedLocation);
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.scheduler.BukkitRunnable;
|
||||
import static org.bukkit.Bukkit.getOfflinePlayer;
|
||||
import static org.bukkit.Bukkit.getOfflinePlayer;
|
||||
|
||||
public abstract class SQLDB extends Database {
|
||||
|
||||
@ -189,10 +190,10 @@ public abstract class SQLDB extends Database {
|
||||
|
||||
ResultSet set = connection.prepareStatement(supportsModification ? ("SHOW TABLES LIKE '" + userName + "'") : "SELECT name FROM sqlite_master WHERE type='table' AND name='" + userName + "'").executeQuery();
|
||||
boolean newDatabase = set.next();
|
||||
set.close();
|
||||
set.close();
|
||||
query("CREATE TABLE IF NOT EXISTS " + userName + " ("
|
||||
+ userColumnID + " integer " + ((usingMySQL) ? "NOT NULL AUTO_INCREMENT" : "PRIMARY KEY") + ", "
|
||||
+ userColumnUUID + " varchar(36) NOT NULL, "
|
||||
+ userColumnUUID + " varchar(36) NOT NULL UNIQUE, "
|
||||
+ userColumnDemAge + " integer NOT NULL, "
|
||||
+ userColumnDemGender + " varchar(8) NOT NULL, "
|
||||
+ userColumnDemGeoLocation + " varchar(50) NOT NULL, "
|
||||
@ -238,7 +239,7 @@ public abstract class SQLDB extends Database {
|
||||
query("CREATE TABLE IF NOT EXISTS " + nicknamesName + " ("
|
||||
+ nicknamesColumnUserID + " integer NOT NULL, "
|
||||
+ nicknamesColumnNick + " varchar(30) NOT NULL, "
|
||||
+ nicknamesColumnCurrent + " boolean NOT NULL DEFAULT (0), "
|
||||
+ nicknamesColumnCurrent + " boolean NOT NULL DEFAULT 0, "
|
||||
+ "FOREIGN KEY(" + nicknamesColumnUserID + ") REFERENCES " + userName + "(" + userColumnID + ")"
|
||||
+ ")"
|
||||
);
|
||||
@ -312,7 +313,7 @@ public abstract class SQLDB extends Database {
|
||||
protected abstract Connection getNewConnection();
|
||||
|
||||
public boolean query(String sql) throws SQLException {
|
||||
boolean success = connection.createStatement().execute(sql);
|
||||
boolean success = connection.createStatement().execute(sql);
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -348,7 +349,7 @@ public abstract class SQLDB extends Database {
|
||||
checkConnection();
|
||||
connection.prepareStatement("DELETE FROM " + versionName).executeUpdate();
|
||||
connection.prepareStatement("INSERT INTO " + versionName + " (version) VALUES (" + version + ")").executeUpdate();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -417,7 +418,6 @@ public abstract class SQLDB extends Database {
|
||||
"DELETE FROM " + commanduseName);
|
||||
statement.execute();
|
||||
statement.close();
|
||||
|
||||
|
||||
statement = connection.prepareStatement("INSERT INTO " + commanduseName + " ("
|
||||
+ commanduseColumnCommand + ", "
|
||||
@ -430,11 +430,11 @@ public abstract class SQLDB extends Database {
|
||||
statement.setInt(2, data.get(key));
|
||||
statement.addBatch();
|
||||
commitRequired = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (commitRequired) {
|
||||
statement.executeBatch();
|
||||
|
||||
|
||||
}
|
||||
statement.close();
|
||||
}
|
||||
@ -499,7 +499,7 @@ public abstract class SQLDB extends Database {
|
||||
statement.setString(1, uuid);
|
||||
statement.execute();
|
||||
statement.close();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -546,14 +546,6 @@ public abstract class SQLDB extends Database {
|
||||
statement.close();
|
||||
String userId = "" + getUserId(uuid.toString());
|
||||
|
||||
List<Location> locations = getLocations(userId, worlds);
|
||||
data.addLocations(locations);
|
||||
if (locations.isEmpty()) {
|
||||
data.setLocation(new Location(defaultWorld, 0, 0, 0));
|
||||
} else {
|
||||
data.setLocation(locations.get(locations.size() - 1));
|
||||
}
|
||||
|
||||
List<String> nicknames = getNicknames(userId);
|
||||
data.addNicknames(nicknames);
|
||||
if (nicknames.size() > 0) {
|
||||
@ -687,7 +679,8 @@ public abstract class SQLDB extends Database {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveMultipleUserData(List<UserData> data) {
|
||||
public void saveMultipleUserData(List<UserData> data) throws SQLException {
|
||||
checkConnection();
|
||||
if (data.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -704,7 +697,7 @@ public abstract class SQLDB extends Database {
|
||||
+ userColumnLastPlayed + "=?, "
|
||||
+ userColumnDeaths + "=?, "
|
||||
+ userColumnMobKills + "=? "
|
||||
+ "WHERE UPPER(" + userColumnUUID + ") LIKE UPPER(?)";
|
||||
+ "WHERE " + userColumnUUID + "=?";
|
||||
|
||||
try {
|
||||
PreparedStatement uStatement = connection.prepareStatement(uSQL);
|
||||
@ -734,9 +727,9 @@ public abstract class SQLDB extends Database {
|
||||
uStatement.setLong(6, uData.getPlayTime());
|
||||
uStatement.setInt(7, uData.getLoginTimes());
|
||||
uStatement.setLong(8, uData.getLastPlayed());
|
||||
uStatement.setString(9, uData.getUuid().toString());
|
||||
uStatement.setInt(10, uData.getDeaths());
|
||||
uStatement.setInt(11, uData.getMobKills());
|
||||
uStatement.setInt(9, uData.getDeaths());
|
||||
uStatement.setInt(10, uData.getMobKills());
|
||||
uStatement.setString(11, uData.getUuid().toString());
|
||||
uStatement.addBatch();
|
||||
} catch (SQLException | NullPointerException e) {
|
||||
saveLast.add(uData);
|
||||
@ -749,11 +742,11 @@ public abstract class SQLDB extends Database {
|
||||
}
|
||||
if (commitRequired) {
|
||||
uStatement.executeBatch();
|
||||
|
||||
|
||||
}
|
||||
uStatement.close();
|
||||
data.removeAll(saveLast);
|
||||
} catch (Exception ex) {
|
||||
} catch (SQLException | IllegalStateException ex) {
|
||||
exceptions.add(ex);
|
||||
}
|
||||
for (UserData uData : data) {
|
||||
@ -763,7 +756,7 @@ public abstract class SQLDB extends Database {
|
||||
uData.access();
|
||||
try {
|
||||
int userId = getUserId(uData.getUuid().toString());
|
||||
saveLocationList(userId, uData.getLocations());
|
||||
saveAdditionalLocationsList(userId, uData.getLocations());
|
||||
saveNickList(userId, uData.getNicknames(), uData.getLastNick());
|
||||
saveIPList(userId, uData.getIps());
|
||||
saveSessionList(userId, uData.getSessions());
|
||||
@ -822,9 +815,9 @@ public abstract class SQLDB extends Database {
|
||||
statement.setLong(6, data.getPlayTime());
|
||||
statement.setInt(7, data.getLoginTimes());
|
||||
statement.setLong(8, data.getLastPlayed());
|
||||
statement.setString(9, uuid.toString());
|
||||
statement.setInt(10, data.getDeaths());
|
||||
statement.setInt(11, data.getMobKills());
|
||||
statement.setInt(9, data.getDeaths());
|
||||
statement.setInt(10, data.getMobKills());
|
||||
statement.setString(11, uuid.toString());
|
||||
update = statement.executeUpdate();
|
||||
}
|
||||
if (update == 0) {
|
||||
@ -863,8 +856,8 @@ public abstract class SQLDB extends Database {
|
||||
statement.close();
|
||||
userId = getUserId(uuid.toString());
|
||||
}
|
||||
|
||||
saveLocationList(userId, data.getLocations());
|
||||
|
||||
saveAdditionalLocationsList(userId, data.getLocations());
|
||||
saveNickList(userId, data.getNicknames(), data.getLastNick());
|
||||
saveIPList(userId, data.getIps());
|
||||
saveSessionList(userId, data.getSessions());
|
||||
@ -873,16 +866,10 @@ public abstract class SQLDB extends Database {
|
||||
data.stopAccessing();
|
||||
}
|
||||
|
||||
public void saveLocationList(int userId, List<Location> locations) throws SQLException {
|
||||
public void saveAdditionalLocationsList(int userId, List<Location> locations) throws SQLException {
|
||||
if (locations.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
PreparedStatement deleteStatement = connection.prepareStatement(
|
||||
"DELETE FROM " + locationName + " WHERE UPPER(" + locationColumnUserID + ") LIKE UPPER(?)");
|
||||
deleteStatement.setString(1, "" + userId);
|
||||
deleteStatement.execute();
|
||||
deleteStatement.close();
|
||||
|
||||
PreparedStatement saveStatement = connection.prepareStatement("INSERT INTO " + locationName + " ("
|
||||
+ locationColumnUserID + ", "
|
||||
+ locationColumnCoordinatesX + ", "
|
||||
@ -905,7 +892,7 @@ public abstract class SQLDB extends Database {
|
||||
}
|
||||
if (commitRequired) {
|
||||
saveStatement.executeBatch();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
saveStatement.close();
|
||||
@ -919,7 +906,7 @@ public abstract class SQLDB extends Database {
|
||||
"DELETE FROM " + nicknamesName + " WHERE UPPER(" + nicknamesColumnUserID + ") LIKE UPPER(?)");
|
||||
statement.setString(1, "" + userId);
|
||||
statement.execute();
|
||||
|
||||
|
||||
statement = connection.prepareStatement("INSERT INTO " + nicknamesName + " ("
|
||||
+ nicknamesColumnUserID + ", "
|
||||
+ nicknamesColumnCurrent + ", "
|
||||
@ -935,7 +922,7 @@ public abstract class SQLDB extends Database {
|
||||
}
|
||||
if (commitRequired) {
|
||||
statement.executeBatch();
|
||||
|
||||
|
||||
}
|
||||
statement.close();
|
||||
}
|
||||
@ -948,7 +935,7 @@ public abstract class SQLDB extends Database {
|
||||
"DELETE FROM " + sessionName + " WHERE UPPER(" + sessionColumnUserID + ") LIKE UPPER(?)");
|
||||
statement.setString(1, "" + userId);
|
||||
statement.execute();
|
||||
|
||||
|
||||
statement = connection.prepareStatement("INSERT INTO " + sessionName + " ("
|
||||
+ sessionColumnUserID + ", "
|
||||
+ sessionColumnSessionStart + ", "
|
||||
@ -961,10 +948,10 @@ public abstract class SQLDB extends Database {
|
||||
statement.setLong(3, session.getSessionEnd());
|
||||
statement.addBatch();
|
||||
commitRequired = true;
|
||||
}
|
||||
}
|
||||
if (commitRequired) {
|
||||
statement.executeBatch();
|
||||
|
||||
|
||||
}
|
||||
statement.close();
|
||||
}
|
||||
@ -977,7 +964,7 @@ public abstract class SQLDB extends Database {
|
||||
"DELETE FROM " + killsName + " WHERE UPPER(" + killsColumnKillerUserID + ") LIKE UPPER(?)");
|
||||
statement.setString(1, "" + userId);
|
||||
statement.execute();
|
||||
|
||||
|
||||
statement = connection.prepareStatement("INSERT INTO " + killsName + " ("
|
||||
+ killsColumnKillerUserID + ", "
|
||||
+ killsColumnVictimUserID + ", "
|
||||
@ -992,10 +979,10 @@ public abstract class SQLDB extends Database {
|
||||
statement.setLong(4, kill.getDate());
|
||||
statement.addBatch();
|
||||
commitRequired = true;
|
||||
}
|
||||
}
|
||||
if (commitRequired) {
|
||||
statement.executeBatch();
|
||||
|
||||
|
||||
}
|
||||
statement.close();
|
||||
}
|
||||
@ -1009,7 +996,7 @@ public abstract class SQLDB extends Database {
|
||||
statement.setString(1, "" + userId);
|
||||
statement.execute();
|
||||
statement.close();
|
||||
|
||||
|
||||
statement = connection.prepareStatement("INSERT INTO " + ipsName + " ("
|
||||
+ ipsColumnUserID + ", "
|
||||
+ ipsColumnIP
|
||||
@ -1020,10 +1007,10 @@ public abstract class SQLDB extends Database {
|
||||
statement.setString(2, ip.getHostAddress());
|
||||
statement.addBatch();
|
||||
commitRequired = true;
|
||||
}
|
||||
}
|
||||
if (commitRequired) {
|
||||
statement.executeBatch();
|
||||
|
||||
|
||||
}
|
||||
statement.close();
|
||||
}
|
||||
@ -1037,7 +1024,7 @@ public abstract class SQLDB extends Database {
|
||||
statement.setString(1, "" + userId);
|
||||
statement.execute();
|
||||
statement.close();
|
||||
|
||||
|
||||
statement = connection.prepareStatement("INSERT INTO " + gamemodetimesName + " ("
|
||||
+ gamemodetimesColumnUserID + ", "
|
||||
+ gamemodetimesColumnSurvivalTime + ", "
|
||||
@ -1062,7 +1049,7 @@ public abstract class SQLDB extends Database {
|
||||
}
|
||||
statement.execute();
|
||||
statement.close();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1089,12 +1076,18 @@ public abstract class SQLDB extends Database {
|
||||
boolean success = true;
|
||||
for (String tableName : queries) {
|
||||
try {
|
||||
query("DROP TABLE " + tableName);
|
||||
query("DELETE FROM " + tableName);
|
||||
} catch (SQLException e) {
|
||||
plugin.toLog(this.getClass().getName(), e);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
checkConnection();
|
||||
} catch (SQLException e) {
|
||||
plugin.toLog(this.getClass().getName(), e);
|
||||
return false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -79,26 +79,7 @@ public class DataRequestHandler {
|
||||
} catch (FileNotFoundException ex) {
|
||||
return "<h1>404 analysis.html was not found</h1>";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the players.html as string with replaced placeholders.
|
||||
*
|
||||
* @return the html
|
||||
*/
|
||||
public String getPlayersHtml() {
|
||||
try {
|
||||
if (!analysisCache.isCached()) {
|
||||
return "<h1>404 Data was not found in cache</h1>";
|
||||
}
|
||||
return HtmlUtils.replacePlaceholders(
|
||||
HtmlUtils.getHtmlStringFromResource("players.html"),
|
||||
PlaceholderUtils.getPlayersReplaceRules(analysisCache.getData())
|
||||
);
|
||||
} catch (FileNotFoundException ex) {
|
||||
return "<h1>404 players.html was not found</h1>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the AnalysisData is cached.
|
||||
|
@ -40,8 +40,8 @@ public enum Html {
|
||||
LINK_CLASS("class=\"link\""),
|
||||
TABLE_START("<table class=\"table\">"),
|
||||
TABLE_END("</table>"),
|
||||
TABLELINE("<tr class=\"tableline\"><td><b>" + REPLACE0 + "</b></td>\r\n<td>" + REPLACE1 + "</td></tr>"),
|
||||
ERROR_TABLE("<p class=\"red\">Error Calcuclating Table (No data)</p>"),
|
||||
TABLELINE("<tr><td><b>" + REPLACE0 + "</b></td>\r\n<td>" + REPLACE1 + "</td></tr>"),
|
||||
ERROR_TABLE("<tr><td>No data</td>\r\n<td>No data</td></tr>"),
|
||||
IMG("<img src=\"" + REPLACE0 + "\">"),
|
||||
TOP_TOWNS("<p><b>Top 20 Towns</b></p>"),
|
||||
TOP_FACTIONS("<p><b>Top 20 Factions</b></p>"),
|
||||
|
@ -0,0 +1,45 @@
|
||||
package main.java.com.djrapitops.plan.ui.tables;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import main.java.com.djrapitops.plan.data.SessionData;
|
||||
import main.java.com.djrapitops.plan.utilities.FormatUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.SessionDataComparator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class SortabeSessionTableCreator {
|
||||
|
||||
public static String createSortedSessionDataTable5(List<SessionData> sessionData) {
|
||||
String html = "<table class=\"sortable table\"><thead><tr>"
|
||||
+ "<th>Session Started</th>"
|
||||
+ "<th>Session Ended</th>"
|
||||
+ "<th>Session Length</th>"
|
||||
+ "</tr></thead>"
|
||||
+ "<tbody>";
|
||||
if (sessionData.isEmpty()) {
|
||||
html += "<tr><td>No Session Data available</td><td></td><td></td></tr>";
|
||||
} else {
|
||||
Collections.sort(sessionData, new SessionDataComparator());
|
||||
Collections.reverse(sessionData);
|
||||
int i = 0;
|
||||
for (SessionData session : sessionData) {
|
||||
if (i > 4) {
|
||||
break;
|
||||
}
|
||||
long start = session.getSessionStart();
|
||||
long end = session.getSessionEnd();
|
||||
long length = end-start;
|
||||
html += "<tr>"
|
||||
+ "<td sorttable_customkey=\""+start+"\">" + FormatUtils.formatTimeStamp(start+"") + "</td>"
|
||||
+ "<td sorttable_customkey=\""+end+"\">" + FormatUtils.formatTimeStamp(end+"") + "</td>"
|
||||
+ "<td sorttable_customkey=\""+length+"\">" + FormatUtils.formatTimeAmount(length+"") + "</td>"
|
||||
+ "</tr>";
|
||||
}
|
||||
}
|
||||
html += "</tbody></table>";
|
||||
return html;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package main.java.com.djrapitops.plan.ui.tables;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import main.java.com.djrapitops.plan.ui.Html;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.MapComparator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class SortableCommandUseTableCreator {
|
||||
|
||||
public static String createSortedCommandUseTable(HashMap<String, Integer> commandUse) {
|
||||
List<String[]> sorted = MapComparator.sortByValue(commandUse);
|
||||
String html = "";
|
||||
if (sorted.isEmpty()) {
|
||||
html = Html.ERROR_TABLE.parse();
|
||||
return html;
|
||||
}
|
||||
Collections.reverse(sorted);
|
||||
for (String[] values : sorted) {
|
||||
html += Html.TABLELINE.parse(values[1], values[0]);
|
||||
}
|
||||
return html;
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package main.java.com.djrapitops.plan.ui.tables;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import main.java.com.djrapitops.plan.data.additional.FactionsHook;
|
||||
import main.java.com.djrapitops.plan.ui.Html;
|
||||
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class SortableFactionsTableCreator {
|
||||
|
||||
public static String createSortableFactionsTable(Collection<String> factionList, FactionsHook fHook) {
|
||||
String html = "<table class=\"sortable table\"><thead><tr>"
|
||||
+ "<th>Faction</th>"
|
||||
+ "<th>Power</th>"
|
||||
+ "<th>Land</th>"
|
||||
+ "<th>Leader</th>"
|
||||
+ "</tr></thead>"
|
||||
+ "<tbody>";
|
||||
if (factionList.isEmpty()) {
|
||||
html += "<tr><td>No Factions</td><td></td><td></td><td></td></tr>";
|
||||
} else {
|
||||
for (String factionName : factionList) {
|
||||
HashMap<String, Serializable> info = fHook.getFactionInfo(factionName);
|
||||
html += "<tr>"
|
||||
+ "<td>" + factionName + "</td>"
|
||||
+ "<td>" + info.get("POWER") + "</td>"
|
||||
+ "<td>" + info.get("LAND") + "</td>"
|
||||
+ "<td>" + Html.LINK.parse(HtmlUtils.getInspectUrl((String) info.get("LEADER")), (String) info.get("LEADER")) + "</td>"
|
||||
+ "</tr>";
|
||||
}
|
||||
}
|
||||
html += "</tbody></table>";
|
||||
return html;
|
||||
}
|
||||
}
|
@ -16,14 +16,15 @@ public class SortablePlayersTableCreator {
|
||||
|
||||
public static String createSortablePlayersTable(Collection<UserData> data) {
|
||||
String html = "";
|
||||
Date now = new Date();
|
||||
for (UserData uData : data) {
|
||||
html += "<tr>"
|
||||
+ "<td>" + Html.LINK.parse(HtmlUtils.getInspectUrl(uData.getName()),uData.getName())+"</td>"
|
||||
+ "<td>" + AnalysisUtils.isActive(uData.getLastPlayed(), uData.getPlayTime(), uData.getLoginTimes()) + "</td>"
|
||||
+ "<td>" + FormatUtils.formatTimeAmount(uData.getPlayTime() + "") + "</td>"
|
||||
+ "<td>" + Html.LINK.parse(HtmlUtils.getInspectUrl(uData.getName()), uData.getName()) + "</td>"
|
||||
+ "<td>" + (uData.isBanned() ? "Banned" : (AnalysisUtils.isActive(uData.getLastPlayed(), uData.getPlayTime(), uData.getLoginTimes())
|
||||
? "Active" : "Inactive")) + "</td>"
|
||||
+ "<td sorttable_customkey=\""+uData.getPlayTime()+"\">" + FormatUtils.formatTimeAmount(uData.getPlayTime() + "") + "</td>"
|
||||
+ "<td>" + uData.getLoginTimes() + "</td>"
|
||||
+ "<td>" + FormatUtils.formatTimeAmountSinceString(uData.getLastPlayed() + "", now) + "</td>"
|
||||
+ "<td sorttable_customkey=\""+uData.getRegistered()+"\">" + FormatUtils.formatTimeStamp(uData.getRegistered() + "") + "</td>"
|
||||
+ "<td sorttable_customkey=\""+uData.getLastPlayed()+"\">" + FormatUtils.formatTimeStamp(uData.getLastPlayed() + "") + "</td>"
|
||||
+ "<td>" + uData.getDemData().getGeoLocation() + "</td>"
|
||||
+ "</tr>";
|
||||
}
|
||||
|
@ -0,0 +1,40 @@
|
||||
package main.java.com.djrapitops.plan.ui.tables;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import main.java.com.djrapitops.plan.data.additional.TownyHook;
|
||||
import main.java.com.djrapitops.plan.ui.Html;
|
||||
import main.java.com.djrapitops.plan.utilities.HtmlUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class SortableTownTableCreator {
|
||||
|
||||
public static String createSortableTownsTable(Collection<String> townNames, TownyHook tHook) {
|
||||
String html = "<table class=\"sortable table\"><thead><tr>"
|
||||
+ "<th>Town</th>"
|
||||
+ "<th>Residents</th>"
|
||||
+ "<th>Land</th>"
|
||||
+ "<th>Mayor</th>"
|
||||
+ "</tr></thead>"
|
||||
+ "<tbody>";
|
||||
if (townNames.isEmpty()) {
|
||||
html += "<tr><td>No Towns</td><td></td><td></td><td></td></tr>";
|
||||
} else {
|
||||
for (String town : townNames) {
|
||||
HashMap<String, Serializable> info = tHook.getTownInfo(town);
|
||||
html += "<tr>"
|
||||
+ "<td>" + town + "</td>"
|
||||
+ "<td>" + info.get("RESIDENTS") + "</td>"
|
||||
+ "<td>" + info.get("LAND") + "</td>"
|
||||
+ "<td>" + Html.LINK.parse(HtmlUtils.getInspectUrl((String) info.get("MAYOR")), (String) info.get("MAYOR")) + "</td>"
|
||||
+ "</tr>";
|
||||
}
|
||||
}
|
||||
html += "</tbody></table>";
|
||||
return html;
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package main.java.com.djrapitops.plan.ui.tables;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import main.java.com.djrapitops.plan.ui.Html;
|
||||
import main.java.com.djrapitops.plan.utilities.FormatUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.MapComparator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class SortedTableCreator {
|
||||
|
||||
public static String createCommandUseTable(HashMap<String, Integer> commandUse) {
|
||||
return "Not Implemented yet";
|
||||
}
|
||||
|
||||
public static String createTableOutOfHashMap(HashMap<String, Integer> commandUse) {
|
||||
return createTableOutOfHashMap(commandUse, 50);
|
||||
}
|
||||
|
||||
public static String createTableOutOfHashMap(HashMap<String, Integer> map, int limit) {
|
||||
List<String[]> sorted = MapComparator.sortByValue(map);
|
||||
String html = Html.TABLE_START.parse();
|
||||
if (sorted.isEmpty()) {
|
||||
html = Html.ERROR_TABLE.parse();
|
||||
return html;
|
||||
}
|
||||
Collections.reverse(sorted);
|
||||
int i = 1;
|
||||
for (String[] values : sorted) {
|
||||
if (i >= limit) {
|
||||
break;
|
||||
}
|
||||
html += Html.TABLELINE.parse(values[1], values[0]);
|
||||
i++;
|
||||
}
|
||||
html += Html.TABLE_END.parse();
|
||||
return html;
|
||||
}
|
||||
|
||||
public static String createActivePlayersTable(HashMap<String, Long> map, int limit) {
|
||||
List<String[]> sorted = MapComparator.sortByValueLong(map);
|
||||
String html = Html.TABLE_START.parse();
|
||||
if (sorted.isEmpty()) {
|
||||
html = Html.ERROR_TABLE.parse() + Html.TABLE_END.parse();
|
||||
return html;
|
||||
}
|
||||
Collections.reverse(sorted);
|
||||
int i = 1;
|
||||
for (String[] values : sorted) {
|
||||
if (i >= limit) {
|
||||
break;
|
||||
}
|
||||
html += Html.TABLELINE.parse(values[1].replaceAll(Html.BUTTON_CLASS.parse(), Html.LINK_CLASS.parse()), FormatUtils.formatTimeAmount(values[0]));
|
||||
i++;
|
||||
}
|
||||
html += Html.TABLE_END.parse();
|
||||
return html;
|
||||
}
|
||||
|
||||
public static String createTableOutOfHashMapLong(HashMap<String, Long> players) {
|
||||
return createActivePlayersTable(players, 20);
|
||||
}
|
||||
}
|
@ -108,16 +108,6 @@ public class Response {
|
||||
output.write((htmlDef + analysisHtml).getBytes());
|
||||
return;
|
||||
}
|
||||
} else if (command.equals("players")) {
|
||||
if (requestHandler.checkIfAnalysisIsCached()) {
|
||||
String playersHtml = requestHandler.getPlayersHtml();
|
||||
String htmlDef = "HTTP/1.1 OK\r\n"
|
||||
+ "Content-Type: text/html; charset=utf-8\r\n"
|
||||
+ "Content-Length: " + playersHtml.length() + "\r\n"
|
||||
+ "\r\n";
|
||||
output.write((htmlDef + playersHtml).getBytes());
|
||||
return;
|
||||
}
|
||||
}
|
||||
String errorMessage = "HTTP/1.1 404 UserData not Found\r\n"
|
||||
+ "Content-Type: text/html\r\n"
|
||||
|
@ -141,7 +141,6 @@ public class Analysis {
|
||||
// Analyze & Save RawAnalysisData to AnalysisData
|
||||
createPlayerActivityGraphs(analysisData, sorted.getSessiondata(), sorted.getRegistered());
|
||||
|
||||
analysisData.setTop20ActivePlayers(AnalysisUtils.createActivePlayersTable(sorted.getPlaytimes(), 20));
|
||||
analysisData.setRecentPlayers(AnalysisUtils.createListStringOutOfHashMapLong(sorted.getLatestLogins(), 20));
|
||||
|
||||
long totalPlaytime = sorted.getTotalPlaytime();
|
||||
|
@ -13,8 +13,8 @@ import main.java.com.djrapitops.plan.ui.Html;
|
||||
import main.java.com.djrapitops.plan.ui.graphs.ActivityPieChartCreator;
|
||||
import main.java.com.djrapitops.plan.ui.graphs.GMTimesPieChartCreator;
|
||||
import main.java.com.djrapitops.plan.ui.graphs.PlayerActivityGraphCreator;
|
||||
import main.java.com.djrapitops.plan.ui.tables.SortableCommandUseTableCreator;
|
||||
import main.java.com.djrapitops.plan.ui.tables.SortablePlayersTableCreator;
|
||||
import main.java.com.djrapitops.plan.ui.tables.SortedTableCreator;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.MapComparator;
|
||||
import org.bukkit.GameMode;
|
||||
|
||||
@ -76,19 +76,7 @@ public class AnalysisUtils {
|
||||
}
|
||||
|
||||
static String createTableOutOfHashMap(HashMap<String, Integer> commandUse) {
|
||||
return SortedTableCreator.createTableOutOfHashMap(commandUse);
|
||||
}
|
||||
|
||||
static String createTableOutOfHashMapLong(HashMap<String, Long> players) {
|
||||
return SortedTableCreator.createTableOutOfHashMapLong(players);
|
||||
}
|
||||
|
||||
static String createTableOutOfHashMap(HashMap<String, Integer> map, int limit) {
|
||||
return SortedTableCreator.createTableOutOfHashMap(map, limit);
|
||||
}
|
||||
|
||||
static String createActivePlayersTable(HashMap<String, Long> map, int limit) {
|
||||
return SortedTableCreator.createActivePlayersTable(map, limit);
|
||||
return SortableCommandUseTableCreator.createSortedCommandUseTable(commandUse);
|
||||
}
|
||||
|
||||
static String createSortablePlayersTable(Collection<UserData> data) {
|
||||
|
@ -3,12 +3,14 @@ package main.java.com.djrapitops.plan.utilities;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import main.java.com.djrapitops.plan.Phrase;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.Settings;
|
||||
import main.java.com.djrapitops.plan.data.AnalysisData;
|
||||
import main.java.com.djrapitops.plan.data.UserData;
|
||||
import main.java.com.djrapitops.plan.ui.Html;
|
||||
import main.java.com.djrapitops.plan.ui.tables.SortabeSessionTableCreator;
|
||||
import org.bukkit.GameMode;
|
||||
import static org.bukkit.plugin.java.JavaPlugin.getPlugin;
|
||||
|
||||
@ -43,7 +45,7 @@ public class PlaceholderUtils {
|
||||
replaceMap.put("%npday%", data.getNewPlayersDay() + "");
|
||||
replaceMap.put("%npweek%", data.getNewPlayersWeek() + "");
|
||||
replaceMap.put("%npmonth%", data.getNewPlayersMonth() + "");
|
||||
replaceMap.put("%top50commands%", data.getTop50CommandsListHtml());
|
||||
replaceMap.put("%commanduse%", data.getTop50CommandsListHtml());
|
||||
replaceMap.put("%avgage%", (data.getAverageAge() != -1) ? "" + data.getAverageAge() : Phrase.DEM_UNKNOWN + "");
|
||||
replaceMap.put("%avgplaytime%", FormatUtils.formatTimeAmount("" + data.getAveragePlayTime()));
|
||||
replaceMap.put("%totalplaytime%", FormatUtils.formatTimeAmount("" + data.getTotalPlayTime()));
|
||||
@ -58,6 +60,8 @@ public class PlaceholderUtils {
|
||||
Plan plugin = getPlugin(Plan.class);
|
||||
replaceMap.put("%version%", plugin.getDescription().getVersion());
|
||||
replaceMap.put("%planlite%", "");
|
||||
replaceMap.put("%sortabletable%", data.getSortablePlayersTable());
|
||||
replaceMap.putAll(plugin.getHookHandler().getAdditionalAnalysisReplaceRules());
|
||||
return replaceMap;
|
||||
}
|
||||
|
||||
@ -71,7 +75,8 @@ public class PlaceholderUtils {
|
||||
public static HashMap<String, String> getInspectReplaceRules(UserData data) throws FileNotFoundException {
|
||||
HashMap<String, String> replaceMap = new HashMap<>();
|
||||
boolean showIPandUUID = Settings.SECURITY_IP_UUID.isTrue();
|
||||
replaceMap.put("%uuid%", (showIPandUUID ? "" + data.getUuid() : Html.HIDDEN.parse()));
|
||||
UUID uuid = data.getUuid();
|
||||
replaceMap.put("%uuid%", (showIPandUUID ? "" + uuid : Html.HIDDEN.parse()));
|
||||
replaceMap.put("%lastseen%", FormatUtils.formatTimeStamp("" + data.getLastPlayed()));
|
||||
replaceMap.put("%logintimes%", "" + data.getLoginTimes());
|
||||
replaceMap.put("%geoloc%", data.getDemData().getGeoLocation());
|
||||
@ -112,21 +117,14 @@ public class PlaceholderUtils {
|
||||
replaceMap.put("%isonline%", (data.isOnline()) ? Html.ONLINE.parse() : Html.OFFLINE.parse());
|
||||
int deaths = data.getDeaths();
|
||||
replaceMap.put("%deaths%", deaths + "");
|
||||
replaceMap.put("%playerkills%", data.getPlayerKills() + "");
|
||||
replaceMap.put("%playerkills%", data.getPlayerKills().size() + "");
|
||||
replaceMap.put("%mobkills%", data.getMobKills() + "");
|
||||
replaceMap.put("%sessionstable%", SortabeSessionTableCreator.createSortedSessionDataTable5(data.getSessions()));
|
||||
Plan plugin = getPlugin(Plan.class);
|
||||
replaceMap.put("%version%", plugin.getDescription().getVersion());
|
||||
replaceMap.put("%planlite%", "");
|
||||
replaceMap.put("%inaccuratedatawarning%", (new Date().getTime() - data.getRegistered() < 180000) ? Html.WARN_INACCURATE.parse() : "");
|
||||
return replaceMap;
|
||||
}
|
||||
|
||||
public static HashMap<String, String> getPlayersReplaceRules(AnalysisData data) {
|
||||
HashMap<String, String> replaceMap = new HashMap<>();
|
||||
Plan plugin = getPlugin(Plan.class);
|
||||
replaceMap.put("%version%", plugin.getDescription().getVersion());
|
||||
replaceMap.put("%total%", "" + data.getTotal());
|
||||
replaceMap.put("%sortabletable%", data.getSortablePlayersTable());
|
||||
replaceMap.putAll(plugin.getHookHandler().getAdditionalInspectReplaceRules(uuid));
|
||||
return replaceMap;
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public class MapComparator {
|
||||
hashMap.keySet().stream().forEach((key) -> {
|
||||
sortedList.add(new String[]{"" + hashMap.get(key), key});
|
||||
});
|
||||
Collections.sort(sortedList, (String[] strings, String[] otherStrings) -> (int) (Long.parseLong(strings[0]) - (Long.parseLong(otherStrings[0]))));
|
||||
Collections.sort(sortedList, (String[] strings, String[] otherStrings) -> Long.valueOf(strings[0]).compareTo(Long.valueOf(otherStrings[0])));
|
||||
return sortedList;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,23 @@
|
||||
package main.java.com.djrapitops.plan.utilities.comparators;
|
||||
|
||||
import java.util.Comparator;
|
||||
import main.java.com.djrapitops.plan.data.SessionData;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class SessionDataComparator implements Comparator<SessionData> {
|
||||
|
||||
// This method should only be used if FactionsHook.isEnabled() returns true.
|
||||
@Override
|
||||
public int compare(SessionData s1, SessionData s2) {
|
||||
if (s1.getSessionStart() == s2.getSessionStart()) {
|
||||
return 0;
|
||||
}
|
||||
if (s1.getSessionStart() > s2.getSessionStart()) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
package main.java.com.djrapitops.plan.utilities.comparators;
|
||||
|
||||
import com.palmergames.bukkit.towny.object.Town;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TownComparator implements Comparator<Town> {
|
||||
|
||||
// This method should only be used if FactionsHook.isEnabled() returns true.
|
||||
// Note: this comparator imposes orderings that are inconsistent with equals.
|
||||
@Override
|
||||
public int compare(Town tow1, Town tow2) {
|
||||
if (tow1.equals(tow2)) {
|
||||
return 0;
|
||||
}
|
||||
int tow1res = tow1.getNumResidents();
|
||||
int tow2res = tow2.getNumResidents();
|
||||
if (tow1res == tow2res) {
|
||||
return 0;
|
||||
} else if (tow1res > tow2res) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
@ -6,6 +6,8 @@
|
||||
<meta name="description" content="Player Analysis window">
|
||||
<meta name="author" content="Rsl1122">
|
||||
<link rel="icon" href="https://puu.sh/tK0KL/6aa2ba141b.ico" type="image/x-icon" />
|
||||
<!--<script src="http://puu.sh/ubCTc/7e611ffe42.js"></script>-->
|
||||
<script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@ -42,7 +44,7 @@
|
||||
display: table;
|
||||
}
|
||||
.info {
|
||||
width: 40%;
|
||||
width: 50%;
|
||||
}
|
||||
.graphs {
|
||||
width: 60%
|
||||
@ -64,12 +66,7 @@
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
padding: 8px 14px;
|
||||
width: 70%;
|
||||
}
|
||||
.tableline {
|
||||
text-align: left;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
.buttons {
|
||||
line-height: 270%;
|
||||
@ -81,7 +78,63 @@
|
||||
.link:hover {
|
||||
color: darkgreen;
|
||||
}
|
||||
|
||||
table.sortable thead {
|
||||
background-color: #267F00;
|
||||
color:white;
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
width: 100%;
|
||||
}
|
||||
table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after {
|
||||
content: " \25B4\25BE"
|
||||
}
|
||||
#wrapper {
|
||||
width: 400%;
|
||||
transform: translate3d(0, 0, 0);
|
||||
transition: transform .5s ease-in-out;
|
||||
}
|
||||
.content {
|
||||
float: left;
|
||||
width: 25%;
|
||||
height: 100%;
|
||||
white-space: normal;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
#contentContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
#navLinks {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
#navLinks ul {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
display: inline-block;
|
||||
margin-top: 6px;
|
||||
}
|
||||
#navLinks ul li {
|
||||
float: left;
|
||||
text-align: center;
|
||||
margin: 10px;
|
||||
list-style: none;
|
||||
cursor: pointer;
|
||||
background-color: #267F00;
|
||||
color: #FFFFFF;
|
||||
font-weight: bold;
|
||||
padding: 8px 14px;
|
||||
}
|
||||
#navLinks ul li:hover {
|
||||
background-color: darkgreen;
|
||||
}
|
||||
#navLinks ul li.active {
|
||||
background-color: darkgreen;
|
||||
color: #FFFFFF;
|
||||
outline-width: 7px;
|
||||
}
|
||||
.itemLinks {}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -93,42 +146,136 @@
|
||||
<h4>Analysis refreshed %refresh% ago</h4>
|
||||
</header>
|
||||
<div class="clearfix">
|
||||
<div class="column graphs">
|
||||
|
||||
<h4>Player Activity | Last 24h - New Players: %npday%</h4>
|
||||
%playerchartday%
|
||||
<h4>Player Activity | Last 7 days - New Players: %npweek%</h4>
|
||||
%playerchartweek%
|
||||
<h4>Player Activity | Last 30 days - New Players: %npmonth%</h4>
|
||||
%playerchartmonth%
|
||||
<div class="buttons">
|
||||
<p><b>Most recent logins</b>: %recentlogins%</p>
|
||||
<div id="navLinks">
|
||||
<ul>
|
||||
<li class="itemLinks" data-pos="0px">Information</li>
|
||||
<li class="itemLinks" data-pos="-25%">Online Activity</li>
|
||||
<li class="itemLinks" data-pos="-50%">Playerlist</li>
|
||||
<li class="itemLinks" data-pos="-75%">Command usage</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div id="contentContainer">
|
||||
<div id="wrapper">
|
||||
<div class="content">
|
||||
<div class="column" style="width: 60%;">
|
||||
<h4>Player Activity | Last 24h - New Players: %npday%</h4>
|
||||
%playerchartday%
|
||||
<div class="buttons">
|
||||
<p><b>Most recent logins</b>: %recentlogins%</p>
|
||||
</div>
|
||||
%towntable%<br/>
|
||||
%factionstable%
|
||||
</div>
|
||||
<div class="column" style="width: 40%;">
|
||||
<h4>Information</h4>
|
||||
<p>%activitytotal% players have played on this server.<br/>
|
||||
A Total of %totalplaytime% has been played with the average of %avgplaytime%<br/>
|
||||
Players have joined %totallogins% times.<br/>
|
||||
Players have died %deaths% times, of which %playerkills% were caused by another Player.<br/>
|
||||
A Total of %mobkills% mobs have been slain.<br/>
|
||||
The average of known player ages is %avgage%.
|
||||
%essentialswarps%</p>
|
||||
<h4>Gamemode Usage</h4>
|
||||
%gmpiechart%
|
||||
<p>Survival: %gm0% | Creative: %gm1% | Adventure: %gm2% | Spectator: %gm3%</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="column" style="width: 60%;">
|
||||
<h4>Player Activity | Last 24h - New Players: %npday%</h4>
|
||||
%playerchartday%
|
||||
<h4>Player Activity | Last 7 days - New Players: %npweek%</h4>
|
||||
%playerchartweek%
|
||||
<h4>Player Activity | Last 30 days - New Players: %npmonth%</h4>
|
||||
%playerchartmonth%
|
||||
</div>
|
||||
<div class="column" style="width: 40%;">
|
||||
<h4>Playerbase composition</h4>
|
||||
%activitypiechart%
|
||||
<p>Active %active% | Inactive %inactive% | Banned %banned% | Joined once %joinleaver% <br/>
|
||||
Total: %activitytotal%</p>
|
||||
<div class="buttons">
|
||||
<p><b>Most recent logins</b>: %recentlogins%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content column">
|
||||
<table class="sortable table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Active</th>
|
||||
<th>Playtime</th>
|
||||
<th>Login times</th>
|
||||
<th>Registered</th>
|
||||
<th>Last seen</th>
|
||||
<th>Geolocation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
%sortabletable%
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="content column">
|
||||
<table class="sortable table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Command</th>
|
||||
<th>Times used</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
%commanduse%
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<h4>Top 20 Most Active</h4>
|
||||
%top20mostactive%
|
||||
|
||||
%planlite%
|
||||
</div>
|
||||
|
||||
<div class="column info">
|
||||
<h4>Information</h4>
|
||||
<p>%activitytotal% players have played on this server.<br/>
|
||||
A Total of %totalplaytime% has been played with the average of %avgplaytime%<br/>
|
||||
Players have joined %totallogins% times.<br/>
|
||||
Players have died %deaths% times, of which %playerkills% were caused by another Player.<br/>
|
||||
A Total of %mobkills% mobs have been slain.<br/>
|
||||
The average of known player ages is %avgage%.</p>
|
||||
<h4>Playerbase composition</h4>
|
||||
%activitypiechart%
|
||||
<p>Active %active% | Inactive %inactive% | Banned %banned% | Joined once %joinleaver% <br/>
|
||||
Total: %activitytotal%</p>
|
||||
<br/><h4>Gamemode Usage</h4>
|
||||
%gmpiechart%
|
||||
<p>Survival: %gm0% | Creative: %gm1% | Adventure: %gm2% | Spectator: %gm3%</p>
|
||||
<h4>Top 50 Most used commands</h4>
|
||||
%top50commands%
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div></div>
|
||||
</body>
|
||||
<script>
|
||||
// just querying the DOM...like a boss!
|
||||
var links = document.querySelectorAll(".itemLinks");
|
||||
var wrapper = document.querySelector("#wrapper");
|
||||
|
||||
// the activeLink provides a pointer to the currently displayed item
|
||||
var activeLink = 0;
|
||||
|
||||
// setup the event listeners
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
var link = links[i];
|
||||
link.addEventListener('click', setClickedItem, false);
|
||||
|
||||
// identify the item for the activeLink
|
||||
link.itemID = i;
|
||||
}
|
||||
|
||||
// set first item as active
|
||||
links[activeLink].classList.add("active");
|
||||
|
||||
function setClickedItem(e) {
|
||||
removeActiveLinks();
|
||||
|
||||
var clickedLink = e.target;
|
||||
activeLink = clickedLink.itemID;
|
||||
|
||||
changePosition(clickedLink);
|
||||
}
|
||||
|
||||
function removeActiveLinks() {
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
links[i].classList.remove("active");
|
||||
}
|
||||
}
|
||||
// Handle changing the slider position as well as ensure
|
||||
// the correct link is highlighted as being active
|
||||
function changePosition(link) {
|
||||
var position = link.getAttribute("data-pos");
|
||||
|
||||
var translateValue = "translate3d(" + position + ", 0px, 0)";
|
||||
wrapper.style.transform = translateValue;
|
||||
|
||||
link.classList.add("active");
|
||||
}
|
||||
</script>
|
||||
</html>
|
@ -6,6 +6,7 @@
|
||||
<meta name="description" content="Player inspect window">
|
||||
<meta name="author" content="Rsl1122">
|
||||
<link rel="icon" href="https://puu.sh/tK0KL/6aa2ba141b.ico" type="image/x-icon" />
|
||||
<script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
@ -44,7 +45,24 @@
|
||||
.info {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.table {
|
||||
border-collapse: collapse;
|
||||
table-layout: fixed;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
padding: 8px 14px;
|
||||
width: 100%;
|
||||
}
|
||||
table.sortable thead {
|
||||
background-color: #267F00;
|
||||
color:white;
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
width: 100%;
|
||||
}
|
||||
table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after {
|
||||
content: " \25B4\25BE"
|
||||
}
|
||||
.black {
|
||||
color: #000000;
|
||||
}
|
||||
@ -108,15 +126,17 @@
|
||||
<div class="column info">
|
||||
|
||||
<h4>Information</h4>
|
||||
<p>Last seen: %lastseen% %active% %isonline%<br/>
|
||||
<p>Last seen: %lastseen% %active% %isonline% %essentials%<br/>
|
||||
Nicknames: %nicknames% | Has connected from ips: %ips%<br/>
|
||||
Geolocation: %geoloc%<br/>
|
||||
Playtime: %playtime%<br/>
|
||||
Has logged in %logintimes% times. | Has been kicked %timeskicked% times.<br/>
|
||||
Age: %age% | Gender: %gender%<br/>
|
||||
Player kills: %playerkills% | Mob kills: %mobkills% | Deaths: %deaths%<br/>
|
||||
UUID: %uuid%</p>
|
||||
%planlite%
|
||||
UUID: %uuid%
|
||||
%achievements%%votes%%faction%%town%</p>
|
||||
<h4>Last 5 Play Sessions</h4>
|
||||
%sessionstable%
|
||||
</div>
|
||||
|
||||
<div class="column info">
|
||||
|
@ -1,95 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Plan | Inspect %name%</title>
|
||||
<meta name="description" content="Player inspect window">
|
||||
<meta name="author" content="Rsl1122">
|
||||
<link rel="icon" href="https://puu.sh/tK0KL/6aa2ba141b.ico" type="image/x-icon" />
|
||||
<script src="http://puu.sh/ubCTc/7e611ffe42.js"></script>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
img {
|
||||
width: auto;
|
||||
}
|
||||
body {
|
||||
line-height: 140%;
|
||||
font-family: Verdana, Geneva, sans-serif;
|
||||
font-style: normal;
|
||||
}
|
||||
header, footer {
|
||||
line-height: 40%;
|
||||
background-color: #267F00;
|
||||
color: white;
|
||||
padding: 10px 15px 5px 15px;
|
||||
font-family: futura-pt, Futura, Futura-Medium, Verdana, Geneva, sans-serif;
|
||||
font-style: normal;
|
||||
}
|
||||
.column {
|
||||
float: left;
|
||||
padding: 15px;
|
||||
}
|
||||
.link {
|
||||
color: green;
|
||||
text-decoration:none!important;
|
||||
}
|
||||
.link:hover {
|
||||
color: darkgreen;
|
||||
}
|
||||
.clearfix::after {
|
||||
content: "";
|
||||
clear: both;
|
||||
display: table;
|
||||
}
|
||||
.green {
|
||||
color: #55FF55;
|
||||
}
|
||||
.red {
|
||||
color: #FF5555;
|
||||
}
|
||||
table.sortable thead {
|
||||
background-color: #267F00;
|
||||
color:white;
|
||||
font-weight: bold;
|
||||
cursor: default;
|
||||
}
|
||||
.table {
|
||||
table-layout: fixed;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
padding: 8px 14px;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<img style="float: right; padding: 5px" src="http://puu.sh/tJZUb/c2e0ab220f.png" alt="Player Analytics | Players">
|
||||
<p style="float: right; text-align: right;">Player Analytics v.%version%</p>
|
||||
<h1>Plan | Players</h1>
|
||||
<h4>Showing %total% players</h4>
|
||||
</header>
|
||||
<div class="clearfix">
|
||||
<div class="column">
|
||||
<table class="sortable table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Player</th>
|
||||
<th>Active</th>
|
||||
<th>Playtime</th>
|
||||
<th>Login times</th>
|
||||
<th>Last seen</th>
|
||||
<th>Geolocation</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
%sortabletable%
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,7 +1,16 @@
|
||||
name: Plan
|
||||
author: Rsl1122
|
||||
main: main.java.com.djrapitops.plan.Plan
|
||||
version: 2.5.2
|
||||
version: 2.6.0
|
||||
|
||||
softdepend:
|
||||
- OnTime
|
||||
- EssentialsX
|
||||
- Towny
|
||||
- Vault
|
||||
- Factions
|
||||
- SuperbVote
|
||||
- AdvancedAchievements
|
||||
|
||||
commands:
|
||||
plan:
|
||||
|
Loading…
Reference in New Issue
Block a user