Prevented multiple concurrent analysis

This commit is contained in:
Rsl1122 2018-07-07 17:28:56 +03:00
parent 916a15299f
commit ef4e5d6d66
16 changed files with 111 additions and 114 deletions

View File

@ -46,10 +46,8 @@ public class AnalyzeCommand extends CommandNode {
Server server = getServer(args).orElseGet(ServerInfo::getServer);
UUID serverUUID = server.getUuid();
// TODO Create a new system to prevent multiple concurrent Analysis
if (!ServerInfo.getServerUUID().equals(serverUUID)) {
InfoSystem.getInstance().generateAnalysisPage(serverUUID);
}
sendWebUserNotificationIfNecessary(sender);
sendLink(server, sender);
} catch (DBOpException | WebException e) {

View File

@ -377,7 +377,7 @@ public class AnalysisContainer extends DataContainer {
// TODO Refactor into a system that supports running the analysis on Bungee
Key<String[]> navAndTabs = new Key<>(new Type<String[]>() {}, "NAV_AND_TABS");
putSupplier(navAndTabs, () ->
AnalysisPluginsTabContentCreator.createContent(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).uuids())
AnalysisPluginsTabContentCreator.createContent(getUnsafe(AnalysisKeys.PLAYERS_MUTATOR))
);
putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(navAndTabs)[0]);
putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(navAndTabs)[1]);

View File

@ -3,6 +3,7 @@ package com.djrapitops.plan.data.store.keys;
import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.PlaceholderKey;
import com.djrapitops.plan.data.store.Type;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
@ -26,11 +27,11 @@ public class CommonKeys {
public static final Key<UUID> UUID = new Key<>(UUID.class, "uuid");
public static final Key<UUID> SERVER_UUID = new Key<>(UUID.class, "server_uuid");
public static final Key<String> NAME = new Key<>(String.class, "name");
public static final Key<Long> REGISTERED = new Key<>(Long.class, "registered");
public static final PlaceholderKey<Long> REGISTERED = new PlaceholderKey<>(Long.class, "registered");
public static final Key<List<Session>> SESSIONS = new Key<>(new Type<List<Session>>() {}, "sessions");
public static final Key<WorldTimes> WORLD_TIMES = new Key<>(WorldTimes.class, "world_times");
public static final Key<Long> LAST_SEEN = new Key<>(Long.class, "last_seen");
public static final PlaceholderKey<Long> LAST_SEEN = new PlaceholderKey<>(Long.class, "lastSeen");
public static final Key<List<PlayerKill>> PLAYER_KILLS = new Key<>(new Type<List<PlayerKill>>() {}, "player_kills");
public static final Key<Integer> PLAYER_KILL_COUNT = new Key<>(Integer.class, "player_kill_count");

View File

@ -4,6 +4,7 @@ import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.PlaceholderKey;
import com.djrapitops.plan.data.store.Type;
import com.djrapitops.plan.data.store.containers.PerServerContainer;
import com.djrapitops.plan.data.store.objects.Nickname;
@ -29,7 +30,7 @@ public class PlayerKeys {
public static final Key<String> NAME = CommonKeys.NAME;
public static final Key<List<Nickname>> NICKNAMES = new Key<>(new Type<List<Nickname>>() {}, "nicknames");
public static final Key<Long> REGISTERED = CommonKeys.REGISTERED;
public static final PlaceholderKey<Long> REGISTERED = CommonKeys.REGISTERED;
public static final Key<Integer> KICK_COUNT = new Key<>(Integer.class, "kick_count");
public static final Key<List<GeoInfo>> GEO_INFO = new Key<>(new Type<List<GeoInfo>>() {}, "geo_info");
@ -43,7 +44,7 @@ public class PlayerKeys {
public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT;
public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT;
public static final Key<PerServerContainer> PER_SERVER = new Key<>(PerServerContainer.class, "per_server_data");
public static final Key<Long> LAST_SEEN = CommonKeys.LAST_SEEN;
public static final PlaceholderKey<Long> LAST_SEEN = CommonKeys.LAST_SEEN;
public static final Key<Boolean> BANNED = CommonKeys.BANNED;
public static final Key<Boolean> OPERATOR = CommonKeys.OPERATOR;

View File

@ -32,7 +32,7 @@ public class PlaceholderReplacer extends HashMap<String, Serializable> implement
}
}
public <T> void addAllPlaceholderFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T> key) {
public <T> void addPlaceholderFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T> key) {
if (!container.supports(key)) {
return;
}
@ -43,9 +43,9 @@ public class PlaceholderReplacer extends HashMap<String, Serializable> implement
Log.debug(key.getPlaceholder() + ": " + Formatters.benchmark().apply(ns));
}
public <T> void addPlaceholdersFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T>... keys) {
public <T> void addAllPlaceholdersFrom(DataContainer container, Formatter<T> formatter, PlaceholderKey<T>... keys) {
for (PlaceholderKey<T> key : keys) {
addAllPlaceholderFrom(container, formatter, key);
addPlaceholderFrom(container, formatter, key);
}
}

View File

@ -31,7 +31,7 @@ public class Version18TransferTable extends TransferTable {
db.getGeoInfoTable().createTable();
execute("INSERT INTO plan_ips (" +
"user_id, ip, ip_hash, geolocation, last_used" +
") SELECT user_id, ip, ip_hash, geolocation, MAX(last_used) FROM plan_ips_temp GROUP BY ip_hash, user_id");
") SELECT user_id, ip, ip_hash, geolocation, MAX(last_used) FROM plan_ips_temp GROUP BY ip_hash, user_id, ip, geolocation");
dropTable(tempTableName);
}
}

View File

@ -18,6 +18,7 @@ import com.djrapitops.plan.system.webserver.response.Response;
import com.djrapitops.plugin.api.utility.log.Log;
import com.djrapitops.plugin.utilities.Verify;
import java.util.Collections;
import java.util.Map;
import java.util.UUID;
@ -28,6 +29,7 @@ import java.util.UUID;
*/
public class GenerateAnalysisPageRequest extends InfoRequestWithVariables implements GenerateRequest {
private boolean runningAnalysis = false;
private final UUID serverUUID;
public GenerateAnalysisPageRequest(UUID serverUUID) {
@ -52,8 +54,9 @@ public class GenerateAnalysisPageRequest extends InfoRequestWithVariables implem
throw new BadRequestException("Requested Analysis page from wrong server.");
}
// TODO Create a new system to prevent multiple concurrent Analysis
if (!runningAnalysis) {
generateAndCache(serverUUID);
}
return DefaultResponses.SUCCESS.get();
}
@ -66,11 +69,15 @@ public class GenerateAnalysisPageRequest extends InfoRequestWithVariables implem
@Override
public void runLocally() throws WebException {
generateAndCache(serverUUID);
// Get the handler from ConnectionSystem and run the request.
InfoSystem.getInstance().getConnectionSystem()
.getInfoRequest(this.getClass().getSimpleName())
.handleRequest(Collections.singletonMap("server", serverUUID.toString()));
}
private String analyseAndGetHtml() throws InternalErrorException {
try {
runningAnalysis = true;
UUID serverUUID = ServerInfo.getServerUUID();
Database db = Database.getActive();
@ -84,6 +91,8 @@ public class GenerateAnalysisPageRequest extends InfoRequestWithVariables implem
} catch (Exception e) {
Log.toLog(this.getClass(), e);
throw new InternalErrorException("Analysis failed due to exception", e);
} finally {
runningAnalysis = false;
}
}

View File

@ -21,7 +21,6 @@ public class BootAnalysisTask extends AbsRunnable {
try {
String bootAnalysisRunMsg = Locale.get(Msg.ENABLE_BOOT_ANALYSIS_RUN_INFO).toString();
Log.info(bootAnalysisRunMsg);
// TODO Create a new system to prevent multiple concurrent Analysis
WebExceptionLogger.logIfOccurs(this.getClass(), () ->
InfoSystem.getInstance().sendRequest(new GenerateAnalysisPageRequest(ServerInfo.getServerUUID()))
);

View File

@ -17,7 +17,6 @@ public class PeriodicAnalysisTask extends AbsRunnable {
@Override
public void run() {
try {
// TODO Create a new system to prevent multiple concurrent Analysis
WebExceptionLogger.logIfOccurs(this.getClass(), () ->
InfoSystem.getInstance().sendRequest(new GenerateAnalysisPageRequest(ServerInfo.getServerUUID()))
);

View File

@ -20,7 +20,7 @@ import static com.djrapitops.plan.data.store.keys.AnalysisKeys.*;
*
* @author Rsl1122
*/
public class AnalysisPage extends Page {
public class AnalysisPage implements Page {
private final AnalysisContainer analysisContainer;
@ -76,7 +76,7 @@ public class AnalysisPage extends Page {
WORLD_MAP_SERIES, ACTIVITY_STACK_SERIES, ACTIVITY_STACK_CATEGORIES,
ACTIVITY_PIE_SERIES, CALENDAR_SERIES
);
placeholderReplacer.addPlaceholdersFrom(analysisContainer, FormatUtils::cutDecimals,
placeholderReplacer.addAllPlaceholdersFrom(analysisContainer, FormatUtils::cutDecimals,
AVG_TPS_MONTH, AVG_TPS_WEEK, AVG_TPS_DAY,
AVG_CPU_MONTH, AVG_CPU_WEEK, AVG_CPU_DAY,
AVG_RAM_MONTH, AVG_RAM_WEEK, AVG_RAM_DAY,

View File

@ -14,6 +14,7 @@ import com.djrapitops.plan.data.store.mutators.PerServerDataMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.data.store.mutators.formatting.PlaceholderReplacer;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.database.databases.Database;
@ -27,7 +28,6 @@ import com.djrapitops.plan.utilities.MiscUtils;
import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
import com.djrapitops.plan.utilities.file.FileUtil;
import com.djrapitops.plan.utilities.html.HtmlStructure;
import com.djrapitops.plan.utilities.html.HtmlUtils;
import com.djrapitops.plan.utilities.html.graphs.PunchCardGraph;
import com.djrapitops.plan.utilities.html.graphs.calendar.PlayerCalendar;
import com.djrapitops.plan.utilities.html.graphs.pie.ServerPreferencePie;
@ -42,14 +42,13 @@ import com.djrapitops.plugin.api.TimeAmount;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
/**
* Used for parsing Inspect page out of database data and the html.
*
* @author Rsl1122
*/
public class InspectPage extends Page {
public class InspectPage implements Page {
private final UUID uuid;
@ -83,9 +82,11 @@ public class InspectPage extends Page {
public String parse(PlayerContainer container, UUID serverUUID, Map<UUID, String> serverNames) throws IOException {
long now = System.currentTimeMillis();
addValue("refresh", FormatUtils.formatTimeStampClock(now));
addValue("version", MiscUtils.getPlanVersion());
addValue("timeZone", MiscUtils.getTimeZoneOffsetHours());
PlaceholderReplacer replacer = new PlaceholderReplacer();
replacer.put("refresh", FormatUtils.formatTimeStampClock(now));
replacer.put("version", MiscUtils.getPlanVersion());
replacer.put("timeZone", MiscUtils.getTimeZoneOffsetHours());
String online = "Offline";
Optional<Session> activeSession = SessionCache.getCachedSession(uuid);
@ -97,36 +98,31 @@ public class InspectPage extends Page {
}
String playerName = container.getValue(PlayerKeys.NAME).orElse("Unknown");
long registered = container.getValue(PlayerKeys.REGISTERED).orElse(-1L);
int timesKicked = container.getValue(PlayerKeys.KICK_COUNT).orElse(0);
long lastSeen = container.getValue(PlayerKeys.LAST_SEEN).orElse(-1L);
addValue("registered", Formatters.year().apply(() -> registered));
addValue("playerName", playerName);
addValue("kickCount", timesKicked);
replacer.addAllPlaceholdersFrom(container, Formatters.yearLongValue(),
PlayerKeys.REGISTERED, PlayerKeys.LAST_SEEN
);
addValue("lastSeen", Formatters.year().apply(() -> lastSeen));
replacer.put("playerName", playerName);
replacer.put("kickCount", timesKicked);
PerServerContainer perServerContainer = container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer());
PerServerDataMutator perServerDataMutator = new PerServerDataMutator(perServerContainer);
Map<UUID, WorldTimes> worldTimesPerServer = perServerDataMutator.worldTimesPerServer();
addValue("serverPieSeries", new ServerPreferencePie(serverNames, worldTimesPerServer).toHighChartsSeries());
addValue("worldPieColors", Theme.getValue(ThemeVal.GRAPH_WORLD_PIE));
addValue("gmPieColors", Theme.getValue(ThemeVal.GRAPH_GM_PIE));
addValue("serverPieColors", Theme.getValue(ThemeVal.GRAPH_SERVER_PREF_PIE));
replacer.put("serverPieSeries", new ServerPreferencePie(serverNames, worldTimesPerServer).toHighChartsSeries());
replacer.put("worldPieColors", Theme.getValue(ThemeVal.GRAPH_WORLD_PIE));
replacer.put("gmPieColors", Theme.getValue(ThemeVal.GRAPH_GM_PIE));
replacer.put("serverPieColors", Theme.getValue(ThemeVal.GRAPH_SERVER_PREF_PIE));
String favoriteServer = serverNames.getOrDefault(perServerDataMutator.favoriteServer(), "Unknown");
addValue("favoriteServer", favoriteServer);
replacer.put("favoriteServer", favoriteServer);
addValue("tableBodyNicknames", new NicknameTable(
replacer.put("tableBodyNicknames", new NicknameTable(
container.getValue(PlayerKeys.NICKNAMES).orElse(new ArrayList<>()), serverNames)
.parseBody());
addValue("tableBodyIPs", new GeoInfoTable(container.getValue(PlayerKeys.GEO_INFO).orElse(new ArrayList<>())).parseBody());
Map<UUID, List<Session>> sessions = perServerDataMutator.sessionsPerServer();
Map<String, List<Session>> sessionsByServerName = sessions.entrySet().stream()
.collect(Collectors.toMap(entry -> serverNames.get(entry.getKey()), Map.Entry::getValue));
replacer.put("tableBodyIPs", new GeoInfoTable(container.getValue(PlayerKeys.GEO_INFO).orElse(new ArrayList<>())).parseBody());
List<Session> allSessions = container.getValue(PlayerKeys.SESSIONS).orElse(new ArrayList<>());
SessionsMutator sessionsMutator = SessionsMutator.forContainer(container);
@ -134,27 +130,26 @@ public class InspectPage extends Page {
String sessionAccordionViewScript = "";
if (allSessions.isEmpty()) {
addValue("accordionSessions", "<div class=\"body\">" + "<p>No Sessions</p>" + "</div>");
replacer.put("accordionSessions", "<div class=\"body\">" + "<p>No Sessions</p>" + "</div>");
} else {
if (Settings.DISPLAY_SESSIONS_AS_TABLE.isTrue()) {
addValue("accordionSessions", new PlayerSessionTable(playerName, allSessions).parseHtml());
replacer.put("accordionSessions", new PlayerSessionTable(playerName, allSessions).parseHtml());
} else {
SessionAccordion sessionAccordion = SessionAccordion.forPlayer(allSessions, () -> serverNames);
addValue("accordionSessions", sessionAccordion.toHtml());
replacer.put("accordionSessions", sessionAccordion.toHtml());
sessionAccordionViewScript = sessionAccordion.toViewScript();
}
}
// TODO Session table if setting is enabled
ServerAccordion serverAccordion = new ServerAccordion(container, serverNames);
PlayerCalendar playerCalendar = new PlayerCalendar(allSessions, registered);
PlayerCalendar playerCalendar = new PlayerCalendar(container);
addValue("calendarSeries", playerCalendar.toCalendarSeries());
addValue("firstDay", 1);
replacer.put("calendarSeries", playerCalendar.toCalendarSeries());
replacer.put("firstDay", 1);
addValue("accordionServers", serverAccordion.toHtml());
addValue("sessionTabGraphViewFunctions", sessionAccordionViewScript + serverAccordion.toViewScript());
replacer.put("accordionServers", serverAccordion.toHtml());
replacer.put("sessionTabGraphViewFunctions", sessionAccordionViewScript + serverAccordion.toViewScript());
long dayAgo = now - TimeAmount.DAY.ms();
long weekAgo = now - TimeAmount.WEEK.ms();
@ -197,70 +192,70 @@ public class InspectPage extends Page {
long sessionAverageMonth = monthSessionsMutator.toAverageSessionLength();
Formatter<Long> formatter = Formatters.timeAmount();
addValue("playtimeTotal", formatter.apply(playtime));
addValue("playtimeDay", formatter.apply(playtimeDay));
addValue("playtimeWeek", formatter.apply(playtimeWeek));
addValue("playtimeMonth", formatter.apply(playtimeMonth));
replacer.put("playtimeTotal", formatter.apply(playtime));
replacer.put("playtimeDay", formatter.apply(playtimeDay));
replacer.put("playtimeWeek", formatter.apply(playtimeWeek));
replacer.put("playtimeMonth", formatter.apply(playtimeMonth));
addValue("activeTotal", formatter.apply(activeTotal));
replacer.put("activeTotal", formatter.apply(activeTotal));
addValue("afkTotal", formatter.apply(afk));
addValue("afkDay", formatter.apply(afkDay));
addValue("afkWeek", formatter.apply(afkWeek));
addValue("afkMonth", formatter.apply(afkMonth));
replacer.put("afkTotal", formatter.apply(afk));
replacer.put("afkDay", formatter.apply(afkDay));
replacer.put("afkWeek", formatter.apply(afkWeek));
replacer.put("afkMonth", formatter.apply(afkMonth));
addValue("sessionLengthLongest", formatter.apply(longestSession));
addValue("sessionLongestDay", formatter.apply(longestSessionDay));
addValue("sessionLongestWeek", formatter.apply(longestSessionWeek));
addValue("sessionLongestMonth", formatter.apply(longestSessionMonth));
replacer.put("sessionLengthLongest", formatter.apply(longestSession));
replacer.put("sessionLongestDay", formatter.apply(longestSessionDay));
replacer.put("sessionLongestWeek", formatter.apply(longestSessionWeek));
replacer.put("sessionLongestMonth", formatter.apply(longestSessionMonth));
addValue("sessionLengthMedian", formatter.apply(sessionMedian));
addValue("sessionMedianDay", formatter.apply(sessionMedianDay));
addValue("sessionMedianWeek", formatter.apply(sessionMedianWeek));
addValue("sessionMedianMonth", formatter.apply(sessionMedianMonth));
replacer.put("sessionLengthMedian", formatter.apply(sessionMedian));
replacer.put("sessionMedianDay", formatter.apply(sessionMedianDay));
replacer.put("sessionMedianWeek", formatter.apply(sessionMedianWeek));
replacer.put("sessionMedianMonth", formatter.apply(sessionMedianMonth));
addValue("sessionAverage", formatter.apply(sessionAverage));
addValue("sessionAverageDay", formatter.apply(sessionAverageDay));
addValue("sessionAverageWeek", formatter.apply(sessionAverageWeek));
addValue("sessionAverageMonth", formatter.apply(sessionAverageMonth));
replacer.put("sessionAverage", formatter.apply(sessionAverage));
replacer.put("sessionAverageDay", formatter.apply(sessionAverageDay));
replacer.put("sessionAverageWeek", formatter.apply(sessionAverageWeek));
replacer.put("sessionAverageMonth", formatter.apply(sessionAverageMonth));
addValue("sessionCount", sessionCount);
addValue("sessionCountDay", sessionCountDay);
addValue("sessionCountWeek", sessionCountWeek);
addValue("sessionCountMonth", sessionCountMonth);
replacer.put("sessionCount", sessionCount);
replacer.put("sessionCountDay", sessionCountDay);
replacer.put("sessionCountWeek", sessionCountWeek);
replacer.put("sessionCountMonth", sessionCountMonth);
String punchCardData = new PunchCardGraph(allSessions).toHighChartsSeries();
WorldTimes worldTimes = container.getValue(PlayerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
WorldPie worldPie = new WorldPie(worldTimes);
addValue("worldPieSeries", worldPie.toHighChartsSeries());
addValue("gmSeries", worldPie.toHighChartsDrilldown());
replacer.put("worldPieSeries", worldPie.toHighChartsSeries());
replacer.put("gmSeries", worldPie.toHighChartsDrilldown());
addValue("punchCardSeries", punchCardData);
replacer.put("punchCardSeries", punchCardData);
long playerKillCount = allSessions.stream().map(Session::getPlayerKills).mapToLong(Collection::size).sum();
long mobKillCount = allSessions.stream().mapToLong(Session::getMobKills).sum();
long deathCount = allSessions.stream().mapToLong(Session::getDeaths).sum();
addValue("playerKillCount", playerKillCount);
addValue("mobKillCount", mobKillCount);
addValue("deathCount", deathCount);
replacer.put("playerKillCount", playerKillCount);
replacer.put("mobKillCount", mobKillCount);
replacer.put("deathCount", deathCount);
ActivityIndex activityIndex = container.getActivityIndex(now);
addValue("activityIndexNumber", activityIndex.getFormattedValue());
addValue("activityIndexColor", activityIndex.getColor());
addValue("activityIndex", activityIndex.getGroup());
replacer.put("activityIndexNumber", activityIndex.getFormattedValue());
replacer.put("activityIndexColor", activityIndex.getColor());
replacer.put("activityIndex", activityIndex.getGroup());
addValue("playerStatus", HtmlStructure.playerStatus(online,
replacer.put("playerStatus", HtmlStructure.playerStatus(online,
container.getValue(PlayerKeys.BANNED).orElse(false),
container.getValue(PlayerKeys.OPERATOR).orElse(false)));
if (!InfoSystem.getInstance().getConnectionSystem().isServerAvailable()) {
addValue("networkName", Settings.SERVER_NAME.toString().replaceAll("[^a-zA-Z0-9_\\s]", "_"));
replacer.put("networkName", Settings.SERVER_NAME.toString().replaceAll("[^a-zA-Z0-9_\\s]", "_"));
}
return HtmlUtils.replacePlaceholders(FileUtil.getStringFromResource("web/player.html"), placeHolders);
return replacer.apply(FileUtil.getStringFromResource("web/player.html"));
}
}

View File

@ -20,7 +20,7 @@ import static com.djrapitops.plan.data.store.keys.NetworkKeys.*;
*
* @author Rsl1122
*/
public class NetworkPage extends Page {
public class NetworkPage implements Page {
@Override
public String toHtml() throws ParseException {

View File

@ -6,27 +6,12 @@ package com.djrapitops.plan.system.webserver.pages.parsing;
import com.djrapitops.plan.api.exceptions.ParseException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
/**
* Abstract class that is responsible for parsing data and html together into a String.
* Interface for parsing page HTML.
*
* @author Rsl1122
*/
public abstract class Page {
public interface Page {
protected final Map<String, Serializable> placeHolders;
public Page() {
this.placeHolders = new HashMap<>();
}
@Deprecated
protected void addValue(String placeholder, Serializable value) {
placeHolders.put(placeholder, value);
}
public abstract String toHtml() throws ParseException;
String toHtml() throws ParseException;
}

View File

@ -20,7 +20,7 @@ import java.util.List;
*
* @author Rsl1122
*/
public class PlayersPage extends Page {
public class PlayersPage implements Page {
@Override
public String toHtml() throws ParseException {

View File

@ -6,6 +6,8 @@ package com.djrapitops.plan.utilities.html.graphs.calendar;
import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.system.settings.theme.Theme;
@ -28,7 +30,14 @@ public class PlayerCalendar {
private final List<Session> allSessions;
private final long registered;
public PlayerCalendar(List<Session> allSessions, long registered) {
public PlayerCalendar(PlayerContainer container) {
this(
container.getValue(PlayerKeys.SESSIONS).orElse(new ArrayList<>()),
container.getValue(PlayerKeys.REGISTERED).orElse(0L)
);
}
private PlayerCalendar(List<Session> allSessions, long registered) {
this.allSessions = allSessions;
this.registered = registered;
}

View File

@ -9,6 +9,7 @@ import com.djrapitops.plan.data.element.AnalysisContainer;
import com.djrapitops.plan.data.element.InspectContainer;
import com.djrapitops.plan.data.plugin.HookHandler;
import com.djrapitops.plan.data.plugin.PluginData;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.utilities.comparators.PluginDataNameComparator;
import com.djrapitops.plan.utilities.html.tables.PluginPlayersTable;
import com.djrapitops.plugin.StaticHolder;
@ -24,11 +25,12 @@ import java.util.*;
*/
public class AnalysisPluginsTabContentCreator {
public static String[] createContent(List<UUID> uuids) {
if (uuids.isEmpty()) {
public static String[] createContent(PlayersMutator mutator) {
if (mutator.all().isEmpty()) {
return new String[]{"<li><a>No Data</a></li>", ""};
}
List<UUID> uuids = mutator.uuids();
Map<PluginData, AnalysisContainer> containers = analyzeAdditionalPluginData(uuids);
List<PluginData> order = new ArrayList<>(containers.keySet());
@ -77,8 +79,7 @@ public class AnalysisPluginsTabContentCreator {
"<div class=\"card\">" +
"<div class=\"header\"><h2><i class=\"fa fa-users\"></i> Plugin Data</h2></div>" +
"<div class=\"body\">" +
// TODO Start using ServerContainer and PlayerContainers instead
new PluginPlayersTable(containers, new ArrayList<>()).parseHtml() +
new PluginPlayersTable(containers, mutator.all()).parseHtml() +
"</div></div></div>" +
"</div></div>";