mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-03-07 17:28:03 +08:00
Added a player table as a result to the query
Rewrote PlayersTableJSONCreator to not use String format anymore
This commit is contained in:
parent
80e5d797b5
commit
5c102458ae
@ -41,6 +41,8 @@ import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.*;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
|
||||
import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@ -80,7 +82,7 @@ public class JSONFactory {
|
||||
this.formatters = formatters;
|
||||
}
|
||||
|
||||
public String serverPlayersTableJSON(UUID serverUUID) {
|
||||
public Map<String, Object> serverPlayersTableJSON(UUID serverUUID) {
|
||||
Integer xMostRecentPlayers = config.get(DisplaySettings.PLAYERS_PER_SERVER_PAGE);
|
||||
Long playtimeThreshold = config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD);
|
||||
boolean openPlayerLinksInNewTab = config.isTrue(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB);
|
||||
@ -92,10 +94,10 @@ public class JSONFactory {
|
||||
database.query(new ExtensionServerPlayerDataTableQuery(serverUUID, xMostRecentPlayers)),
|
||||
openPlayerLinksInNewTab,
|
||||
formatters, locale
|
||||
).toJSONString();
|
||||
).toJSONMap();
|
||||
}
|
||||
|
||||
public String networkPlayersTableJSON() {
|
||||
public Map<String, Object> networkPlayersTableJSON() {
|
||||
Integer xMostRecentPlayers = config.get(DisplaySettings.PLAYERS_PER_PLAYERS_PAGE);
|
||||
Long playtimeThreshold = config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD);
|
||||
boolean openPlayerLinksInNewTab = config.isTrue(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB);
|
||||
@ -110,7 +112,7 @@ public class JSONFactory {
|
||||
pluginData,
|
||||
openPlayerLinksInNewTab,
|
||||
formatters, locale
|
||||
).toJSONString();
|
||||
).toJSONMap();
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> serverSessionsAsJSONMap(UUID serverUUID) {
|
||||
|
@ -28,6 +28,7 @@ import com.djrapitops.plan.extension.icon.Color;
|
||||
import com.djrapitops.plan.extension.implementation.results.*;
|
||||
import com.djrapitops.plan.settings.locale.Locale;
|
||||
import com.djrapitops.plan.settings.locale.lang.HtmlLang;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
@ -94,38 +95,32 @@ public class PlayersTableJSONCreator {
|
||||
}
|
||||
}
|
||||
|
||||
public String toJSONString() {
|
||||
String data = createData();
|
||||
String columnHeaders = createColumnHeaders();
|
||||
return "{\"columns\":" + columnHeaders + ",\"data\":" + data + '}';
|
||||
public Map<String, Object> toJSONMap() {
|
||||
return Maps.builder(String.class, Object.class)
|
||||
.put("columns", createColumnHeaders())
|
||||
.put("data", createData())
|
||||
.build();
|
||||
}
|
||||
|
||||
private String createData() {
|
||||
StringBuilder dataJSON = new StringBuilder("[");
|
||||
private List<Map<String, Object>> createData() {
|
||||
List<Map<String, Object>> dataJson = new ArrayList<>();
|
||||
|
||||
int currentPlayerNumber = 0;
|
||||
ExtensionTabData emptyExtensionData = new ExtensionTabData.Builder(null).build();
|
||||
for (TablePlayer player : players) {
|
||||
UUID playerUUID = player.getPlayerUUID();
|
||||
if (playerUUID == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (currentPlayerNumber > 0) {
|
||||
dataJSON.append(','); // Previous item
|
||||
}
|
||||
dataJSON.append('{'); // Start new item
|
||||
|
||||
appendPlayerData(dataJSON, player);
|
||||
appendExtensionData(dataJSON, extensionData.getOrDefault(playerUUID, new ExtensionTabData.Builder(null).build()));
|
||||
|
||||
dataJSON.append('}'); // Close new item
|
||||
|
||||
currentPlayerNumber++;
|
||||
Map<String, Object> playerEntry = new HashMap<>();
|
||||
addPlayerData(playerEntry, player);
|
||||
addExtensionData(playerEntry, extensionData.getOrDefault(playerUUID, emptyExtensionData));
|
||||
dataJson.add(playerEntry);
|
||||
}
|
||||
return dataJSON.append(']').toString();
|
||||
return dataJson;
|
||||
}
|
||||
|
||||
private void appendPlayerData(StringBuilder dataJSON, TablePlayer player) {
|
||||
private void addPlayerData(Map<String, Object> dataJson, TablePlayer player) {
|
||||
String name = player.getName().orElse(player.getPlayerUUID().toString());
|
||||
String url = "../player/" + Html.encodeToURL(name);
|
||||
|
||||
@ -143,33 +138,35 @@ public class PlayersTableJSONCreator {
|
||||
|
||||
Html link = openPlayerPageInNewTab ? Html.LINK_EXTERNAL : Html.LINK;
|
||||
|
||||
dataJSON.append(makeDataEntry(link.create(url, StringUtils.replace(StringEscapeUtils.escapeHtml4(name), "\\", "\\\\")), "name")).append(',') // Backslashes escaped to prevent json errors
|
||||
.append(makeDataEntry(activityIndex.getValue(), activityString, "index")).append(',')
|
||||
.append(makeDataEntry(playtime, numberFormatters.get(FormatType.TIME_MILLISECONDS).apply(playtime), "playtime")).append(',')
|
||||
.append(makeDataEntry(loginTimes, "sessions")).append(',')
|
||||
.append(makeDataEntry(registered, numberFormatters.get(FormatType.DATE_YEAR).apply(registered), "registered")).append(',')
|
||||
.append(makeDataEntry(lastSeen, numberFormatters.get(FormatType.DATE_YEAR).apply(lastSeen), "seen")).append(',')
|
||||
.append(makeDataEntry(geolocation, "geolocation"));
|
||||
putDataEntry(dataJson, link.create(url, StringUtils.replace(StringEscapeUtils.escapeHtml4(name), "\\", "\\\\") /* Backslashes escaped to prevent json errors */), "name");
|
||||
putDataEntry(dataJson, activityIndex.getValue(), activityString, "index");
|
||||
putDataEntry(dataJson, playtime, numberFormatters.get(FormatType.TIME_MILLISECONDS).apply(playtime), "playtime");
|
||||
putDataEntry(dataJson, loginTimes, "sessions");
|
||||
putDataEntry(dataJson, registered, numberFormatters.get(FormatType.DATE_YEAR).apply(registered), "registered");
|
||||
putDataEntry(dataJson, lastSeen, numberFormatters.get(FormatType.DATE_YEAR).apply(lastSeen), "seen");
|
||||
putDataEntry(dataJson, geolocation, "geolocation");
|
||||
}
|
||||
|
||||
private String makeDataEntry(Object data, String dataName) {
|
||||
return "\"" + dataName + "\":\"" + StringEscapeUtils.escapeJson(data.toString()) + "\"";
|
||||
private void putDataEntry(Map<String, Object> dataJson, Object data, String dataName) {
|
||||
dataJson.put(dataName, data.toString());
|
||||
}
|
||||
|
||||
private String makeDataEntry(Object data, String formatted, String dataName) {
|
||||
return "\"" + dataName + "\":{\"v\":\"" + StringEscapeUtils.escapeJson(data.toString()) + "\", \"d\":\"" + StringEscapeUtils.escapeJson(formatted) + "\"}";
|
||||
private void putDataEntry(Map<String, Object> dataJson, Object data, String formatted, String dataName) {
|
||||
dataJson.put(dataName, Maps.builder(String.class, Object.class)
|
||||
.put("v", data.toString())
|
||||
.put("d", formatted)
|
||||
.build());
|
||||
}
|
||||
|
||||
private void appendExtensionData(StringBuilder dataJSON, ExtensionTabData tabData) {
|
||||
private void addExtensionData(Map<String, Object> dataJson, ExtensionTabData tabData) {
|
||||
for (ExtensionDescriptive descriptive : extensionDescriptives) {
|
||||
dataJSON.append(',');
|
||||
String key = descriptive.getName();
|
||||
|
||||
// If it's a double, append a double
|
||||
Optional<ExtensionDoubleData> doubleValue = tabData.getDouble(key);
|
||||
|
||||
if (doubleValue.isPresent()) {
|
||||
dataJSON.append(makeDataEntry(doubleValue.get().getRawValue(), doubleValue.get().getFormattedValue(decimalFormatter), key));
|
||||
putDataEntry(dataJson, doubleValue.get().getRawValue(), doubleValue.get().getFormattedValue(decimalFormatter), key);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -177,48 +174,53 @@ public class PlayersTableJSONCreator {
|
||||
if (numberValue.isPresent()) {
|
||||
ExtensionNumberData numberData = numberValue.get();
|
||||
FormatType formatType = numberData.getFormatType();
|
||||
dataJSON.append(makeDataEntry(numberData.getRawValue(), numberData.getFormattedValue(numberFormatters.get(formatType)), key));
|
||||
putDataEntry(dataJson, numberData.getRawValue(), numberData.getFormattedValue(numberFormatters.get(formatType)), key);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If it's a String append a String, otherwise the player has no value for this extension provider.
|
||||
// If it's a String add a String, otherwise the player has no value for this extension provider.
|
||||
String stringValue = tabData.getString(key).map(ExtensionStringData::getFormattedValue).orElse("-");
|
||||
dataJSON.append(makeDataEntry(stringValue, stringValue, key));
|
||||
putDataEntry(dataJson, stringValue, stringValue, key);
|
||||
}
|
||||
}
|
||||
|
||||
private String createColumnHeaders() {
|
||||
StringBuilder columnHeaders = new StringBuilder("[");
|
||||
private List<Map<String, Object>> createColumnHeaders() {
|
||||
List<Map<String, Object>> columnHeaders = new ArrayList<>();
|
||||
|
||||
// Is the data for the column formatted
|
||||
columnHeaders.add(makeColumnHeader(Icon.called("user") + " " + locale.get(HtmlLang.LABEL_NAME), "name"));
|
||||
columnHeaders.add(makeFColumnHeader(Icon.called("check") + " " + locale.get(HtmlLang.LABEL_ACTIVITY_INDEX), "index"));
|
||||
columnHeaders.add(makeFColumnHeader(Icon.called("clock").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_PLAYTIME), "playtime"));
|
||||
columnHeaders.add(makeColumnHeader(Icon.called("calendar-plus").of(Family.REGULAR) + " " + locale.get(HtmlLang.SIDE_SESSIONS), "sessions"));
|
||||
columnHeaders.add(makeFColumnHeader(Icon.called("user-plus") + " " + locale.get(HtmlLang.LABEL_REGISTERED), "registered"));
|
||||
columnHeaders.add(makeFColumnHeader(Icon.called("calendar-check").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_LAST_SEEN), "seen"));
|
||||
columnHeaders.add(makeColumnHeader(Icon.called("globe") + " " + locale.get(HtmlLang.TITLE_COUNTRY), "geolocation"));
|
||||
|
||||
columnHeaders
|
||||
.append(makeColumnHeader(Icon.called("user") + " " + locale.get(HtmlLang.LABEL_NAME), "name")).append(',')
|
||||
.append(makeFColumnHeader(Icon.called("check") + " " + locale.get(HtmlLang.LABEL_ACTIVITY_INDEX), "index")).append(',')
|
||||
.append(makeFColumnHeader(Icon.called("clock").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_PLAYTIME), "playtime")).append(',')
|
||||
.append(makeColumnHeader(Icon.called("calendar-plus").of(Family.REGULAR) + " " + locale.get(HtmlLang.SIDE_SESSIONS), "sessions")).append(',')
|
||||
.append(makeFColumnHeader(Icon.called("user-plus") + " " + locale.get(HtmlLang.LABEL_REGISTERED), "registered")).append(',')
|
||||
.append(makeFColumnHeader(Icon.called("calendar-check").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_LAST_SEEN), "seen")).append(',')
|
||||
.append(makeColumnHeader(Icon.called("globe") + " " + locale.get(HtmlLang.TITLE_COUNTRY), "geolocation"));
|
||||
addExtensionHeaders(columnHeaders);
|
||||
|
||||
appendExtensionHeaders(columnHeaders);
|
||||
|
||||
return columnHeaders.append(']').toString();
|
||||
return columnHeaders;
|
||||
}
|
||||
|
||||
private String makeColumnHeader(String title, String dataProperty) {
|
||||
return "{\"title\": \"" + StringEscapeUtils.escapeJson(title) + "\",\"data\":\"" + dataProperty + "\"}";
|
||||
private Map<String, Object> makeColumnHeader(String title, String dataProperty) {
|
||||
return Maps.builder(String.class, Object.class)
|
||||
.put("title", title)
|
||||
.put("data", dataProperty)
|
||||
.build();
|
||||
}
|
||||
|
||||
private String makeFColumnHeader(String title, String dataProperty) {
|
||||
return "{\"title\": \"" + StringEscapeUtils.escapeJson(title) + "\",\"data\":{\"_\":\"" + dataProperty + ".v\",\"display\":\"" + dataProperty + ".d\"}}";
|
||||
private Map<String, Object> makeFColumnHeader(String title, String dataProperty) {
|
||||
return Maps.builder(String.class, Object.class)
|
||||
.put("title", title)
|
||||
.put("data", Maps.builder(String.class, String.class)
|
||||
.put("_", dataProperty + ".v")
|
||||
.put("display", dataProperty + ".d")
|
||||
.build()
|
||||
).build();
|
||||
}
|
||||
|
||||
private void appendExtensionHeaders(StringBuilder columnHeaders) {
|
||||
private void addExtensionHeaders(List<Map<String, Object>> columnHeaders) {
|
||||
for (ExtensionDescriptive provider : extensionDescriptives) {
|
||||
columnHeaders.append(',');
|
||||
String headerText = Icon.fromExtensionIcon(provider.getIcon().setColor(Color.NONE)).toHtml().replace('"', '\'') + ' ' + provider.getText();
|
||||
columnHeaders.append(makeFColumnHeader(headerText, provider.getName()));
|
||||
columnHeaders.add(makeFColumnHeader(headerText, provider.getName()));
|
||||
}
|
||||
}
|
||||
}
|
@ -16,34 +16,55 @@
|
||||
*/
|
||||
package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||
|
||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||
import com.djrapitops.plan.delivery.rendering.json.PlayersTableJSONCreator;
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.config.paths.DisplaySettings;
|
||||
import com.djrapitops.plan.settings.config.paths.TimeSettings;
|
||||
import com.djrapitops.plan.settings.locale.Locale;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.Filter;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.QueryFilters;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.QueryTablePlayersQuery;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
@Singleton
|
||||
public class QueryJSONResolver implements Resolver {
|
||||
|
||||
private final QueryFilters filters;
|
||||
|
||||
private final PlanConfig config;
|
||||
private final DBSystem dbSystem;
|
||||
private final Locale locale;
|
||||
private final Formatters formatters;
|
||||
|
||||
@Inject
|
||||
public QueryJSONResolver(
|
||||
QueryFilters filters
|
||||
QueryFilters filters,
|
||||
PlanConfig config,
|
||||
DBSystem dbSystem,
|
||||
Locale locale,
|
||||
Formatters formatters
|
||||
) {
|
||||
this.filters = filters;
|
||||
this.config = config;
|
||||
this.dbSystem = dbSystem;
|
||||
this.locale = locale;
|
||||
this.formatters = formatters;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -59,20 +80,37 @@ public class QueryJSONResolver implements Resolver {
|
||||
|
||||
private Response getResponse(Request request) {
|
||||
String q = request.getQuery().get("q").orElseThrow(() -> new BadRequestException("'q' parameter not set (expecting json array)"));
|
||||
String view = request.getQuery().get("view").orElseThrow(() -> new BadRequestException("'view' parameter not set (expecting json object {afterDate, afterTime, beforeDate, beforeTime})"));
|
||||
try {
|
||||
q = URLDecoder.decode(q, "UTF-8");
|
||||
List<FilterQuery> queries = FilterQuery.parse(q);
|
||||
Filter.Result result = filters.apply(queries);
|
||||
|
||||
Map<String, Object> json = Maps.builder(String.class, Object.class)
|
||||
.put("path", result.getResultPath())
|
||||
.build();
|
||||
if (!result.isEmpty()) {
|
||||
json.put("data", getDataFor(result.getResultUUIDs()));
|
||||
}
|
||||
return Response.builder()
|
||||
.setMimeType(MimeType.JSON)
|
||||
.setJSONContent(Maps.builder(String.class, Object.class)
|
||||
.put("path", result.getResultPath())
|
||||
.put("uuids", result.getResultUUIDs())
|
||||
.build())
|
||||
.setJSONContent(json)
|
||||
.build();
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new BadRequestException("Failed to parse json: '" + q + "'" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> getDataFor(Set<UUID> playerUUIDs) {
|
||||
Database database = dbSystem.getDatabase();
|
||||
return Maps.builder(String.class, Object.class)
|
||||
.put("players", new PlayersTableJSONCreator(
|
||||
database.query(new QueryTablePlayersQuery(playerUUIDs, System.currentTimeMillis(), config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD))),
|
||||
Collections.emptyMap(),
|
||||
config.get(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB),
|
||||
formatters, locale
|
||||
).toJSONMap())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@
|
||||
* 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.storage.database.queries.objects;
|
||||
package com.djrapitops.plan.storage.database.queries.objects.playertable;
|
||||
|
||||
import com.djrapitops.plan.delivery.domain.TablePlayer;
|
||||
import com.djrapitops.plan.delivery.domain.mutators.ActivityIndex;
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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.storage.database.queries.objects.playertable;
|
||||
|
||||
import com.djrapitops.plan.delivery.domain.TablePlayer;
|
||||
import com.djrapitops.plan.delivery.domain.mutators.ActivityIndex;
|
||||
import com.djrapitops.plan.storage.database.SQLDB;
|
||||
import com.djrapitops.plan.storage.database.queries.Query;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryStatement;
|
||||
import com.djrapitops.plan.storage.database.queries.analysis.NetworkActivityIndexQueries;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.GeoInfoTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
|
||||
import org.apache.commons.text.TextStringBuilder;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
|
||||
|
||||
/**
|
||||
* Query for displaying players on /query page players table.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class QueryTablePlayersQuery implements Query<List<TablePlayer>> {
|
||||
|
||||
private final Collection<UUID> playerUUIDs;
|
||||
private final long date;
|
||||
private final long activeMsThreshold;
|
||||
|
||||
/**
|
||||
* Create a new query.
|
||||
*
|
||||
* @param playerUUIDs UUIDs of the players in the query
|
||||
* @param date Date used for Activity Index calculation
|
||||
* @param activeMsThreshold Playtime threshold for Activity Index calculation
|
||||
*/
|
||||
public QueryTablePlayersQuery(Collection<UUID> playerUUIDs, long date, long activeMsThreshold) {
|
||||
this.playerUUIDs = playerUUIDs;
|
||||
this.date = date;
|
||||
this.activeMsThreshold = activeMsThreshold;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TablePlayer> executeQuery(SQLDB db) {
|
||||
String uuidsInSet = " IN ('" + new TextStringBuilder().appendWithSeparators(playerUUIDs, "','").build() + "')";
|
||||
|
||||
String selectGeolocations = SELECT + DISTINCT +
|
||||
GeoInfoTable.USER_UUID + ", " +
|
||||
GeoInfoTable.GEOLOCATION + ", " +
|
||||
GeoInfoTable.LAST_USED +
|
||||
FROM + GeoInfoTable.TABLE_NAME;
|
||||
String selectLatestGeolocationDate = SELECT +
|
||||
GeoInfoTable.USER_UUID + ", " +
|
||||
"MAX(" + GeoInfoTable.LAST_USED + ") as last_used_g" +
|
||||
FROM + GeoInfoTable.TABLE_NAME +
|
||||
GROUP_BY + GeoInfoTable.USER_UUID;
|
||||
String selectLatestGeolocations = SELECT +
|
||||
"g1." + GeoInfoTable.GEOLOCATION + ',' +
|
||||
"g1." + GeoInfoTable.USER_UUID +
|
||||
FROM + "(" + selectGeolocations + ") AS g1" +
|
||||
INNER_JOIN + "(" + selectLatestGeolocationDate + ") AS g2 ON g1.uuid = g2.uuid" +
|
||||
WHERE + GeoInfoTable.LAST_USED + "=last_used_g";
|
||||
|
||||
String selectSessionData = SELECT + "s." + SessionsTable.USER_UUID + ',' +
|
||||
"MAX(" + SessionsTable.SESSION_END + ") as last_seen," +
|
||||
"COUNT(1) as count," +
|
||||
"SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" +
|
||||
FROM + SessionsTable.TABLE_NAME + " s" +
|
||||
WHERE + "s." + SessionsTable.USER_UUID +
|
||||
uuidsInSet +
|
||||
GROUP_BY + "s." + SessionsTable.USER_UUID;
|
||||
|
||||
String selectBaseUsers = SELECT +
|
||||
"u." + UsersTable.USER_UUID + ',' +
|
||||
"u." + UsersTable.USER_NAME + ',' +
|
||||
"u." + UsersTable.REGISTERED + ',' +
|
||||
UserInfoTable.BANNED + ',' +
|
||||
"geoloc." + GeoInfoTable.GEOLOCATION + ',' +
|
||||
"ses.last_seen," +
|
||||
"ses.count," +
|
||||
"ses.playtime," +
|
||||
"act.activity_index" +
|
||||
FROM + UsersTable.TABLE_NAME + " u" +
|
||||
INNER_JOIN + UserInfoTable.TABLE_NAME + " on u." + UsersTable.USER_UUID + "=" + UserInfoTable.TABLE_NAME + '.' + UserInfoTable.USER_UUID +
|
||||
LEFT_JOIN + '(' + selectLatestGeolocations + ") geoloc on geoloc." + GeoInfoTable.USER_UUID + "=u." + UsersTable.USER_UUID +
|
||||
LEFT_JOIN + '(' + selectSessionData + ") ses on ses." + SessionsTable.USER_UUID + "=u." + UsersTable.USER_UUID +
|
||||
LEFT_JOIN + '(' + NetworkActivityIndexQueries.selectActivityIndexSQL() + ") act on u." + SessionsTable.USER_UUID + "=act." + UserInfoTable.USER_UUID +
|
||||
WHERE + "u." + UserInfoTable.USER_UUID +
|
||||
uuidsInSet +
|
||||
ORDER_BY + "ses.last_seen DESC";
|
||||
|
||||
return db.query(new QueryStatement<List<TablePlayer>>(selectBaseUsers, 1000) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
NetworkActivityIndexQueries.setSelectActivityIndexSQLParameters(statement, 1, activeMsThreshold, date);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TablePlayer> processResults(ResultSet set) throws SQLException {
|
||||
List<TablePlayer> players = new ArrayList<>();
|
||||
while (set.next()) {
|
||||
TablePlayer.Builder player = TablePlayer.builder()
|
||||
.uuid(UUID.fromString(set.getString(UsersTable.USER_UUID)))
|
||||
.name(set.getString(UsersTable.USER_NAME))
|
||||
.geolocation(set.getString(GeoInfoTable.GEOLOCATION))
|
||||
.registered(set.getLong(UsersTable.REGISTERED))
|
||||
.lastSeen(set.getLong("last_seen"))
|
||||
.sessionCount(set.getInt("count"))
|
||||
.playtime(set.getLong("playtime"))
|
||||
.activityIndex(new ActivityIndex(set.getDouble("activity_index"), date));
|
||||
if (set.getBoolean(UserInfoTable.BANNED)) {
|
||||
player.banned();
|
||||
}
|
||||
players.add(player.build());
|
||||
}
|
||||
return players;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
* 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.storage.database.queries.objects;
|
||||
package com.djrapitops.plan.storage.database.queries.objects.playertable;
|
||||
|
||||
import com.djrapitops.plan.delivery.domain.TablePlayer;
|
||||
import com.djrapitops.plan.delivery.domain.mutators.ActivityIndex;
|
@ -258,6 +258,10 @@ function setFilterOption(
|
||||
}
|
||||
|
||||
function performQuery() {
|
||||
const queryButton = document.querySelector('#query-button');
|
||||
queryButton.setAttribute('disabled', 'true');
|
||||
queryButton.classList.add('disabled');
|
||||
|
||||
const query = [];
|
||||
for (filter of filterQuery) {
|
||||
query.push(filter.toObject());
|
||||
@ -269,5 +273,33 @@ function performQuery() {
|
||||
console.log(filterQuery);
|
||||
if (json) console.log(json);
|
||||
if (error) console.error(error);
|
||||
|
||||
renderDataResultScreen();
|
||||
|
||||
$('.player-table').DataTable({
|
||||
responsive: true,
|
||||
columns: json.data.players.columns,
|
||||
data: json.data.players.data,
|
||||
order: [[5, "desc"]]
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function renderDataResultScreen() {
|
||||
document.querySelector('#content .tab').innerHTML +=
|
||||
`<div class="row">
|
||||
<div class="col-xs-12 col-sm-12 col-lg-11">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-body">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-striped table-hover player-table dataTable">
|
||||
<tr>
|
||||
<td>Loading..</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
@ -151,7 +151,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button class="mt-2 mb-2 btn col-plan" onclick="performQuery()"><i
|
||||
<button class="mt-2 mb-2 btn col-plan" id="query-button" onclick="performQuery()"><i
|
||||
class="fa fa-search"></i> Perform Query!
|
||||
</button>
|
||||
</div>
|
||||
@ -313,6 +313,10 @@
|
||||
<script src="./js/xmlhttprequests.js"></script>
|
||||
<script src="./js/color-selector.js"></script>
|
||||
|
||||
<!-- Page level plugins -->
|
||||
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
|
||||
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
|
||||
|
||||
<!-- Page level custom scripts -->
|
||||
<script src='./js/query.js'></script>
|
||||
|
||||
|
@ -32,6 +32,8 @@ import com.djrapitops.plan.storage.database.queries.*;
|
||||
import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.containers.ServerPlayerContainersQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.*;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.sql.building.Sql;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
|
||||
import com.djrapitops.plan.storage.database.transactions.StoreConfigTransaction;
|
||||
|
@ -23,9 +23,9 @@ import com.djrapitops.plan.delivery.domain.mutators.SessionsMutator;
|
||||
import com.djrapitops.plan.gathering.domain.Session;
|
||||
import com.djrapitops.plan.storage.database.DatabaseTestPreparer;
|
||||
import com.djrapitops.plan.storage.database.queries.analysis.ActivityIndexQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.NetworkTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.ServerTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.PlayerServerRegisterTransaction;
|
||||
|
@ -26,9 +26,9 @@ import com.djrapitops.plan.gathering.domain.WorldTimes;
|
||||
import com.djrapitops.plan.storage.database.DatabaseTestPreparer;
|
||||
import com.djrapitops.plan.storage.database.queries.containers.PlayerContainerQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.KillQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.ServerTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.WorldTimesQueries;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
|
||||
import com.djrapitops.plan.storage.database.transactions.Transaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythingTransaction;
|
||||
import com.djrapitops.plan.storage.database.transactions.events.PlayerServerRegisterTransaction;
|
||||
|
Loading…
Reference in New Issue
Block a user