diff --git a/Core/src/main/java/com/intellectualcrafters/plot/config/Settings.java b/Core/src/main/java/com/intellectualcrafters/plot/config/Settings.java index a5b93dfc3..acd375394 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/config/Settings.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/config/Settings.java @@ -153,6 +153,7 @@ public class Settings extends Config { @Create // This value has to be generated since an instance isn't static public CALIBRATION CALIBRATION = null; public int THRESHOLD = 1; + public int REQUIRED_PLOTS = -1; public boolean CONFIRMATION = true; public int DAYS = 7; public List WORLDS = new ArrayList<>(Collections.singletonList("*")); diff --git a/Core/src/main/java/com/intellectualcrafters/plot/util/expiry/ExpiryTask.java b/Core/src/main/java/com/intellectualcrafters/plot/util/expiry/ExpiryTask.java index 0c1dbd13b..231113030 100644 --- a/Core/src/main/java/com/intellectualcrafters/plot/util/expiry/ExpiryTask.java +++ b/Core/src/main/java/com/intellectualcrafters/plot/util/expiry/ExpiryTask.java @@ -1,8 +1,14 @@ package com.intellectualcrafters.plot.util.expiry; +import com.intellectualcrafters.plot.PS; import com.intellectualcrafters.plot.config.Settings; +import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.PlotArea; - +import com.intellectualcrafters.plot.object.PlotFilter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; import java.util.concurrent.TimeUnit; public class ExpiryTask { @@ -12,12 +18,85 @@ public class ExpiryTask { this.settings = settings; } - public boolean applies(PlotArea area) { + public boolean allowsArea(PlotArea area) { return settings.WORLDS.contains(area.toString()) || settings.WORLDS.contains(area.worldname) || settings.WORLDS.contains("*"); } + public boolean applies(PlotArea area) { + if (allowsArea(area)) { + if (settings.REQUIRED_PLOTS <= 0) { + return true; + } + Set plots = null; + if (cutoffThreshold != Long.MAX_VALUE && area.getPlots().size() > settings.REQUIRED_PLOTS || (plots = getPlotsToCheck()).size() > settings.REQUIRED_PLOTS) { + // calculate cutoff + if (cutoffThreshold == Long.MIN_VALUE) { + plots = plots != null ? plots : getPlotsToCheck(); + int diff = settings.REQUIRED_PLOTS; + boolean min = true; + if (settings.REQUIRED_PLOTS - plots.size() < settings.REQUIRED_PLOTS) { + min = false; + diff = settings.REQUIRED_PLOTS - plots.size(); + } + List entireList = new ArrayList<>(); + for (Plot plot : plots) { + entireList.add(ExpireManager.IMP.getAge(plot)); + } + List top = new ArrayList<>(diff + 1); + if (diff > 1000) { + Collections.sort(entireList); + cutoffThreshold = entireList.get(settings.REQUIRED_PLOTS); + } else { + loop: + for (long num : entireList) { + int size = top.size(); + if (size == 0) { + top.add(num); + continue; + } + long end = top.get(size - 1); + if (min ? num < end : num > end) { + for (int i = 0; i < size; i++) { + long existing = top.get(i); + if (min ? num < existing : num > existing) { + top.add(i, num); + if (size == diff) { + top.remove(size); + } + continue loop; + } + } + } + if (size < diff) { + top.add(num); + } + } + cutoffThreshold = top.get(top.size() - 1); + } + // Add half a day, as expiry is performed each day + cutoffThreshold += (TimeUnit.DAYS.toMillis(1) / 2); + } + return true; + } else { + cutoffThreshold = Long.MAX_VALUE; + } + } + return false; + } + + public Set getPlotsToCheck() { + return PS.get().getPlots(new PlotFilter() { + @Override + public boolean allowsArea(PlotArea area) { + return ExpiryTask.this.allowsArea(area); + } + }); + } + + private long cutoffThreshold = Long.MIN_VALUE; + public boolean applies(long diff) { - return diff > TimeUnit.DAYS.toMillis(settings.DAYS); + return diff > TimeUnit.DAYS.toMillis(settings.DAYS) && diff > cutoffThreshold; } public boolean needsAnalysis() { @@ -31,4 +110,6 @@ public class ExpiryTask { public boolean requiresConfirmation() { return settings.CONFIRMATION; } + + }