Begun work on Filters:

- Filter interface
- Wrote 5 filters
- Wrote QueryFilters that manages different Filters

Plan is to link the QueryFilters to Resolvers:
- One that returns all filters and their options as json
- One that users the query parameters (eg ?q={json}) and gets the filters
  - FilterQuery has a static method to parse the json
This commit is contained in:
Risto Lahtela 2020-03-24 12:03:39 +02:00
parent b479753fc9
commit aac7bdc632
25 changed files with 932 additions and 13 deletions

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.addons.placeholderapi.BukkitPlaceholderRegistrar;
import com.djrapitops.plan.commands.PlanCommand; import com.djrapitops.plan.commands.PlanCommand;
import com.djrapitops.plan.gathering.ServerShutdownSave; import com.djrapitops.plan.gathering.ServerShutdownSave;
import com.djrapitops.plan.modules.APFModule; import com.djrapitops.plan.modules.APFModule;
import com.djrapitops.plan.modules.FiltersModule;
import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.PlaceholderModule;
import com.djrapitops.plan.modules.ServerCommandModule; import com.djrapitops.plan.modules.ServerCommandModule;
import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.SystemObjectProvidingModule;
@ -42,6 +43,7 @@ import javax.inject.Singleton;
BukkitPlanModule.class, BukkitPlanModule.class,
SystemObjectProvidingModule.class, SystemObjectProvidingModule.class,
APFModule.class, APFModule.class,
FiltersModule.class,
PlaceholderModule.class, PlaceholderModule.class,
ServerCommandModule.class, ServerCommandModule.class,

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan;
import com.djrapitops.plan.commands.PlanCommand; import com.djrapitops.plan.commands.PlanCommand;
import com.djrapitops.plan.modules.APFModule; import com.djrapitops.plan.modules.APFModule;
import com.djrapitops.plan.modules.FiltersModule;
import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.PlaceholderModule;
import com.djrapitops.plan.modules.ProxySuperClassBindingModule; import com.djrapitops.plan.modules.ProxySuperClassBindingModule;
import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.SystemObjectProvidingModule;
@ -38,6 +39,7 @@ import javax.inject.Singleton;
BungeeCommandModule.class, BungeeCommandModule.class,
SystemObjectProvidingModule.class, SystemObjectProvidingModule.class,
APFModule.class, APFModule.class,
FiltersModule.class,
PlaceholderModule.class, PlaceholderModule.class,
ProxySuperClassBindingModule.class, ProxySuperClassBindingModule.class,

View File

@ -101,11 +101,11 @@ public class ActivityIndex {
}; };
} }
return new String[]{ return new String[]{
locale.get(HtmlLang.INDEX_VERY_ACTIVE).toString(), locale.getString(HtmlLang.INDEX_VERY_ACTIVE),
locale.get(HtmlLang.INDEX_ACTIVE).toString(), locale.getString(HtmlLang.INDEX_ACTIVE),
locale.get(HtmlLang.INDEX_REGULAR).toString(), locale.getString(HtmlLang.INDEX_REGULAR),
locale.get(HtmlLang.INDEX_IRREGULAR).toString(), locale.getString(HtmlLang.INDEX_IRREGULAR),
locale.get(HtmlLang.INDEX_INACTIVE).toString() locale.getString(HtmlLang.INDEX_INACTIVE)
}; };
} }
@ -175,4 +175,18 @@ public class ActivityIndex {
public String getGroup() { public String getGroup() {
return getGroup(value); return getGroup(value);
} }
public String getGroup(Locale locale) {
if (value >= VERY_ACTIVE) {
return locale.getString(HtmlLang.INDEX_VERY_ACTIVE);
} else if (value >= ACTIVE) {
return locale.getString(HtmlLang.INDEX_ACTIVE);
} else if (value >= REGULAR) {
return locale.getString(HtmlLang.INDEX_REGULAR);
} else if (value >= IRREGULAR) {
return locale.getString(HtmlLang.INDEX_IRREGULAR);
} else {
return locale.getString(HtmlLang.INDEX_INACTIVE);
}
}
} }

View File

@ -0,0 +1,48 @@
/*
* 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.modules;
import com.djrapitops.plan.storage.database.queries.filter.Filter;
import com.djrapitops.plan.storage.database.queries.filter.filters.*;
import dagger.Binds;
import dagger.Module;
import dagger.multibindings.IntoSet;
@Module
public interface FiltersModule {
@Binds
@IntoSet
Filter filter1(PlayedBetweenDateRangeFilter filter);
@Binds
@IntoSet
Filter filter2(RegisteredBetweenDateRangeFilter filter);
@Binds
@IntoSet
Filter filter3(OperatorsFilter filter);
@Binds
@IntoSet
Filter filter4(BannedFilter filter);
@Binds
@IntoSet
Filter filter5(ActivityIndexFilter filter);
}

View File

@ -0,0 +1,42 @@
/*
* 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.settings.locale.lang;
public enum FilterLang implements Lang {
OPERATORS("Operators"),
NON_OPERATORS("Non operators"),
BANNED("Banned"),
NOT_BANNED("Not banned"),
;
private final String defaultValue;
FilterLang(String defaultValue) {
this.defaultValue = defaultValue;
}
@Override
public String getIdentifier() {
return "HTML - " + name() + " (Filters)";
}
@Override
public String getDefault() {
return defaultValue;
}
}

View File

@ -25,10 +25,7 @@ import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import static com.djrapitops.plan.storage.database.sql.building.Sql.*; import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
@ -429,4 +426,26 @@ public class NetworkActivityIndexQueries {
} }
}; };
} }
public static Query<Map<UUID, ActivityIndex>> activityIndexForAllPlayers(long date, long playtimeThreshold) {
String selectActivityIndex = selectActivityIndexSQL();
return new QueryStatement<Map<UUID, ActivityIndex>>(selectActivityIndex, 1000) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
setSelectActivityIndexSQLParameters(statement, 1, playtimeThreshold, date);
}
@Override
public Map<UUID, ActivityIndex> processResults(ResultSet set) throws SQLException {
Map<UUID, ActivityIndex> indexes = new HashMap<>();
while (set.next()) {
indexes.put(
UUID.fromString(set.getString(SessionsTable.USER_UUID)),
new ActivityIndex(set.getDouble("activity_index"), date)
);
}
return indexes;
}
};
}
} }

View File

@ -0,0 +1,25 @@
/*
* 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;
/**
* Exception to throw when a {@link Filter} results in a complete set.
*
* @author Rsl1122
*/
public class CompleteSetException extends IllegalStateException {
}

View File

@ -0,0 +1,49 @@
/*
* 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;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.UUID;
/**
* Represents a query filter for /query page.
*
* @author Rsl1122
*/
public interface Filter {
String getKind();
String[] getExpectedParameters();
default List<String> getOptions() {
return Collections.emptyList();
}
/**
* Match some UUIDs to the filter.
*
* @param query Query for the filter
* @return Set of UUIDs this filter applies to
* @throws IllegalArgumentException If the arguments are not valid.
* @throws CompleteSetException If the arguments produce a complete set.
*/
Set<UUID> getMatchingUUIDs(FilterQuery query);
}

View File

@ -0,0 +1,53 @@
/*
* 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;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
* Represents parameters for a single {@link Filter} parsed from the query json.
*
* @author Rsl1122
*/
public class FilterQuery {
private final String kind;
private final Map<String, String> parameters;
public FilterQuery(String kind, Map<String, String> parameters) {
this.kind = kind;
this.parameters = parameters;
}
public static List<FilterQuery> parse(String json) throws IOException {
return new Gson().getAdapter(new TypeToken<List<FilterQuery>>() {}).fromJson(json);
}
public String getKind() {
return kind;
}
public Optional<String> get(String key) {
return Optional.ofNullable(parameters.get(key));
}
}

View File

@ -0,0 +1,53 @@
/*
* 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;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* Contains a single instance of each filter kind.
*
* @author Rsl1122
* @see com.djrapitops.plan.modules.FiltersModule for list of Filters
*/
@Singleton
public class QueryFilters {
private Map<String, Filter> filters;
@Inject
public QueryFilters(Set<Filter> filters) {
this.filters = new HashMap<>();
put(filters);
}
private void put(Iterable<Filter> filters) {
for (Filter filter : filters) {
this.filters.put(filter.getKind(), filter);
}
}
public Optional<Filter> getFilter(String kind) {
return Optional.ofNullable(filters.get(kind));
}
}

View File

@ -0,0 +1,88 @@
/*
* 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.delivery.domain.mutators.ActivityIndex;
import com.djrapitops.plan.settings.config.PlanConfig;
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.queries.analysis.NetworkActivityIndexQueries;
import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.*;
import java.util.stream.Collectors;
@Singleton
public class ActivityIndexFilter extends MultiOptionFilter {
private final PlanConfig config;
private final Locale locale;
private final DBSystem dbSystem;
@Inject
public ActivityIndexFilter(
PlanConfig config,
Locale locale,
DBSystem dbSystem
) {
this.dbSystem = dbSystem;
this.config = config;
this.locale = locale;
}
@Override
public String getKind() {
return "activityIndexNow";
}
private String[] getOptionsArray() {
return ActivityIndex.getGroups(locale);
}
@Override
public List<String> getOptions() {
return Collections.singletonList(serializeOptions(getOptionsArray()));
}
@Override
public Set<UUID> getMatchingUUIDs(FilterQuery query) {
List<String> selected = getSelected(query);
String[] options = getOptionsArray();
boolean includeVeryActive = selected.contains(options[0]);
boolean includeActive = selected.contains(options[1]);
boolean includeRegular = selected.contains(options[2]);
boolean includeIrregular = selected.contains(options[3]);
boolean includeInactive = selected.contains(options[4]);
if (includeVeryActive && includeActive && includeRegular && includeIrregular && includeInactive) {
throw new CompleteSetException(); // Full set, no need for query
}
long date = System.currentTimeMillis();
long playtimeThreshold = config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD);
Map<UUID, ActivityIndex> indexes = dbSystem.getDatabase().query(NetworkActivityIndexQueries.activityIndexForAllPlayers(date, playtimeThreshold));
return indexes.entrySet().stream()
.filter(entry -> selected.contains(entry.getValue().getGroup(locale)))
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.FilterLang;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.*;
@Singleton
public class BannedFilter extends MultiOptionFilter {
private final DBSystem dbSystem;
private final Locale locale;
@Inject
public BannedFilter(
DBSystem dbSystem,
Locale locale
) {
this.dbSystem = dbSystem;
this.locale = locale;
}
@Override
public String getKind() {
return "banned";
}
private String[] getOptionsArray() {
return new String[]{locale.getString(FilterLang.BANNED), locale.getString(FilterLang.NOT_BANNED)};
}
@Override
public List<String> getOptions() {
return Collections.singletonList(serializeOptions(getOptionsArray()));
}
@Override
public Set<UUID> getMatchingUUIDs(FilterQuery query) {
List<String> selected = getSelected(query);
Set<UUID> uuids = new HashSet<>();
String[] options = getOptionsArray();
boolean includeBanned = selected.contains(options[0]);
boolean includeNotBanned = selected.contains(options[1]);
if (includeBanned && includeNotBanned) throw new CompleteSetException(); // Full set, no need for query
if (includeBanned) uuids.addAll(dbSystem.getDatabase().query(UserInfoQueries.uuidsOfBanned()));
if (includeNotBanned) uuids.addAll(dbSystem.getDatabase().query(UserInfoQueries.uuidsOfNotBanned()));
return uuids;
}
}

View File

@ -0,0 +1,78 @@
/*
* 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.storage.database.DBSystem;
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.objects.BaseUserQueries;
import org.apache.commons.lang3.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
public abstract class DateRangeFilter implements Filter {
private final DBSystem dbSystem;
private final SimpleDateFormat dateFormat;
public DateRangeFilter(DBSystem dbSystem) {
this.dbSystem = dbSystem;
this.dateFormat = new SimpleDateFormat("dd/MM/yyyy kk:mm");
}
@Override
public String[] getExpectedParameters() {
return new String[]{
"dateAfter",
"timeAfter",
"dateBefore",
"timeBefore"
};
}
@Override
public List<String> getOptions() {
long earliestData = dbSystem.getDatabase().query(BaseUserQueries.minimumRegisterDate());
long now = System.currentTimeMillis();
if (earliestData == -1) earliestData = now;
String[] afterDate = StringUtils.split(dateFormat.format(earliestData), ' ');
String[] beforeDate = StringUtils.split(dateFormat.format(now), ' ');
return Arrays.asList(afterDate[0], afterDate[1], beforeDate[0], beforeDate[1]);
}
protected long getAfter(FilterQuery query) {
return getTime(query, "dateAfter", "timeAfter");
}
protected long getBefore(FilterQuery query) {
return getTime(query, "dateBefore", "timeBefore");
}
private long getTime(FilterQuery query, String dateKey, String timeKey) {
String date = query.get(dateKey).orElseThrow(IllegalArgumentException::new);
String time = query.get(timeKey).orElseThrow(IllegalArgumentException::new);
try {
return dateFormat.parse(date + ' ' + time).getTime();
} catch (ParseException e) {
throw new IllegalArgumentException(e);
}
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.storage.database.queries.filter.Filter;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.TextStringBuilder;
import java.util.Arrays;
import java.util.List;
public abstract class MultiOptionFilter implements Filter {
@Override
public String[] getExpectedParameters() {
return new String[]{"selected"};
}
protected List<String> getSelected(FilterQuery query) {
String selected = query.get("selected").orElseThrow(IllegalArgumentException::new);
return Arrays.asList(deserializeOptions(selected));
}
protected String serializeOptions(String... options) {
return new TextStringBuilder().appendWithSeparators(options, ",").build();
}
private String[] deserializeOptions(String selected) {
return StringUtils.split(selected, ',');
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.FilterLang;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.CompleteSetException;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import com.djrapitops.plan.storage.database.queries.objects.UserInfoQueries;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.*;
@Singleton
public class OperatorsFilter extends MultiOptionFilter {
private final DBSystem dbSystem;
private final Locale locale;
@Inject
public OperatorsFilter(
DBSystem dbSystem,
Locale locale
) {
this.dbSystem = dbSystem;
this.locale = locale;
}
@Override
public String getKind() {
return "operators";
}
private String[] getOptionsArray() {
return new String[]{locale.getString(FilterLang.OPERATORS), locale.getString(FilterLang.NON_OPERATORS)};
}
@Override
public List<String> getOptions() {
return Collections.singletonList(serializeOptions(getOptionsArray()));
}
@Override
public Set<UUID> getMatchingUUIDs(FilterQuery query) {
List<String> selected = getSelected(query);
Set<UUID> uuids = new HashSet<>();
String[] options = getOptionsArray();
boolean includeOperators = selected.contains(options[0]);
boolean includeNonOperators = selected.contains(options[1]);
if (includeOperators && includeNonOperators) throw new CompleteSetException(); // Full set, no need for query
if (includeOperators) uuids.addAll(dbSystem.getDatabase().query(UserInfoQueries.uuidsOfOperators()));
if (includeNonOperators) uuids.addAll(dbSystem.getDatabase().query(UserInfoQueries.uuidsOfNonOperators()));
return uuids;
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Set;
import java.util.UUID;
@Singleton
public class PlayedBetweenDateRangeFilter extends DateRangeFilter {
private DBSystem dbSystem;
@Inject
public PlayedBetweenDateRangeFilter(DBSystem dbSystem) {
super(dbSystem);
this.dbSystem = dbSystem;
}
@Override
public String getKind() {
return "playedBetween";
}
@Override
public Set<UUID> getMatchingUUIDs(FilterQuery query) {
long after = getAfter(query);
long before = getBefore(query);
return dbSystem.getDatabase().query(SessionQueries.uuidsOfPlayedBetween(after, before));
}
}

View File

@ -0,0 +1,56 @@
/*
* 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.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public class PluginGroupsFilter extends MultiOptionFilter {
private final DBSystem dbSystem;
private final String pluginName;
private final List<String> groups;
public PluginGroupsFilter(
DBSystem dbSystem,
String pluginName,
List<String> groups
) {
this.dbSystem = dbSystem;
this.pluginName = pluginName;
this.groups = groups;
}
@Override
public String getKind() {
return null;
}
@Override
public List<String> getOptions() {
return null;
}
@Override
public Set<UUID> getMatchingUUIDs(FilterQuery query) {
return null;
}
}

View File

@ -0,0 +1,50 @@
/*
* 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.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import com.djrapitops.plan.storage.database.queries.objects.BaseUserQueries;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Set;
import java.util.UUID;
@Singleton
public class RegisteredBetweenDateRangeFilter extends DateRangeFilter {
private DBSystem dbSystem;
@Inject
public RegisteredBetweenDateRangeFilter(DBSystem dbSystem) {
super(dbSystem);
this.dbSystem = dbSystem;
}
@Override
public String getKind() {
return "registeredBetween";
}
@Override
public Set<UUID> getMatchingUUIDs(FilterQuery query) {
long after = getAfter(query);
long before = getBefore(query);
return dbSystem.getDatabase().query(BaseUserQueries.uuidsOfRegisteredBetween(after, before));
}
}

View File

@ -28,10 +28,7 @@ import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Collection; import java.util.*;
import java.util.HashSet;
import java.util.Optional;
import java.util.UUID;
import static com.djrapitops.plan.storage.database.sql.building.Sql.*; import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
@ -142,4 +139,38 @@ public class BaseUserQueries {
}; };
} }
public static Query<Set<UUID>> uuidsOfRegisteredBetween(long after, long before) {
String sql = SELECT + DISTINCT + UsersTable.USER_UUID +
FROM + UsersTable.TABLE_NAME +
WHERE + UsersTable.REGISTERED + ">=?" +
AND + UsersTable.REGISTERED + "<=?";
return new QueryStatement<Set<UUID>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, after);
statement.setLong(2, before);
}
@Override
public Set<UUID> processResults(ResultSet set) throws SQLException {
Set<UUID> uuids = new HashSet<>();
while (set.next()) {
uuids.add(UUID.fromString(set.getString(UsersTable.USER_UUID)));
}
return uuids;
}
};
}
public static Query<Long> minimumRegisterDate() {
String sql = SELECT + "MIN(" + UsersTable.REGISTERED + ") as min" +
FROM + UsersTable.TABLE_NAME;
return new QueryAllStatement<Long>(sql) {
@Override
public Long processResults(ResultSet set) throws SQLException {
return set.next() ? set.getLong("min") : -1;
}
};
}
} }

View File

@ -813,4 +813,27 @@ public class SessionQueries {
} }
}; };
} }
public static Query<Set<UUID>> uuidsOfPlayedBetween(long after, long before) {
String sql = SELECT + DISTINCT + SessionsTable.USER_UUID +
FROM + SessionsTable.TABLE_NAME +
WHERE + SessionsTable.SESSION_END + ">=?" +
AND + SessionsTable.SESSION_START + "<=?";
return new QueryStatement<Set<UUID>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setLong(1, after);
statement.setLong(2, before);
}
@Override
public Set<UUID> processResults(ResultSet set) throws SQLException {
Set<UUID> uuids = new HashSet<>();
while (set.next()) {
uuids.add(UUID.fromString(set.getString(SessionsTable.USER_UUID)));
}
return uuids;
}
};
}
} }

View File

@ -183,4 +183,40 @@ public class UserInfoQueries {
} }
}; };
} }
public static Query<Set<UUID>> uuidsOfOperators() {
return getUUIDsForBooleanGroup(UserInfoTable.OP, true);
}
public static Query<Set<UUID>> getUUIDsForBooleanGroup(String column, boolean value) {
String sql = SELECT + UserInfoTable.USER_UUID + FROM + UserInfoTable.TABLE_NAME +
WHERE + column + "=?";
return new QueryStatement<Set<UUID>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setBoolean(1, value);
}
@Override
public Set<UUID> processResults(ResultSet set) throws SQLException {
Set<UUID> uuids = new HashSet<>();
while (set.next()) {
uuids.add(UUID.fromString(set.getString(UserInfoTable.USER_UUID)));
}
return uuids;
}
};
}
public static Query<Set<UUID>> uuidsOfNonOperators() {
return getUUIDsForBooleanGroup(UserInfoTable.OP, false);
}
public static Query<Set<UUID>> uuidsOfBanned() {
return getUUIDsForBooleanGroup(UserInfoTable.BANNED, true);
}
public static Query<Set<UUID>> uuidsOfNotBanned() {
return getUUIDsForBooleanGroup(UserInfoTable.BANNED, false);
}
} }

View File

@ -19,6 +19,7 @@ package utilities.dagger;
import com.djrapitops.plan.PlanPlugin; import com.djrapitops.plan.PlanPlugin;
import com.djrapitops.plan.PlanSystem; import com.djrapitops.plan.PlanSystem;
import com.djrapitops.plan.commands.PlanCommand; import com.djrapitops.plan.commands.PlanCommand;
import com.djrapitops.plan.modules.FiltersModule;
import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.PlaceholderModule;
import com.djrapitops.plan.utilities.logging.PluginErrorLogger; import com.djrapitops.plan.utilities.logging.PluginErrorLogger;
import dagger.BindsInstance; import dagger.BindsInstance;
@ -38,6 +39,7 @@ import java.nio.file.Path;
PlanPluginModule.class, PlanPluginModule.class,
TestSystemObjectProvidingModule.class, TestSystemObjectProvidingModule.class,
TestAPFModule.class, TestAPFModule.class,
FiltersModule.class,
PlaceholderModule.class, PlaceholderModule.class,
PluginServerPropertiesModule.class, PluginServerPropertiesModule.class,

View File

@ -20,6 +20,7 @@ import com.djrapitops.plan.addons.placeholderapi.NukkitPlaceholderRegistrar;
import com.djrapitops.plan.commands.PlanCommand; import com.djrapitops.plan.commands.PlanCommand;
import com.djrapitops.plan.gathering.ServerShutdownSave; import com.djrapitops.plan.gathering.ServerShutdownSave;
import com.djrapitops.plan.modules.APFModule; import com.djrapitops.plan.modules.APFModule;
import com.djrapitops.plan.modules.FiltersModule;
import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.PlaceholderModule;
import com.djrapitops.plan.modules.ServerCommandModule; import com.djrapitops.plan.modules.ServerCommandModule;
import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.SystemObjectProvidingModule;
@ -42,6 +43,7 @@ import javax.inject.Singleton;
NukkitPlanModule.class, NukkitPlanModule.class,
SystemObjectProvidingModule.class, SystemObjectProvidingModule.class,
APFModule.class, APFModule.class,
FiltersModule.class,
PlaceholderModule.class, PlaceholderModule.class,
ServerCommandModule.class, ServerCommandModule.class,

View File

@ -19,6 +19,7 @@ package com.djrapitops.plan;
import com.djrapitops.plan.commands.PlanCommand; import com.djrapitops.plan.commands.PlanCommand;
import com.djrapitops.plan.gathering.ServerShutdownSave; import com.djrapitops.plan.gathering.ServerShutdownSave;
import com.djrapitops.plan.modules.APFModule; import com.djrapitops.plan.modules.APFModule;
import com.djrapitops.plan.modules.FiltersModule;
import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.PlaceholderModule;
import com.djrapitops.plan.modules.ServerCommandModule; import com.djrapitops.plan.modules.ServerCommandModule;
import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.SystemObjectProvidingModule;
@ -41,6 +42,7 @@ import javax.inject.Singleton;
SpongePlanModule.class, SpongePlanModule.class,
SystemObjectProvidingModule.class, SystemObjectProvidingModule.class,
APFModule.class, APFModule.class,
FiltersModule.class,
PlaceholderModule.class, PlaceholderModule.class,
ServerCommandModule.class, ServerCommandModule.class,

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan;
import com.djrapitops.plan.commands.PlanCommand; import com.djrapitops.plan.commands.PlanCommand;
import com.djrapitops.plan.modules.APFModule; import com.djrapitops.plan.modules.APFModule;
import com.djrapitops.plan.modules.FiltersModule;
import com.djrapitops.plan.modules.PlaceholderModule; import com.djrapitops.plan.modules.PlaceholderModule;
import com.djrapitops.plan.modules.ProxySuperClassBindingModule; import com.djrapitops.plan.modules.ProxySuperClassBindingModule;
import com.djrapitops.plan.modules.SystemObjectProvidingModule; import com.djrapitops.plan.modules.SystemObjectProvidingModule;
@ -38,6 +39,7 @@ import javax.inject.Singleton;
VelocityCommandModule.class, VelocityCommandModule.class,
SystemObjectProvidingModule.class, SystemObjectProvidingModule.class,
APFModule.class, APFModule.class,
FiltersModule.class,
PlaceholderModule.class, PlaceholderModule.class,
ProxySuperClassBindingModule.class, ProxySuperClassBindingModule.class,