🚸 Sort results by pack name first, then bot name
[xudocci.git] / src / main / java / net / pterodactylus / xdcc / ui / stdin / Result.java
index b09b061..47430ca 100644 (file)
 package net.pterodactylus.xdcc.ui.stdin;
 
 import static com.google.common.collect.FluentIterable.from;
+import static java.util.regex.Pattern.compile;
 
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
-import java.util.List;
 import java.util.function.Predicate;
 import java.util.regex.Pattern;
 
@@ -41,85 +40,65 @@ import com.google.common.collect.ComparisonChain;
  */
 public class Result implements Comparable<Result> {
 
-       /** {@link Predicate} that matches {@link Result}s that contain an archive. */
-       private static final Predicate<Result> isArchive = new Predicate<Result>() {
-
-               /** All suffixes that are recognized as archives. */
-               private final List<String> archiveSuffixes = Arrays.asList("rar", "tar", "zip", "tar.gz", "tar.bz2", "tar.lzma", "7z");
+       private static Predicate<String> matches(String regex) {
+               Pattern pattern = compile(regex);
+               return new Predicate<String>() {
+                       @Override
+                       public boolean test(String input) {
+                               return pattern.matcher(input).find();
+                       }
+               };
+       }
 
-               @Override
-               public boolean test(Result result) {
-                       for (String suffix : archiveSuffixes) {
-                               if (result.pack().name().toLowerCase().endsWith(suffix)) {
-                                       return true;
+       private static Comparator<Result> preferredComparator(Predicate<String> preferredName, Function<Result, String> stringExtractor) {
+               return new Comparator<Result>() {
+                       @Override
+                       public int compare(Result leftResult, Result rightResult) {
+                               boolean leftStringMatches = preferredName.test(stringExtractor.apply(leftResult));
+                               boolean rightStringMatches = preferredName.test(stringExtractor.apply(rightResult));
+                               if (leftStringMatches && !rightStringMatches) {
+                                       return -1;
+                               } else if (rightStringMatches && !leftStringMatches) {
+                                       return 1;
                                }
+                               return 0;
                        }
-                       return false;
-               }
-       };
+               };
+       }
 
-       /**
-        * {@link Comparator} for {@link Result}s that sorts archives (as per {@link
-        * #isArchive} to the back of the list.
-        */
-       private static final Comparator<Result> packArchiveComparator = new Comparator<Result>() {
-               @Override
-               public int compare(Result leftResult, Result rightResult) {
-                       if (isArchive.test(leftResult) && !isArchive.test(rightResult)) {
-                               return 1;
-                       }
-                       if (!isArchive.test(leftResult) && isArchive.test(rightResult)) {
-                               return -1;
-                       }
-                       return 0;
-               }
-       };
+       /** {@link Comparator} for {@link Result}s that sorts archives to the back of the list. */
+       private static final Comparator<Result> packArchiveComparator = preferredComparator(matches("(rar|tar|zip|tar\\.(gz|bz2|lzma)|7z)$").negate(), (result) -> result.pack().name());
 
-       /**
-        * {@link Comparator} for bot nicknames. It comprises different strategies: one
-        * name pattern is preferred (and thus listed first), one pattern is disliked
-        * (and thus listed last), the rest is sorted alphabetically.
-        */
-       private static final Comparator<Result> botNameComparator = new Comparator<Result>() {
+       /** {@link Comparator} for bot nicknames. */
+       private static final Comparator<Result> botNameComparator =
+                       sortEuropeanBotsToTheFront().thenComparing(sortAmericanBotsToTheBack()).thenComparing(sortPassiveBotsToTheBack());
 
-               /** Regular expression pattern for preferred names. */
-               private final Pattern preferredNames = Pattern.compile("(?i)[^\\w]EUR?[^\\w]");
+       private static Comparator<Result> sortEuropeanBotsToTheFront() {
+               return preferredComparator(matches("(?i)[^\\w]EUR?[^\\w]"), (result) -> result.bot().name());
+       }
 
-               /** Regular expression pattern for disliked names. */
-               private final Pattern dislikedNames = Pattern.compile("(?i)[^\\w]USA?[^\\w]");
+       private static Comparator<Result> sortAmericanBotsToTheBack() {
+               return preferredComparator(matches("(?i)[^\\w]USA?[^\\w]").negate(), (result) -> result.bot().name());
+       }
 
-               @Override
-               public int compare(Result leftResult, Result rightResult) {
-                       String leftBotName = leftResult.bot().name();
-                       String rightBotName = rightResult.bot().name();
-                       /* preferred names to the front! */
-                       if (preferredNames.matcher(leftBotName).find() && !preferredNames.matcher(rightBotName).find()) {
-                               return -1;
-                       }
-                       if (preferredNames.matcher(rightBotName).find() && !preferredNames.matcher(leftBotName).find()) {
-                               return 1;
-                       }
-                       /* disliked names to the back. */
-                       if (dislikedNames.matcher(leftBotName).find() && !dislikedNames.matcher(rightBotName).find()) {
-                               return 1;
-                       }
-                       if (dislikedNames.matcher(rightBotName).find() && !dislikedNames.matcher(leftBotName).find()) {
-                               return -1;
-                       }
-                       return 0;
-               }
-       };
+       private static Comparator<Result> sortPassiveBotsToTheBack() {
+               return preferredComparator(matches("[-|]P[-|]").negate(), (result) -> result.bot().name());
+       }
 
-       /**
-        * {@link Comparator} for {@link Result}s that sorts them by the name of the
-        * {@link Pack}.
-        */
-       private static final Comparator<Result> packNameComparator = new Comparator<Result>() {
-               @Override
-               public int compare(Result leftResult, Result rightResult) {
-                       return leftResult.pack().name().compareToIgnoreCase(rightResult.pack().name());
-               }
-       };
+       private static final Comparator<Result> packNameComparator = sortRepacksFirst().thenComparing(sortPacksAlphabetically());
+
+       private static Comparator<Result> sortRepacksFirst() {
+               return preferredComparator(matches("\\.(PROPER|REPACK)\\."), (result) -> result.pack().name());
+       }
+
+       private static Comparator<Result> sortPacksAlphabetically() {
+               return new Comparator<Result>() {
+                       @Override
+                       public int compare(Result leftResult, Result rightResult) {
+                               return leftResult.pack().name().compareToIgnoreCase(rightResult.pack().name());
+                       }
+               };
+       }
 
        /** Comparator that sorts bots with running downloads to the back of the list. */
        private final Comparator<Result> botsWithRunningTransfersComparator = new Comparator<Result>() {
@@ -199,8 +178,8 @@ public class Result implements Comparable<Result> {
                return ComparisonChain.start()
                                .compare(this, result, botsWithRunningTransfersComparator)
                                .compare(this, result, packArchiveComparator)
-                               .compare(this, result, botNameComparator)
-                               .compare(this, result, packNameComparator).result();
+                               .compare(this, result, packNameComparator)
+                               .compare(this, result, botNameComparator).result();
        }
 
 }