diff --git a/Core/src/main/java/com/plotsquared/core/PlotSquared.java b/Core/src/main/java/com/plotsquared/core/PlotSquared.java index af94ed1dd..c053c822a 100644 --- a/Core/src/main/java/com/plotsquared/core/PlotSquared.java +++ b/Core/src/main/java/com/plotsquared/core/PlotSquared.java @@ -713,8 +713,6 @@ public class PlotSquared { case CREATION_DATE_TIMESTAMP -> toReturn.addAll(sortPlotsByTimestamp(map.get(area))); case DISTANCE_FROM_ORIGIN -> toReturn.addAll(sortPlotsByHash(map.get(area))); case LAST_MODIFIED -> toReturn.addAll(sortPlotsByModified(map.get(area))); - default -> { - } } } return toReturn; diff --git a/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByCreationDateComparator.java b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByCreationDateComparator.java new file mode 100644 index 000000000..c4d7734ae --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByCreationDateComparator.java @@ -0,0 +1,35 @@ +package com.plotsquared.core.util.comparator; + +import com.plotsquared.core.plot.Plot; +import org.jetbrains.annotations.ApiStatus; + +import java.util.Comparator; + +/** + * Sort plots by {@link Plot#temp} (being the auto increment id in database) in natural order for {@code temp > 0}. + * For {@code temp < 1} sort by {@link Plot#hashCode()} + */ +@ApiStatus.Internal +public class PlotByCreationDateComparator implements Comparator { + + @ApiStatus.Internal + public static final Comparator INSTANCE = new PlotByCreationDateComparator(); + + private PlotByCreationDateComparator() { + } + + @Override + @SuppressWarnings("deprecation") // Plot#temp + public int compare(final Plot first, final Plot second) { + if (first.temp > 0 && second.temp > 0) { + return Integer.compare(first.temp, second.temp); + } + // second is implicitly `< 1` (due to previous condition) + if (first.temp > 0) { + return 1; + } + // sort dangling plots (temp < 1) by their hashcode + return Integer.compare(first.hashCode(), second.hashCode()); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByDoneComparator.java b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByDoneComparator.java new file mode 100644 index 000000000..937cb8d62 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByDoneComparator.java @@ -0,0 +1,34 @@ +package com.plotsquared.core.util.comparator; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.flag.implementations.DoneFlag; +import com.plotsquared.core.util.MathMan; + +import java.util.Comparator; + +/** + * Sort plots by their {@link DoneFlag} in reverse numeric natural order. (more recent "finished plots" first) + *
+ * Non-finished plots last, unsorted. + */ +public class PlotByDoneComparator implements Comparator { + + public static final PlotByDoneComparator INSTANCE = new PlotByDoneComparator(); + + private PlotByDoneComparator() { + } + + @Override + public int compare(final Plot first, final Plot second) { + String firstDone = first.getFlag(DoneFlag.class); + String lastDone = second.getFlag(DoneFlag.class); + if (MathMan.isInteger(firstDone)) { + if (MathMan.isInteger(lastDone)) { + return Integer.parseInt(lastDone) - Integer.parseInt(firstDone); + } + return -1; // only "first" is finished, so sort "second" after "first" + } + return 0; // neither is finished + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByRatingComparator.java b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByRatingComparator.java new file mode 100644 index 000000000..ab15487ae --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotByRatingComparator.java @@ -0,0 +1,43 @@ +package com.plotsquared.core.util.comparator; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.Rating; + +import java.util.Comparator; +import java.util.Map; +import java.util.UUID; + +public class PlotByRatingComparator implements Comparator { + + public static final PlotByRatingComparator INSTANCE = new PlotByRatingComparator(); + + PlotByRatingComparator() { + } + + @Override + public int compare(final Plot p1, final Plot p2) { + double v1 = 0; + int p1s = p1.getSettings().getRatings().size(); + int p2s = p2.getRatings().size(); + if (!p1.getSettings().getRatings().isEmpty()) { + v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) + .map(av -> av * av).sum(); + v1 /= p1s; + v1 += p1s; + } + double v2 = 0; + if (!p2.getSettings().getRatings().isEmpty()) { + for (Map.Entry entry : p2.getRatings().entrySet()) { + double av = entry.getValue().getAverageRating(); + v2 += av * av; + } + v2 /= p2s; + v2 += p2s; + } + if (v2 == v1 && v2 != 0) { + return p2s - p1s; + } + return (int) Math.signum(v2 - v1); + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/comparator/PlotInPrioritizedAreaComparator.java b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotInPrioritizedAreaComparator.java new file mode 100644 index 000000000..930526b68 --- /dev/null +++ b/Core/src/main/java/com/plotsquared/core/util/comparator/PlotInPrioritizedAreaComparator.java @@ -0,0 +1,31 @@ +package com.plotsquared.core.util.comparator; + +import com.plotsquared.core.plot.Plot; +import com.plotsquared.core.plot.PlotArea; + +import javax.annotation.Nullable; +import java.util.Comparator; + +public class PlotInPrioritizedAreaComparator implements Comparator { + + private final PlotArea priorityArea; + + public PlotInPrioritizedAreaComparator(@Nullable final PlotArea area) { + this.priorityArea = area; + } + + @Override + public int compare(final Plot first, final Plot second) { + if (this.priorityArea == null) { + return 0; // no defined priority? don't sort + } + if (this.priorityArea.equals(first.getArea())) { + return -1; + } + if (this.priorityArea.equals(second.getArea())) { + return 1; + } + return 0; // same area, don't sort + } + +} diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java index eee73b4c8..70d0bce4c 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotProvider.java @@ -54,9 +54,6 @@ interface PlotProvider { @Override public Plot next() { - if (currentAreaPlots == null) { - currentAreaPlots = areas[++areaIndex].getPlots().iterator(); - } return currentAreaPlots.next(); } }, Spliterator.IMMUTABLE), false); diff --git a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java index 6d4d6e3a6..43af78370 100644 --- a/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java +++ b/Core/src/main/java/com/plotsquared/core/util/query/PlotQuery.java @@ -23,10 +23,11 @@ import com.plotsquared.core.PlotSquared; import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.PlotArea; -import com.plotsquared.core.plot.Rating; -import com.plotsquared.core.plot.flag.implementations.DoneFlag; import com.plotsquared.core.plot.world.PlotAreaManager; -import com.plotsquared.core.util.MathMan; +import com.plotsquared.core.util.comparator.PlotByDoneComparator; +import com.plotsquared.core.util.comparator.PlotByRatingComparator; +import com.plotsquared.core.util.comparator.PlotByCreationDateComparator; +import com.plotsquared.core.util.comparator.PlotInPrioritizedAreaComparator; import org.checkerframework.checker.nullness.qual.NonNull; import java.util.ArrayList; @@ -37,7 +38,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.function.Predicate; @@ -308,7 +308,15 @@ public final class PlotQuery implements Iterable { * @return Matching plots */ public @NonNull Stream asStream() { - return this.asList().stream(); // TODO: use stream functionality from PlotProvider? + Stream stream = this.plotProvider.streamPlots().filter(testPlotAgainstFilters()); + if (this.sortingStrategy == SortingStrategy.NO_SORTING) { + return stream; + } + stream = stream.sorted(getConfiguredComparator()); + if (this.priorityArea != null) { + stream = stream.sorted(new PlotInPrioritizedAreaComparator(this.priorityArea)); + } + return stream; } /** @@ -335,49 +343,10 @@ public final class PlotQuery implements Iterable { } if (this.sortingStrategy == SortingStrategy.NO_SORTING) { return result; - } else if (this.sortingStrategy == SortingStrategy.SORT_BY_TEMP) { - return PlotSquared.get().sortPlotsByTemp(result); - } else if (this.sortingStrategy == SortingStrategy.SORT_BY_DONE) { - result.sort((a, b) -> { - String va = a.getFlag(DoneFlag.class); - String vb = b.getFlag(DoneFlag.class); - if (MathMan.isInteger(va)) { - if (MathMan.isInteger(vb)) { - return Integer.parseInt(vb) - Integer.parseInt(va); - } - return -1; - } - return 1; - }); - } else if (this.sortingStrategy == SortingStrategy.SORT_BY_RATING) { - result.sort((p1, p2) -> { - double v1 = 0; - int p1s = p1.getSettings().getRatings().size(); - int p2s = p2.getRatings().size(); - if (!p1.getSettings().getRatings().isEmpty()) { - v1 = p1.getRatings().values().stream().mapToDouble(Rating::getAverageRating) - .map(av -> av * av).sum(); - v1 /= p1s; - v1 += p1s; - } - double v2 = 0; - if (!p2.getSettings().getRatings().isEmpty()) { - for (Map.Entry entry : p2.getRatings().entrySet()) { - double av = entry.getValue().getAverageRating(); - v2 += av * av; - } - v2 /= p2s; - v2 += p2s; - } - if (v2 == v1 && v2 != 0) { - return p2s - p1s; - } - return (int) Math.signum(v2 - v1); - }); - } else if (this.sortingStrategy == SortingStrategy.SORT_BY_CREATION) { - return PlotSquared.get().sortPlots(result, PlotSquared.SortType.CREATION_DATE, this.priorityArea); - } else if (this.sortingStrategy == SortingStrategy.COMPARATOR) { - result.sort(this.plotComparator); + } + result.sort(getConfiguredComparator()); + if (this.priorityArea != null) { + result.sort(new PlotInPrioritizedAreaComparator(this.priorityArea)); } return result; } @@ -443,20 +412,7 @@ public final class PlotQuery implements Iterable { * @since TODO */ public boolean hasMinimumMatches(int minimum) { - return this.plotProvider.streamPlots().filter(plot -> { - for (final PlotFilter filter : filters) { - if (!filter.accepts(plot)) { - return false; - } - } - return true; - }).limit(minimum).count() == minimum; - } - - @NonNull - private PlotQuery addFilter(final @NonNull PlotFilter filter) { - this.filters.add(filter); - return this; + return this.plotProvider.streamPlots().filter(testPlotAgainstFilters()).limit(minimum).count() == minimum; } @NonNull @@ -465,4 +421,34 @@ public final class PlotQuery implements Iterable { return this.asCollection().iterator(); } + @NonNull + private PlotQuery addFilter(final @NonNull PlotFilter filter) { + this.filters.add(filter); + return this; + } + + private Comparator getConfiguredComparator() { + return switch (sortingStrategy) { + case NO_SORTING -> (p1, p2) -> 0; + case SORT_BY_TEMP, SORT_BY_CREATION -> PlotByCreationDateComparator.INSTANCE; + case SORT_BY_DONE -> PlotByDoneComparator.INSTANCE; + case SORT_BY_RATING -> PlotByRatingComparator.INSTANCE; + case COMPARATOR -> plotComparator; + }; + } + + private Predicate testPlotAgainstFilters() { + if (this.filters.isEmpty()) { + return plot -> true; + } + return plot -> { + for (final PlotFilter filter : filters) { + if (!filter.accepts(plot)) { + return false; + } + } + return true; + }; + } + }