mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2024-12-23 17:47:38 +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
|
@IntoSet
|
||||||
Filter filter7(GeolocationsFilter filter);
|
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.queries.QueryStatement;
|
||||||
import com.djrapitops.plan.storage.database.sql.building.Select;
|
import com.djrapitops.plan.storage.database.sql.building.Select;
|
||||||
import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
|
import com.djrapitops.plan.storage.database.sql.tables.ServerTable;
|
||||||
|
import com.djrapitops.plan.utilities.java.Maps;
|
||||||
import org.apache.commons.lang3.math.NumberUtils;
|
import org.apache.commons.lang3.math.NumberUtils;
|
||||||
|
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
@ -148,7 +149,7 @@ public class ServerQueries {
|
|||||||
|
|
||||||
public static Query<Map<ServerUUID, String>> fetchServerNames() {
|
public static Query<Map<ServerUUID, String>> fetchServerNames() {
|
||||||
String sql = Select.from(ServerTable.TABLE_NAME,
|
String sql = Select.from(ServerTable.TABLE_NAME,
|
||||||
ServerTable.SERVER_UUID, ServerTable.NAME)
|
ServerTable.SERVER_ID, ServerTable.SERVER_UUID, ServerTable.NAME)
|
||||||
.toString();
|
.toString();
|
||||||
|
|
||||||
return new QueryAllStatement<Map<ServerUUID, String>>(sql) {
|
return new QueryAllStatement<Map<ServerUUID, String>>(sql) {
|
||||||
@ -157,7 +158,7 @@ public class ServerQueries {
|
|||||||
Map<ServerUUID, String> names = new HashMap<>();
|
Map<ServerUUID, String> names = new HashMap<>();
|
||||||
while (set.next()) {
|
while (set.next()) {
|
||||||
ServerUUID serverUUID = ServerUUID.fromString(set.getString(ServerTable.SERVER_UUID));
|
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;
|
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<>();
|
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> {
|
public static class Builder<K, V> {
|
||||||
private final Map<K, V> map;
|
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 {
|
class PluginGroupsFilter extends MultipleChoiceFilter {
|
||||||
constructor(
|
constructor(
|
||||||
id, kind, options
|
id, kind, options
|
||||||
@ -220,6 +228,8 @@ function createFilter(filter, id) {
|
|||||||
return new PlayedBetweenFilter(id, filter.options);
|
return new PlayedBetweenFilter(id, filter.options);
|
||||||
case "registeredBetween":
|
case "registeredBetween":
|
||||||
return new RegisteredBetweenFilter(id, filter.options);
|
return new RegisteredBetweenFilter(id, filter.options);
|
||||||
|
case "pluginsBooleanGroups":
|
||||||
|
return new PluginBooleanGroupsFilter(id, filter.options);
|
||||||
default:
|
default:
|
||||||
throw new Error("Unsupported filter kind: '" + filter.kind + "'");
|
throw new Error("Unsupported filter kind: '" + filter.kind + "'");
|
||||||
}
|
}
|
||||||
@ -246,6 +256,8 @@ function getReadableFilterName(filter) {
|
|||||||
return "Played between";
|
return "Played between";
|
||||||
case "registeredBetween":
|
case "registeredBetween":
|
||||||
return "Registered between";
|
return "Registered between";
|
||||||
|
case "pluginsBooleanGroups":
|
||||||
|
return "Has plugin boolean value";
|
||||||
default:
|
default:
|
||||||
return filter.kind;
|
return filter.kind;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user