Players table for server page split into a new class

This commit is contained in:
Rsl1122 2018-06-19 14:22:15 +03:00
parent 5ed77a1940
commit 55733169b1
14 changed files with 283 additions and 76 deletions

View File

@ -112,7 +112,7 @@ public class QInspectCommand extends CommandNode {
List<GeoInfo> geoInfo = container.getValue(PlayerKeys.GEO_INFO).orElse(new ArrayList<>());
Optional<GeoInfo> mostRecentGeoInfo = new GeoInfoMutator(geoInfo).mostRecent();
String loginLocation = mostRecentGeoInfo.isPresent() ? mostRecentGeoInfo.get().getGeolocation() : "-";
SessionsMutator sessionsMutator = new SessionsMutator(container.getValue(PlayerKeys.SESSIONS).orElse(new ArrayList<>()));
SessionsMutator sessionsMutator = SessionsMutator.forContainer(container);
sender.sendMessage(colM + " Activity Index: " + colS + activityIndex.getFormattedValue() + " | " + activityIndex.getGroup());
sender.sendMessage(colM + " Registered: " + colS + timestamp.apply(() -> registered));

View File

@ -1,16 +1,10 @@
package com.djrapitops.plan.data.calculation;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.utilities.Verify;
import java.util.ArrayList;
import java.util.List;
public class ActivityIndex {
@ -23,8 +17,6 @@ public class ActivityIndex {
}
public ActivityIndex(DataContainer container, long date) {
Verify.isTrue(container.supports(PlayerKeys.SESSIONS),
() -> new IllegalArgumentException("Given container does not support sessions."));
value = calculate(container, date);
}
@ -49,10 +41,10 @@ public class ActivityIndex {
long activePlayThreshold = loadSetting(Settings.ACTIVE_PLAY_THRESHOLD.getNumber() * TimeAmount.MINUTE.ms());
int activeLoginThreshold = loadSetting(Settings.ACTIVE_LOGIN_THRESHOLD.getNumber());
List<Session> sessions = container.getValue(PlayerKeys.SESSIONS).orElse(new ArrayList<>());
SessionsMutator weekOne = new SessionsMutator(sessions).filterSessionsBetween(weekAgo, date);
SessionsMutator weekTwo = new SessionsMutator(sessions).filterSessionsBetween(twoWeeksAgo, weekAgo);
SessionsMutator weekThree = new SessionsMutator(sessions).filterSessionsBetween(threeWeeksAgo, twoWeeksAgo);
SessionsMutator sessionsMutator = SessionsMutator.forContainer(container);
SessionsMutator weekOne = SessionsMutator.copyOf(sessionsMutator).filterSessionsBetween(weekAgo, date);
SessionsMutator weekTwo = SessionsMutator.copyOf(sessionsMutator).filterSessionsBetween(twoWeeksAgo, weekAgo);
SessionsMutator weekThree = SessionsMutator.copyOf(sessionsMutator).filterSessionsBetween(threeWeeksAgo, twoWeeksAgo);
// Playtime per week multipliers, max out to avoid too high values.
double max = 4.0;

View File

@ -4,6 +4,7 @@
*/
package com.djrapitops.plan.data.element;
import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.html.Html;
@ -19,6 +20,7 @@ import java.util.List;
public class TableContainer {
protected final String[] header;
protected final Formatter[] formatters;
private List<Serializable[]> values;
private boolean jqueryDatatable;
@ -32,11 +34,13 @@ public class TableContainer {
*/
public TableContainer(String... header) {
this.header = header;
this.formatters = new Formatter[header.length];
values = new ArrayList<>();
}
public TableContainer(boolean players, String... header) {
this.header = FormatUtils.mergeArrays(new String[]{Html.FONT_AWESOME_ICON.parse("user") + " Player"}, header);
this.formatters = new Formatter[header.length];
values = new ArrayList<>();
}
@ -48,7 +52,7 @@ public class TableContainer {
return getTableHeader() +
parseHeader() +
parseBody() +
"</table>";
"</table>" + (jqueryDatatable ? "</div>" : "");
}
public final String parseBody() {
@ -58,21 +62,30 @@ public class TableContainer {
addRow("No Data");
}
for (Serializable[] row : values) {
int maxIndex = row.length - 1;
body.append("<tr>");
for (int i = 0; i < header.length; i++) {
body.append("<td>");
if (i > maxIndex) {
body.append("-");
} else {
body.append(row[i]);
try {
Serializable value = row[i];
Formatter formatter = formatters[i];
body.append("<td").append(formatter != null ? " data-order=\"" + value + "\">" : ">");
if (i > maxIndex) {
body.append("-");
} else {
body.append(formatter != null ? formatter.apply(value) : value);
}
body.append("</td>");
} catch (ClassCastException e) {
throw new IllegalStateException("Invalid formatter given at index " + i + ": " + e.getMessage(), e);
}
body.append("</td>");
}
body.append("</tr>");
}
return Html.TABLE_BODY.parse(body.toString());
}
public final void setColor(String color) {
@ -88,6 +101,12 @@ public class TableContainer {
return header.toString();
}
public final void setFormatter(int index, Formatter formatter) {
if (index < formatters.length) {
formatters[index] = formatter;
}
}
/**
* Make use of JQuery Datatables plugin.
* <p>
@ -99,7 +118,7 @@ public class TableContainer {
private String getTableHeader() {
if (jqueryDatatable) {
return "<div class=\"table-responsive\">" + Html.TABLE_JQUERY.parse() + "</div>";
return "<div class=\"table-responsive\">" + Html.TABLE_JQUERY.parse();
} else {
return Html.TABLE_SCROLL.parse();
}

View File

@ -5,6 +5,7 @@ import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.keys.AnalysisKeys;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.data.store.mutators.CommandUseMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.data.store.mutators.TPSMutator;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
@ -20,12 +21,15 @@ import com.djrapitops.plan.utilities.html.graphs.line.*;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plan.utilities.html.structure.RecentLoginList;
import com.djrapitops.plan.utilities.html.structure.SessionAccordion;
import com.djrapitops.plan.utilities.html.tables.CommandUseTable;
import com.djrapitops.plan.utilities.html.tables.PlayersTable;
import com.djrapitops.plan.utilities.html.tables.ServerSessionTable;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
@ -45,7 +49,15 @@ public class AnalysisContainer extends DataContainer {
}
private void addAnalysisSuppliers() {
putSupplier(AnalysisKeys.SESSIONS_MUTATOR, () -> SessionsMutator.forContainer(serverContainer));
putSupplier(AnalysisKeys.TPS_MUTATOR, () -> TPSMutator.forContainer(serverContainer));
addConstants();
addPlayerSuppliers();
addSessionSuppliers();
addGraphSuppliers();
addTPSAverageSuppliers();
addCommandSuppliers();
}
private void addConstants() {
@ -62,15 +74,8 @@ public class AnalysisContainer extends DataContainer {
putRawData(AnalysisKeys.TPS_MEDIUM, Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber());
putRawData(AnalysisKeys.TPS_HIGH, Settings.THEME_GRAPH_TPS_THRESHOLD_HIGH.getNumber());
putSupplier(AnalysisKeys.SESSIONS_MUTATOR, () -> new SessionsMutator(serverContainer.getValue(ServerKeys.SESSIONS).orElse(new ArrayList<>())));
putSupplier(AnalysisKeys.TPS_MUTATOR, () -> new TPSMutator(serverContainer.getValue(ServerKeys.TPS).orElse(new ArrayList<>())));
addServerProperties();
addThemeColors();
addPlayerSuppliers();
addSessionSuppliers();
addGraphSuppliers();
addTPSAverageSuppliers();
}
private void addServerProperties() {
@ -117,6 +122,9 @@ public class AnalysisContainer extends DataContainer {
.map(dateObj -> Formatters.year().apply(dateObj)).orElse("-")
);
putSupplier(AnalysisKeys.OPERATORS, () -> serverContainer.getValue(ServerKeys.OPERATORS).map(List::size).orElse(0));
putSupplier(AnalysisKeys.PLAYERS_TABLE, () ->
PlayersTable.forServerPage(serverContainer.getValue(ServerKeys.PLAYERS).orElse(new ArrayList<>())).parseHtml()
);
}
private void addSessionSuppliers() {
@ -203,4 +211,10 @@ public class AnalysisContainer extends DataContainer {
putSupplier(AnalysisKeys.AVG_ENTITY_DAY, () -> getUnsafe(tpsDay).averageEntities());
putSupplier(AnalysisKeys.AVG_CHUNK_DAY, () -> getUnsafe(tpsDay).averageChunks());
}
private void addCommandSuppliers() {
putSupplier(AnalysisKeys.COMMAND_USAGE_TABLE, () -> new CommandUseTable(serverContainer).parseHtml());
putSupplier(AnalysisKeys.COMMAND_COUNT_UNIQUE, () -> serverContainer.getValue(ServerKeys.COMMAND_USAGE).map(Map::size).orElse(0));
putSupplier(AnalysisKeys.COMMAND_COUNT, () -> CommandUseMutator.forContainer(serverContainer).commandUsageCount());
}
}

View File

@ -0,0 +1,35 @@
package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.keys.ServerKeys;
import java.util.HashMap;
import java.util.Map;
/**
* Mutator for Command Usage Map objects.
* <p>
* Can be used to easily get different values about the map.
*
* @author Rsl1122
*/
public class CommandUseMutator {
private Map<String, Integer> commandUsage;
public CommandUseMutator(Map<String, Integer> commandUsage) {
this.commandUsage = commandUsage;
}
public static CommandUseMutator forContainer(DataContainer container) {
return new CommandUseMutator(container.getValue(ServerKeys.COMMAND_USAGE).orElse(new HashMap<>()));
}
public int commandUsageCount() {
int total = 0;
for (Integer value : commandUsage.values()) {
total += value;
}
return total;
}
}

View File

@ -1,6 +1,8 @@
package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.utilities.comparators.GeoInfoComparator;
import java.util.ArrayList;
@ -18,6 +20,10 @@ public class GeoInfoMutator {
private final List<GeoInfo> geoInfo;
public static GeoInfoMutator forContainer(DataContainer container) {
return new GeoInfoMutator(container.getValue(PlayerKeys.GEO_INFO).orElse(new ArrayList<>()));
}
public GeoInfoMutator(List<GeoInfo> geoInfo) {
this.geoInfo = geoInfo;
}

View File

@ -5,7 +5,6 @@ import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.keys.CommonKeys;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plugin.utilities.Verify;
import java.util.*;
import java.util.stream.Collectors;
@ -22,8 +21,6 @@ public class SessionsMutator {
private List<Session> sessions;
public static SessionsMutator forContainer(DataContainer dataContainer) {
Verify.isTrue(dataContainer.supports(CommonKeys.SESSIONS),
() -> new IllegalArgumentException("Given DataContainer does not support SESSIONS-key"));
return new SessionsMutator(dataContainer.getValue(CommonKeys.SESSIONS).orElse(new ArrayList<>()));
}

View File

@ -6,7 +6,6 @@ import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.utilities.html.graphs.line.Point;
import com.djrapitops.plugin.api.TimeAmount;
import com.djrapitops.plugin.utilities.Verify;
import java.util.ArrayList;
import java.util.List;
@ -29,8 +28,6 @@ public class TPSMutator {
}
public static TPSMutator forContainer(DataContainer dataContainer) {
Verify.isTrue(dataContainer.supports(ServerKeys.TPS),
() -> new IllegalArgumentException("Given DataContainer does not support SESSIONS-key"));
return new TPSMutator(dataContainer.getValue(ServerKeys.TPS).orElse(new ArrayList<>()));
}

View File

@ -21,6 +21,12 @@ public class Formatters {
};
}
public static Formatter<Long> yearLongValue() {
return date -> {
return date > 0 ? FormatUtils.formatTimeStampYear(date) : "-";
};
}
public static Formatter<DateHolder> day() {
return dateHolder -> {
long date = dateHolder.getDate();

View File

@ -60,13 +60,10 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
// Calculating getters
container.putSupplier(ServerKeys.OPERATORS, () -> container.getUnsafe(ServerKeys.PLAYERS).stream()
.filter(player -> player.getValue(PlayerKeys.OPERATOR).orElse(false)).collect(Collectors.toList()));
container.putSupplier(ServerKeys.PLAYER_KILLS,
new SessionsMutator(container.getUnsafe(ServerKeys.SESSIONS))::toPlayerKillList);
container.putSupplier(ServerKeys.PLAYER_KILLS, SessionsMutator.forContainer(container)::toPlayerKillList);
container.putSupplier(ServerKeys.PLAYER_KILL_COUNT, container.getUnsafe(ServerKeys.PLAYER_KILLS)::size);
container.putSupplier(ServerKeys.MOB_KILL_COUNT,
new SessionsMutator(container.getUnsafe(ServerKeys.SESSIONS))::toMobKillCount);
container.putSupplier(ServerKeys.DEATH_COUNT,
new SessionsMutator(container.getUnsafe(ServerKeys.SESSIONS))::toDeathCount);
container.putSupplier(ServerKeys.MOB_KILL_COUNT, SessionsMutator.forContainer(container)::toMobKillCount);
container.putSupplier(ServerKeys.DEATH_COUNT, SessionsMutator.forContainer(container)::toDeathCount);
return container;
}
@ -113,16 +110,12 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
return worldTimes;
});
container.putSupplier(PlayerKeys.LAST_SEEN,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toLastSeen);
container.putSupplier(PlayerKeys.LAST_SEEN, SessionsMutator.forContainer(container)::toLastSeen);
container.putSupplier(PlayerKeys.PLAYER_KILLS,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toPlayerKillList);
container.putSupplier(PlayerKeys.PLAYER_KILLS, SessionsMutator.forContainer(container)::toPlayerKillList);
container.putSupplier(PlayerKeys.PLAYER_KILL_COUNT, container.getUnsafe(PlayerKeys.PLAYER_KILLS)::size);
container.putSupplier(PlayerKeys.MOB_KILL_COUNT,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toMobKillCount);
container.putSupplier(PlayerKeys.DEATH_COUNT,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toDeathCount);
container.putSupplier(PlayerKeys.MOB_KILL_COUNT, SessionsMutator.forContainer(container)::toMobKillCount);
container.putSupplier(PlayerKeys.DEATH_COUNT, SessionsMutator.forContainer(container)::toDeathCount);
}
return containers;
@ -211,16 +204,12 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
return worldTimes;
});
container.putSupplier(PlayerKeys.LAST_SEEN,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toLastSeen);
container.putSupplier(PlayerKeys.LAST_SEEN, SessionsMutator.forContainer(container)::toLastSeen);
container.putSupplier(PlayerKeys.PLAYER_KILLS,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toPlayerKillList);
container.putSupplier(PlayerKeys.PLAYER_KILLS, SessionsMutator.forContainer(container)::toPlayerKillList);
container.putSupplier(PlayerKeys.PLAYER_KILL_COUNT, container.getUnsafe(PlayerKeys.PLAYER_KILLS)::size);
container.putSupplier(PlayerKeys.MOB_KILL_COUNT,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toMobKillCount);
container.putSupplier(PlayerKeys.DEATH_COUNT,
new SessionsMutator(container.getUnsafe(PlayerKeys.SESSIONS))::toDeathCount);
container.putSupplier(PlayerKeys.MOB_KILL_COUNT, SessionsMutator.forContainer(container)::toMobKillCount);
container.putSupplier(PlayerKeys.DEATH_COUNT, SessionsMutator.forContainer(container)::toDeathCount);
return container;
}
@ -248,18 +237,13 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
DataContainer container = perServerContainer.getOrDefault(serverUUID, new DataContainer());
container.putRawData(PerServerKeys.SESSIONS, serverSessions);
container.putSupplier(PerServerKeys.LAST_SEEN,
new SessionsMutator(container.getUnsafe(PerServerKeys.SESSIONS))::toLastSeen);
container.putSupplier(PerServerKeys.LAST_SEEN, SessionsMutator.forContainer(container)::toLastSeen);
container.putSupplier(PerServerKeys.WORLD_TIMES,
new SessionsMutator(container.getUnsafe(PerServerKeys.SESSIONS))::toTotalWorldTimes);
container.putSupplier(PerServerKeys.PLAYER_KILLS,
new SessionsMutator(container.getUnsafe(PerServerKeys.SESSIONS))::toPlayerKillList);
container.putSupplier(PerServerKeys.WORLD_TIMES, SessionsMutator.forContainer(container)::toTotalWorldTimes);
container.putSupplier(PerServerKeys.PLAYER_KILLS, SessionsMutator.forContainer(container)::toPlayerKillList);
container.putSupplier(PerServerKeys.PLAYER_KILL_COUNT, container.getUnsafe(PerServerKeys.PLAYER_KILLS)::size);
container.putSupplier(PerServerKeys.MOB_KILL_COUNT,
new SessionsMutator(container.getUnsafe(PerServerKeys.SESSIONS))::toMobKillCount);
container.putSupplier(PerServerKeys.DEATH_COUNT,
new SessionsMutator(container.getUnsafe(PerServerKeys.SESSIONS))::toDeathCount);
container.putSupplier(PerServerKeys.MOB_KILL_COUNT, SessionsMutator.forContainer(container)::toMobKillCount);
container.putSupplier(PerServerKeys.DEATH_COUNT, SessionsMutator.forContainer(container)::toDeathCount);
perServerContainer.put(serverUUID, container);
}

View File

@ -132,7 +132,7 @@ public class InspectPage extends Page {
.collect(Collectors.toMap(entry -> serverNames.get(entry.getKey()), Map.Entry::getValue));
List<Session> allSessions = container.getValue(PlayerKeys.SESSIONS).orElse(new ArrayList<>());
SessionsMutator allSessionsMutator = new SessionsMutator(allSessions);
SessionsMutator sessionsMutator = SessionsMutator.forContainer(container);
allSessions.sort(new SessionStartComparator());
String sessionAccordionViewScript = "";
@ -163,38 +163,38 @@ public class InspectPage extends Page {
long weekAgo = now - TimeAmount.WEEK.ms();
long monthAgo = now - TimeAmount.MONTH.ms();
SessionsMutator daySessionsMutator = new SessionsMutator(allSessions).filterSessionsBetween(dayAgo, now);
SessionsMutator weekSessionsMutator = new SessionsMutator(allSessions).filterSessionsBetween(weekAgo, now);
SessionsMutator monthSessionsMutator = new SessionsMutator(allSessions).filterSessionsBetween(monthAgo, now);
SessionsMutator daySessionsMutator = SessionsMutator.copyOf(sessionsMutator).filterSessionsBetween(dayAgo, now);
SessionsMutator weekSessionsMutator = SessionsMutator.copyOf(sessionsMutator).filterSessionsBetween(weekAgo, now);
SessionsMutator monthSessionsMutator = SessionsMutator.copyOf(sessionsMutator).filterSessionsBetween(monthAgo, now);
long playtime = allSessionsMutator.toPlaytime();
long playtime = sessionsMutator.toPlaytime();
long playtimeDay = daySessionsMutator.toPlaytime();
long playtimeWeek = weekSessionsMutator.toPlaytime();
long playtimeMonth = monthSessionsMutator.toPlaytime();
long afk = allSessionsMutator.toAfkTime();
long afk = sessionsMutator.toAfkTime();
long afkDay = daySessionsMutator.toAfkTime();
long afkWeek = weekSessionsMutator.toAfkTime();
long afkMonth = monthSessionsMutator.toAfkTime();
long activeTotal = playtime - afk;
long longestSession = allSessionsMutator.toLongestSessionLength();
long longestSession = sessionsMutator.toLongestSessionLength();
long longestSessionDay = daySessionsMutator.toLongestSessionLength();
long longestSessionWeek = weekSessionsMutator.toLongestSessionLength();
long longestSessionMonth = monthSessionsMutator.toLongestSessionLength();
long sessionMedian = allSessionsMutator.toMedianSessionLength();
long sessionMedian = sessionsMutator.toMedianSessionLength();
long sessionMedianDay = daySessionsMutator.toMedianSessionLength();
long sessionMedianWeek = weekSessionsMutator.toMedianSessionLength();
long sessionMedianMonth = monthSessionsMutator.toMedianSessionLength();
int sessionCount = allSessionsMutator.count();
int sessionCount = sessionsMutator.count();
int sessionCountDay = daySessionsMutator.count();
int sessionCountWeek = weekSessionsMutator.count();
int sessionCountMonth = monthSessionsMutator.count();
long sessionAverage = allSessionsMutator.toAverageSessionLength();
long sessionAverage = sessionsMutator.toAverageSessionLength();
long sessionAverageDay = daySessionsMutator.toAverageSessionLength();
long sessionAverageWeek = weekSessionsMutator.toAverageSessionLength();
long sessionAverageMonth = monthSessionsMutator.toAverageSessionLength();

View File

@ -1,10 +1,13 @@
package com.djrapitops.plan.utilities.html.tables;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.utilities.comparators.MapComparator;
import com.djrapitops.plan.utilities.html.HtmlUtils;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -13,6 +16,10 @@ import java.util.Map;
*/
public class CommandUseTable extends TableContainer {
public CommandUseTable(DataContainer container) {
this(container.getValue(ServerKeys.COMMAND_USAGE).orElse(new HashMap<>()));
}
public CommandUseTable(Map<String, Integer> commandUse) {
super("Command", "Times Used");

View File

@ -0,0 +1,94 @@
package com.djrapitops.plan.utilities.html.tables;
import com.djrapitops.plan.api.PlanAPI;
import com.djrapitops.plan.data.calculation.ActivityIndex;
import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.mutators.GeoInfoMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.utilities.html.Html;
import java.util.List;
/**
* Utility for creating Players table html.
*
* @author Rsl1122
*/
public class PlayersTable extends TableContainer {
private final List<PlayerContainer> players;
private final int maxPlayers;
private PlayersTable(List<PlayerContainer> players, int maxPlayers) {
super(
Html.FONT_AWESOME_ICON.parse("user") + " Name",
Html.FONT_AWESOME_ICON.parse("check") + " Activity Index",
Html.FONT_AWESOME_ICON.parse("clock-o") + " Playtime",
Html.FONT_AWESOME_ICON.parse("calendar-plus-o") + " Sessions",
Html.FONT_AWESOME_ICON.parse("user-plus") + " Registered",
Html.FONT_AWESOME_ICON.parse("calendar-check-o") + " Registered",
Html.FONT_AWESOME_ICON.parse("globe") + " Geolocation"
);
this.players = players;
this.maxPlayers = maxPlayers;
useJqueryDataTables();
setFormatter(2, Formatters.timeAmount());
setFormatter(4, Formatters.yearLongValue());
setFormatter(5, Formatters.yearLongValue());
addRows();
}
public static PlayersTable forServerPage(List<PlayerContainer> players) {
return new PlayersTable(players, Settings.MAX_PLAYERS.getNumber());
}
public static PlayersTable forPlayersPage(List<PlayerContainer> players) {
return new PlayersTable(players, Settings.MAX_PLAYERS_PLAYERS_PAGE.getNumber());
}
private void addRows() {
PlanAPI planAPI = PlanAPI.getInstance();
long now = System.currentTimeMillis();
int i = 0;
for (PlayerContainer player : players) {
if (i >= maxPlayers) {
break;
}
String name = player.getValue(PlayerKeys.NAME).orElse("Unknown");
String url = planAPI.getPlayerInspectPageLink(name);
SessionsMutator sessionsMutator = SessionsMutator.forContainer(player);
int loginTimes = sessionsMutator.count();
long playtime = sessionsMutator.toPlaytime();
long registered = player.getValue(PlayerKeys.REGISTERED).orElse(0L);
long lastSeen = sessionsMutator.toLastSeen();
ActivityIndex activityIndex = new ActivityIndex(player, now);
boolean isBanned = player.getValue(PlayerKeys.BANNED).orElse(false);
String activityString = activityIndex.getFormattedValue()
+ (isBanned ? " (<b>Banned</b>)" : " (" + activityIndex.getGroup() + ")");
String geolocation = GeoInfoMutator.forContainer(player).mostRecent().map(GeoInfo::getGeolocation).orElse("-");
addRow(
Html.LINK_EXTERNAL.parse(url, name),
activityString,
playtime,
loginTimes,
registered,
lastSeen,
geolocation
);
i++;
}
}
}

View File

@ -0,0 +1,56 @@
package com.djrapitops.plan.utilities.html.tables;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import utilities.Teardown;
import utilities.mocks.SystemMockUtil;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import static org.junit.Assert.assertTrue;
/**
* Tests for {@link PlayersTable}
*
* @author Rsl1122
*/
public class PlayersTableTest {
@ClassRule
public static TemporaryFolder temporaryFolder = new TemporaryFolder();
@BeforeClass
public static void setUpClass() throws Exception {
SystemMockUtil.setUp(temporaryFolder.getRoot())
.enableConfigSystem();
Teardown.resetSettingsTempValues();
}
@Test
public void noClassCastExceptionsFromFormatting() {
List<PlayerContainer> players = Collections.singletonList(new PlayerContainer());
String html = PlayersTable.forServerPage(players).parseHtml();
testHtmlValidity(html);
}
private void testHtmlValidity(String html) {
Stack<String> stack = new Stack<>();
String[] split = html.split("<");
for (String s : split) {
if (s.startsWith("/")) {
String expectedElement = stack.pop();
assertTrue("Element not properly closed: " + expectedElement, s.startsWith("/" + expectedElement));
} else {
stack.push(s.split(" ", 2)[0].split(">", 2)[0]);
}
}
stack.pop(); // Pop the empty string since the html string starts with <
assertTrue("Stack was not empty: " + stack.toString(), stack.empty());
}
}