mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-23 09:37:54 +01:00
Implemented a PluginBooleanGroupFilter (#2025)
Affects issues: - Close #1860
This commit is contained in:
parent
750428a033
commit
a2cface3e0
@ -53,4 +53,8 @@ public interface FiltersModule {
|
||||
@IntoSet
|
||||
Filter filter7(GeolocationsFilter filter);
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
Filter filter8(PluginBooleanGroupFilter filter);
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,248 @@
|
||||
/*
|
||||
* 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.filter.filters;
|
||||
|
||||
import com.djrapitops.plan.identification.Server;
|
||||
import com.djrapitops.plan.identification.ServerUUID;
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
import com.djrapitops.plan.storage.database.Database;
|
||||
import com.djrapitops.plan.storage.database.queries.Query;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryAllStatement;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryStatement;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.SpecifiedFilterInformation;
|
||||
import com.djrapitops.plan.storage.database.queries.objects.ServerQueries;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.ExtensionPlayerValueTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.ExtensionPluginTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.ExtensionProviderTable;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
|
||||
import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
|
||||
|
||||
@Singleton
|
||||
public class PluginBooleanGroupFilter extends MultiOptionFilter {
|
||||
|
||||
private final DBSystem dbSystem;
|
||||
|
||||
@Inject
|
||||
public PluginBooleanGroupFilter(DBSystem dbSystem) {
|
||||
this.dbSystem = dbSystem;
|
||||
}
|
||||
|
||||
private static Query<List<PluginBooleanOption>> pluginBooleanOptionsQuery() {
|
||||
String selectOptions = SELECT +
|
||||
"server." + ServerTable.SERVER_ID + " as server_id," +
|
||||
"server." + ServerTable.NAME + " as server_name," +
|
||||
"plugin." + ExtensionPluginTable.PLUGIN_NAME + " as plugin_name," +
|
||||
"provider." + ExtensionProviderTable.TEXT + " as provider_text" +
|
||||
FROM + ServerTable.TABLE_NAME + " server" +
|
||||
INNER_JOIN + ExtensionPluginTable.TABLE_NAME + " plugin on plugin." + ExtensionPluginTable.SERVER_UUID + "=server." + ServerTable.SERVER_UUID +
|
||||
INNER_JOIN + ExtensionProviderTable.TABLE_NAME + " provider on provider." + ExtensionProviderTable.PLUGIN_ID + "=plugin." + ExtensionPluginTable.ID +
|
||||
INNER_JOIN + ExtensionPlayerValueTable.TABLE_NAME + " value on value." + ExtensionPlayerValueTable.PROVIDER_ID + "=provider." + ExtensionProviderTable.ID +
|
||||
WHERE + "value." + ExtensionPlayerValueTable.BOOLEAN_VALUE + " IS NOT NULL" +
|
||||
ORDER_BY + "server_name ASC, plugin_name ASC, provider_text ASC";
|
||||
return new QueryAllStatement<List<PluginBooleanOption>>(selectOptions) {
|
||||
@Override
|
||||
public List<PluginBooleanOption> processResults(ResultSet set) throws SQLException {
|
||||
List<PluginBooleanOption> options = new ArrayList<>();
|
||||
while (set.next()) {
|
||||
int serverId = set.getInt("server_id");
|
||||
String serverName = set.getString("server_name");
|
||||
String pluginName = set.getString("plugin_name");
|
||||
String providerText = set.getString("provider_text");
|
||||
options.add(new PluginBooleanOption(
|
||||
Server.getIdentifiableName(serverName, serverId),
|
||||
pluginName,
|
||||
providerText
|
||||
));
|
||||
}
|
||||
Collections.sort(options);
|
||||
return options;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static Query<Set<UUID>> playersInGroups(
|
||||
Map<PluginBooleanOption, SelectedBoolean> selected,
|
||||
Map<String, ServerUUID> namesToUUIDs
|
||||
) {
|
||||
return db -> {
|
||||
Set<UUID> playerUUIDs = new HashSet<>();
|
||||
for (Map.Entry<PluginBooleanOption, SelectedBoolean> option : selected.entrySet()) {
|
||||
PluginBooleanOption pluginBooleanOption = option.getKey();
|
||||
SelectedBoolean selectedBoolean = option.getValue();
|
||||
playerUUIDs.addAll(
|
||||
db.query(playersInGroup(
|
||||
namesToUUIDs.get(pluginBooleanOption.getServerName()),
|
||||
pluginBooleanOption.getPluginName(),
|
||||
pluginBooleanOption.getProviderText(),
|
||||
selectedBoolean
|
||||
))
|
||||
);
|
||||
}
|
||||
return playerUUIDs;
|
||||
};
|
||||
}
|
||||
|
||||
private static Query<Set<UUID>> playersInGroup(
|
||||
ServerUUID serverUUID, String pluginName, String providerText, SelectedBoolean selectedBoolean
|
||||
) {
|
||||
String selectUUIDsWithBooleanValues = SELECT + DISTINCT + "value." + ExtensionPlayerValueTable.USER_UUID + " as uuid" +
|
||||
FROM + ExtensionPluginTable.TABLE_NAME + " plugin" +
|
||||
INNER_JOIN + ExtensionProviderTable.TABLE_NAME + " provider on provider." + ExtensionProviderTable.PLUGIN_ID + "=plugin." + ExtensionPluginTable.ID +
|
||||
INNER_JOIN + ExtensionPlayerValueTable.TABLE_NAME + " value on value." + ExtensionPlayerValueTable.PROVIDER_ID + "=provider." + ExtensionProviderTable.ID +
|
||||
WHERE + "plugin." + ExtensionPluginTable.SERVER_UUID + "=?" +
|
||||
AND + "plugin." + ExtensionPluginTable.PLUGIN_NAME + "=?" +
|
||||
AND + "provider." + ExtensionProviderTable.TEXT + "=?" +
|
||||
AND + "value." + ExtensionPlayerValueTable.BOOLEAN_VALUE + (selectedBoolean == SelectedBoolean.BOTH ? "IS NOT NULL" : "=?");
|
||||
|
||||
return new QueryStatement<Set<UUID>>(selectUUIDsWithBooleanValues) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
statement.setString(1, serverUUID.toString());
|
||||
statement.setString(2, pluginName);
|
||||
statement.setString(3, providerText);
|
||||
if (selectedBoolean != SelectedBoolean.BOTH) {
|
||||
statement.setBoolean(4, selectedBoolean == SelectedBoolean.TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> processResults(ResultSet set) throws SQLException {
|
||||
Set<UUID> uuids = new HashSet<>();
|
||||
while (set.next()) {
|
||||
uuids.add(UUID.fromString(set.getString("uuid")));
|
||||
}
|
||||
return uuids;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKind() {
|
||||
return "pluginsBooleanGroups";
|
||||
}
|
||||
|
||||
private List<String> getOptionList() {
|
||||
Database database = dbSystem.getDatabase();
|
||||
List<PluginBooleanOption> pluginBooleanOptions = database.query(pluginBooleanOptionsQuery());
|
||||
|
||||
List<String> options = new ArrayList<>();
|
||||
for (PluginBooleanOption pluginBooleanOption : pluginBooleanOptions) {
|
||||
String names = pluginBooleanOption.format();
|
||||
options.add(names + ": true");
|
||||
options.add(names + ": false");
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getOptions() {
|
||||
return Collections.singletonMap("options", getOptionList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getMatchingUUIDs(SpecifiedFilterInformation query) {
|
||||
Map<PluginBooleanOption, SelectedBoolean> selectedBooleanOptions = new HashMap<>();
|
||||
for (String selected : getSelected(query)) {
|
||||
String[] optionAndBoolean = StringUtils.split(selected, ":", 2);
|
||||
PluginBooleanOption pluginBooleanOption = PluginBooleanOption.parse(optionAndBoolean[0].trim());
|
||||
String selectedBoolean = optionAndBoolean[1].trim().toUpperCase();
|
||||
selectedBooleanOptions.computeIfPresent(pluginBooleanOption, (key, existing) -> SelectedBoolean.BOTH);
|
||||
selectedBooleanOptions.computeIfAbsent(pluginBooleanOption, key -> SelectedBoolean.valueOf(selectedBoolean));
|
||||
}
|
||||
|
||||
Database db = dbSystem.getDatabase();
|
||||
Map<String, ServerUUID> namesToUUIDs = db.query(ServerQueries.fetchServerNamesToUUIDs());
|
||||
return db.query(playersInGroups(selectedBooleanOptions, namesToUUIDs));
|
||||
}
|
||||
|
||||
public enum SelectedBoolean {
|
||||
TRUE,
|
||||
FALSE,
|
||||
BOTH
|
||||
}
|
||||
|
||||
private static class PluginBooleanOption implements Comparable<PluginBooleanOption> {
|
||||
private final String serverName;
|
||||
private final String pluginName;
|
||||
private final String providerText;
|
||||
|
||||
public PluginBooleanOption(String serverName, String pluginName, String providerText) {
|
||||
this.serverName = serverName;
|
||||
this.pluginName = pluginName;
|
||||
this.providerText = providerText;
|
||||
}
|
||||
|
||||
public static PluginBooleanOption parse(String fromFormatted) {
|
||||
String[] split1 = StringUtils.split(fromFormatted, ",", 2);
|
||||
String[] split2 = StringUtils.split(split1[1], "-", 2);
|
||||
String serverName = split1[0].trim();
|
||||
String pluginName = split2[0].trim();
|
||||
String providerName = split2[1].trim();
|
||||
return new PluginBooleanOption(serverName, pluginName, providerName);
|
||||
}
|
||||
|
||||
public String getServerName() {
|
||||
return serverName;
|
||||
}
|
||||
|
||||
public String getPluginName() {
|
||||
return pluginName;
|
||||
}
|
||||
|
||||
public String getProviderText() {
|
||||
return providerText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
PluginBooleanOption that = (PluginBooleanOption) o;
|
||||
return Objects.equals(getServerName(), that.getServerName()) && Objects.equals(getPluginName(), that.getPluginName()) && Objects.equals(getProviderText(), that.getProviderText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getServerName(), getPluginName(), getProviderText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PluginBooleanOption o) {
|
||||
int serverNameAlphabetical = String.CASE_INSENSITIVE_ORDER.compare(serverName, o.serverName);
|
||||
if (serverNameAlphabetical != 0) return serverNameAlphabetical;
|
||||
|
||||
int pluginNameAlphabetical = String.CASE_INSENSITIVE_ORDER.compare(pluginName, o.pluginName);
|
||||
if (pluginNameAlphabetical != 0) return pluginNameAlphabetical;
|
||||
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(providerText, o.providerText);
|
||||
}
|
||||
|
||||
public String format() {
|
||||
return serverName + ", " + pluginName + " - " + providerText;
|
||||
}
|
||||
}
|
||||
}
|
@ -23,6 +23,7 @@ import com.djrapitops.plan.storage.database.queries.QueryAllStatement;
|
||||
import com.djrapitops.plan.storage.database.queries.QueryStatement;
|
||||
import com.djrapitops.plan.storage.database.sql.building.Select;
|
||||
import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
@ -148,7 +149,7 @@ public class ServerQueries {
|
||||
|
||||
public static Query<Map<ServerUUID, String>> fetchServerNames() {
|
||||
String sql = Select.from(ServerTable.TABLE_NAME,
|
||||
ServerTable.SERVER_UUID, ServerTable.NAME)
|
||||
ServerTable.SERVER_ID, ServerTable.SERVER_UUID, ServerTable.NAME)
|
||||
.toString();
|
||||
|
||||
return new QueryAllStatement<Map<ServerUUID, String>>(sql) {
|
||||
@ -157,7 +158,7 @@ public class ServerQueries {
|
||||
Map<ServerUUID, String> names = new HashMap<>();
|
||||
while (set.next()) {
|
||||
ServerUUID serverUUID = ServerUUID.fromString(set.getString(ServerTable.SERVER_UUID));
|
||||
names.put(serverUUID, set.getString(ServerTable.NAME));
|
||||
names.put(serverUUID, Server.getIdentifiableName(set.getString(ServerTable.NAME), set.getInt(ServerTable.SERVER_ID)));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
@ -233,4 +234,8 @@ public class ServerQueries {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Query<Map<String, ServerUUID>> fetchServerNamesToUUIDs() {
|
||||
return db -> Maps.reverse(db.query(fetchServerNames()));
|
||||
}
|
||||
}
|
@ -44,6 +44,14 @@ public class Maps {
|
||||
return new Builder<>();
|
||||
}
|
||||
|
||||
public static <K, V> Map<V, K> reverse(Map<K, V> map) {
|
||||
Map<V, K> reversed = new HashMap<>();
|
||||
for (Map.Entry<K, V> entry : map.entrySet()) {
|
||||
reversed.put(entry.getValue(), entry.getKey());
|
||||
}
|
||||
return reversed;
|
||||
}
|
||||
|
||||
public static class Builder<K, V> {
|
||||
private final Map<K, V> map;
|
||||
|
||||
|
@ -102,6 +102,14 @@ class geolocationsFilter extends MultipleChoiceFilter {
|
||||
}
|
||||
}
|
||||
|
||||
class PluginBooleanGroupsFilter extends MultipleChoiceFilter {
|
||||
constructor(
|
||||
id, options
|
||||
) {
|
||||
super(id, "pluginsBooleanGroups", `have Plugin boolean value`, options);
|
||||
}
|
||||
}
|
||||
|
||||
class PluginGroupsFilter extends MultipleChoiceFilter {
|
||||
constructor(
|
||||
id, kind, options
|
||||
@ -220,6 +228,8 @@ function createFilter(filter, id) {
|
||||
return new PlayedBetweenFilter(id, filter.options);
|
||||
case "registeredBetween":
|
||||
return new RegisteredBetweenFilter(id, filter.options);
|
||||
case "pluginsBooleanGroups":
|
||||
return new PluginBooleanGroupsFilter(id, filter.options);
|
||||
default:
|
||||
throw new Error("Unsupported filter kind: '" + filter.kind + "'");
|
||||
}
|
||||
@ -246,6 +256,8 @@ function getReadableFilterName(filter) {
|
||||
return "Played between";
|
||||
case "registeredBetween":
|
||||
return "Registered between";
|
||||
case "pluginsBooleanGroups":
|
||||
return "Has plugin boolean value";
|
||||
default:
|
||||
return filter.kind;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user