mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-01-01 05:57:50 +01:00
Started work on Activity Index
- New settings for Activity index - HasDate interface - Deprecated more AnalysisUtils methods - playerStatus HtmlStructure parser - Online status to Inspect page #408 #396 - JavaDocs for more comparators - More work on ServerProfile - TPS spike count, playerkills, mob kills, deaths, server worldtimes, player peaks, online/offline players
This commit is contained in:
parent
7e743a4eaf
commit
0ff2fe89d6
@ -31,6 +31,8 @@ public enum Settings {
|
||||
WEBSERVER_PORT("WebServer.Port"),
|
||||
DB_PORT("Database.MySQL.Port"),
|
||||
ANALYSIS_AUTO_REFRESH("Analysis.AutoRefreshPeriod"),
|
||||
ACTIVE_PLAY_THRESHOLD("Analysis.Active.PlaytimeThreshold"),
|
||||
ACTIVE_LOGIN_THRESHOLD("Analysis.Active.LoginThreshold"),
|
||||
|
||||
// String
|
||||
DEBUG("Plugin.Debug"),
|
||||
|
@ -15,7 +15,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Action {
|
||||
public class Action implements HasDate {
|
||||
private final long date;
|
||||
private final Actions doneAction;
|
||||
private final String additionalInfo;
|
||||
|
@ -11,7 +11,7 @@ import com.google.common.base.Objects;
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class GeoInfo {
|
||||
public class GeoInfo implements HasDate {
|
||||
|
||||
private final String ip;
|
||||
private final String geolocation;
|
||||
@ -35,6 +35,11 @@ public class GeoInfo {
|
||||
return lastUsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDate() {
|
||||
return getLastUsed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
|
16
Plan/src/main/java/com/djrapitops/plan/data/HasDate.java
Normal file
16
Plan/src/main/java/com/djrapitops/plan/data/HasDate.java
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Licence is provided in the jar as license.yml also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.data;
|
||||
|
||||
/**
|
||||
* //TODO Class Javadoc Comment
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public interface HasDate {
|
||||
|
||||
long getDate();
|
||||
|
||||
}
|
@ -13,7 +13,7 @@ import java.util.UUID;
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PlayerKill {
|
||||
public class PlayerKill implements HasDate {
|
||||
|
||||
private final UUID victim;
|
||||
private final long time;
|
||||
@ -50,6 +50,11 @@ public class PlayerKill {
|
||||
return time;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDate() {
|
||||
return getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Weapon used as string.
|
||||
*
|
||||
|
@ -4,6 +4,8 @@
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.data;
|
||||
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import main.java.com.djrapitops.plan.Settings;
|
||||
import main.java.com.djrapitops.plan.data.time.WorldTimes;
|
||||
import main.java.com.djrapitops.plan.utilities.MiscUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.ActionComparator;
|
||||
@ -51,7 +53,7 @@ public class PlayerProfile implements OfflinePlayer {
|
||||
private Map<String, String> pluginReplaceMap;
|
||||
|
||||
// Value that requires lot of processing
|
||||
private Double activityIndex;
|
||||
private Map<Long, Double> activityIndex;
|
||||
|
||||
public PlayerProfile(UUID uuid, String name, long registered) {
|
||||
this.uuid = uuid;
|
||||
@ -67,19 +69,67 @@ public class PlayerProfile implements OfflinePlayer {
|
||||
worldTimesMap = new HashMap<>();
|
||||
|
||||
pluginReplaceMap = new HashMap<>();
|
||||
activityIndex = new HashMap<>();
|
||||
}
|
||||
|
||||
// Calculating Getters
|
||||
|
||||
public boolean isActive() {
|
||||
return getActivityIndex() > 1.0;
|
||||
public boolean isActive(long date) {
|
||||
return getActivityIndex(date) > 1.0;
|
||||
}
|
||||
|
||||
public double getActivityIndex() {
|
||||
if (activityIndex != null) {
|
||||
return activityIndex;
|
||||
public double getActivityIndex(long date) {
|
||||
Double activityIndx = activityIndex.get(date);
|
||||
if (activityIndx != null) {
|
||||
return activityIndx;
|
||||
}
|
||||
return 0.0; // TODO
|
||||
|
||||
long week = TimeAmount.WEEK.ms();
|
||||
long weekAgo = date - week;
|
||||
long twoWeeksAgo = date - 2L * week;
|
||||
long threeWeeksAgo = date - 3L * week;
|
||||
|
||||
long activePlayThreshold = Settings.ACTIVE_PLAY_THRESHOLD.getNumber() * TimeAmount.MINUTE.ms();
|
||||
int activeLoginThreshold = Settings.ACTIVE_LOGIN_THRESHOLD.getNumber();
|
||||
|
||||
List<Session> sessionsWeek = getSessions(weekAgo, date).collect(Collectors.toList());
|
||||
List<Session> sessionsWeek2 = getSessions(twoWeeksAgo, weekAgo).collect(Collectors.toList());
|
||||
List<Session> sessionsWeek3 = getSessions(threeWeeksAgo, twoWeeksAgo).collect(Collectors.toList());
|
||||
|
||||
double weekPlay = (PlayerProfile.getPlaytime(sessionsWeek.stream()) * 1.0 / activePlayThreshold);
|
||||
double week2Play = (PlayerProfile.getPlaytime(sessionsWeek2.stream()) * 1.0 / activePlayThreshold);
|
||||
double week3Play = (PlayerProfile.getPlaytime(sessionsWeek3.stream()) * 1.0 / activePlayThreshold);
|
||||
|
||||
// Reduce the harshness for new players and players who have had a vacation
|
||||
if (weekPlay > 1 && week3Play > 1 && week2Play == 0.0) {
|
||||
week2Play = 0.5;
|
||||
}
|
||||
if (weekPlay > 1 && week2Play == 0.0) {
|
||||
week2Play = 0.6;
|
||||
}
|
||||
if (weekPlay > 1 && week3Play == 0.0) {
|
||||
week3Play = 0.75;
|
||||
}
|
||||
|
||||
double playAvg = (weekPlay + week2Play + week3Play) / 3.0;
|
||||
|
||||
double weekLogin = sessionsWeek.size() > activeLoginThreshold ? 1.0 : 0.5;
|
||||
double week2Login = sessionsWeek2.size() > activeLoginThreshold ? 1.0 : 0.5;
|
||||
double week3Login = sessionsWeek3.size() > activeLoginThreshold ? 1.0 : 0.5;
|
||||
|
||||
double extraMultiplier = 1.0;
|
||||
double loginTotal = weekLogin + week2Login + week3Login;
|
||||
|
||||
double loginAvg = loginTotal / 3.0;
|
||||
if (loginTotal < 2.0) {
|
||||
extraMultiplier = 0.75;
|
||||
}
|
||||
|
||||
activityIndx = playAvg * loginAvg * extraMultiplier;
|
||||
|
||||
activityIndex.put(date, activityIndx);
|
||||
|
||||
return activityIndx;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -232,6 +282,9 @@ public class PlayerProfile implements OfflinePlayer {
|
||||
}
|
||||
|
||||
public GeoInfo getMostRecentGeoInfo() {
|
||||
if (geoInformation.isEmpty()) {
|
||||
return new GeoInfo("-", "Not Known", MiscUtils.getTime());
|
||||
}
|
||||
geoInformation.sort(new GeoInfoComparator());
|
||||
return geoInformation.get(0);
|
||||
}
|
||||
@ -447,7 +500,7 @@ public class PlayerProfile implements OfflinePlayer {
|
||||
|
||||
@Override
|
||||
public boolean isBanned() {
|
||||
return bannedOnServers.contains(MiscUtils.getIPlan().getServerUuid());
|
||||
return bannedOnServers.size() != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,9 +4,20 @@
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.data;
|
||||
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.PlanBungee;
|
||||
import main.java.com.djrapitops.plan.Settings;
|
||||
import main.java.com.djrapitops.plan.data.time.WorldTimes;
|
||||
import main.java.com.djrapitops.plan.utilities.MiscUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.analysis.MathUtils;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.PlayerProfileLastPlayedComparator;
|
||||
import main.java.com.djrapitops.plan.utilities.comparators.TPSComparator;
|
||||
import main.java.com.djrapitops.plan.utilities.html.tables.PlayersTableCreator;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
@ -25,6 +36,13 @@ public class ServerProfile {
|
||||
private List<TPS> tps;
|
||||
private Map<String, Integer> commandUsage;
|
||||
|
||||
// Information calculated with SQL
|
||||
private WorldTimes serverWorldtimes;
|
||||
private long lastPeakDate;
|
||||
private int lastPeakPlayers;
|
||||
private long allTimePeak;
|
||||
private int allTimePeakPlayers;
|
||||
|
||||
// Active information
|
||||
private int playersOnline;
|
||||
private int playersMax;
|
||||
@ -60,6 +78,29 @@ public class ServerProfile {
|
||||
this.commandUsage = commandUsage;
|
||||
}
|
||||
|
||||
public long getLowSpikeCount(long after, long before) {
|
||||
List<TPS> tpsData = getTPSData(after, before).sorted(new TPSComparator()).collect(Collectors.toList());
|
||||
|
||||
int mediumThreshold = Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber();
|
||||
|
||||
boolean wasLow = false;
|
||||
long spikeCount = 0L;
|
||||
|
||||
for (TPS tpsObj : tpsData) {
|
||||
double tps = tpsObj.getTicksPerSecond();
|
||||
if (tps < mediumThreshold) {
|
||||
if (!wasLow) {
|
||||
spikeCount++;
|
||||
wasLow = true;
|
||||
}
|
||||
} else {
|
||||
wasLow = false;
|
||||
}
|
||||
}
|
||||
|
||||
return spikeCount;
|
||||
}
|
||||
|
||||
public double getAverageTPS(long after, long before) {
|
||||
OptionalDouble average = getTPSData(after, before)
|
||||
.mapToDouble(TPS::getTicksPerSecond)
|
||||
@ -136,4 +177,110 @@ public class ServerProfile {
|
||||
public Stream<TPS> getTPSData(long after, long before) {
|
||||
return tps.stream().filter(tps -> tps.getDate() >= after && tps.getDate() <= before);
|
||||
}
|
||||
|
||||
public String createPlayersTableBody() {
|
||||
players.sort(new PlayerProfileLastPlayedComparator());
|
||||
return PlayersTableCreator.createTable(players);
|
||||
}
|
||||
|
||||
public List<String> getGeoLocations() {
|
||||
return players.stream()
|
||||
.map(PlayerProfile::getMostRecentGeoInfo)
|
||||
.map(GeoInfo::getGeolocation)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public long getTotalPlaytime() {
|
||||
return serverWorldtimes.getTotal();
|
||||
}
|
||||
|
||||
public long getAveragePlayTime() {
|
||||
return MathUtils.averageLong(getTotalPlaytime(), getPlayerCount());
|
||||
}
|
||||
|
||||
public long getPlayerCount() {
|
||||
return players.size();
|
||||
}
|
||||
|
||||
public List<Session> getSessions() {
|
||||
return players.stream().map(p -> p.getSessions(serverUUID)).flatMap(Collection::stream).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<PlayerKill> getPlayerKills(List<Session> s) {
|
||||
List<PlayerKill> kills = new ArrayList<>();
|
||||
for (Session session : s) {
|
||||
kills.addAll(session.getPlayerKills());
|
||||
}
|
||||
return kills;
|
||||
}
|
||||
|
||||
public long getMobKillCount(List<Session> s) {
|
||||
long total = 0;
|
||||
for (Session session : s) {
|
||||
total += session.getMobKills();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public long getDeathCount(List<Session> s) {
|
||||
long total = 0;
|
||||
for (Session session : s) {
|
||||
total += session.getDeaths();
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
// Default setters & getters
|
||||
|
||||
public WorldTimes getServerWorldtimes() {
|
||||
return serverWorldtimes;
|
||||
}
|
||||
|
||||
public void setServerWorldtimes(WorldTimes serverWorldtimes) {
|
||||
this.serverWorldtimes = serverWorldtimes;
|
||||
}
|
||||
|
||||
public long getLastPeakDate() {
|
||||
return lastPeakDate;
|
||||
}
|
||||
|
||||
public void setLastPeakDate(long lastPeakDate) {
|
||||
this.lastPeakDate = lastPeakDate;
|
||||
}
|
||||
|
||||
public int getLastPeakPlayers() {
|
||||
return lastPeakPlayers;
|
||||
}
|
||||
|
||||
public void setLastPeakPlayers(int lastPeakPlayers) {
|
||||
this.lastPeakPlayers = lastPeakPlayers;
|
||||
}
|
||||
|
||||
public long getAllTimePeak() {
|
||||
return allTimePeak;
|
||||
}
|
||||
|
||||
public void setAllTimePeak(long allTimePeak) {
|
||||
this.allTimePeak = allTimePeak;
|
||||
}
|
||||
|
||||
public int getAllTimePeakPlayers() {
|
||||
return allTimePeakPlayers;
|
||||
}
|
||||
|
||||
public void setAllTimePeakPlayers(int allTimePeakPlayers) {
|
||||
this.allTimePeakPlayers = allTimePeakPlayers;
|
||||
}
|
||||
|
||||
public int getPlayersOnline() {
|
||||
if (Check.isBungeeAvailable()) {
|
||||
return PlanBungee.getInstance().getProxy().getOnlineCount();
|
||||
} else {
|
||||
return Plan.getInstance().getServer().getOnlinePlayers().size();
|
||||
}
|
||||
}
|
||||
|
||||
public int getPlayersMax() {
|
||||
return MiscUtils.getIPlan().getVariable().getMaxPlayers();
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package main.java.com.djrapitops.plan.data;
|
||||
|
||||
import main.java.com.djrapitops.plan.data.time.WorldTimes;
|
||||
import main.java.com.djrapitops.plan.utilities.MiscUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -26,7 +27,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class Session {
|
||||
public class Session implements HasDate {
|
||||
|
||||
private final long sessionStart;
|
||||
private Integer sessionID;
|
||||
@ -119,6 +120,9 @@ public class Session {
|
||||
* @return Long in ms.
|
||||
*/
|
||||
public long getLength() {
|
||||
if (sessionEnd == -1) {
|
||||
return MiscUtils.getTime() - sessionStart;
|
||||
}
|
||||
return sessionEnd - sessionStart;
|
||||
}
|
||||
|
||||
@ -212,4 +216,9 @@ public class Session {
|
||||
.append("deaths", deaths)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDate() {
|
||||
return getSessionStart();
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import java.util.Objects;
|
||||
* @author Rsl1122
|
||||
* @since 3.5.0
|
||||
*/
|
||||
public class TPS {
|
||||
public class TPS implements HasDate {
|
||||
|
||||
private final long date;
|
||||
private final double ticksPerSecond;
|
||||
|
@ -30,10 +30,7 @@ import main.java.com.djrapitops.plan.utilities.html.graphs.ServerPreferencePieCr
|
||||
import main.java.com.djrapitops.plan.utilities.html.graphs.WorldPieCreator;
|
||||
import main.java.com.djrapitops.plan.utilities.html.tables.ActionsTableCreator;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@ -58,6 +55,8 @@ public class InspectPageParser extends PageParser {
|
||||
Benchmark.start("Inspect Parse, Fetch");
|
||||
Database db = plugin.getDB();
|
||||
|
||||
UUID serverUuid = MiscUtils.getIPlan().getServerUuid();
|
||||
Map<UUID, String> serverNames = db.getServerTable().getServerNames();
|
||||
long now = MiscUtils.getTime();
|
||||
|
||||
addValue("refresh", FormatUtils.formatTimeStamp(now));
|
||||
@ -66,6 +65,14 @@ public class InspectPageParser extends PageParser {
|
||||
|
||||
PlayerProfile profile = db.getPlayerProfile(uuid);
|
||||
|
||||
String online = "Offline";
|
||||
Optional<Session> activeSession = plugin.getInfoManager().getDataCache().getCachedSession(uuid);
|
||||
if (activeSession.isPresent()) {
|
||||
profile.addActiveSession(activeSession.get());
|
||||
online = serverNames.get(serverUuid);
|
||||
}
|
||||
activeSession.ifPresent(profile::addActiveSession);
|
||||
|
||||
Benchmark.stop("Inspect Parse, Fetch");
|
||||
|
||||
String playerName = profile.getName();
|
||||
@ -82,8 +89,6 @@ public class InspectPageParser extends PageParser {
|
||||
addValue("lastSeen", "-");
|
||||
}
|
||||
|
||||
Map<UUID, String> serverNames = db.getServerTable().getServerNames();
|
||||
|
||||
Map<UUID, WorldTimes> worldTimesPerServer = profile.getWorldTimesPerServer();
|
||||
addValue("serverPieSeries", ServerPreferencePieCreator.createSeriesData(serverNames, worldTimesPerServer));
|
||||
addValue("worldPieColors", Settings.THEME_GRAPH_WORLD_PIE.toString());
|
||||
@ -211,7 +216,16 @@ public class InspectPageParser extends PageParser {
|
||||
addValue("mobKillCount", mobKillCount);
|
||||
addValue("deathCount", deathCount);
|
||||
|
||||
boolean isActive = AnalysisUtils.isActive(MiscUtils.getTime(), lastSeen, playtime, sessionCount);
|
||||
double activityIndex = profile.getActivityIndex(now);
|
||||
String[] activityIndexFormat = FormatUtils.readableActivityIndex(activityIndex);
|
||||
|
||||
addValue("activityIndexNumber", /*FormatUtils.cutDecimals(*/activityIndex);
|
||||
addValue("activityIndexColor", activityIndexFormat[0]);
|
||||
addValue("activityIndex", activityIndexFormat[1]);
|
||||
|
||||
addValue("playerStatus", HtmlStructure.playerStatus(online, profile.getBannedOnServers(), profile.isOp()));
|
||||
|
||||
boolean isActive = profile.isActive(now);
|
||||
String active = isActive ? "Active" : "Inactive";
|
||||
playerClassification(profile, active);
|
||||
|
||||
|
@ -211,4 +211,18 @@ public class FormatUtils {
|
||||
public static String cutDecimals(double d) {
|
||||
return df.format(d);
|
||||
}
|
||||
|
||||
public static String[] readableActivityIndex(double activityIndex) {
|
||||
if (activityIndex >= 5.0) {
|
||||
return new String[]{"green", "Very Active"};
|
||||
} else if (activityIndex >= 2.0) {
|
||||
return new String[]{"green", "Active"};
|
||||
} else if (activityIndex >= 1.0) {
|
||||
return new String[]{"green", "Regular"};
|
||||
} else if (activityIndex >= 0.5) {
|
||||
return new String[]{"amber", "Irregular"};
|
||||
} else {
|
||||
return new String[]{"blue-gray", "Inactive"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ public class AnalysisUtils {
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static boolean isActive(long now, long lastPlayed, long playTime, int loginTimes) {
|
||||
public static boolean isActive(long now, long lastPlayed, long playTime, long loginTimes) {
|
||||
int timeToActive = 10;
|
||||
long twoWeeks = 1209600000;
|
||||
return now - lastPlayed < twoWeeks
|
||||
@ -175,6 +175,7 @@ public class AnalysisUtils {
|
||||
* @param scale Scale (milliseconds), time before (Current epoch - scale) will be ignored.
|
||||
* @return Amount of Unique joins within the time span.
|
||||
*/
|
||||
@Deprecated
|
||||
public static int getUniqueJoins(Map<UUID, List<Session>> sessions, long scale) {
|
||||
long now = MiscUtils.getTime();
|
||||
long nowMinusScale = now - scale;
|
||||
@ -190,6 +191,7 @@ public class AnalysisUtils {
|
||||
return uniqueJoins.size();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int getUniqueJoinsPerDay(Map<UUID, List<Session>> sessions, long scale) {
|
||||
Map<Integer, Set<UUID>> uniqueJoins = new HashMap<>();
|
||||
long now = MiscUtils.getTime();
|
||||
@ -284,7 +286,7 @@ public class AnalysisUtils {
|
||||
return day.get(Calendar.DAY_OF_YEAR);
|
||||
}
|
||||
|
||||
public double getAveragePerDay(long after, long before, long total) {
|
||||
public static double getAveragePerDay(long after, long before, long total) {
|
||||
return total / getNumberOfDaysBetween(after, before);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Licence is provided in the jar as license.yml also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/license.yml
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.utilities.comparators;
|
||||
|
||||
import main.java.com.djrapitops.plan.data.HasDate;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Comparator for HasDate interface Objects.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class HasDateComparator implements Comparator<HasDate> {
|
||||
|
||||
private final boolean reversed;
|
||||
|
||||
public HasDateComparator() {
|
||||
this(false);
|
||||
}
|
||||
|
||||
public HasDateComparator(boolean reversed) {
|
||||
this.reversed = reversed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(HasDate o1, HasDate o2) {
|
||||
return (reversed ? -1 : 1) * Long.compare(o1.getDate(), o2.getDate());
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.utilities.comparators;
|
||||
|
||||
import main.java.com.djrapitops.plan.data.PlayerProfile;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Comparator for PlayerProfile so that most recently seen is first.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PlayerProfileLastPlayedComparator implements Comparator<PlayerProfile> {
|
||||
|
||||
@Override
|
||||
public int compare(PlayerProfile u1, PlayerProfile u2) {
|
||||
return Long.compare(u2.getLastSeen(), u1.getLastSeen());
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package main.java.com.djrapitops.plan.utilities.comparators;
|
||||
|
||||
import main.java.com.djrapitops.plan.data.PlayerProfile;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Comparator for PlayerProfile for Alphabetical Name order.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class PlayerProfileNameComparator implements Comparator<PlayerProfile> {
|
||||
|
||||
@Override
|
||||
public int compare(PlayerProfile u1, PlayerProfile u2) {
|
||||
return u1.getName().compareTo(u2.getName());
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ import main.java.com.djrapitops.plan.data.TPS;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Compares TPS objects so that earliest is first.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 3.5.0
|
||||
*/
|
||||
|
@ -10,7 +10,9 @@ import main.java.com.djrapitops.plan.data.UserInfo;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* @author Risto
|
||||
* Comparator for UserInfo so that most recently seen is first.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class UserInfoLastPlayedComparator implements Comparator<UserInfo> {
|
||||
|
||||
|
@ -10,9 +10,11 @@ import main.java.com.djrapitops.plan.data.UserInfo;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* @author Risto
|
||||
* Comparator for UserInfo for Alphabetical Name order.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class UserDataNameComparator implements Comparator<UserInfo> {
|
||||
public class UserInfoNameComparator implements Comparator<UserInfo> {
|
||||
|
||||
@Override
|
||||
public int compare(UserInfo u1, UserInfo u2) {
|
@ -55,6 +55,22 @@ public enum Html {
|
||||
TABLE_SESSIONS(DIV_W_CLASS_STYLE.parse("box-footer scrollbar", "padding: 2px;",
|
||||
TABLE_START_4.parse("Player", "Started", "Length", "World - Time") + "${3}" + TABLE_END.parse())
|
||||
),
|
||||
TABLE_PLAYERS("<table class=\"table table-bordered table-striped table-hover player-table dataTable\"><thead><tr>" +
|
||||
"<th><i class=\"fa fa-user\"></i> Name</th>" +
|
||||
"<th><i class=\"fa fa-check\"></i> Active</th>" +
|
||||
"<th><i class=\"fa fa-clock-o\"></i> Playtime</th>" +
|
||||
"<th><i class=\"fa fa-calendar-plus-o\"></i> Sessions</th>" +
|
||||
"<th><i class=\"fa fa-user-plus\"></i> Registered</th>" +
|
||||
"<th><i class=\"fa fa-calendar-check-o\"></i> Last Seen</th>" +
|
||||
"<th><i class=\"fa fa-globe\"></i> Geolocation</th></thead>" +
|
||||
"<tfoot><tr><th><i class=\"fa fa-user\"></i> Name</th>" +
|
||||
"<th><i class=\"fa fa-check\"></i> Active</th>" +
|
||||
"<th><i class=\"fa fa-clock-o\"></i> Playtime</th>" +
|
||||
"<th><i class=\"fa fa-calendar-plus-o\"></i> Sessions</th>" +
|
||||
"<th><i class=\"fa fa-user-plus\"></i> Registered</th>" +
|
||||
"<th><i class=\"fa fa-calendar-check-o\"></i> Last Seen</th>" +
|
||||
"<th><i class=\"fa fa-globe\"></i> Geolocation</th>" +
|
||||
"</tr></tfoot><tbody>${0}</tbody></table>"),
|
||||
TABLE_SESSIONS_START(TABLE_START_3.parse("Session Started", "Session Ended", "Session Length")),
|
||||
TABLE_KILLS_START(TABLE_START_3.parse(FONT_AWESOME_ICON.parse("clock-o") + " Time", "Killed", "With")),
|
||||
TABLE_FACTIONS_START(TABLE_START_4.parse(FONT_AWESOME_ICON.parse("flag") + " Faction", FONT_AWESOME_ICON.parse("bolt") + " Power", FONT_AWESOME_ICON.parse("map-o") + " Land", FONT_AWESOME_ICON.parse("user") + " Leader")),
|
||||
|
@ -351,4 +351,24 @@ public class HtmlStructure {
|
||||
String[] split2 = split[1].split("box-footer", 2);
|
||||
return split[0] + "<p>Offline</p></div><div class=\"box-footer" + split2[1];
|
||||
}
|
||||
|
||||
public static String playerStatus(String online, Set<UUID> banned, boolean op) {
|
||||
boolean offline = "offline".equalsIgnoreCase(online);
|
||||
|
||||
StringBuilder html = new StringBuilder("<p>");
|
||||
if (offline) {
|
||||
html.append(Html.FA_COLORED_ICON.parse("red", "ball")).append(" ").append(online);
|
||||
} else {
|
||||
html.append(Html.FA_COLORED_ICON.parse("green", "ball")).append(" ").append(online);
|
||||
}
|
||||
html.append("</p>");
|
||||
if (op) {
|
||||
html.append("<p>").append(Html.FA_COLORED_ICON.parse("blue", "superpowers")).append(" Operator</p>");
|
||||
}
|
||||
int bannedOn = banned.size();
|
||||
if (bannedOn != 0) {
|
||||
html.append("<p>").append(Html.FA_COLORED_ICON.parse("red", "gavel")).append(" Banned (").append(bannedOn).append(")");
|
||||
}
|
||||
return html.toString();
|
||||
}
|
||||
}
|
@ -1,6 +1,9 @@
|
||||
package main.java.com.djrapitops.plan.utilities.html.tables;
|
||||
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import main.java.com.djrapitops.plan.Plan;
|
||||
import main.java.com.djrapitops.plan.Settings;
|
||||
import main.java.com.djrapitops.plan.data.PlayerProfile;
|
||||
import main.java.com.djrapitops.plan.data.Session;
|
||||
import main.java.com.djrapitops.plan.data.UserInfo;
|
||||
import main.java.com.djrapitops.plan.data.analysis.GeolocationPart;
|
||||
@ -26,6 +29,7 @@ public class PlayersTableCreator {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static String createTable(List<UserInfo> userInfo, JoinInfoPart joinInfoPart, GeolocationPart geolocationPart) {
|
||||
if (userInfo.isEmpty()) {
|
||||
return Html.TABLELINE_PLAYERS.parse("<b>No Players</b>", "", "", "", "", "", "", "", "", "");
|
||||
@ -77,8 +81,10 @@ public class PlayersTableCreator {
|
||||
String.valueOf(lastSeen), lastSeen != 0 ? FormatUtils.formatTimeStamp(lastSeen) : "-",
|
||||
String.valueOf(geoLocation)
|
||||
));
|
||||
} catch (NullPointerException ignored) {
|
||||
ignored.printStackTrace(); // TODO IGNORE AGAIN
|
||||
} catch (NullPointerException e) {
|
||||
if (Settings.DEV_MODE.isTrue()) {
|
||||
Log.toLog(PlayersTableCreator.class.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
@ -98,4 +104,55 @@ public class PlayersTableCreator {
|
||||
|
||||
return isActive ? "Active" : "Inactive";
|
||||
}
|
||||
|
||||
public static String createTable(List<PlayerProfile> players) {
|
||||
if (players.isEmpty()) {
|
||||
return Html.TABLELINE_PLAYERS.parse("<b>No Players</b>", "", "", "", "", "", "", "", "", "");
|
||||
}
|
||||
|
||||
StringBuilder html = new StringBuilder();
|
||||
|
||||
long now = MiscUtils.getTime();
|
||||
UUID serverUUID = MiscUtils.getIPlan().getServerUuid();
|
||||
|
||||
int i = 0;
|
||||
for (PlayerProfile profile : players) {
|
||||
if (i >= 2000) {
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean isBanned = profile.isBanned();
|
||||
long loginTimes = profile.getSessionCount(serverUUID);
|
||||
long playtime = profile.getPlaytime(serverUUID);
|
||||
boolean isUnknown = loginTimes <= 1;
|
||||
long registered = profile.getRegistered();
|
||||
|
||||
boolean isActive = AnalysisUtils.isActive(now, profile.getLastSeen(), playtime, loginTimes);
|
||||
|
||||
long lastSeen = profile.getLastSeen();
|
||||
|
||||
String activityString = getActivityString(isBanned, isUnknown, isActive);
|
||||
|
||||
String geoLocation = profile.getMostRecentGeoInfo().getGeolocation();
|
||||
html.append(Html.TABLELINE_PLAYERS.parse(
|
||||
Html.LINK.parse(Plan.getPlanAPI().getPlayerInspectPageLink(profile.getName()), profile.getName()),
|
||||
activityString,
|
||||
String.valueOf(playtime), FormatUtils.formatTimeAmount(playtime),
|
||||
String.valueOf(loginTimes),
|
||||
String.valueOf(registered), FormatUtils.formatTimeStampYear(registered),
|
||||
String.valueOf(lastSeen), lastSeen != 0 ? FormatUtils.formatTimeStamp(lastSeen) : "-",
|
||||
String.valueOf(geoLocation)
|
||||
));
|
||||
} catch (NullPointerException e) {
|
||||
if (Settings.DEV_MODE.isTrue()) {
|
||||
Log.toLog(PlayersTableCreator.class.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return html.toString();
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,11 @@ Commands:
|
||||
|
||||
Analysis:
|
||||
AutoRefreshPeriod: 60
|
||||
Active:
|
||||
# Minutes a player should play per week to be considered active
|
||||
PlaytimeThreshold: 30
|
||||
# How many days player should join per week to be considered active
|
||||
LoginThreshold: 2
|
||||
LogProgress: true
|
||||
Export:
|
||||
Enabled: false
|
||||
|
@ -81,7 +81,7 @@ public class ComparatorTest {
|
||||
List<String> stringValues = userInfo.stream().map(UserInfo::getName).collect(Collectors.toList());
|
||||
Collections.sort(stringValues);
|
||||
|
||||
userInfo.sort(new UserDataNameComparator());
|
||||
userInfo.sort(new UserInfoNameComparator());
|
||||
List<String> afterSort = userInfo.stream().map(UserInfo::getName).collect(Collectors.toList());
|
||||
|
||||
assertEquals(stringValues, afterSort);
|
||||
|
Loading…
Reference in New Issue
Block a user