[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:
Rsl1122 2017-02-21 22:04:05 +02:00
parent f0daeb91c4
commit 091e3eb1c5
36 changed files with 760 additions and 410 deletions

View File

@ -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>

View File

@ -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.
*/

View File

@ -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();

View File

@ -1,10 +0,0 @@
package main.java.com.djrapitops.plan.data;
/**
*
* @author Rsl1122
*/
public class AdditionalData {
}

View File

@ -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)) {

View File

@ -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);
}
}
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
};

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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>"),

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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>";
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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"

View File

@ -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();

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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">

View File

@ -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>

View File

@ -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: