diff --git a/forge-core/src/main/java/forge/card/CardEdition.java b/forge-core/src/main/java/forge/card/CardEdition.java index 51f3fc55226..81329c740f9 100644 --- a/forge-core/src/main/java/forge/card/CardEdition.java +++ b/forge-core/src/main/java/forge/card/CardEdition.java @@ -147,7 +147,7 @@ public final class CardEdition implements Comparable { // immutable } } - public static class CardInSet { + public static class CardInSet implements Comparable { public final CardRarity rarity; public final String collectorNumber; public final String name; @@ -171,6 +171,51 @@ public final class CardEdition implements Comparable { // immutable sb.append(name); return sb.toString(); } + + /** + * This method implements the main strategy to allow for natural ordering of collectorNumber + * (i.e. "1" < "10"), overloading the default lexicographic order (i.e. "10" < "1"). + * Any non-numerical parts in the input collectorNumber will be also accounted for, and attached to the + * resulting sorting key, accordingly. + * + * @param collectorNumber: Input collectorNumber tro transform in a Sorting Key + * @return A 5-digits zero-padded collector number + any non-numerical parts attached. + */ + public static String getSortableCollectorNumber(final String collectorNumber){ + String sortableCollNr = collectorNumber; + if (sortableCollNr == null || sortableCollNr.length() == 0) + sortableCollNr = "50000"; // very big number of 5 digits to have them in last positions + + // Now, for proper sorting, let's zero-pad the collector number (if integer) + int collNr; + try { + collNr = Integer.parseInt(sortableCollNr); + sortableCollNr = String.format("%05d", collNr); + } catch (NumberFormatException ex) { + String nonNumeric = sortableCollNr.replaceAll("[0-9]", ""); + String onlyNumeric = sortableCollNr.replaceAll("[^0-9]", ""); + if (sortableCollNr.startsWith(onlyNumeric)) // e.g. 12a, 37+, 2018f, + sortableCollNr = String.format("%05d", Integer.parseInt(onlyNumeric)) + nonNumeric; + else // e.g. WS6, S1 + sortableCollNr = nonNumeric + String.format("%05d", Integer.parseInt(onlyNumeric)); + } + return sortableCollNr; + } + + @Override + public int compareTo(CardInSet o) { + final int nameCmp = name.compareToIgnoreCase(o.name); + if (0 != nameCmp) { + return nameCmp; + } + String thisCollNr = getSortableCollectorNumber(collectorNumber); + String othrCollNr = getSortableCollectorNumber(o.collectorNumber); + final int collNrCmp = thisCollNr.compareTo(othrCollNr); + if (0 != collNrCmp) { + return collNrCmp; + } + return rarity.compareTo(o.rarity); + } } private final static SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd"); @@ -286,7 +331,9 @@ public final class CardEdition implements Comparable { // immutable public List getCards() { return cardMap.get("cards"); } public List getAllCardsInSet() { - return Lists.newArrayList(cardMap.values()); + ArrayList cardsInSet = Lists.newArrayList(cardMap.values()); + Collections.sort(cardsInSet); + return cardsInSet; } public boolean isModern() { return getDate().after(parseDate("2003-07-27")); } //8ED and above are modern except some promo cards and others @@ -305,7 +352,10 @@ public final class CardEdition implements Comparable { // immutable if (o == null) { return 1; } - return date.compareTo(o.date); + int dateComp = date.compareTo(o.date); + if (0 != dateComp) + return dateComp; + return name.compareTo(o.name); } @Override @@ -413,7 +463,7 @@ public final class CardEdition implements Comparable { // immutable * rarity - grouping #4 * name - grouping #5 */ - "(^([0-9]+.?) )?(([SCURML]) )?(.*)$" + "(^([0-9A-Z]+.?) )?(([SCURML]) )?(.*)$" ); ListMultimap cardMap = ArrayListMultimap.create(); diff --git a/forge-core/src/main/java/forge/item/PaperCard.java b/forge-core/src/main/java/forge/item/PaperCard.java index 395882cee5a..16e5d0ea8cb 100644 --- a/forge-core/src/main/java/forge/item/PaperCard.java +++ b/forge-core/src/main/java/forge/item/PaperCard.java @@ -243,6 +243,34 @@ public final class PaperCard implements Comparable, InventoryItemFro // return String.format("%s|%s", name, cardSet); } + /* + * This (utility) method transform a collectorNumber String into a key string for sorting. + * This method proxies the same strategy implemented in CardEdition.CardInSet class from which the + * collectorNumber of PaperCard instances are originally retrieved. + * This is also to centralise the criterion, whilst avoiding code duplication. + * + * Note: The method has been made private as this is for internal API use **only**, to allow + * for generalised comparison with IPaperCard instances (see compareTo) + * + * The public API of PaperCard includes a method (i.e. getCollectorNumberSortingKey) which applies + * this method on instance's own collector number. + * + * @return a zero-padded 5-digits String + any non-numerical content in the input String, properly attached. + */ + private static String makeCollectorNumberSortingKey(final String collectorNumber0){ + String collectorNumber = collectorNumber0; + if (collectorNumber.equals(NO_COLLECTOR_NUMBER)) + collectorNumber = null; + return CardEdition.CardInSet.getSortableCollectorNumber(collectorNumber); + } + + public String getCollectorNumberSortingKey(){ + // Hardly the case, but just invoke getter rather than direct + // attribute to be sure that collectorNumber has been retrieved already! + return makeCollectorNumberSortingKey(getCollectorNumber()); + } + + @Override public int compareTo(final IPaperCard o) { final int nameCmp = name.compareToIgnoreCase(o.getName()); @@ -253,7 +281,9 @@ public final class PaperCard implements Comparable, InventoryItemFro int setDiff = edition.compareTo(o.getEdition()); if (0 != setDiff) return setDiff; - final int collNrCmp = getCollectorNumber().compareTo(o.getCollectorNumber()); + String thisCollNrKey = getCollectorNumberSortingKey(); + String othrCollNrKey = makeCollectorNumberSortingKey(o.getCollectorNumber()); + final int collNrCmp = thisCollNrKey.compareTo(othrCollNrKey); if (0 != collNrCmp) { return collNrCmp; } diff --git a/forge-gui/res/editions/Alliances.txt b/forge-gui/res/editions/Alliances.txt index 2196f28be42..73d2dbfb0aa 100644 --- a/forge-gui/res/editions/Alliances.txt +++ b/forge-gui/res/editions/Alliances.txt @@ -105,10 +105,10 @@ Foil=NotSupported 30a C Lat-Nam's Legacy 30b C Lat-Nam's Legacy 31 R Library of Lat-Nam -55a C Lim-Dûl's High Guard -55b C Lim-Dûl's High Guard -108 U Lim-Dûl's Paladin -107 U Lim-Dûl's Vault +55a C Lim-Dul's High Guard +55b C Lim-Dul's High Guard +108 U Lim-Dul's Paladin +107 U Lim-Dul's Vault 122 R Lodestone Bauble 112 R Lord of Tresserhorn 10a C Martyrdom diff --git a/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java b/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java index 2c3864557e3..cd00ccc1b7c 100644 --- a/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java +++ b/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java @@ -661,24 +661,11 @@ public enum ColumnDef { //make sure it's a card. if not, pointless to proceed. String collectorNumber; if (i instanceof PaperCard) { - collectorNumber = ((PaperCard) i).getCollectorNumber(); - // First off, make all NO_COLLECTOR_NUMBER the last in sortings - if (collectorNumber.equals(IPaperCard.NO_COLLECTOR_NUMBER)) - collectorNumber = "50000"; // very big number of 5 digits to have them in last positions - - // Now, for proper sorting, let's zero-pad the collector number (if integer) - try { - int collNr = Integer.parseInt(collectorNumber); - collectorNumber = String.format("%05d", collNr); - } catch (NumberFormatException ex) { - String nonNumeric = collectorNumber.replaceAll("[0-9]", ""); - String onlyNumeric = collectorNumber.replaceAll("[^0-9]", ""); - collectorNumber = String.format("%05d", Integer.parseInt(onlyNumeric)) + nonNumeric; - } + collectorNumber = ((PaperCard) i).getCollectorNumberSortingKey(); } else { collectorNumber = IPaperCard.NO_COLLECTOR_NUMBER; } - return collectorNumber + toSortableName(i.getName()); + return collectorNumber; } /**