Server ExtensionData visualization

This commit is contained in:
Rsl1122 2019-03-30 12:16:57 +02:00
parent 09f7801934
commit 2ad5f979f6
5 changed files with 176 additions and 6 deletions

View File

@ -37,6 +37,7 @@ import com.djrapitops.plan.utilities.html.graphs.bar.BarGraph;
import com.djrapitops.plan.utilities.html.graphs.line.PingGraph;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plan.utilities.html.graphs.stack.StackGraph;
import com.djrapitops.plan.utilities.html.pages.AnalysisPluginTabs;
import com.djrapitops.plan.utilities.html.structure.Accordions;
import com.djrapitops.plan.utilities.html.structure.AnalysisPluginsTabContentCreator;
import com.djrapitops.plan.utilities.html.structure.RecentLoginList;
@ -488,13 +489,14 @@ public class AnalysisContainer extends DynamicDataContainer {
private void addPluginSuppliers() {
// TODO Refactor into a system that supports running the analysis on Bungee
Key<String[]> navAndTabs = new Key<>(new Type<String[]>() {
}, "NAV_AND_TABS");
Key<String[]> navAndTabs = new Key<>(new Type<String[]>() {}, "NAV_AND_TABS");
Key<AnalysisPluginTabs> pluginTabs = new Key<>(AnalysisPluginTabs.class, "PLUGIN_TABS");
putCachingSupplier(navAndTabs, () -> pluginsTabContentCreator.createContent(
this, getValue(AnalysisKeys.PLAYERS_MUTATOR).orElse(new PlayersMutator(new ArrayList<>()))
));
putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(navAndTabs)[0]);
putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(navAndTabs)[1]);
putCachingSupplier(pluginTabs, () -> new AnalysisPluginTabs(serverContainer.getValue(ServerKeys.EXTENSION_DATA).orElse(new ArrayList<>()), formatters));
putSupplier(AnalysisKeys.PLUGINS_TAB_NAV, () -> getUnsafe(pluginTabs).getNav() + getUnsafe(navAndTabs)[0]);
putSupplier(AnalysisKeys.PLUGINS_TAB, () -> getUnsafe(pluginTabs).getTabs() + getUnsafe(navAndTabs)[1]);
}
@Singleton

View File

@ -25,6 +25,7 @@ import com.djrapitops.plan.data.store.Type;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.objects.DateObj;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.extension.implementation.results.server.ExtensionServerData;
import java.util.List;
import java.util.Map;
@ -63,4 +64,5 @@ public class ServerKeys {
public static final Key<DateObj<Integer>> ALL_TIME_PEAK_PLAYERS = new Key<>(new Type<DateObj<Integer>>() {}, "all_time_peak_players");
public static final Key<DateObj<Integer>> RECENT_PEAK_PLAYERS = new Key<>(new Type<DateObj<Integer>>() {}, "recent_peak_players");
public static final Key<Map<String, Integer>> COMMAND_USAGE = new Key<>(new Type<Map<String, Integer>>() {}, "command_usage");
public static final Key<List<ExtensionServerData>> EXTENSION_DATA = new Key<>(new Type<List<ExtensionServerData>>() {}, "extension_data");
}

View File

@ -27,6 +27,7 @@ import com.djrapitops.plan.db.access.queries.ServerAggregateQueries;
import com.djrapitops.plan.db.access.queries.objects.ServerQueries;
import com.djrapitops.plan.db.access.queries.objects.TPSQueries;
import com.djrapitops.plan.db.access.queries.objects.WorldTimesQueries;
import com.djrapitops.plan.extension.implementation.storage.queries.ExtensionServerDataQuery;
import com.djrapitops.plan.system.cache.SessionCache;
import com.djrapitops.plan.system.info.server.Server;
@ -94,6 +95,8 @@ public class ServerContainerQuery implements Query<ServerContainer> {
container.putCachingSupplier(ServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
container.putCachingSupplier(ServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
container.putCachingSupplier(ServerKeys.EXTENSION_DATA, () -> db.query(new ExtensionServerDataQuery(serverUUID)));
return container;
}
}

View File

@ -0,0 +1,163 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.utilities.html.pages;
import com.djrapitops.plan.extension.FormatType;
import com.djrapitops.plan.extension.implementation.TabInformation;
import com.djrapitops.plan.extension.implementation.results.ExtensionDescriptive;
import com.djrapitops.plan.extension.implementation.results.ExtensionInformation;
import com.djrapitops.plan.extension.implementation.results.ExtensionTabData;
import com.djrapitops.plan.extension.implementation.results.server.ExtensionServerData;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.formatting.Formatters;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.icon.Icon;
import com.djrapitops.plan.utilities.html.structure.TabsElement;
import java.util.*;
/**
* Responsible for generating /server page plugin tabs based on DataExtension API data.
* <p>
* Currently very similar to {@link InspectPluginTab}.
* This will become more complex once tables are added, since some big tables will be moved to their own tabs.
*
* @author Rsl1122
*/
public class AnalysisPluginTabs {
private List<ExtensionServerData> serverData;
private Map<FormatType, Formatter<Long>> numberFormatters;
private Formatter<Double> decimalFormatter;
private Formatter<Double> percentageFormatter;
private String nav;
private String tab;
public AnalysisPluginTabs(String nav, String tab) {
this.nav = nav;
this.tab = tab;
}
public AnalysisPluginTabs(
List<ExtensionServerData> serverData,
Formatters formatters
) {
this.serverData = serverData;
numberFormatters = new EnumMap<>(FormatType.class);
numberFormatters.put(FormatType.DATE_SECOND, formatters.secondLong());
numberFormatters.put(FormatType.DATE_YEAR, formatters.yearLong());
numberFormatters.put(FormatType.TIME_MILLISECONDS, formatters.timeAmount());
numberFormatters.put(FormatType.NONE, Object::toString);
this.decimalFormatter = formatters.decimals();
this.percentageFormatter = formatters.percentage();
generate();
}
public String getNav() {
return nav;
}
public String getTabs() {
return tab;
}
private void generate() {
if (serverData.isEmpty()) {
nav = "<li><a class=\"nav-button\" href=\"javascript:void(0)\">Extensions (No Data)</a></li>";
tab = "<div class=\"tab\"><div class=\"row clearfix\">" +
"<div class=\"col-md-12\">" + Html.CARD.parse("<p>No Extension Data</p>") +
"</div></div></div>";
} else {
nav = "<li><a class=\"nav-button\" href=\"javascript:void(0)\">General</a></li>";
tab = generatePageTab();
}
}
private String generatePageTab() {
Collections.sort(serverData);
StringBuilder tabBuilder = new StringBuilder();
for (ExtensionServerData datum : serverData) {
ExtensionInformation extensionInformation = datum.getExtensionInformation();
boolean onlyGeneric = datum.hasOnlyGenericTab();
String tabsElement;
if (onlyGeneric) {
ExtensionTabData genericTabData = datum.getTabs().get(0);
tabsElement = Html.BODY.parse(parseDataHtml(genericTabData));
} else {
tabsElement = new TabsElement(
datum.getTabs().stream().map(this::wrapToTabElementTab).toArray(TabsElement.Tab[]::new)
).toHtmlFull();
}
tabBuilder.append(wrapInContainer(extensionInformation, tabsElement));
}
return wrapInTab(tabBuilder.toString());
}
private String wrapInTab(String content) {
return "<div class=\"tab\"><div class=\"row clearfix\">" + content + "</div></div>";
}
private TabsElement.Tab wrapToTabElementTab(ExtensionTabData tabData) {
TabInformation tabInformation = tabData.getTabInformation();
return new TabsElement.Tab(tabInformation.getTabName(), parseDataHtml(tabData));
}
private String parseDataHtml(ExtensionTabData tabData) {
StringBuilder builder = new StringBuilder();
for (String key : tabData.getValueOrder()) {
tabData.getBoolean(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue()));
tabData.getDouble(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue(decimalFormatter)));
tabData.getPercentage(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue(percentageFormatter)));
tabData.getNumber(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue(numberFormatters.get(data.getFormatType()))));
tabData.getString(key).ifPresent(data -> append(builder, data.getDescriptive(), data.getFormattedValue()));
}
return builder.toString();
}
private void append(StringBuilder builder, ExtensionDescriptive descriptive, String formattedValue) {
Optional<String> description = descriptive.getDescription();
if (description.isPresent()) {
builder.append("<p title=\"").append(description.get()).append("\">");
} else {
builder.append("<p>");
}
builder.append(Icon.fromExtensionIcon(descriptive.getIcon()))
.append(' ').append(descriptive.getText()).append(": ").append(formattedValue).append("</p>");
}
private String wrapInContainer(ExtensionInformation information, String tabsElement) {
return "<div class=\"col-xs-12 col-sm-12 col-md-4 col-lg-4\"><div class=\"card\">" +
"<div class=\"header\">" +
"<h2>" + Icon.fromExtensionIcon(information.getIcon()) + ' ' + information.getPluginName() + "</h2>" +
"</div>" +
tabsElement +
"</div></div>";
}
}

View File

@ -68,7 +68,7 @@ public class AnalysisPluginsTabContentCreator {
) {
if (mutator.all().isEmpty()) {
return new String[]{"<li><a>No Data</a></li>", ""};
return new String[]{"", ""};
}
List<UUID> uuids = mutator.uuids();
@ -125,7 +125,7 @@ public class AnalysisPluginsTabContentCreator {
"</div></div>";
return new String[]{
(displayGeneralTab ? "<li><a class=\"nav-button\" href=\"javascript:void(0)\">General</a></li>" : "")
(displayGeneralTab ? "<li><a class=\"nav-button\" href=\"javascript:void(0)\">General (Legacy)</a></li>" : "")
+ "<li><a class=\"nav-button\" href=\"javascript:void(0)\">Player Data</a></li>" + nav.toString(),
(displayGeneralTab ? generalTab.toString() : "") + playerListTab + otherTabs.toString()
};