mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-21 05:50:18 +08:00
Merge pull request #687 from Rsl1122/cleaning
PR for cleaning to update sonarcloud smells
This commit is contained in:
commit
4078831362
@ -117,7 +117,7 @@ public class Plan extends BukkitPlugin implements PlanPlugin {
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
|
||||
// Nothing to be done, systems are disabled
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -161,6 +161,7 @@ public class Plan extends BukkitPlugin implements PlanPlugin {
|
||||
throw new IllegalStateException("This method should be used on this plugin.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BukkitSystem getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ public class PlanBungee extends BungeePlugin implements PlanPlugin {
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
// Nothing to be done, systems are disabled
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -92,6 +93,7 @@ public class PlanBungee extends BungeePlugin implements PlanPlugin {
|
||||
return PlanColorScheme.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BungeeSystem getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin {
|
||||
|
||||
@Override
|
||||
public void onReload() {
|
||||
|
||||
// Nothing to be done, systems are disabled
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -124,6 +124,7 @@ public class PlanSponge extends SpongePlugin implements PlanPlugin {
|
||||
return getClass().getAnnotation(Plugin.class).version();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpongeSystem getSystem() {
|
||||
return system;
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ import java.sql.SQLException;
|
||||
*/
|
||||
public class DBOpException extends RuntimeException {
|
||||
|
||||
private boolean fatal = false;
|
||||
|
||||
public DBOpException(String message) {
|
||||
super(message);
|
||||
}
|
||||
@ -23,11 +21,4 @@ public class DBOpException extends RuntimeException {
|
||||
return new DBOpException("SQL Failed: " + sql + "; " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
public boolean isFatal() {
|
||||
return fatal;
|
||||
}
|
||||
|
||||
public void setFatal(boolean fatal) {
|
||||
this.fatal = fatal;
|
||||
}
|
||||
}
|
@ -49,10 +49,6 @@ public class PlanBungeeCommand extends TreeCmdNode {
|
||||
new StatusCommand<>(plugin, Permissions.MANAGE.getPermission(), plugin.getColorScheme()),
|
||||
// (Settings.ALLOW_UPDATE.isTrue() ? new UpdateCommand() : null)
|
||||
};
|
||||
setNodeGroups(
|
||||
analyticsGroup,
|
||||
webGroup,
|
||||
manageGroup
|
||||
);
|
||||
setNodeGroups(analyticsGroup, webGroup, manageGroup);
|
||||
}
|
||||
}
|
||||
|
@ -74,11 +74,7 @@ public class InspectCommand extends CommandNode {
|
||||
checkWebUserAndNotify(activeDB, sender);
|
||||
Processing.submit(new InspectCacheRequestProcessor(uuid, sender, playerName, locale));
|
||||
} catch (DBOpException e) {
|
||||
if (e.isFatal()) {
|
||||
sender.sendMessage("§cFatal database exception occurred: " + e.getMessage());
|
||||
} else {
|
||||
sender.sendMessage("§eNon-Fatal database exception occurred: " + e.getMessage());
|
||||
}
|
||||
sender.sendMessage("§eDatabase exception occurred: " + e.getMessage());
|
||||
Log.toLog(this.getClass(), e);
|
||||
} finally {
|
||||
this.cancel();
|
||||
|
@ -26,22 +26,22 @@ public class ManageCommand extends TreeCmdNode {
|
||||
setShortHelp(locale.getString(CmdHelpLang.MANAGE));
|
||||
setInDepthHelp(locale.getArray(DeepHelpLang.MANAGE));
|
||||
super.setColorScheme(plugin.getColorScheme());
|
||||
setNodeGroups(
|
||||
new CommandNode[]{
|
||||
new ManageRawDataCommand(plugin),
|
||||
new ManageMoveCommand(plugin),
|
||||
new ManageBackupCommand(plugin),
|
||||
new ManageRestoreCommand(plugin),
|
||||
new ManageRemoveCommand(plugin),
|
||||
new ManageHotSwapCommand(plugin),
|
||||
new ManageClearCommand(plugin),
|
||||
},
|
||||
new CommandNode[]{
|
||||
new ManageSetupCommand(plugin),
|
||||
new ManageConDebugCommand(plugin),
|
||||
new ManageImportCommand(plugin),
|
||||
new ManageDisableCommand(plugin)
|
||||
}
|
||||
);
|
||||
CommandNode[] databaseGroup = {
|
||||
new ManageRawDataCommand(plugin),
|
||||
new ManageMoveCommand(plugin),
|
||||
new ManageBackupCommand(plugin),
|
||||
new ManageRestoreCommand(plugin),
|
||||
new ManageRemoveCommand(plugin),
|
||||
new ManageHotSwapCommand(plugin),
|
||||
new ManageClearCommand(plugin),
|
||||
};
|
||||
CommandNode[] pluginGroup = {
|
||||
new ManageSetupCommand(plugin),
|
||||
new ManageConDebugCommand(plugin),
|
||||
new ManageImportCommand(plugin),
|
||||
new ManageDisableCommand(plugin),
|
||||
new ManageUninstalledCommand(plugin)
|
||||
};
|
||||
setNodeGroups(databaseGroup, pluginGroup);
|
||||
}
|
||||
}
|
||||
|
@ -88,11 +88,7 @@ public class QInspectCommand extends CommandNode {
|
||||
|
||||
sendMessages(sender, container);
|
||||
} catch (DBOpException e) {
|
||||
if (e.isFatal()) {
|
||||
sender.sendMessage("§cFatal database exception occurred: " + e.getMessage());
|
||||
} else {
|
||||
sender.sendMessage("§eNon-Fatal database exception occurred: " + e.getMessage());
|
||||
}
|
||||
sender.sendMessage("§eDatabase exception occurred: " + e.getMessage());
|
||||
Log.toLog(this.getClass(), e);
|
||||
} finally {
|
||||
this.cancel();
|
||||
|
@ -29,14 +29,13 @@ public class WebUserCommand extends TreeCmdNode {
|
||||
|
||||
setShortHelp(locale.getString(CmdHelpLang.WEB));
|
||||
setInDepthHelp(locale.getArray(DeepHelpLang.WEB));
|
||||
setNodeGroups(
|
||||
new CommandNode[]{
|
||||
register,
|
||||
new WebLevelCommand(plugin),
|
||||
new WebListUsersCommand(plugin),
|
||||
new WebCheckCommand(plugin),
|
||||
new WebDeleteCommand(plugin)
|
||||
}
|
||||
);
|
||||
CommandNode[] webGroup = {
|
||||
register,
|
||||
new WebLevelCommand(plugin),
|
||||
new WebListUsersCommand(plugin),
|
||||
new WebCheckCommand(plugin),
|
||||
new WebDeleteCommand(plugin)
|
||||
};
|
||||
setNodeGroups(webGroup);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
package com.djrapitops.plan.command.commands.manage;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBOpException;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.CmdHelpLang;
|
||||
import com.djrapitops.plan.system.locale.lang.DeepHelpLang;
|
||||
import com.djrapitops.plan.system.locale.lang.ManageLang;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.settings.Permissions;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.command.CommandNode;
|
||||
import com.djrapitops.plugin.command.CommandType;
|
||||
import com.djrapitops.plugin.command.ISender;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This SubCommand is used to set a server as uninstalled on Plan.
|
||||
*
|
||||
* @author Rsl1122
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ManageUninstalledCommand extends CommandNode {
|
||||
|
||||
private final Locale locale;
|
||||
|
||||
public ManageUninstalledCommand(PlanPlugin plugin) {
|
||||
super("uninstalled", Permissions.MANAGE.getPermission(), CommandType.ALL_WITH_ARGS);
|
||||
|
||||
locale = plugin.getSystem().getLocaleSystem().getLocale();
|
||||
|
||||
setShortHelp(locale.getString(CmdHelpLang.MANAGE_UNINSTALLED));
|
||||
setInDepthHelp(locale.getArray(DeepHelpLang.MANAGE_UNINSTALLED));
|
||||
setArguments("[server/id]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCommand(ISender sender, String commandLabel, String[] args) {
|
||||
sender.sendMessage(locale.getString(ManageLang.PROGRESS_START));
|
||||
|
||||
Processing.submitNonCritical(() -> {
|
||||
try {
|
||||
Optional<Server> serverOptional = getServer(args);
|
||||
if (!serverOptional.isPresent()) {
|
||||
sender.sendMessage(locale.getString(ManageLang.PROGRESS_FAIL, locale.getString(ManageLang.NO_SERVER)));
|
||||
return;
|
||||
}
|
||||
Server server = serverOptional.get();
|
||||
UUID serverUUID = server.getUuid();
|
||||
if (ServerInfo.getServerUUID().equals(serverUUID)) {
|
||||
sender.sendMessage(locale.getString(ManageLang.UNINSTALLING_SAME_SERVER));
|
||||
return;
|
||||
}
|
||||
|
||||
Database.getActive().save().setAsUninstalled(serverUUID);
|
||||
sender.sendMessage(locale.getString(ManageLang.PROGRESS_SUCCESS));
|
||||
} catch (DBOpException e) {
|
||||
sender.sendMessage("§cError occurred: " + e.toString());
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Optional<Server> getServer(String[] args) {
|
||||
if (args.length >= 1 && ConnectionSystem.getInstance().isServerAvailable()) {
|
||||
Map<UUID, Server> bukkitServers = Database.getActive().fetch().getBukkitServers();
|
||||
String serverIdentifier = getGivenIdentifier(args);
|
||||
for (Map.Entry<UUID, Server> entry : bukkitServers.entrySet()) {
|
||||
Server server = entry.getValue();
|
||||
|
||||
if (Integer.toString(server.getId()).equals(serverIdentifier)
|
||||
|| server.getName().equalsIgnoreCase(serverIdentifier)) {
|
||||
return Optional.of(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private String getGivenIdentifier(String[] args) {
|
||||
StringBuilder idBuilder = new StringBuilder(args[0]);
|
||||
if (args.length > 1) {
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
idBuilder.append(" ").append(args[i]);
|
||||
}
|
||||
}
|
||||
return idBuilder.toString();
|
||||
}
|
||||
}
|
@ -2,9 +2,11 @@ package com.djrapitops.plan.data.container;
|
||||
|
||||
import com.djrapitops.plan.data.store.containers.DataContainer;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
import com.djrapitops.plan.data.store.objects.DateHolder;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.settings.WorldAliasSettings;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@ -55,6 +57,8 @@ public class Session extends DataContainer implements DateHolder {
|
||||
getValue(SessionKeys.END).orElse(System.currentTimeMillis()) - getUnsafe(SessionKeys.START));
|
||||
putSupplier(SessionKeys.ACTIVE_TIME, () -> getUnsafe(SessionKeys.LENGTH) - getUnsafe(SessionKeys.AFK_TIME));
|
||||
putSupplier(SessionKeys.SERVER_UUID, ServerInfo::getServerUUID);
|
||||
|
||||
putSupplier(SessionKeys.LONGEST_WORLD_PLAYED, this::getLongestWorldPlayed);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -96,6 +100,8 @@ public class Session extends DataContainer implements DateHolder {
|
||||
putSupplier(SessionKeys.LENGTH, () ->
|
||||
getValue(SessionKeys.END).orElse(System.currentTimeMillis()) - getUnsafe(SessionKeys.START));
|
||||
putSupplier(SessionKeys.ACTIVE_TIME, () -> getUnsafe(SessionKeys.LENGTH) - getUnsafe(SessionKeys.AFK_TIME));
|
||||
|
||||
putSupplier(SessionKeys.LONGEST_WORLD_PLAYED, this::getLongestWorldPlayed);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,4 +220,32 @@ public class Session extends DataContainer implements DateHolder {
|
||||
private long getAfkTime() {
|
||||
return afkTime;
|
||||
}
|
||||
|
||||
private String getLongestWorldPlayed() {
|
||||
Map<String, String> aliases = WorldAliasSettings.getAliases();
|
||||
if (worldTimes == null) {
|
||||
return "No World Time Data";
|
||||
}
|
||||
if (!supports(SessionKeys.END)) {
|
||||
return "Current: " + aliases.get(worldTimes.getCurrentWorld());
|
||||
}
|
||||
|
||||
Map<String, Long> playtimePerAlias = worldTimes.getPlaytimePerAlias();
|
||||
long total = worldTimes.getTotal();
|
||||
|
||||
long longest = 0;
|
||||
String theWorld = "-";
|
||||
for (Map.Entry<String, Long> entry : playtimePerAlias.entrySet()) {
|
||||
String world = entry.getKey();
|
||||
long time = entry.getValue();
|
||||
if (time > longest) {
|
||||
longest = time;
|
||||
theWorld = world;
|
||||
}
|
||||
}
|
||||
|
||||
double quotient = longest * 1.0 / total;
|
||||
|
||||
return theWorld + " (" + Formatters.percentage().apply(quotient) + ")";
|
||||
}
|
||||
}
|
||||
|
@ -48,25 +48,25 @@ public class InspectContainer {
|
||||
}
|
||||
|
||||
public final String parseHtml() {
|
||||
StringBuilder html = new StringBuilder();
|
||||
StringBuilder parsed = new StringBuilder();
|
||||
|
||||
if (!values.isEmpty()) {
|
||||
html.append("<div class=\"body\">");
|
||||
parsed.append("<div class=\"body\">");
|
||||
for (Map.Entry<String, String> entry : values.entrySet()) {
|
||||
html.append("<p>").append(entry.getKey()).append(": ").append(entry.getValue()).append("</p>");
|
||||
parsed.append("<p>").append(entry.getKey()).append(": ").append(entry.getValue()).append("</p>");
|
||||
}
|
||||
html.append("</div>");
|
||||
parsed.append("</div>");
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> entry : this.html.entrySet()) {
|
||||
html.append(entry.getValue());
|
||||
parsed.append(entry.getValue());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, TableContainer> entry : tables.entrySet()) {
|
||||
html.append(entry.getValue().parseHtml());
|
||||
parsed.append(entry.getValue().parseHtml());
|
||||
}
|
||||
|
||||
return html.toString();
|
||||
return parsed.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,12 +40,10 @@ public class TableContainer {
|
||||
}
|
||||
|
||||
public TableContainer(boolean players, String... header) {
|
||||
this.header = FormatUtils.mergeArrays(
|
||||
this(FormatUtils.mergeArrays(
|
||||
new String[]{Icon.called("user").build() + " Player"},
|
||||
header
|
||||
);
|
||||
this.formatters = new Formatter[this.header.length];
|
||||
values = new ArrayList<>();
|
||||
));
|
||||
}
|
||||
|
||||
public final void addRow(Serializable... values) {
|
||||
@ -60,36 +58,40 @@ public class TableContainer {
|
||||
}
|
||||
|
||||
public final String parseBody() {
|
||||
StringBuilder body = new StringBuilder();
|
||||
|
||||
if (values.isEmpty()) {
|
||||
addRow("No Data");
|
||||
}
|
||||
return Html.TABLE_BODY.parse(buildBody());
|
||||
|
||||
}
|
||||
|
||||
private String buildBody() {
|
||||
StringBuilder body = new StringBuilder();
|
||||
for (Serializable[] row : values) {
|
||||
|
||||
int maxIndex = row.length - 1;
|
||||
body.append("<tr>");
|
||||
for (int i = 0; i < header.length; i++) {
|
||||
try {
|
||||
if (i > maxIndex) {
|
||||
body.append("<td>-");
|
||||
} else {
|
||||
Serializable value = row[i];
|
||||
Formatter formatter = formatters[i];
|
||||
body.append("<td").append(formatter != null ? " data-order=\"" + value + "\">" : ">");
|
||||
body.append(formatter != null ? formatter.apply(value) : value);
|
||||
}
|
||||
body.append("</td>");
|
||||
} catch (ClassCastException | ArrayIndexOutOfBoundsException e) {
|
||||
throw new IllegalStateException("Invalid formatter given at index " + i + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
body.append("</tr>");
|
||||
|
||||
appendRow(body, row);
|
||||
}
|
||||
return body.toString();
|
||||
}
|
||||
|
||||
return Html.TABLE_BODY.parse(body.toString());
|
||||
|
||||
private void appendRow(StringBuilder body, Serializable[] row) {
|
||||
int maxIndex = row.length - 1;
|
||||
body.append("<tr>");
|
||||
for (int i = 0; i < header.length; i++) {
|
||||
try {
|
||||
if (i > maxIndex) {
|
||||
body.append("<td>-");
|
||||
} else {
|
||||
Serializable value = row[i];
|
||||
Formatter formatter = formatters[i];
|
||||
body.append("<td").append(formatter != null ? " data-order=\"" + value + "\">" : ">");
|
||||
body.append(formatter != null ? formatter.apply(value) : value);
|
||||
}
|
||||
body.append("</td>");
|
||||
} catch (ClassCastException | ArrayIndexOutOfBoundsException e) {
|
||||
throw new IllegalStateException("Invalid formatter given at index " + i + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
body.append("</tr>");
|
||||
}
|
||||
|
||||
public final void setColor(String color) {
|
||||
@ -97,12 +99,12 @@ public class TableContainer {
|
||||
}
|
||||
|
||||
public final String parseHeader() {
|
||||
StringBuilder header = new StringBuilder("<thead" + (color != null ? " class=\"bg-" + color + "\"" : "") + "><tr>");
|
||||
for (String title : this.header) {
|
||||
header.append("<th>").append(title).append("</th>");
|
||||
StringBuilder parsedHeader = new StringBuilder("<thead" + (color != null ? " class=\"bg-" + color + "\"" : "") + "><tr>");
|
||||
for (String title : header) {
|
||||
parsedHeader.append("<th>").append(title).append("</th>");
|
||||
}
|
||||
header.append("</tr></thead>");
|
||||
return header.toString();
|
||||
parsedHeader.append("</tr></thead>");
|
||||
return parsedHeader.toString();
|
||||
}
|
||||
|
||||
public final void setFormatter(int index, Formatter formatter) {
|
||||
|
@ -47,7 +47,7 @@ public class HookHandler implements SubSystem {
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
|
||||
// Nothing to disable
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,6 @@ public abstract class PluginData {
|
||||
private final String sourcePlugin;
|
||||
|
||||
private Icon pluginIcon;
|
||||
private String iconColor;
|
||||
|
||||
private String helpText;
|
||||
|
||||
|
@ -22,4 +22,14 @@ public class PlaceholderKey<T> extends Key<T> {
|
||||
public String getPlaceholder() {
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return super.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
}
|
@ -201,14 +201,12 @@ public class AnalysisContainer extends DataContainer {
|
||||
|
||||
putSupplier(AnalysisKeys.UNIQUE_PLAYERS_PER_DAY, () -> getUnsafe(AnalysisKeys.SESSIONS_MUTATOR).uniqueJoinsPerDay());
|
||||
putSupplier(AnalysisKeys.NEW_PLAYERS_PER_DAY, () -> getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).newPerDay());
|
||||
putSupplier(AnalysisKeys.UNIQUE_PLAYERS_SERIES, () ->
|
||||
new AbstractLineGraph(MutatorFunctions.toPoints(
|
||||
getUnsafe(AnalysisKeys.UNIQUE_PLAYERS_PER_DAY))
|
||||
putSupplier(AnalysisKeys.UNIQUE_PLAYERS_SERIES, () -> new AbstractLineGraph(
|
||||
MutatorFunctions.toPoints(getUnsafe(AnalysisKeys.UNIQUE_PLAYERS_PER_DAY))
|
||||
).toHighChartsSeries()
|
||||
);
|
||||
putSupplier(AnalysisKeys.NEW_PLAYERS_SERIES, () ->
|
||||
new AbstractLineGraph(MutatorFunctions.toPoints(
|
||||
getUnsafe(AnalysisKeys.NEW_PLAYERS_PER_DAY))
|
||||
putSupplier(AnalysisKeys.NEW_PLAYERS_SERIES, () -> new AbstractLineGraph(
|
||||
MutatorFunctions.toPoints(getUnsafe(AnalysisKeys.NEW_PLAYERS_PER_DAY))
|
||||
).toHighChartsSeries()
|
||||
);
|
||||
|
||||
|
@ -23,12 +23,7 @@ public class PlayerContainer extends DataContainer {
|
||||
}
|
||||
|
||||
public ActivityIndex getActivityIndex(long date) {
|
||||
ActivityIndex index = activityIndexCache.get(date);
|
||||
if (index == null) {
|
||||
index = new ActivityIndex(this, date);
|
||||
activityIndexCache.put(date, index);
|
||||
}
|
||||
return index;
|
||||
return activityIndexCache.computeIfAbsent(date, time -> new ActivityIndex(this, time));
|
||||
}
|
||||
|
||||
public boolean playedBetween(long after, long before) {
|
||||
|
@ -32,6 +32,8 @@ public class SessionKeys {
|
||||
public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT;
|
||||
public static final Key<List<PlayerDeath>> PLAYER_DEATHS = CommonKeys.PLAYER_DEATHS;
|
||||
|
||||
public static final Key<String> LONGEST_WORLD_PLAYED = new Key<>(String.class, "longest_world_played");
|
||||
|
||||
private SessionKeys() {
|
||||
/* Static variable class */
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class DateHoldersMutator<T extends DateHolder> {
|
||||
@ -15,11 +16,11 @@ public class DateHoldersMutator<T extends DateHolder> {
|
||||
this.dateHolders = dateHolders;
|
||||
}
|
||||
|
||||
public TreeMap<Long, List<T>> groupByStartOfMinute() {
|
||||
public SortedMap<Long, List<T>> groupByStartOfMinute() {
|
||||
return groupByStartOfSections(TimeAmount.MINUTE.ms());
|
||||
}
|
||||
|
||||
private TreeMap<Long, List<T>> groupByStartOfSections(long sectionLength) {
|
||||
private SortedMap<Long, List<T>> groupByStartOfSections(long sectionLength) {
|
||||
TreeMap<Long, List<T>> map = new TreeMap<>();
|
||||
|
||||
if (dateHolders.isEmpty()) {
|
||||
@ -37,9 +38,9 @@ public class DateHoldersMutator<T extends DateHolder> {
|
||||
return map;
|
||||
}
|
||||
|
||||
public TreeMap<Long, List<T>> groupByStartOfDay() {
|
||||
public SortedMap<Long, List<T>> groupByStartOfDay() {
|
||||
long twentyFourHours = 24L * TimeAmount.HOUR.ms();
|
||||
TreeMap<Long, List<T>> map = groupByStartOfSections(twentyFourHours);
|
||||
SortedMap<Long, List<T>> map = groupByStartOfSections(twentyFourHours);
|
||||
|
||||
// Empty map firstKey attempt causes NPE if not checked.
|
||||
if (!map.isEmpty()) {
|
||||
|
@ -21,4 +21,8 @@ public class MutatorFunctions {
|
||||
.average().orElse(0);
|
||||
}
|
||||
|
||||
private MutatorFunctions() {
|
||||
// Static method class.
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import com.djrapitops.plan.data.store.keys.CommonKeys;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
import java.util.SortedMap;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
@ -33,7 +33,7 @@ public class PingMutator {
|
||||
|
||||
public PingMutator mutateToByMinutePings() {
|
||||
DateHoldersMutator<Ping> dateMutator = new DateHoldersMutator<>(pings);
|
||||
TreeMap<Long, List<Ping>> byStartOfMinute = dateMutator.groupByStartOfMinute();
|
||||
SortedMap<Long, List<Ping>> byStartOfMinute = dateMutator.groupByStartOfMinute();
|
||||
|
||||
return new PingMutator(byStartOfMinute.entrySet().stream()
|
||||
.map(entry -> {
|
||||
|
@ -9,7 +9,6 @@ import com.djrapitops.plan.data.store.keys.PlayerKeys;
|
||||
import com.djrapitops.plan.data.store.keys.ServerKeys;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.objects.DateObj;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
|
||||
import java.util.*;
|
||||
@ -158,7 +157,7 @@ public class PlayersMutator {
|
||||
List<DateObj> registerDates = registerDates().stream()
|
||||
.map(value -> new DateObj<>(value, value))
|
||||
.collect(Collectors.toList());
|
||||
TreeMap<Long, List<DateObj>> byDay = new DateHoldersMutator<>(registerDates).groupByStartOfDay();
|
||||
SortedMap<Long, List<DateObj>> byDay = new DateHoldersMutator<>(registerDates).groupByStartOfDay();
|
||||
TreeMap<Long, Integer> byDayCounts = new TreeMap<>();
|
||||
|
||||
for (Map.Entry<Long, List<DateObj>> entry : byDay.entrySet()) {
|
||||
@ -210,8 +209,8 @@ public class PlayersMutator {
|
||||
.map(player -> new RetentionData(player, onlineResolver))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
RetentionData avgRetained = AnalysisUtils.average(retained);
|
||||
RetentionData avgNotRetained = AnalysisUtils.average(notRetained);
|
||||
RetentionData avgRetained = RetentionData.average(retained);
|
||||
RetentionData avgNotRetained = RetentionData.average(notRetained);
|
||||
|
||||
List<PlayerContainer> toBeRetained = new ArrayList<>();
|
||||
for (PlayerContainer player : compareTo) {
|
||||
|
@ -9,6 +9,7 @@ import com.djrapitops.plan.data.store.keys.PlayerKeys;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@ -22,6 +23,23 @@ public class RetentionData {
|
||||
private final double activityIndex;
|
||||
private double onlineOnJoin;
|
||||
|
||||
public static RetentionData average(Collection<RetentionData> stuck) {
|
||||
int size = stuck.size();
|
||||
|
||||
double totalIndex = 0.0;
|
||||
double totalPlayersOnline = 0.0;
|
||||
|
||||
for (RetentionData retentionData : stuck) {
|
||||
totalIndex += retentionData.getActivityIndex();
|
||||
totalPlayersOnline += retentionData.getOnlineOnJoin();
|
||||
}
|
||||
|
||||
double averageIndex = totalIndex / (double) size;
|
||||
double averagePlayersOnline = totalPlayersOnline / (double) size;
|
||||
|
||||
return new RetentionData(averageIndex, averagePlayersOnline);
|
||||
}
|
||||
|
||||
public RetentionData(double activityIndex, double onlineOnJoin) {
|
||||
this.activityIndex = activityIndex;
|
||||
this.onlineOnJoin = onlineOnJoin;
|
||||
|
@ -156,7 +156,7 @@ public class SessionsMutator {
|
||||
}
|
||||
|
||||
public TreeMap<Long, Integer> uniqueJoinsPerDay() {
|
||||
TreeMap<Long, List<Session>> byStartOfDay = toDateHoldersMutator().groupByStartOfDay();
|
||||
SortedMap<Long, List<Session>> byStartOfDay = toDateHoldersMutator().groupByStartOfDay();
|
||||
|
||||
TreeMap<Long, Integer> uniqueJoins = new TreeMap<>();
|
||||
for (Map.Entry<Long, List<Session>> entry : byStartOfDay.entrySet()) {
|
||||
|
@ -11,13 +11,13 @@ import org.apache.commons.lang3.StringUtils;
|
||||
public class TimeAmountFormatter implements Formatter<Long> {
|
||||
|
||||
// Placeholders for the config settings
|
||||
private final String zeroPH = "%zero%";
|
||||
private final String secondsPH = "%seconds%";
|
||||
private final String minutesPH = "%minutes%";
|
||||
private final String hoursPH = "%hours%";
|
||||
private final String daysPH = "%days%";
|
||||
private final String monthsPH = "%months%";
|
||||
private final String yearsPH = "%years%";
|
||||
private static final String ZERO_PH = "%zero%";
|
||||
private static final String SECONDS_PH = "%seconds%";
|
||||
private static final String MINUTES_PH = "%minutes%";
|
||||
private static final String HOURS_PH = "%hours%";
|
||||
private static final String DAYS_PH = "%days%";
|
||||
private static final String MONTHS_PH = "%months%";
|
||||
private static final String YEARS_PH = "%years%";
|
||||
|
||||
@Override
|
||||
public String apply(Long ms) {
|
||||
@ -50,7 +50,7 @@ public class TimeAmountFormatter implements Formatter<Long> {
|
||||
appendMinutes(builder, minutes, hours, hourFormat, minuteFormat);
|
||||
appendSeconds(builder, seconds, minutes, hours, hourFormat, minuteFormat, secondFormat);
|
||||
|
||||
String formattedTime = StringUtils.remove(builder.toString(), zeroPH);
|
||||
String formattedTime = StringUtils.remove(builder.toString(), ZERO_PH);
|
||||
if (formattedTime.isEmpty()) {
|
||||
return Settings.FORMAT_ZERO_SECONDS.toString();
|
||||
}
|
||||
@ -59,15 +59,15 @@ public class TimeAmountFormatter implements Formatter<Long> {
|
||||
|
||||
private void appendSeconds(StringBuilder builder, long seconds, long minutes, long hours, String fHours, String fMinutes, String fSeconds) {
|
||||
if (seconds != 0) {
|
||||
String s = fSeconds.replace(secondsPH, String.valueOf(seconds));
|
||||
if (minutes == 0 && s.contains(minutesPH)) {
|
||||
if (hours == 0 && fMinutes.contains(hoursPH)) {
|
||||
builder.append(fHours.replace(zeroPH, "0").replace(hoursPH, "0"));
|
||||
String s = fSeconds.replace(SECONDS_PH, String.valueOf(seconds));
|
||||
if (minutes == 0 && s.contains(MINUTES_PH)) {
|
||||
if (hours == 0 && fMinutes.contains(HOURS_PH)) {
|
||||
builder.append(fHours.replace(ZERO_PH, "0").replace(HOURS_PH, "0"));
|
||||
}
|
||||
builder.append(fMinutes.replace(hoursPH, "").replace(zeroPH, "0").replace(minutesPH, "0"));
|
||||
builder.append(fMinutes.replace(HOURS_PH, "").replace(ZERO_PH, "0").replace(MINUTES_PH, "0"));
|
||||
}
|
||||
s = s.replace(minutesPH, "");
|
||||
if (s.contains(zeroPH) && String.valueOf(seconds).length() == 1) {
|
||||
s = s.replace(MINUTES_PH, "");
|
||||
if (s.contains(ZERO_PH) && String.valueOf(seconds).length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(s);
|
||||
@ -76,13 +76,13 @@ public class TimeAmountFormatter implements Formatter<Long> {
|
||||
|
||||
private void appendMinutes(StringBuilder builder, long minutes, long hours, String fHours, String fMinutes) {
|
||||
if (minutes != 0) {
|
||||
String m = fMinutes.replace(minutesPH, String.valueOf(minutes));
|
||||
if (hours == 0 && m.contains(hoursPH)) {
|
||||
builder.append(fHours.replace(zeroPH, "0").replace(hoursPH, "0"));
|
||||
m = m.replace(hoursPH, "");
|
||||
String m = fMinutes.replace(MINUTES_PH, String.valueOf(minutes));
|
||||
if (hours == 0 && m.contains(HOURS_PH)) {
|
||||
builder.append(fHours.replace(ZERO_PH, "0").replace(HOURS_PH, "0"));
|
||||
m = m.replace(HOURS_PH, "");
|
||||
}
|
||||
m = m.replace(hoursPH, "");
|
||||
if (m.contains(zeroPH) && String.valueOf(minutes).length() == 1) {
|
||||
m = m.replace(HOURS_PH, "");
|
||||
if (m.contains(ZERO_PH) && String.valueOf(minutes).length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(m);
|
||||
@ -91,8 +91,8 @@ public class TimeAmountFormatter implements Formatter<Long> {
|
||||
|
||||
private void appendHours(StringBuilder builder, long hours, String fHours) {
|
||||
if (hours != 0) {
|
||||
String h = fHours.replace(hoursPH, String.valueOf(hours));
|
||||
if (h.contains(zeroPH) && String.valueOf(hours).length() == 1) {
|
||||
String h = fHours.replace(HOURS_PH, String.valueOf(hours));
|
||||
if (h.contains(ZERO_PH) && String.valueOf(hours).length() == 1) {
|
||||
builder.append('0');
|
||||
}
|
||||
builder.append(h);
|
||||
@ -102,21 +102,21 @@ public class TimeAmountFormatter implements Formatter<Long> {
|
||||
private void appendDays(StringBuilder builder, long days) {
|
||||
String singular = Settings.FORMAT_DAY.toString();
|
||||
String plural = Settings.FORMAT_DAYS.toString();
|
||||
appendValue(builder, days, singular, plural, daysPH);
|
||||
appendValue(builder, days, singular, plural, DAYS_PH);
|
||||
}
|
||||
|
||||
private void appendMonths(StringBuilder builder, long months) {
|
||||
String singular = Settings.FORMAT_MONTH.toString();
|
||||
String plural = Settings.FORMAT_MONTHS.toString();
|
||||
|
||||
appendValue(builder, months, singular, plural, monthsPH);
|
||||
appendValue(builder, months, singular, plural, MONTHS_PH);
|
||||
}
|
||||
|
||||
private void appendYears(StringBuilder builder, long years) {
|
||||
String singular = Settings.FORMAT_YEAR.toString();
|
||||
String plural = Settings.FORMAT_YEARS.toString();
|
||||
|
||||
appendValue(builder, years, singular, plural, yearsPH);
|
||||
appendValue(builder, years, singular, plural, YEARS_PH);
|
||||
}
|
||||
|
||||
private void appendValue(StringBuilder builder, long amount, String singular, String plural, String replace) {
|
||||
|
@ -63,7 +63,7 @@ public abstract class AbstractHealthInfo {
|
||||
regularRemainCompareSet.removeAll(veryActiveNow);
|
||||
int notRegularAnymore = regularRemainCompareSet.size();
|
||||
int remain = activeFWAGNum - notRegularAnymore;
|
||||
double percRemain = remain * 100.0 / activeFWAGNum;
|
||||
double percRemain = activeFWAGNum != 0 ? remain * 100.0 / activeFWAGNum : 100.0;
|
||||
|
||||
int newActive = getNewActive(veryActiveNow, activeNow, regularNow, veryActiveFWAG, activeFWAG, regularFWAG);
|
||||
|
||||
|
@ -38,6 +38,7 @@ public class HealthInformation extends AbstractHealthInfo {
|
||||
calculate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toHtml() {
|
||||
StringBuilder healthNoteBuilder = new StringBuilder();
|
||||
for (String healthNote : notes) {
|
||||
|
@ -2,7 +2,6 @@ package com.djrapitops.plan.data.time;
|
||||
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -12,7 +11,7 @@ import java.util.Objects;
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public abstract class TimeKeeper implements Serializable {
|
||||
public abstract class TimeKeeper {
|
||||
|
||||
protected Map<String, Long> times;
|
||||
protected String state;
|
||||
|
@ -1,9 +1,11 @@
|
||||
package com.djrapitops.plan.data.time;
|
||||
|
||||
import java.io.Serializable;
|
||||
import com.djrapitops.plan.system.settings.WorldAliasSettings;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Class that tracks the time spent in each World based on GMTimes.
|
||||
@ -11,9 +13,9 @@ import java.util.Objects;
|
||||
* @author Rsl1122
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public class WorldTimes implements Serializable {
|
||||
public class WorldTimes {
|
||||
|
||||
private final Map<String, GMTimes> worldTimes;
|
||||
private final Map<String, GMTimes> times;
|
||||
private String currentWorld;
|
||||
private String currentGamemode;
|
||||
|
||||
@ -25,7 +27,7 @@ public class WorldTimes implements Serializable {
|
||||
* @param time Epoch ms the time calculation should start
|
||||
*/
|
||||
public WorldTimes(String startingWorld, String startingGM, long time) {
|
||||
worldTimes = new HashMap<>();
|
||||
times = new HashMap<>();
|
||||
currentWorld = startingWorld;
|
||||
currentGamemode = startingGM;
|
||||
addWorld(startingWorld, startingGM, time);
|
||||
@ -37,11 +39,11 @@ public class WorldTimes implements Serializable {
|
||||
* @param times Map of each World's GMTimes object.
|
||||
*/
|
||||
public WorldTimes(Map<String, GMTimes> times) {
|
||||
worldTimes = times;
|
||||
this.times = times;
|
||||
}
|
||||
|
||||
private void addWorld(String worldName, String gameMode, long changeTime) {
|
||||
worldTimes.put(worldName, new GMTimes(gameMode, changeTime));
|
||||
times.put(worldName, new GMTimes(gameMode, changeTime));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,18 +64,18 @@ public class WorldTimes implements Serializable {
|
||||
* @param changeTime Epoch ms the change occurred.
|
||||
*/
|
||||
public void updateState(String worldName, String gameMode, long changeTime) {
|
||||
GMTimes currentGMTimes = worldTimes.get(currentWorld);
|
||||
GMTimes currentGMTimes = times.get(currentWorld);
|
||||
if (worldName.equals(currentWorld)) {
|
||||
currentGMTimes.changeState(gameMode, changeTime);
|
||||
} else {
|
||||
GMTimes newGMTimes = worldTimes.get(worldName);
|
||||
GMTimes newGMTimes = times.get(worldName);
|
||||
if (newGMTimes == null) {
|
||||
addWorld(worldName, gameMode, currentGMTimes.getLastStateChange());
|
||||
}
|
||||
currentGMTimes.changeState(currentGamemode, changeTime);
|
||||
}
|
||||
|
||||
for (GMTimes gmTimes : worldTimes.values()) {
|
||||
for (GMTimes gmTimes : times.values()) {
|
||||
gmTimes.setLastStateChange(changeTime);
|
||||
}
|
||||
|
||||
@ -88,12 +90,12 @@ public class WorldTimes implements Serializable {
|
||||
* @return total milliseconds spent in a world.
|
||||
*/
|
||||
public long getWorldPlaytime(String world) {
|
||||
GMTimes gmTimes = worldTimes.get(world);
|
||||
GMTimes gmTimes = times.get(world);
|
||||
return gmTimes != null ? gmTimes.getTotal() : 0;
|
||||
}
|
||||
|
||||
public long getTotal() {
|
||||
return worldTimes.values().stream()
|
||||
return times.values().stream()
|
||||
.mapToLong(GMTimes::getTotal)
|
||||
.sum();
|
||||
}
|
||||
@ -109,20 +111,15 @@ public class WorldTimes implements Serializable {
|
||||
* @return GMTimes object with play times of each GameMode.
|
||||
*/
|
||||
public GMTimes getGMTimes(String world) {
|
||||
return worldTimes.getOrDefault(world, new GMTimes());
|
||||
return times.getOrDefault(world, new GMTimes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get the Map for saving.
|
||||
*
|
||||
* @return Current time map.
|
||||
*/
|
||||
public Map<String, GMTimes> getWorldTimes() {
|
||||
return worldTimes;
|
||||
return times;
|
||||
}
|
||||
|
||||
public void setGMTimesForWorld(String world, GMTimes gmTimes) {
|
||||
worldTimes.put(world, gmTimes);
|
||||
times.put(world, gmTimes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -130,21 +127,21 @@ public class WorldTimes implements Serializable {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
WorldTimes that = (WorldTimes) o;
|
||||
return Objects.equals(worldTimes, that.worldTimes) &&
|
||||
return Objects.equals(times, that.times) &&
|
||||
Objects.equals(currentWorld, that.currentWorld) &&
|
||||
Objects.equals(currentGamemode, that.currentGamemode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(worldTimes, currentWorld, currentGamemode);
|
||||
return Objects.hash(times, currentWorld, currentGamemode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder b = new StringBuilder("WorldTimes (Current: " + currentWorld + "){\n");
|
||||
|
||||
for (Map.Entry<String, GMTimes> entry : worldTimes.entrySet()) {
|
||||
for (Map.Entry<String, GMTimes> entry : times.entrySet()) {
|
||||
GMTimes value = entry.getValue();
|
||||
b.append("World '").append(entry.getKey()).append("':\n")
|
||||
.append(" Total: ").append(value.getTotal()).append("\n")
|
||||
@ -160,8 +157,7 @@ public class WorldTimes implements Serializable {
|
||||
}
|
||||
|
||||
public void add(WorldTimes toAdd) {
|
||||
Map<String, GMTimes> times = toAdd.getWorldTimes();
|
||||
for (Map.Entry<String, GMTimes> entry : times.entrySet()) {
|
||||
for (Map.Entry<String, GMTimes> entry : toAdd.getWorldTimes().entrySet()) {
|
||||
String worldName = entry.getKey();
|
||||
GMTimes gmTimes = entry.getValue();
|
||||
|
||||
@ -169,7 +165,34 @@ public class WorldTimes implements Serializable {
|
||||
for (String gm : GMTimes.getGMKeyArray()) {
|
||||
currentGMTimes.addTime(gm, gmTimes.getTime(gm));
|
||||
}
|
||||
worldTimes.put(worldName, currentGMTimes);
|
||||
this.times.put(worldName, currentGMTimes);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Long> getPlaytimePerAlias() {
|
||||
Map<String, Long> playtimePerWorld = getWorldTimes() // WorldTimes Map<String, GMTimes>
|
||||
.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().getTotal() // GMTimes.getTotal
|
||||
));
|
||||
|
||||
Map<String, String> aliases = WorldAliasSettings.getAliases();
|
||||
|
||||
Map<String, Long> playtimePerAlias = new HashMap<>();
|
||||
for (Map.Entry<String, Long> entry : playtimePerWorld.entrySet()) {
|
||||
String worldName = entry.getKey();
|
||||
long playtime = entry.getValue();
|
||||
|
||||
if (!aliases.containsKey(worldName)) {
|
||||
aliases.put(worldName, worldName);
|
||||
WorldAliasSettings.addWorld(worldName);
|
||||
}
|
||||
|
||||
String alias = aliases.get(worldName);
|
||||
|
||||
playtimePerAlias.put(alias, playtimePerAlias.getOrDefault(alias, 0L) + playtime);
|
||||
}
|
||||
return playtimePerAlias;
|
||||
}
|
||||
}
|
||||
|
@ -44,6 +44,9 @@ public class DataCache extends SessionCache implements SubSystem {
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
playerNames.clear();
|
||||
uuids.clear();
|
||||
displayNames.clear();
|
||||
}
|
||||
|
||||
public static DataCache getInstance() {
|
||||
|
@ -3,7 +3,6 @@ package com.djrapitops.plan.system.cache;
|
||||
import com.djrapitops.plan.data.store.Key;
|
||||
import com.djrapitops.plan.data.store.containers.AnalysisContainer;
|
||||
import com.djrapitops.plan.data.store.containers.DataContainer;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.data.store.containers.PlayerContainer;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
@ -20,8 +19,6 @@ public class DataContainerCache extends DataContainer {
|
||||
|
||||
public DataContainerCache() {
|
||||
super(TimeAmount.SECOND.ms() * 10L);
|
||||
|
||||
putSupplier(Keys.NETWORK_CONTAINER, Suppliers.NETWORK_CONTAINER);
|
||||
}
|
||||
|
||||
public PlayerContainer getPlayerContainer(UUID uuid) {
|
||||
@ -32,20 +29,14 @@ public class DataContainerCache extends DataContainer {
|
||||
return getAndCacheSupplier(Keys.analysisContainer(serverUUID), Suppliers.analysisContainer(serverUUID));
|
||||
}
|
||||
|
||||
public <T> T getAndCacheSupplier(Key<T> key, Supplier<T> ifNotPresent) {
|
||||
private <T> T getAndCacheSupplier(Key<T> key, Supplier<T> ifNotPresent) {
|
||||
if (!supports(key)) {
|
||||
putSupplier(key, ifNotPresent);
|
||||
}
|
||||
return getUnsafe(key);
|
||||
}
|
||||
|
||||
public NetworkContainer getNetworkContainer() {
|
||||
return getAndCacheSupplier(Keys.NETWORK_CONTAINER, Suppliers.NETWORK_CONTAINER);
|
||||
}
|
||||
|
||||
public static class Keys {
|
||||
static final Key<NetworkContainer> NETWORK_CONTAINER = new Key<>(NetworkContainer.class, "NETWORK_CONTAINER");
|
||||
|
||||
private static class Keys {
|
||||
static Key<AnalysisContainer> analysisContainer(UUID serverUUID) {
|
||||
return new Key<>(AnalysisContainer.class, "ANALYSIS_CONTAINER:" + serverUUID);
|
||||
}
|
||||
@ -54,11 +45,12 @@ public class DataContainerCache extends DataContainer {
|
||||
return new Key<>(PlayerContainer.class, "PLAYER_CONTAINER:" + uuid);
|
||||
}
|
||||
|
||||
private Keys() {
|
||||
// Static utility class
|
||||
}
|
||||
}
|
||||
|
||||
public static class Suppliers {
|
||||
static final Supplier<NetworkContainer> NETWORK_CONTAINER = () -> Database.getActive().fetch().getNetworkContainer();
|
||||
|
||||
private static class Suppliers {
|
||||
static Supplier<AnalysisContainer> analysisContainer(UUID serverUUID) {
|
||||
return () -> new AnalysisContainer(Database.getActive().fetch().getServerContainer(serverUUID));
|
||||
}
|
||||
@ -66,6 +58,10 @@ public class DataContainerCache extends DataContainer {
|
||||
static Supplier<PlayerContainer> playerContainer(UUID uuid) {
|
||||
return () -> Database.getActive().fetch().getPlayerContainer(uuid);
|
||||
}
|
||||
|
||||
private Suppliers() {
|
||||
// Static utility class
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -37,12 +37,12 @@ import java.util.zip.GZIPInputStream;
|
||||
public class GeolocationCache implements SubSystem {
|
||||
|
||||
private final Supplier<Locale> locale;
|
||||
private final Map<String, String> geolocationCache;
|
||||
private final Map<String, String> cached;
|
||||
private File geolocationDB;
|
||||
|
||||
public GeolocationCache(Supplier<Locale> locale) {
|
||||
this.locale = locale;
|
||||
geolocationCache = new HashMap<>();
|
||||
cached = new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -61,20 +61,10 @@ public class GeolocationCache implements SubSystem {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
}
|
||||
|
||||
private static GeolocationCache getInstance() {
|
||||
GeolocationCache geolocationCache = CacheSystem.getInstance().getGeolocationCache();
|
||||
Verify.nullCheck(geolocationCache, () -> new IllegalStateException("GeolocationCache was not initialized."));
|
||||
return geolocationCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the country in full length (e.g. United States) from the IP Address.
|
||||
* <p>
|
||||
* This method uses the {@code geolocationCache}, every first access is getting cached and then retrieved later.
|
||||
* This method uses {@code cached}, every first access is getting cached and then retrieved later.
|
||||
*
|
||||
* @param ipAddress The IP Address from which the country is retrieved
|
||||
* @return The name of the country in full length.
|
||||
@ -90,12 +80,28 @@ public class GeolocationCache implements SubSystem {
|
||||
return country;
|
||||
} else {
|
||||
country = getUnCachedCountry(ipAddress);
|
||||
getInstance().geolocationCache.put(ipAddress, country);
|
||||
getInstance().cached.put(ipAddress, country);
|
||||
|
||||
return country;
|
||||
}
|
||||
}
|
||||
|
||||
private static GeolocationCache getInstance() {
|
||||
GeolocationCache geolocationCache = CacheSystem.getInstance().getGeolocationCache();
|
||||
Verify.nullCheck(geolocationCache, () -> new IllegalStateException("GeolocationCache was not initialized."));
|
||||
return geolocationCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached country
|
||||
*
|
||||
* @param ipAddress The IP Address which is retrieved out of the cache
|
||||
* @return The cached country, {@code null} if the country is not cached
|
||||
*/
|
||||
private static String getCachedCountry(String ipAddress) {
|
||||
return getInstance().cached.get(ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the country in full length (e.g. United States) from the IP Address.
|
||||
* <p>
|
||||
@ -147,16 +153,6 @@ public class GeolocationCache implements SubSystem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cached country
|
||||
*
|
||||
* @param ipAddress The IP Address which is retrieved out of the cache
|
||||
* @return The cached country, {@code null} if the country is not cached
|
||||
*/
|
||||
private static String getCachedCountry(String ipAddress) {
|
||||
return getInstance().geolocationCache.get(ipAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the IP Address is cached
|
||||
*
|
||||
@ -164,13 +160,18 @@ public class GeolocationCache implements SubSystem {
|
||||
* @return true if the IP Address is cached
|
||||
*/
|
||||
public static boolean isCached(String ipAddress) {
|
||||
return getInstance().geolocationCache.containsKey(ipAddress);
|
||||
return getInstance().cached.containsKey(ipAddress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
cached.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the cache
|
||||
*/
|
||||
public void clearCache() {
|
||||
geolocationCache.clear();
|
||||
cached.clear();
|
||||
}
|
||||
}
|
||||
|
@ -69,4 +69,6 @@ public interface SaveOperations {
|
||||
void webUser(WebUser webUser);
|
||||
|
||||
void ping(UUID uuid, Ping ping);
|
||||
|
||||
void setAsUninstalled(UUID serverUUID);
|
||||
}
|
@ -135,4 +135,9 @@ public class SQLSaveOps extends SQLOps implements SaveOperations {
|
||||
public void ping(UUID uuid, Ping ping) {
|
||||
pingTable.insertPing(uuid, ping);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAsUninstalled(UUID serverUUID) {
|
||||
serverTable.setAsUninstalled(serverUUID);
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class ServerTable extends Table {
|
||||
.column(Col.SERVER_UUID, Sql.varchar(36)).notNull().unique()
|
||||
.column(Col.NAME, Sql.varchar(100))
|
||||
.column(Col.WEBSERVER_ADDRESS, Sql.varchar(100))
|
||||
.column(Col.INSTALLED, Sql.BOOL).notNull().defaultValue(false)
|
||||
.column(Col.INSTALLED, Sql.BOOL).notNull().defaultValue(true)
|
||||
.column(Col.MAX_PLAYERS, Sql.INT).notNull().defaultValue("-1")
|
||||
.primaryKey(usingMySQL, Col.SERVER_ID)
|
||||
.toString()
|
||||
@ -246,12 +246,14 @@ public class ServerTable extends Table {
|
||||
public Map<UUID, Server> getBukkitServers() {
|
||||
String sql = Select.from(tableName, "*")
|
||||
.where(Col.NAME + "!=?")
|
||||
.and(Col.INSTALLED + "=?")
|
||||
.toString();
|
||||
|
||||
return query(new QueryStatement<Map<UUID, Server>>(sql, 100) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, "BungeeCord");
|
||||
statement.setBoolean(2, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -364,6 +366,18 @@ public class ServerTable extends Table {
|
||||
});
|
||||
}
|
||||
|
||||
public void setAsUninstalled(UUID serverUUID) {
|
||||
String sql = "UPDATE " + tableName + " SET (" + Col.INSTALLED + "=?) WHERE " + Col.SERVER_UUID + "=?";
|
||||
|
||||
execute(new ExecStatement(sql) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setBoolean(1, false);
|
||||
statement.setString(2, serverUUID.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public enum Col implements Column {
|
||||
SERVER_ID("id"),
|
||||
SERVER_UUID("uuid"),
|
||||
|
@ -178,5 +178,20 @@ public class WorldTable extends Table {
|
||||
return column;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof WorldTable)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
WorldTable that = (WorldTable) o;
|
||||
return Objects.equals(statementSelectID, that.statementSelectID) &&
|
||||
Objects.equals(serverTable, that.serverTable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), statementSelectID, serverTable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,8 +286,8 @@ public class WorldTimesTable extends UserIDTable {
|
||||
public void addWorldTimesToSessions(Map<UUID, Map<UUID, List<Session>>> map) {
|
||||
Map<Integer, WorldTimes> worldTimesBySessionID = getAllWorldTimesBySessionID();
|
||||
|
||||
for (UUID serverUUID : map.keySet()) {
|
||||
for (List<Session> sessions : map.get(serverUUID).values()) {
|
||||
for (Map.Entry<UUID, Map<UUID, List<Session>>> entry : map.entrySet()) {
|
||||
for (List<Session> sessions : entry.getValue().values()) {
|
||||
for (Session session : sessions) {
|
||||
WorldTimes worldTimes = worldTimesBySessionID.get(session.getUnsafe(SessionKeys.DB_ID));
|
||||
if (worldTimes != null) {
|
||||
@ -377,4 +377,21 @@ public class WorldTimesTable extends UserIDTable {
|
||||
return column;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof WorldTimesTable)) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
WorldTimesTable that = (WorldTimesTable) o;
|
||||
return Objects.equals(serverTable, that.serverTable) &&
|
||||
Objects.equals(worldTable, that.worldTable) &&
|
||||
Objects.equals(sessionsTable, that.sessionsTable) &&
|
||||
Objects.equals(insertStatement, that.insertStatement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), serverTable, worldTable, sessionsTable, insertStatement);
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,6 @@ public class FileSystem implements SubSystem {
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
|
||||
// No disable actions necessary.
|
||||
}
|
||||
}
|
||||
|
@ -7,18 +7,15 @@ package com.djrapitops.plan.system.info;
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.NoServersException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebFailException;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.info.connection.BungeeConnectionSystem;
|
||||
import com.djrapitops.plan.system.info.request.CacheRequest;
|
||||
import com.djrapitops.plan.system.info.request.GenerateInspectPageRequest;
|
||||
import com.djrapitops.plan.system.info.request.InfoRequest;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.pages.parsing.NetworkPage;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.AnalysisPageResponse;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.InternalErrorResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.NetworkPageResponse;
|
||||
|
||||
/**
|
||||
* InfoSystem for Bungee.
|
||||
@ -43,13 +40,13 @@ public class BungeeInfoSystem extends InfoSystem {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNetworkPage() throws WebException {
|
||||
try {
|
||||
NetworkContainer networkContainer = CacheSystem.getInstance().getDataContainerCache().getNetworkContainer();
|
||||
String html = new NetworkPage(networkContainer).toHtml();
|
||||
ResponseCache.cacheResponse(PageId.SERVER.of(ServerInfo.getServerUUID()), () -> new AnalysisPageResponse(html));
|
||||
} catch (ParseException e) {
|
||||
throw new WebFailException("Exception during Network Page Parsing", e);
|
||||
}
|
||||
public void updateNetworkPage() {
|
||||
ResponseCache.cacheResponse(PageId.SERVER.of(ServerInfo.getServerUUID()), () -> {
|
||||
try {
|
||||
return new NetworkPageResponse();
|
||||
} catch (ParseException e) {
|
||||
return new InternalErrorResponse("Network page parsing failed.", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,6 @@ public abstract class InfoSystem implements SubSystem {
|
||||
Server bungee = new Server(-1, null, "Bungee", addressToRequestServer, -1);
|
||||
String addressOfThisServer = WebServerSystem.getInstance().getWebServer().getAccessAddress();
|
||||
|
||||
ConnectionSystem connectionSystem = ConnectionSystem.getInstance();
|
||||
connectionSystem.setSetupAllowed(true);
|
||||
connectionSystem.sendInfoRequest(new SendDBSettingsRequest(addressOfThisServer), bungee);
|
||||
}
|
||||
|
@ -14,9 +14,7 @@ import com.djrapitops.plan.system.webserver.WebServerSystem;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
/**
|
||||
* ConnectionSystem for Bungee.
|
||||
@ -59,20 +57,6 @@ public class BungeeConnectionSystem extends ConnectionSystem {
|
||||
return server;
|
||||
}
|
||||
|
||||
private Server getOneBukkitServer() {
|
||||
int rand = ThreadLocalRandom.current().nextInt(bukkitServers.size());
|
||||
int i = 0;
|
||||
for (Server server : bukkitServers.values()) {
|
||||
if (i == rand) {
|
||||
return server;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
// Fallback if code above fails (Shouldn't)
|
||||
Optional<Server> first = bukkitServers.values().stream().findAny();
|
||||
return first.orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendWideInfoRequest(WideRequest infoRequest) throws NoServersException {
|
||||
refreshServerMap();
|
||||
@ -99,8 +83,4 @@ public class BungeeConnectionSystem extends ConnectionSystem {
|
||||
refreshServerMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -68,9 +68,9 @@ public class ConnectionIn {
|
||||
|
||||
private Map<String, String> readVariables(Request request) throws WebException {
|
||||
String requestBody = readRequestBody(request.getRequestBody());
|
||||
String[] variables = requestBody.split(";&variable;");
|
||||
String[] bodyVariables = requestBody.split(";&variable;");
|
||||
|
||||
return Arrays.stream(variables)
|
||||
return Arrays.stream(bodyVariables)
|
||||
.map(variable -> variable.split("=", 2))
|
||||
.filter(splitVariables -> splitVariables.length == 2)
|
||||
.collect(Collectors.toMap(splitVariables -> splitVariables[0], splitVariables -> splitVariables[1], (a, b) -> b));
|
||||
|
@ -11,6 +11,7 @@ import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Class responsible for logging what ConnectionOut objects get in return.
|
||||
@ -90,6 +91,20 @@ public class ConnectionLog {
|
||||
public int compareTo(Entry o) {
|
||||
return Long.compare(o.date, this.date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof Entry)) return false;
|
||||
Entry entry = (Entry) o;
|
||||
return responseCode == entry.responseCode &&
|
||||
date == entry.date;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(responseCode, date);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,6 +32,8 @@ import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Represents an outbound action request to another Plan server.
|
||||
@ -51,7 +53,7 @@ public class ConnectionOut {
|
||||
properties.setProperty("sun.net.client.defaultReadTimeout", Long.toString(TimeAmount.MINUTE.ms()));
|
||||
properties.setProperty("sun.net.http.retryPost", Boolean.toString(false));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Logger.getGlobal().log(Level.WARNING, "[Plan] Failed to set sun client timeout system properties.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +92,7 @@ public class ConnectionOut {
|
||||
handleResult(url, parameters, responseCode);
|
||||
} catch (SocketTimeoutException e) {
|
||||
ConnectionLog.logConnectionTo(toServer, infoRequest, 0);
|
||||
throw new ConnectionFailException("Connection timed out after 10 seconds.", e);
|
||||
throw new ConnectionFailException("Connection to " + address + " timed out after 10 seconds.", e);
|
||||
} catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
|
||||
if (Settings.DEV_MODE.isTrue()) {
|
||||
Log.warn("THIS ERROR IS ONLY LOGGED IN DEV MODE:");
|
||||
|
@ -111,4 +111,11 @@ public abstract class ConnectionSystem implements SubSystem {
|
||||
public List<Server> getBukkitServers() {
|
||||
return new ArrayList<>(bukkitServers.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
setupAllowed = false;
|
||||
bukkitServers.clear();
|
||||
dataRequests.clear();
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import com.djrapitops.plan.system.locale.lang.ErrorPageLang;
|
||||
import com.djrapitops.plan.system.webserver.Request;
|
||||
import com.djrapitops.plan.system.webserver.pages.PageHandler;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.api.BadRequestResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.BadRequestResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.NotFoundResponse;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
|
@ -116,9 +116,4 @@ public class ServerConnectionSystem extends ConnectionSystem {
|
||||
Log.info(locale.get().getString(PluginLang.ENABLE_NOTIFY_ADDRESS_CONFIRMATION, webServerAddress));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -25,11 +25,11 @@ public class WebExceptionLogger {
|
||||
function.apply();
|
||||
} catch (ConnectionFailException e) {
|
||||
if (shouldLog(e)) {
|
||||
Log.warn(e.getMessage());
|
||||
Log.debug(e.getMessage());
|
||||
}
|
||||
} catch (UnsupportedTransferDatabaseException | UnauthorizedServerException
|
||||
| NotFoundException | NoServersException e) {
|
||||
Log.warn(e.getMessage());
|
||||
Log.debug(e.getMessage());
|
||||
} catch (WebException e) {
|
||||
Log.toLog(c, e);
|
||||
}
|
||||
@ -63,4 +63,7 @@ public class WebExceptionLogger {
|
||||
return null;
|
||||
}
|
||||
|
||||
private WebExceptionLogger() {
|
||||
// Static method class.
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,10 @@ import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.AnalysisPageResponse;
|
||||
import com.djrapitops.plan.utilities.Base64Util;
|
||||
import com.djrapitops.plan.utilities.file.export.HtmlExport;
|
||||
@ -50,13 +50,13 @@ public class CacheAnalysisPageRequest extends InfoRequestWithVariables implement
|
||||
public Response handleRequest(Map<String, String> variables) throws WebException {
|
||||
// Available variables: sender, html (Base64)
|
||||
|
||||
UUID serverUUID = UUID.fromString(variables.get("sender"));
|
||||
UUID sender = UUID.fromString(variables.get("sender"));
|
||||
|
||||
String html = variables.get("html");
|
||||
Verify.nullCheck(html, () -> new BadRequestException("HTML 'html' variable not supplied in the request"));
|
||||
String sentHtml = variables.get("html");
|
||||
Verify.nullCheck(sentHtml, () -> new BadRequestException("HTML 'html' variable not supplied in the request"));
|
||||
|
||||
boolean export = Settings.ANALYSIS_EXPORT.isTrue();
|
||||
cache(export, serverUUID, Base64Util.decode(html));
|
||||
cache(export, sender, Base64Util.decode(sentHtml));
|
||||
return DefaultResponses.SUCCESS.get();
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,10 @@ import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.InspectPageResponse;
|
||||
import com.djrapitops.plan.utilities.Base64Util;
|
||||
import com.djrapitops.plan.utilities.file.export.HtmlExport;
|
||||
|
@ -7,10 +7,10 @@ package com.djrapitops.plan.system.info.request;
|
||||
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent;
|
||||
import com.djrapitops.plan.utilities.Base64Util;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
@ -6,12 +6,11 @@ package com.djrapitops.plan.system.info.request;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.connection.BadRequestException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.parts.NetworkPageContent;
|
||||
import com.djrapitops.plan.utilities.Base64Util;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
@ -52,8 +51,8 @@ public class CacheNetworkPageContentRequest extends InfoRequestWithVariables imp
|
||||
|
||||
NetworkPageContent serversTab = getNetworkPageContent();
|
||||
serversTab.addElement(serverName, Base64Util.decode(html));
|
||||
|
||||
InfoSystem.getInstance().updateNetworkPage();
|
||||
|
||||
ResponseCache.clearResponse(PageId.SERVER.of(ServerInfo.getServerUUID()));
|
||||
|
||||
return DefaultResponses.SUCCESS.get();
|
||||
}
|
||||
|
@ -12,9 +12,9 @@ import com.djrapitops.plan.data.store.containers.AnalysisContainer;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.pages.parsing.AnalysisPage;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.utilities.html.pages.AnalysisPage;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
|
@ -8,10 +8,10 @@ import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.*;
|
||||
import com.djrapitops.plan.api.exceptions.database.DBException;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.webserver.pages.parsing.InspectPage;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.NotFoundResponse;
|
||||
import com.djrapitops.plan.utilities.html.pages.InspectPage;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -10,7 +10,7 @@ import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.api.BadRequestResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.BadRequestResponse;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.TimeAmount;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
@ -13,7 +13,7 @@ import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.api.BadRequestResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.BadRequestResponse;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.utilities.Verify;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.update.ShutdownUpdateHook;
|
||||
import com.djrapitops.plan.system.webserver.response.DefaultResponses;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.api.BadRequestResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.BadRequestResponse;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -6,11 +6,13 @@ package com.djrapitops.plan.system.listeners.bungee;
|
||||
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.processing.processors.info.NetworkPageUpdateProcessor;
|
||||
import com.djrapitops.plan.system.processing.processors.info.PlayerPageUpdateProcessor;
|
||||
import com.djrapitops.plan.system.processing.processors.player.BungeePlayerRegisterProcessor;
|
||||
import com.djrapitops.plan.system.processing.processors.player.IPUpdateProcessor;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.PostLoginEvent;
|
||||
@ -44,7 +46,7 @@ public class PlayerOnlineListener implements Listener {
|
||||
new IPUpdateProcessor(uuid, address, now))
|
||||
);
|
||||
Processing.submit(new PlayerPageUpdateProcessor(uuid));
|
||||
Processing.submit(new NetworkPageUpdateProcessor());
|
||||
ResponseCache.clearResponse(PageId.SERVER.of(ServerInfo.getServerUUID()));
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
@ -58,7 +60,7 @@ public class PlayerOnlineListener implements Listener {
|
||||
|
||||
SessionCache.getInstance().endSession(uuid, System.currentTimeMillis());
|
||||
Processing.submit(new PlayerPageUpdateProcessor(uuid));
|
||||
Processing.submit(new NetworkPageUpdateProcessor());
|
||||
ResponseCache.clearResponse(PageId.SERVER.of(ServerInfo.getServerUUID()));
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
|
@ -40,7 +40,8 @@ public enum CmdHelpLang implements Lang {
|
||||
WEB_LIST("Command Help - /plan web list", "List Web Users"),
|
||||
WEB_CHECK("Command Help - /plan web check", "Inspect a Web User"),
|
||||
WEB_DELETE("Command Help - /plan web delete", "Delete a Web User"),
|
||||
MANAGE_RAW_DATA("Command Help - /plan manage raw", "View raw JSON of player data");
|
||||
MANAGE_RAW_DATA("Command Help - /plan manage raw", "View raw JSON of player data"),
|
||||
MANAGE_UNINSTALLED("Command Help - /plan manage uninstalled", "Mark a server as uninstalled in the database.");
|
||||
|
||||
private final String identifier;
|
||||
private final String defaultValue;
|
||||
|
@ -32,7 +32,8 @@ public enum DeepHelpLang implements Lang {
|
||||
MANAGE_SETUP("In Depth Help - /plan manage setup ?", "> §2Setup Subcommand\\ Set-up a connection between Bungee and this server for network functionality.\\ BungeeAddress can be found in the enable log on console when Plan enables on Bungee."),
|
||||
|
||||
WEB_REGISTER("In Depth Help - /plan web register ?", "> §2Register Subcommand\\ Registers a new Web User.\\ Registering a user for another player requires plan.webmanage permission.\\ Passwords are hashed with PBKDF2 (64,000 iterations of SHA1) using a cryptographically-random salt."),
|
||||
MANAGE_RAW_DATA("In Depth Help - /plan manage raw ?", "> §2Raw Data Subcommand\\ Displays link to raw JSON data page.\\ Not available if Plan webserver is not enabled.");
|
||||
MANAGE_RAW_DATA("In Depth Help - /plan manage raw ?", "> §2Raw Data Subcommand\\ Displays link to raw JSON data page.\\ Not available if Plan webserver is not enabled."),
|
||||
MANAGE_UNINSTALLED("In Depth Help - /plan manage uninstalled ?", "> §2Uninstalled Server Subcommand\\ Marks a server as uninstalled in the database.\\ Can not mark the server the command is being used on as uninstalled.\\ Will affect ConnectionSystem.");
|
||||
|
||||
private final String identifier;
|
||||
private final String defaultValue;
|
||||
|
@ -18,7 +18,10 @@ public enum ErrorPageLang implements Lang {
|
||||
NOT_FOUND_404("Not Found"),
|
||||
PAGE_NOT_FOUND_404("Page does not exist."),
|
||||
ANALYSIS_REFRESH("Analysis is being refreshed.."),
|
||||
ANALYSIS_REFRESH_LONG("Analysis is being run, refresh the page after a few seconds..");
|
||||
ANALYSIS_REFRESH_LONG("Analysis is being run, refresh the page after a few seconds.."),
|
||||
INSPECT_REFRESH("Player page request is being processed.."),
|
||||
INSPECT_REFRESH_LONG("Page will refresh automatically.."),
|
||||
PLUGIN_TAB_REFRESH("Calculating...");
|
||||
|
||||
private final String defaultValue;
|
||||
|
||||
|
@ -28,7 +28,9 @@ public enum ManageLang implements Lang {
|
||||
FAIL_SAME_DB("Manage - Fail Same Database", "> §cCan not operate on to and from the same database!"),
|
||||
FAIL_INCORRECT_DB("Manage - Fail Incorrect Database", "> §c'${0}' is not a supported database."),
|
||||
FAIL_FILE_NOT_FOUND("Manage - Fail File not found", "> §cNo File found at ${0}"),
|
||||
FAIL_IMPORTER_NOT_FOUND("Manage - Fail No Importer", "§eImporter '${0}' doesn't exist");
|
||||
FAIL_IMPORTER_NOT_FOUND("Manage - Fail No Importer", "§eImporter '${0}' doesn't exist"),
|
||||
NO_SERVER("Manage - Fail No Server", "No server found with given parameters."),
|
||||
UNINSTALLING_SAME_SERVER("Manage - Fail Same server", "Can not mark this server as uninstalled (You are on it)");
|
||||
|
||||
private final String identifier;
|
||||
private final String defaultValue;
|
||||
|
@ -32,13 +32,7 @@ public class PlanErrorManager implements ErrorManager {
|
||||
} else {
|
||||
Log.warn("It has been logged to ErrorLog.txt");
|
||||
}
|
||||
try {
|
||||
if ((Check.isBukkitAvailable() && Check.isBungeeAvailable()) || Settings.DEV_MODE.isTrue()) {
|
||||
Logger.getGlobal().log(Level.WARNING, source, e);
|
||||
}
|
||||
} catch (IllegalStateException ignored) {
|
||||
/* Config system not initialized */
|
||||
}
|
||||
logGlobally(source, e);
|
||||
ErrorLogger.logThrowable(e, logsFolder);
|
||||
} catch (Exception exception) {
|
||||
System.out.println("Failed to log error to file because of " + exception);
|
||||
@ -48,4 +42,14 @@ public class PlanErrorManager implements ErrorManager {
|
||||
Logger.getGlobal().log(Level.WARNING, source, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void logGlobally(String source, Throwable e) {
|
||||
try {
|
||||
if ((Check.isBukkitAvailable() && Check.isBungeeAvailable()) || Settings.DEV_MODE.isTrue()) {
|
||||
Logger.getGlobal().log(Level.WARNING, source, e);
|
||||
}
|
||||
} catch (IllegalStateException ignored) {
|
||||
/* Config system not initialized */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,11 +30,13 @@ public class BukkitTaskSystem extends ServerTaskSystem {
|
||||
@Override
|
||||
public void enable() {
|
||||
super.enable();
|
||||
if (Check.isSpigotAvailable()) {
|
||||
try {
|
||||
PingCountTimer pingCountTimer = new PingCountTimer();
|
||||
((Plan) plugin).registerListener(pingCountTimer);
|
||||
RunnableFactory.createNew("PingCountTimer", pingCountTimer)
|
||||
.runTaskTimer(20L, PingCountTimer.PING_INTERVAL);
|
||||
} catch (ExceptionInInitializerError | NoClassDefFoundError ignore) {
|
||||
// Running CraftBukkit
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,11 +9,10 @@ import com.djrapitops.plan.api.exceptions.connection.*;
|
||||
import com.djrapitops.plan.system.info.connection.InfoRequestPageHandler;
|
||||
import com.djrapitops.plan.system.locale.lang.ErrorPageLang;
|
||||
import com.djrapitops.plan.system.webserver.auth.Authentication;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.pages.*;
|
||||
import com.djrapitops.plan.system.webserver.response.*;
|
||||
import com.djrapitops.plan.system.webserver.response.api.BadRequestResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.*;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
|
@ -8,7 +8,7 @@ import com.djrapitops.plan.api.exceptions.EnableException;
|
||||
import com.djrapitops.plan.system.PlanSystem;
|
||||
import com.djrapitops.plan.system.SubSystem;
|
||||
import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plugin.api.Benchmark;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.response.cache;
|
||||
package com.djrapitops.plan.system.webserver.cache;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.djrapitops.plan.system.webserver.response.cache;
|
||||
package com.djrapitops.plan.system.webserver.cache;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
|
||||
@ -97,4 +97,8 @@ public class ResponseCache {
|
||||
public static Set<String> getCacheKeys() {
|
||||
return cache.keySet();
|
||||
}
|
||||
|
||||
public static void clearResponse(String identifier) {
|
||||
cache.remove(identifier);
|
||||
}
|
||||
}
|
@ -14,9 +14,9 @@ import com.djrapitops.plan.system.locale.Locale;
|
||||
import com.djrapitops.plan.system.locale.lang.ErrorPageLang;
|
||||
import com.djrapitops.plan.system.webserver.Request;
|
||||
import com.djrapitops.plan.system.webserver.auth.Authentication;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.NotFoundResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.InspectPageResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.RawPlayerDataResponse;
|
||||
|
@ -7,9 +7,9 @@ package com.djrapitops.plan.system.webserver.pages;
|
||||
import com.djrapitops.plan.api.exceptions.WebUserAuthException;
|
||||
import com.djrapitops.plan.system.webserver.Request;
|
||||
import com.djrapitops.plan.system.webserver.auth.Authentication;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.PlayersPageResponse;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -11,9 +11,9 @@ import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.Request;
|
||||
import com.djrapitops.plan.system.webserver.auth.Authentication;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.AnalysisPageResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.RawServerDataResponse;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
|
@ -4,8 +4,6 @@
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.response;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.api.SuccessResponse;
|
||||
|
||||
/**
|
||||
* Enum containing default responses that don't need to be cached because they're always the same.
|
||||
*
|
||||
@ -13,7 +11,7 @@ import com.djrapitops.plan.system.webserver.response.api.SuccessResponse;
|
||||
*/
|
||||
public enum DefaultResponses {
|
||||
BASIC_AUTH(PromptAuthorizationResponse.getBasicAuthResponse()),
|
||||
SUCCESS(new SuccessResponse());
|
||||
SUCCESS(new TextResponse("Success"));
|
||||
|
||||
private final Response response;
|
||||
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.djrapitops.plan.system.webserver.response;
|
||||
|
||||
/**
|
||||
* Response for raw text.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class TextResponse extends Response {
|
||||
|
||||
public TextResponse(String content) {
|
||||
setHeader("HTTP/1.1 200 OK");
|
||||
setContent(content);
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.response.api;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.ResponseType;
|
||||
import com.google.gson.Gson;
|
||||
|
||||
/**
|
||||
* @author Fuzzlemann
|
||||
*/
|
||||
public class JsonResponse extends Response {
|
||||
|
||||
public <T> JsonResponse(T object) {
|
||||
super(ResponseType.JSON);
|
||||
Gson gson = new Gson();
|
||||
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
super.setContent(gson.toJson(object));
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
/*
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.response.api;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
|
||||
/**
|
||||
* @author Fuzzlemann
|
||||
*/
|
||||
public class SuccessResponse extends Response {
|
||||
|
||||
public SuccessResponse() {
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
super.setContent("Success");
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.response.api;
|
||||
package com.djrapitops.plan.system.webserver.response.errors;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
|
@ -5,11 +5,11 @@ import com.djrapitops.plan.api.exceptions.connection.NoServersException;
|
||||
import com.djrapitops.plan.api.exceptions.connection.WebException;
|
||||
import com.djrapitops.plan.system.info.InfoSystem;
|
||||
import com.djrapitops.plan.system.processing.Processing;
|
||||
import com.djrapitops.plan.system.webserver.pages.parsing.AnalysisPage;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.NotFoundResponse;
|
||||
import com.djrapitops.plan.utilities.html.pages.AnalysisPage;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -4,40 +4,9 @@
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.store.CachingSupplier;
|
||||
import com.djrapitops.plan.data.store.Key;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
import com.djrapitops.plan.data.store.objects.DateHolder;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionLog;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.ErrorResponse;
|
||||
import com.djrapitops.plan.utilities.file.FileUtil;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
import com.djrapitops.plan.utilities.html.HtmlStructure;
|
||||
import com.djrapitops.plan.utilities.html.icon.Icon;
|
||||
import com.djrapitops.plan.utilities.html.structure.TabsElement;
|
||||
import com.djrapitops.plugin.api.Benchmark;
|
||||
import com.djrapitops.plugin.api.utility.log.ErrorLogger;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
import com.djrapitops.plan.utilities.html.pages.DebugPage;
|
||||
|
||||
/**
|
||||
* WebServer response for /debug-page used for easing issue reporting.
|
||||
@ -49,288 +18,8 @@ public class DebugPageResponse extends ErrorResponse {
|
||||
public DebugPageResponse() {
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
super.setTitle(Icon.called("bug") + " Debug Information");
|
||||
super.setParagraph(buildContent());
|
||||
super.setParagraph(new DebugPage().toHtml());
|
||||
replacePlaceholders();
|
||||
}
|
||||
|
||||
private String buildContent() {
|
||||
StringBuilder preContent = new StringBuilder();
|
||||
|
||||
String issueLink = Html.LINK_EXTERNAL.parse("https://github.com/Rsl1122/Plan-PlayerAnalytics/issues/new", "Create new issue on Github");
|
||||
String hastebinLink = Html.LINK_EXTERNAL.parse("https://hastebin.com/", "Create a new hastebin paste");
|
||||
|
||||
preContent.append("<p>")
|
||||
.append(HtmlStructure.separateWithDots(issueLink, hastebinLink)).append("<br><br>")
|
||||
.append("This page contains debug information for an issue ticket. You can copy it directly into the issue, the info is pre-formatted.")
|
||||
.append("</p>");
|
||||
|
||||
TabsElement.Tab info = new TabsElement.Tab(Icon.called("server") + " Server Information", createServerInfoContent());
|
||||
TabsElement.Tab errors = new TabsElement.Tab(Icon.called("exclamation-circle") + " Errors", createErrorContent());
|
||||
TabsElement.Tab debugLog = new TabsElement.Tab(Icon.called("bug") + " Debug Log", createDebugLogContent());
|
||||
TabsElement.Tab config = new TabsElement.Tab(Icon.called("cogs") + " Plan Config", createConfigContent());
|
||||
TabsElement.Tab caches = new TabsElement.Tab(Icon.called("archive") + " Plan Caches", createCacheContent());
|
||||
|
||||
TabsElement tabs = new TabsElement(info, errors, debugLog, config, caches);
|
||||
|
||||
return preContent + tabs.toHtmlFull();
|
||||
}
|
||||
|
||||
private String createCacheContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendResponseCache(content);
|
||||
appendSessionCache(content);
|
||||
appendDataContainerCache(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private void appendResponseCache(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### Cached Responses:<br><br>");
|
||||
List<String> cacheKeys = new ArrayList<>(ResponseCache.getCacheKeys());
|
||||
if (cacheKeys.isEmpty()) {
|
||||
content.append("Empty");
|
||||
}
|
||||
Collections.sort(cacheKeys);
|
||||
for (String cacheKey : cacheKeys) {
|
||||
content.append("- ").append(cacheKey).append("<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendSessionCache(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### Session Cache:<br><br>");
|
||||
content.append("UUID | Session Started <br>")
|
||||
.append("-- | -- <br>");
|
||||
Formatter<Long> timeStamp = Formatters.yearLongValue();
|
||||
Set<Map.Entry<UUID, Session>> sessions = SessionCache.getActiveSessions().entrySet();
|
||||
if (sessions.isEmpty()) {
|
||||
content.append("Empty");
|
||||
}
|
||||
for (Map.Entry<UUID, Session> entry : sessions) {
|
||||
UUID uuid = entry.getKey();
|
||||
String start = entry.getValue().getValue(SessionKeys.START).map(timeStamp).orElse("Unknown");
|
||||
content.append(uuid.toString()).append(" | ").append(start).append("<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendDataContainerCache(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### DataContainer Cache:<br><br>");
|
||||
|
||||
content.append("Key | Is Cached | Cache Time <br>")
|
||||
.append("-- | -- | -- <br>");
|
||||
Formatter<Long> timeStamp = Formatters.yearLongValue();
|
||||
Set<Map.Entry<Key, Supplier>> dataContainers = CacheSystem.getInstance().getDataContainerCache().getMap().entrySet();
|
||||
if (dataContainers.isEmpty()) {
|
||||
content.append("Empty");
|
||||
}
|
||||
for (Map.Entry<Key, Supplier> entry : dataContainers) {
|
||||
String keyName = entry.getKey().getKeyName();
|
||||
Supplier supplier = entry.getValue();
|
||||
if (supplier instanceof CachingSupplier) {
|
||||
CachingSupplier cachingSupplier = (CachingSupplier) supplier;
|
||||
boolean isCached = cachingSupplier.isCached();
|
||||
String cacheText = isCached ? "Yes" : "No";
|
||||
String cacheTime = isCached ? timeStamp.apply(cachingSupplier.getCacheTime()) : "-";
|
||||
content.append(keyName).append(" | ").append(cacheText).append(" | ").append(cacheTime).append("<br>");
|
||||
} else {
|
||||
content.append(keyName).append(" | ").append("Non-caching Supplier").append(" | ").append("-").append("<br>");
|
||||
}
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String createConfigContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendConfig(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private String createDebugLogContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendDebugLog(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private String createErrorContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendLoggedErrors(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private String createServerInfoContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
|
||||
appendServerInformation(content);
|
||||
appendConnectionLog(content);
|
||||
appendBenchmarks(content);
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private void appendConnectionLog(StringBuilder content) {
|
||||
try {
|
||||
Map<String, Map<String, ConnectionLog.Entry>> logEntries = ConnectionLog.getLogEntries();
|
||||
|
||||
content.append("<pre>### Connection Log:<br><br>");
|
||||
content.append("Server Address | Request Type | Response | Sent<br>")
|
||||
.append("-- | -- | -- | --<br>");
|
||||
|
||||
Formatter<DateHolder> formatter = Formatters.second();
|
||||
|
||||
if (logEntries.isEmpty()) {
|
||||
content.append("**No Connections Logged**<br>");
|
||||
}
|
||||
for (Map.Entry<String, Map<String, ConnectionLog.Entry>> entry : logEntries.entrySet()) {
|
||||
String address = entry.getKey();
|
||||
Map<String, ConnectionLog.Entry> requests = entry.getValue();
|
||||
for (Map.Entry<String, ConnectionLog.Entry> requestEntry : requests.entrySet()) {
|
||||
String infoRequest = requestEntry.getKey();
|
||||
ConnectionLog.Entry logEntry = requestEntry.getValue();
|
||||
|
||||
content.append(address).append(" | ")
|
||||
.append(infoRequest).append(" | ")
|
||||
.append(logEntry.getResponseCode()).append(" | ")
|
||||
.append(formatter.apply(logEntry)).append("<br>");
|
||||
}
|
||||
|
||||
}
|
||||
content.append("</pre>");
|
||||
|
||||
content.append("<pre>### Servers:<br><br>");
|
||||
List<Server> servers = ConnectionSystem.getInstance().getBukkitServers();
|
||||
content.append("Server Name | Address | UUID <br>")
|
||||
.append("-- | -- | --<br>");
|
||||
for (Server server : servers) {
|
||||
content.append(server.getName()).append(" | ")
|
||||
.append(server.getWebAddress()).append(" | ")
|
||||
.append(server.getUuid()).append("<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendServerInformation(StringBuilder content) {
|
||||
PlanPlugin plugin = PlanPlugin.getInstance();
|
||||
ServerProperties variable = ServerInfo.getServerProperties();
|
||||
|
||||
content.append("<pre>### Server Information<br>")
|
||||
.append("**Plan Version:** ").append(plugin.getVersion()).append("<br>");
|
||||
|
||||
content.append("**Server:** ");
|
||||
content.append(variable.getName())
|
||||
.append(" ").append(variable.getImplVersion())
|
||||
.append(" ").append(variable.getVersion());
|
||||
content.append("<br>");
|
||||
|
||||
Database database = Database.getActive();
|
||||
content.append("**Database:** ").append(database.getName());
|
||||
content.append("<br><br>");
|
||||
|
||||
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
|
||||
Properties properties = System.getProperties();
|
||||
|
||||
String osName = properties.getProperty("os.name");
|
||||
String osVersion = properties.getProperty("os.version");
|
||||
String osArch = properties.getProperty("os.arch");
|
||||
|
||||
String javaVendor = properties.getProperty("java.vendor");
|
||||
String javaVersion = properties.getProperty("java.version");
|
||||
|
||||
String javaVMVendor = properties.getProperty("java.vm.vendor");
|
||||
String javaVMName = properties.getProperty("java.vm.name");
|
||||
String javaVMVersion = properties.getProperty("java.vm.version");
|
||||
List<String> javaVMFlags = runtimeMxBean.getInputArguments();
|
||||
|
||||
content.append("**Operating SubSystem:** ").append(osName).append(" (").append(osArch)
|
||||
.append(") version ").append(osVersion).append("<br>");
|
||||
|
||||
content.append("**Java Version:** ").append(javaVersion).append(", ").append(javaVendor).append("<br>");
|
||||
content.append("**Java VM Version:** ").append(javaVMName).append(" version ").append(javaVMVersion)
|
||||
.append(", ").append(javaVMVendor).append("<br>");
|
||||
content.append("**Java VM Flags:** ").append(javaVMFlags).append("<br>");
|
||||
|
||||
content.append("</pre>");
|
||||
}
|
||||
|
||||
private void appendConfig(StringBuilder content) {
|
||||
try {
|
||||
File configFile = new File(PlanPlugin.getInstance().getDataFolder(), "config.yml");
|
||||
if (configFile.exists()) {
|
||||
content.append("<pre>### config.yml<br>```<br>");
|
||||
FileUtil.lines(configFile, Charset.forName("UTF-8"))
|
||||
.stream().filter(line -> !line.toLowerCase().contains("pass") && !line.toLowerCase().contains("secret"))
|
||||
.forEach(line -> content.append(line).append("<br>"));
|
||||
content.append("```</pre>");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendBenchmarks(StringBuilder content) {
|
||||
content.append("<pre>### Benchmarks<br>```<br>");
|
||||
try {
|
||||
for (String line : Benchmark.getAverages().asStringArray()) {
|
||||
content.append(line).append("<br>");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
content.append("Exception on Benchmark.getAverages().asStringArray()");
|
||||
}
|
||||
content.append("```</pre>");
|
||||
}
|
||||
|
||||
private void appendLoggedErrors(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### Logged Errors<br>");
|
||||
|
||||
SortedMap<String, List<String>> errors = ErrorLogger.getLoggedErrors(PlanPlugin.getInstance());
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
List<String> errorLines = new ArrayList<>();
|
||||
for (Map.Entry<String, List<String>> entry : errors.entrySet()) {
|
||||
StringBuilder errorLineBuilder = new StringBuilder();
|
||||
for (String line : entry.getValue()) {
|
||||
errorLineBuilder.append(line).append("<br>");
|
||||
}
|
||||
String error = errorLineBuilder.toString();
|
||||
if (!errorLines.contains(error)) {
|
||||
errorLines.add(error);
|
||||
}
|
||||
}
|
||||
for (String error : errorLines) {
|
||||
content.append("</pre><pre>```<br>")
|
||||
.append(error)
|
||||
.append("```");
|
||||
}
|
||||
} else {
|
||||
content.append("**No Errors logged.**<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (IOException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendDebugLog(StringBuilder content) {
|
||||
content.append("<pre>### Debug Log<br>```<br>");
|
||||
for (String line : Log.getDebugLogInMemory()) {
|
||||
content.append(line).append("<br>");
|
||||
}
|
||||
content.append("```</pre>");
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.system.settings.theme.Theme;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.ErrorResponse;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.parts.InspectPagePluginsContent;
|
||||
import org.apache.commons.text.StringSubstitutor;
|
||||
|
@ -0,0 +1,21 @@
|
||||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.utilities.html.pages.NetworkPage;
|
||||
|
||||
/**
|
||||
* Response for /network page.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class NetworkPageResponse extends Response {
|
||||
|
||||
public NetworkPageResponse() throws ParseException {
|
||||
super.setHeader("HTTP/1.1 200 OK");
|
||||
NetworkContainer networkContainer = Database.getActive().fetch().getNetworkContainer(); // Not cached, big.
|
||||
setContent(new NetworkPage(networkContainer).toHtml());
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package com.djrapitops.plan.system.webserver.response.pages;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.system.webserver.pages.parsing.PlayersPage;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.errors.InternalErrorResponse;
|
||||
import com.djrapitops.plan.utilities.html.pages.PlayersPage;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
/**
|
||||
|
@ -1,126 +0,0 @@
|
||||
package com.djrapitops.plan.utilities.analysis;
|
||||
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.RetentionData;
|
||||
import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.settings.WorldAliasSettings;
|
||||
import com.djrapitops.plan.utilities.FormatUtils;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Class that contains various methods that are used in analysis.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class AnalysisUtils {
|
||||
|
||||
private AnalysisUtils() {
|
||||
/* static method class.*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the session start list into a list of int arrays.
|
||||
* <p>
|
||||
* First number signifies the Day of Week. (0 = Monday, 6 = Sunday)
|
||||
* Second number signifies the Hour of Day. (0 = 0 AM, 23 = 11 PM)
|
||||
*
|
||||
* @param sessionStarts List of Session start Epoch ms.
|
||||
* @return list of int arrays.
|
||||
*/
|
||||
public static List<int[]> getDaysAndHours(List<Long> sessionStarts) {
|
||||
return sessionStarts.stream().map((Long start) -> {
|
||||
Calendar day = Calendar.getInstance();
|
||||
day.setTimeInMillis(start);
|
||||
int hourOfDay = day.get(Calendar.HOUR_OF_DAY); // 0 AM is 0
|
||||
int dayOfWeek = day.get(Calendar.DAY_OF_WEEK) - 2; // Monday is 0, Sunday is -1
|
||||
if (hourOfDay == 24) { // If hour is 24 (Should be impossible but.)
|
||||
hourOfDay = 0;
|
||||
dayOfWeek += 1;
|
||||
}
|
||||
if (dayOfWeek > 6) { // If Hour added a day on Sunday, move to Monday
|
||||
dayOfWeek = 0;
|
||||
}
|
||||
if (dayOfWeek < 0) { // Move Sunday to 6
|
||||
dayOfWeek = 6;
|
||||
}
|
||||
return new int[]{dayOfWeek, hourOfDay};
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static Map<String, Long> getPlaytimePerAlias(WorldTimes worldTimes) {
|
||||
// WorldTimes Map<String, GMTimes>
|
||||
Map<String, Long> playtimePerWorld = worldTimes.getWorldTimes()
|
||||
.entrySet().stream()
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> entry.getValue().getTotal() // GMTimes.getTotal
|
||||
));
|
||||
|
||||
Map<String, String> aliases = WorldAliasSettings.getAliases();
|
||||
|
||||
Map<String, Long> playtimePerAlias = new HashMap<>();
|
||||
for (Map.Entry<String, Long> entry : playtimePerWorld.entrySet()) {
|
||||
String worldName = entry.getKey();
|
||||
long playtime = entry.getValue();
|
||||
|
||||
if (!aliases.containsKey(worldName)) {
|
||||
aliases.put(worldName, worldName);
|
||||
WorldAliasSettings.addWorld(worldName);
|
||||
}
|
||||
|
||||
String alias = aliases.get(worldName);
|
||||
|
||||
playtimePerAlias.put(alias, playtimePerAlias.getOrDefault(alias, 0L) + playtime);
|
||||
}
|
||||
return playtimePerAlias;
|
||||
}
|
||||
|
||||
public static RetentionData average(Collection<RetentionData> stuck) {
|
||||
int size = stuck.size();
|
||||
|
||||
double totalIndex = 0.0;
|
||||
double totalPlayersOnline = 0.0;
|
||||
|
||||
for (RetentionData retentionData : stuck) {
|
||||
totalIndex += retentionData.getActivityIndex();
|
||||
totalPlayersOnline += retentionData.getOnlineOnJoin();
|
||||
}
|
||||
|
||||
double averageIndex = totalIndex / (double) size;
|
||||
double averagePlayersOnline = totalPlayersOnline / (double) size;
|
||||
|
||||
return new RetentionData(averageIndex, averagePlayersOnline);
|
||||
}
|
||||
|
||||
public static String getLongestWorldPlayed(Session session) {
|
||||
Map<String, String> aliases = WorldAliasSettings.getAliases();
|
||||
if (!session.supports(SessionKeys.WORLD_TIMES)) {
|
||||
return "No World Time Data";
|
||||
}
|
||||
if (!session.supports(SessionKeys.END)) {
|
||||
return "Current: " + aliases.get(session.getUnsafe(SessionKeys.WORLD_TIMES).getCurrentWorld());
|
||||
}
|
||||
|
||||
WorldTimes worldTimes = session.getUnsafe(SessionKeys.WORLD_TIMES);
|
||||
Map<String, Long> playtimePerAlias = getPlaytimePerAlias(worldTimes);
|
||||
long total = worldTimes.getTotal();
|
||||
|
||||
long longest = 0;
|
||||
String theWorld = "-";
|
||||
for (Map.Entry<String, Long> entry : playtimePerAlias.entrySet()) {
|
||||
String world = entry.getKey();
|
||||
long time = entry.getValue();
|
||||
if (time > longest) {
|
||||
longest = time;
|
||||
theWorld = world;
|
||||
}
|
||||
}
|
||||
|
||||
double percentage = longest * 100.0 / total;
|
||||
|
||||
return theWorld + " (" + FormatUtils.cutDecimals(percentage) + "%)";
|
||||
}
|
||||
}
|
@ -7,9 +7,9 @@ package com.djrapitops.plan.utilities.file.export;
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plugin.api.Check;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
import com.djrapitops.plugin.task.AbsRunnable;
|
||||
|
@ -7,8 +7,8 @@ package com.djrapitops.plan.utilities.html.graphs;
|
||||
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -33,11 +33,45 @@ public class PunchCardGraph implements HighChart {
|
||||
this.sessions = sessions;
|
||||
}
|
||||
|
||||
/*
|
||||
* First number signifies the Day of Week. (0 = Monday, 6 = Sunday)
|
||||
* Second number signifies the Hour of Day. (0 = 0 AM, 23 = 11 PM)
|
||||
*/
|
||||
private static List<int[]> getDaysAndHours(Collection<Long> sessionStarts) {
|
||||
return sessionStarts.stream().map((Long start) -> {
|
||||
Calendar day = Calendar.getInstance();
|
||||
day.setTimeInMillis(start);
|
||||
int hourOfDay = day.get(Calendar.HOUR_OF_DAY); // 0 AM is 0
|
||||
int dayOfWeek = day.get(Calendar.DAY_OF_WEEK) - 2; // Monday is 0, Sunday is -1
|
||||
if (hourOfDay == 24) { // If hour is 24 (Should be impossible but.)
|
||||
hourOfDay = 0;
|
||||
dayOfWeek += 1;
|
||||
}
|
||||
if (dayOfWeek > 6) { // If Hour added a day on Sunday, move to Monday
|
||||
dayOfWeek = 0;
|
||||
}
|
||||
if (dayOfWeek < 0) { // Move Sunday to 6
|
||||
dayOfWeek = 6;
|
||||
}
|
||||
return new int[]{dayOfWeek, hourOfDay};
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private static int[][] turnIntoArray(Collection<Long> sessionStarts) {
|
||||
List<int[]> daysAndHours = getDaysAndHours(sessionStarts);
|
||||
int[][] dataArray = createEmptyArray();
|
||||
for (int[] dAndH : daysAndHours) {
|
||||
int d = dAndH[0];
|
||||
int h = dAndH[1];
|
||||
dataArray[d][h] = dataArray[d][h] + 1;
|
||||
}
|
||||
return dataArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toHighChartsSeries() {
|
||||
List<Long> sessionStarts = getSessionStarts(sessions);
|
||||
List<int[]> daysAndHours = AnalysisUtils.getDaysAndHours(sessionStarts);
|
||||
int[][] dataArray = turnIntoArray(daysAndHours);
|
||||
int[][] dataArray = turnIntoArray(sessionStarts);
|
||||
int big = findBiggestValue(dataArray);
|
||||
int[][] scaled = scale(dataArray, big);
|
||||
StringBuilder arrayBuilder = new StringBuilder("[");
|
||||
@ -62,16 +96,6 @@ public class PunchCardGraph implements HighChart {
|
||||
return arrayBuilder.toString();
|
||||
}
|
||||
|
||||
private static int[][] turnIntoArray(List<int[]> daysAndHours) {
|
||||
int[][] dataArray = createEmptyArray();
|
||||
for (int[] dAndH : daysAndHours) {
|
||||
int d = dAndH[0];
|
||||
int h = dAndH[1];
|
||||
dataArray[d][h] = dataArray[d][h] + 1;
|
||||
}
|
||||
return dataArray;
|
||||
}
|
||||
|
||||
private static List<Long> getSessionStarts(Collection<Session> data) {
|
||||
return data.stream()
|
||||
.filter(Objects::nonNull)
|
||||
|
@ -64,7 +64,7 @@ public class ServerCalendar {
|
||||
|
||||
private void appendSessionRelatedData(StringBuilder series) {
|
||||
SessionsMutator sessionsMutator = new SessionsMutator(mutator.getSessions());
|
||||
TreeMap<Long, List<Session>> byStartOfDay = sessionsMutator.toDateHoldersMutator().groupByStartOfDay();
|
||||
SortedMap<Long, List<Session>> byStartOfDay = sessionsMutator.toDateHoldersMutator().groupByStartOfDay();
|
||||
|
||||
for (Map.Entry<Long, Integer> entry : uniquePerDay.entrySet()) {
|
||||
if (entry.getValue() <= 0) {
|
||||
|
@ -6,7 +6,6 @@ import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.WorldAliasSettings;
|
||||
import com.djrapitops.plan.system.settings.theme.Theme;
|
||||
import com.djrapitops.plan.system.settings.theme.ThemeVal;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import com.djrapitops.plan.utilities.comparators.PieSliceComparator;
|
||||
|
||||
import java.util.*;
|
||||
@ -29,7 +28,7 @@ public class WorldPie extends AbstractPieChartWithDrilldown {
|
||||
String[] colors = Theme.getValue(ThemeVal.GRAPH_WORLD_PIE).split(", ");
|
||||
int colLength = colors.length;
|
||||
|
||||
Map<String, Long> playtimePerAlias = AnalysisUtils.getPlaytimePerAlias(worldTimes);
|
||||
Map<String, Long> playtimePerAlias = worldTimes.getPlaytimePerAlias();
|
||||
|
||||
List<String> worlds = new ArrayList<>(playtimePerAlias.keySet());
|
||||
Collections.sort(worlds);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.pages.parsing;
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.data.store.containers.AnalysisContainer;
|
@ -0,0 +1,325 @@
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.data.container.Session;
|
||||
import com.djrapitops.plan.data.store.CachingSupplier;
|
||||
import com.djrapitops.plan.data.store.Key;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
import com.djrapitops.plan.data.store.objects.DateHolder;
|
||||
import com.djrapitops.plan.system.cache.CacheSystem;
|
||||
import com.djrapitops.plan.system.cache.SessionCache;
|
||||
import com.djrapitops.plan.system.database.databases.Database;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionLog;
|
||||
import com.djrapitops.plan.system.info.connection.ConnectionSystem;
|
||||
import com.djrapitops.plan.system.info.server.Server;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.info.server.properties.ServerProperties;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.utilities.file.FileUtil;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
import com.djrapitops.plan.utilities.html.HtmlStructure;
|
||||
import com.djrapitops.plan.utilities.html.icon.Icon;
|
||||
import com.djrapitops.plan.utilities.html.structure.TabsElement;
|
||||
import com.djrapitops.plugin.api.Benchmark;
|
||||
import com.djrapitops.plugin.api.utility.log.ErrorLogger;
|
||||
import com.djrapitops.plugin.api.utility.log.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Html parsing for the Debug page.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class DebugPage implements Page {
|
||||
|
||||
@Override
|
||||
public String toHtml() {
|
||||
StringBuilder preContent = new StringBuilder();
|
||||
|
||||
String issueLink = Html.LINK_EXTERNAL.parse("https://github.com/Rsl1122/Plan-PlayerAnalytics/issues/new", "Create new issue on Github");
|
||||
String hastebinLink = Html.LINK_EXTERNAL.parse("https://hastebin.com/", "Create a new hastebin paste");
|
||||
|
||||
preContent.append("<p>")
|
||||
.append(HtmlStructure.separateWithDots(issueLink, hastebinLink)).append("<br><br>")
|
||||
.append("This page contains debug information for an issue ticket. You can copy it directly into the issue, the info is pre-formatted.")
|
||||
.append("</p>");
|
||||
|
||||
TabsElement.Tab info = new TabsElement.Tab(Icon.called("server") + " Server Information", createServerInfoContent());
|
||||
TabsElement.Tab errors = new TabsElement.Tab(Icon.called("exclamation-circle") + " Errors", createErrorContent());
|
||||
TabsElement.Tab debugLog = new TabsElement.Tab(Icon.called("bug") + " Debug Log", createDebugLogContent());
|
||||
TabsElement.Tab config = new TabsElement.Tab(Icon.called("cogs") + " Plan Config", createConfigContent());
|
||||
TabsElement.Tab caches = new TabsElement.Tab(Icon.called("archive") + " Plan Caches", createCacheContent());
|
||||
|
||||
TabsElement tabs = new TabsElement(info, errors, debugLog, config, caches);
|
||||
|
||||
return preContent + tabs.toHtmlFull();
|
||||
}
|
||||
|
||||
private String createCacheContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendResponseCache(content);
|
||||
appendSessionCache(content);
|
||||
appendDataContainerCache(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private void appendResponseCache(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### Cached Responses:<br><br>");
|
||||
List<String> cacheKeys = new ArrayList<>(ResponseCache.getCacheKeys());
|
||||
if (cacheKeys.isEmpty()) {
|
||||
content.append("Empty");
|
||||
}
|
||||
Collections.sort(cacheKeys);
|
||||
for (String cacheKey : cacheKeys) {
|
||||
content.append("- ").append(cacheKey).append("<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendSessionCache(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### Session Cache:<br><br>");
|
||||
content.append("UUID | Session Started <br>")
|
||||
.append("-- | -- <br>");
|
||||
Formatter<Long> timeStamp = Formatters.yearLongValue();
|
||||
Set<Map.Entry<UUID, Session>> sessions = SessionCache.getActiveSessions().entrySet();
|
||||
if (sessions.isEmpty()) {
|
||||
content.append("Empty");
|
||||
}
|
||||
for (Map.Entry<UUID, Session> entry : sessions) {
|
||||
UUID uuid = entry.getKey();
|
||||
String start = entry.getValue().getValue(SessionKeys.START).map(timeStamp).orElse("Unknown");
|
||||
content.append(uuid.toString()).append(" | ").append(start).append("<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendDataContainerCache(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### DataContainer Cache:<br><br>");
|
||||
|
||||
content.append("Key | Is Cached | Cache Time <br>")
|
||||
.append("-- | -- | -- <br>");
|
||||
Formatter<Long> timeStamp = Formatters.yearLongValue();
|
||||
Set<Map.Entry<Key, Supplier>> dataContainers = CacheSystem.getInstance().getDataContainerCache().getMap().entrySet();
|
||||
if (dataContainers.isEmpty()) {
|
||||
content.append("Empty");
|
||||
}
|
||||
for (Map.Entry<Key, Supplier> entry : dataContainers) {
|
||||
String keyName = entry.getKey().getKeyName();
|
||||
Supplier supplier = entry.getValue();
|
||||
if (supplier instanceof CachingSupplier) {
|
||||
CachingSupplier cachingSupplier = (CachingSupplier) supplier;
|
||||
boolean isCached = cachingSupplier.isCached();
|
||||
String cacheText = isCached ? "Yes" : "No";
|
||||
String cacheTime = isCached ? timeStamp.apply(cachingSupplier.getCacheTime()) : "-";
|
||||
content.append(keyName).append(" | ").append(cacheText).append(" | ").append(cacheTime).append("<br>");
|
||||
} else {
|
||||
content.append(keyName).append(" | ").append("Non-caching Supplier").append(" | ").append("-").append("<br>");
|
||||
}
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String createConfigContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendConfig(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private String createDebugLogContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendDebugLog(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private String createErrorContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
appendLoggedErrors(content);
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private String createServerInfoContent() {
|
||||
StringBuilder content = new StringBuilder();
|
||||
|
||||
appendServerInformation(content);
|
||||
appendConnectionLog(content);
|
||||
appendBenchmarks(content);
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
private void appendConnectionLog(StringBuilder content) {
|
||||
try {
|
||||
Map<String, Map<String, ConnectionLog.Entry>> logEntries = ConnectionLog.getLogEntries();
|
||||
|
||||
content.append("<pre>### Connection Log:<br><br>");
|
||||
content.append("Server Address | Request Type | Response | Sent<br>")
|
||||
.append("-- | -- | -- | --<br>");
|
||||
|
||||
Formatter<DateHolder> formatter = Formatters.second();
|
||||
|
||||
if (logEntries.isEmpty()) {
|
||||
content.append("**No Connections Logged**<br>");
|
||||
}
|
||||
for (Map.Entry<String, Map<String, ConnectionLog.Entry>> entry : logEntries.entrySet()) {
|
||||
String address = entry.getKey();
|
||||
Map<String, ConnectionLog.Entry> requests = entry.getValue();
|
||||
for (Map.Entry<String, ConnectionLog.Entry> requestEntry : requests.entrySet()) {
|
||||
String infoRequest = requestEntry.getKey();
|
||||
ConnectionLog.Entry logEntry = requestEntry.getValue();
|
||||
|
||||
content.append(address).append(" | ")
|
||||
.append(infoRequest).append(" | ")
|
||||
.append(logEntry.getResponseCode()).append(" | ")
|
||||
.append(formatter.apply(logEntry)).append("<br>");
|
||||
}
|
||||
|
||||
}
|
||||
content.append("</pre>");
|
||||
|
||||
content.append("<pre>### Servers:<br><br>");
|
||||
List<Server> servers = ConnectionSystem.getInstance().getBukkitServers();
|
||||
content.append("Server Name | Address | UUID <br>")
|
||||
.append("-- | -- | --<br>");
|
||||
for (Server server : servers) {
|
||||
content.append(server.getName()).append(" | ")
|
||||
.append(server.getWebAddress()).append(" | ")
|
||||
.append(server.getUuid()).append("<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendServerInformation(StringBuilder content) {
|
||||
PlanPlugin plugin = PlanPlugin.getInstance();
|
||||
ServerProperties variable = ServerInfo.getServerProperties();
|
||||
|
||||
content.append("<pre>### Server Information<br>")
|
||||
.append("**Plan Version:** ").append(plugin.getVersion()).append("<br>");
|
||||
|
||||
content.append("**Server:** ");
|
||||
content.append(variable.getName())
|
||||
.append(" ").append(variable.getImplVersion())
|
||||
.append(" ").append(variable.getVersion());
|
||||
content.append("<br>");
|
||||
|
||||
Database database = Database.getActive();
|
||||
content.append("**Database:** ").append(database.getName());
|
||||
content.append("<br><br>");
|
||||
|
||||
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
|
||||
Properties properties = System.getProperties();
|
||||
|
||||
String osName = properties.getProperty("os.name");
|
||||
String osVersion = properties.getProperty("os.version");
|
||||
String osArch = properties.getProperty("os.arch");
|
||||
|
||||
String javaVendor = properties.getProperty("java.vendor");
|
||||
String javaVersion = properties.getProperty("java.version");
|
||||
|
||||
String javaVMVendor = properties.getProperty("java.vm.vendor");
|
||||
String javaVMName = properties.getProperty("java.vm.name");
|
||||
String javaVMVersion = properties.getProperty("java.vm.version");
|
||||
List<String> javaVMFlags = runtimeMxBean.getInputArguments();
|
||||
|
||||
content.append("**Operating SubSystem:** ").append(osName).append(" (").append(osArch)
|
||||
.append(") version ").append(osVersion).append("<br>");
|
||||
|
||||
content.append("**Java Version:** ").append(javaVersion).append(", ").append(javaVendor).append("<br>");
|
||||
content.append("**Java VM Version:** ").append(javaVMName).append(" version ").append(javaVMVersion)
|
||||
.append(", ").append(javaVMVendor).append("<br>");
|
||||
content.append("**Java VM Flags:** ").append(javaVMFlags).append("<br>");
|
||||
|
||||
content.append("</pre>");
|
||||
}
|
||||
|
||||
private void appendConfig(StringBuilder content) {
|
||||
try {
|
||||
File configFile = new File(PlanPlugin.getInstance().getDataFolder(), "config.yml");
|
||||
if (configFile.exists()) {
|
||||
content.append("<pre>### config.yml<br>```<br>");
|
||||
FileUtil.lines(configFile, Charset.forName("UTF-8"))
|
||||
.stream().filter(line -> !line.toLowerCase().contains("pass") && !line.toLowerCase().contains("secret"))
|
||||
.forEach(line -> content.append(line).append("<br>"));
|
||||
content.append("```</pre>");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendBenchmarks(StringBuilder content) {
|
||||
content.append("<pre>### Benchmarks<br>```<br>");
|
||||
try {
|
||||
for (String line : Benchmark.getAverages().asStringArray()) {
|
||||
content.append(line).append("<br>");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
content.append("Exception on Benchmark.getAverages().asStringArray()");
|
||||
}
|
||||
content.append("```</pre>");
|
||||
}
|
||||
|
||||
private void appendLoggedErrors(StringBuilder content) {
|
||||
try {
|
||||
content.append("<pre>### Logged Errors<br>");
|
||||
|
||||
SortedMap<String, List<String>> errors = ErrorLogger.getLoggedErrors(PlanPlugin.getInstance());
|
||||
|
||||
if (!errors.isEmpty()) {
|
||||
List<String> errorLines = new ArrayList<>();
|
||||
for (Map.Entry<String, List<String>> entry : errors.entrySet()) {
|
||||
StringBuilder errorLineBuilder = new StringBuilder();
|
||||
for (String line : entry.getValue()) {
|
||||
errorLineBuilder.append(line).append("<br>");
|
||||
}
|
||||
String error = errorLineBuilder.toString();
|
||||
if (!errorLines.contains(error)) {
|
||||
errorLines.add(error);
|
||||
}
|
||||
}
|
||||
for (String error : errorLines) {
|
||||
content.append("</pre><pre>```<br>")
|
||||
.append(error)
|
||||
.append("```");
|
||||
}
|
||||
} else {
|
||||
content.append("**No Errors logged.**<br>");
|
||||
}
|
||||
content.append("</pre>");
|
||||
} catch (IOException e) {
|
||||
Log.toLog(this.getClass(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendDebugLog(StringBuilder content) {
|
||||
content.append("<pre>### Debug Log<br>```<br>");
|
||||
for (String line : Log.getDebugLogInMemory()) {
|
||||
content.append(line).append("<br>");
|
||||
}
|
||||
content.append("```</pre>");
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.pages.parsing;
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.data.container.Session;
|
@ -2,13 +2,15 @@
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.pages.parsing;
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
import com.djrapitops.plan.data.store.containers.NetworkContainer;
|
||||
import com.djrapitops.plan.data.store.keys.NetworkKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.PlaceholderReplacer;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.info.server.ServerInfo;
|
||||
import com.djrapitops.plan.system.webserver.cache.PageId;
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.pages.parts.NetworkPageContent;
|
||||
import com.djrapitops.plan.utilities.file.FileUtil;
|
||||
|
||||
@ -30,6 +32,8 @@ public class NetworkPage implements Page {
|
||||
@Override
|
||||
public String toHtml() throws ParseException {
|
||||
try {
|
||||
networkContainer.putSupplier(NetworkKeys.PLAYERS_ONLINE, ServerInfo.getServerProperties()::getOnlinePlayers);
|
||||
|
||||
PlaceholderReplacer placeholderReplacer = new PlaceholderReplacer();
|
||||
placeholderReplacer.addAllPlaceholdersFrom(networkContainer,
|
||||
VERSION, NETWORK_NAME, TIME_ZONE,
|
@ -2,7 +2,7 @@
|
||||
* License is provided in the jar as LICENSE also here:
|
||||
* https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE
|
||||
*/
|
||||
package com.djrapitops.plan.system.webserver.pages.parsing;
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.djrapitops.plan.system.webserver.pages.parsing;
|
||||
package com.djrapitops.plan.utilities.html.pages;
|
||||
|
||||
import com.djrapitops.plan.PlanPlugin;
|
||||
import com.djrapitops.plan.api.exceptions.ParseException;
|
@ -10,7 +10,6 @@ import com.djrapitops.plan.data.time.WorldTimes;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.system.settings.theme.Theme;
|
||||
import com.djrapitops.plan.system.settings.theme.ThemeVal;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
|
||||
import com.djrapitops.plan.utilities.html.HtmlStructure;
|
||||
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
|
||||
@ -98,6 +97,7 @@ public class SessionAccordion extends AbstractAccordion {
|
||||
|
||||
WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
|
||||
WorldPie worldPie = new WorldPie(worldTimes);
|
||||
String longestWorldPlayed = session.getValue(SessionKeys.LONGEST_WORLD_PLAYED).orElse("Unknown");
|
||||
|
||||
boolean hasEnded = session.supports(SessionKeys.END);
|
||||
String sessionEnd = hasEnded ? timeStampFormatter.apply(() -> session.getUnsafe(SessionKeys.END)) : "Online";
|
||||
@ -110,7 +110,7 @@ public class SessionAccordion extends AbstractAccordion {
|
||||
int deaths = session.getValue(SessionKeys.DEATH_COUNT).orElse(0);
|
||||
|
||||
String info = appendWorldPercentage
|
||||
? HtmlStructure.separateWithDots(sessionStart, AnalysisUtils.getLongestWorldPlayed(session))
|
||||
? HtmlStructure.separateWithDots(sessionStart, longestWorldPlayed)
|
||||
: sessionStart;
|
||||
String title = HtmlStructure.separateWithDots(playerName, info) + "<span class=\"pull-right\">" + length + "</span>";
|
||||
String htmlID = "" + session.getValue(SessionKeys.START).orElse(0L) + i;
|
||||
@ -170,6 +170,7 @@ public class SessionAccordion extends AbstractAccordion {
|
||||
|
||||
WorldTimes worldTimes = session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
|
||||
WorldPie worldPie = new WorldPie(worldTimes);
|
||||
String longestWorldPlayed = session.getValue(SessionKeys.LONGEST_WORLD_PLAYED).orElse("Unknown");
|
||||
|
||||
boolean hasEnded = session.supports(SessionKeys.END);
|
||||
String sessionEnd = hasEnded ? timeStampFormatter.apply(() -> session.getValue(SessionKeys.END).orElse(0L)) : "Online";
|
||||
@ -182,7 +183,7 @@ public class SessionAccordion extends AbstractAccordion {
|
||||
int deaths = session.getValue(SessionKeys.DEATH_COUNT).orElse(0);
|
||||
|
||||
String info = appendWorldPercentage
|
||||
? HtmlStructure.separateWithDots(sessionStart, AnalysisUtils.getLongestWorldPlayed(session))
|
||||
? HtmlStructure.separateWithDots(sessionStart, longestWorldPlayed)
|
||||
: sessionStart;
|
||||
String title = HtmlStructure.separateWithDots(serverName, info) + "<span class=\"pull-right\">" + length + "</span>";
|
||||
String htmlID = "" + session.getValue(SessionKeys.START).orElse(0L) + i;
|
||||
|
@ -8,7 +8,6 @@ import com.djrapitops.plan.data.store.keys.PlayerKeys;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -57,7 +56,7 @@ public class PlayerSessionTable extends TableContainer {
|
||||
String length = session.supports(SessionKeys.END)
|
||||
? Formatters.timeAmount().apply(session.getValue(SessionKeys.LENGTH).orElse(0L))
|
||||
: "Online";
|
||||
String world = AnalysisUtils.getLongestWorldPlayed(session);
|
||||
String world = session.getValue(SessionKeys.LONGEST_WORLD_PLAYED).orElse("Unknown");
|
||||
|
||||
String toolTip = "Session ID: " + session.getValue(SessionKeys.DB_ID)
|
||||
.map(id -> Integer.toString(id))
|
||||
|
@ -6,7 +6,6 @@ import com.djrapitops.plan.data.element.TableContainer;
|
||||
import com.djrapitops.plan.data.store.keys.SessionKeys;
|
||||
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
|
||||
import com.djrapitops.plan.system.settings.Settings;
|
||||
import com.djrapitops.plan.utilities.analysis.AnalysisUtils;
|
||||
import com.djrapitops.plan.utilities.html.Html;
|
||||
|
||||
import java.util.List;
|
||||
@ -47,7 +46,7 @@ public class ServerSessionTable extends TableContainer {
|
||||
String length = session.supports(SessionKeys.END)
|
||||
? Formatters.timeAmount().apply(session.getValue(SessionKeys.LENGTH).orElse(0L))
|
||||
: "Online";
|
||||
String world = AnalysisUtils.getLongestWorldPlayed(session);
|
||||
String world = session.getValue(SessionKeys.LONGEST_WORLD_PLAYED).orElse("Unknown");
|
||||
|
||||
String toolTip = "Session ID: " + session.getValue(SessionKeys.DB_ID)
|
||||
.map(id -> Integer.toString(id))
|
||||
|
@ -58,9 +58,7 @@ public class UUIDUtility {
|
||||
try {
|
||||
uuid = db.fetch().getUuidOf(playerName);
|
||||
} catch (DBOpException e) {
|
||||
if (e.isFatal()) {
|
||||
Log.toLog(UUIDUtility.class, e);
|
||||
}
|
||||
Log.toLog(UUIDUtility.class, e);
|
||||
}
|
||||
try {
|
||||
if (uuid == null) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
package com.djrapitops.plan.data.cache;
|
||||
|
||||
import com.djrapitops.plan.system.webserver.cache.ResponseCache;
|
||||
import com.djrapitops.plan.system.webserver.response.Response;
|
||||
import com.djrapitops.plan.system.webserver.response.cache.ResponseCache;
|
||||
import org.junit.Test;
|
||||
import utilities.RandomData;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user