diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main/java/tlIItools/Affix.java | 431 | ||||
| -rw-r--r-- | src/main/java/tlIItools/AffixGroup.java | 130 | ||||
| -rw-r--r-- | src/main/java/tlIItools/AffixLister.java | 428 | ||||
| -rw-r--r-- | src/main/java/tlIItools/AffixSet.java | 47 | ||||
| -rw-r--r-- | src/main/java/tlIItools/Effect.java | 453 | ||||
| -rw-r--r-- | src/main/java/tlIItools/EffectGroup.java | 120 | ||||
| -rw-r--r-- | src/main/java/tlIItools/EffectRepo.java | 85 | ||||
| -rw-r--r-- | src/main/java/tlIItools/LevelRange.java | 135 | ||||
| -rw-r--r-- | src/main/java/tlIItools/Main.java | 6 | ||||
| -rw-r--r-- | src/main/java/tlIItools/NameFileReader.java | 124 | ||||
| -rw-r--r-- | src/main/java/tlIItools/ReplPair.java | 173 |
11 files changed, 1074 insertions, 1058 deletions
diff --git a/src/main/java/tlIItools/Affix.java b/src/main/java/tlIItools/Affix.java index d90c0108..c49e6e2a 100644 --- a/src/main/java/tlIItools/Affix.java +++ b/src/main/java/tlIItools/Affix.java @@ -1,112 +1,79 @@ package tlIItools; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Scanner; - -/** - * Represents a Torchlight II affix. - */ +import java.util.*; + +/** Represents a Torchlight II affix. + * + * @author Ben Culkin */ public class Affix { - /** - * Whether or not to record timing info. - */ + /** Details which sort of affix this is. + * + * @author Ben Culkin */ + public enum AffixType { + /** An affix that applies to a normal item. */ + ITEM, + /** An affix that applies to a socketable. */ + SOCKETABLE, + /** An affix that applies to a monster/person. */ + PERSONAL, + /** An affix that applies as an item enchantment. */ + ENCHANTMENT + } + + /** Whether or not to record timing info. */ public static boolean doTiming; - /** - * Internal name of the affix. - */ + + /** Internal name of the affix. */ public String intName; - /* - * The prefix/suffix attached to the affix. + /* The prefix/suffix attached to the affix. * * In general, only one of these is set for a given affix. * * NOTE: Some affixes have a mis-set suffix/prefix ordering, and may need to be - * changed in their files. - */ - /** - * The 'suffix name' attached to this affix. + * changed in their files. */ + + /** The 'suffix name' attached to this affix. * * Include the word [ITEM] to indicate where the item name should go. * * Note that it is not guaranteed that this is actually a suffix; it could be a - * prefix. - */ + * prefix. */ public String affixSuffix; - /** - * The 'prefix name' attached to this affix. + /** The 'prefix name' attached to this affix. * * Include the word [ITEM] to indicate where the item name should go. * * Note that it is not guaranteed that this is actually a prefix; it could be a - * suffix. - */ + * suffix. */ public String affixPrefix; - /* - * The min/max levels the affix can spawn at. - */ - /** - * The minimum level of an item this affix can spawn on. - */ - public int minLevel; - /** - * The maximum level of an item this affix can spawn on. - */ - public int maxLevel; - - /** - * The spawn weight for the affix. - */ + /** The min/max levels the affix can spawn at. */ + public LevelRange spawnRange = new LevelRange(); + + /** The spawn weight for the affix. */ public int weight; - /** - * The number of affix slots taken up. - */ + /** The number of affix slots taken up. */ public int slots; - /** - * Whether this is a socketable affix. - */ - public boolean isSocketable; - /** - * Whether this is an enchantment, instead of a standard affix. - */ - public boolean isEnchantment; - /** - * Whether this is a mob/player affix. - */ - public boolean isPerson; - - /** - * The types of equipment this can spawn on. - */ + /** The type of thing this affix applies to. */ + public AffixType type = AffixType.ITEM; + + /** The types of equipment this can spawn on. */ public List<String> equipTypes; - /** - * The types of equipment this can't spawn on. - */ + /** The types of equipment this can spawn on. */ public List<String> nonequipTypes; - - /** - * Places to get this enchantment from; - */ + /** The types of equipment this can spawn on. */ public List<String> enchantSources; - - /** - * The socketable types this spawns on. - */ + /** The types of equipment this can spawn on. */ public List<String> socketableTypes; - /** - * The effects attached to this affix. - */ + /** The effects attached to this affix. */ public List<Effect> effects; - /** - * Is this affix in an 'affix group' with another affix? + /** Determine whether this affix is in an 'affix group' with another affix. * * By 'affix group', what we mean is that it is essentially the same affix, with * generally just differing levels/values. @@ -115,50 +82,51 @@ public class Affix { * strength would be considered to be in the same affix group (assuming that * both of those strength bonuses had the same effect name). * - * @param afx - * The affix to check if we are in an affix group with. + * @param afx The affix to check if we are in an affix group with. * - * @return Whether or now we are in an affix group with the specified affix. - */ + * @return Whether or now we are in an affix group with the specified affix. */ public boolean isInAffixGroup(Affix afx) { if (effects == null) { - if (afx.effects != null) - return false; - } else if (!effects.equals(afx.effects)) // TODO this isn't actually an equals; - // maybe make this a 'isEquivalent' or - // 'isSimilarEffect'? - return false; + if (afx.effects != null) return false; + } else if (!effects.equals(afx.effects)) { + Iterator<Effect> leftIter = effects.iterator(); + Iterator<Effect> rightIter = afx.effects.iterator(); + + while (leftIter.hasNext() && rightIter.hasNext()) { + Effect left = leftIter.next(); + Effect right = rightIter.next(); + + if (!left.group.equals(right.group)) return false; + } + } + if (enchantSources == null) { - if (afx.enchantSources != null) - return false; - } else if (!enchantSources.equals(afx.enchantSources)) - return false; - if (equipTypes == null) { - if (afx.equipTypes != null) - return false; - } else if (!equipTypes.equals(afx.equipTypes)) + if (afx.enchantSources != null) return false; + } else if (!enchantSources.equals(afx.enchantSources)) { return false; - if (isEnchantment != afx.isEnchantment) + } else if (equipTypes == null) { + if (afx.equipTypes != null) return false; + } else if (!equipTypes.equals(afx.equipTypes)) { return false; - if (isPerson != afx.isPerson) + } else if (type == null) { + if (afx.type != null) return false; + } else if (type != afx.type) { return false; - if (isSocketable != afx.isSocketable) + } else if (nonequipTypes == null) { + if (afx.nonequipTypes != null) return false; + } else if (!nonequipTypes.equals(afx.nonequipTypes)) { return false; - if (nonequipTypes == null) { - if (afx.nonequipTypes != null) - return false; - } else if (!nonequipTypes.equals(afx.nonequipTypes)) - return false; - if (socketableTypes == null) { - if (afx.socketableTypes != null) - return false; - } else if (!socketableTypes.equals(afx.socketableTypes)) + } else if (socketableTypes == null) { + if (afx.socketableTypes != null) return false; + } else if (!socketableTypes.equals(afx.socketableTypes)) { return false; + } else { + return true; + } return true; } - - /** - * Gets the name of the 'affix group' that this affix is in. + + /** Gets the 'affix group' that this affix is in. * * By 'affix group', what we mean is that it is essentially the same affix, with * generally just differing levels/values. @@ -168,85 +136,62 @@ public class Affix { * both of those strength bonuses had the same effect name, and applied to the * same sorts of items). * - * @return The name of the affix group - */ - public String getAffixGroupName() { - StringBuilder sb = new StringBuilder(); - - for (Effect eft : effects) { - sb.append(eft.getEffectGroup()); - } - - for (String enchantSource : enchantSources) { - sb.append(enchantSource); - } - - for (String equipType : equipTypes) { - sb.append(equipType); - } - - for (String nonEquipType : nonequipTypes) { - sb.append(nonEquipType); - } - - for (String socketableType : socketableTypes) { - sb.append(socketableType); - } - - return sb.toString(); + * @return The affix group */ + public AffixGroup toAffixGroup() { + AffixGroup group = new AffixGroup(); + + group.type = type; + group.enchantSources = enchantSources; + group.equipTypes = equipTypes; + group.nonequipTypes = nonequipTypes; + group.socketableTypes = socketableTypes; + + for (Effect eff : effects) group.effects.add(eff.group); + + return group; } - /* - * Are invalid equip types being added? + /* Are invalid equip types being added? * * NOTE: This is kinda bad practice. It should really be handled via two * separate affix methods, one to add a valid affix, one to add an invalid, w/ - * the caller keeping tracking/calling the right one. - */ + * the caller keeping tracking/calling the right one. */ private boolean inNonEquip; - /** - * Create a new blank affix. - */ + /** Create a new blank affix. */ public Affix() { - equipTypes = new ArrayList<>(); - nonequipTypes = new ArrayList<>(); - enchantSources = new ArrayList<>(); + equipTypes = new ArrayList<>(); + nonequipTypes = new ArrayList<>(); + enchantSources = new ArrayList<>(); socketableTypes = new ArrayList<>(); - effects = new ArrayList<>(); + effects = new ArrayList<>(); } - /** - * Sets the set of equip types that is added to. + /** Sets the set of equip types that is added to. * - * @param nonequip - * True if the equip types being added are prohibited, or false - * if they are allowed. - */ + * @param nonequip True if the equip types being added are prohibited, or false + * if they are allowed. */ public void setEquipType(boolean nonequip) { inNonEquip = nonequip; } - /** - * Add an equip type to the right set of equip types. + /** Add an equip type to the right set of equip types. * - * @param type - * The equip type to add. - */ - public void addEquipType(String type) { + * @param equipType The equip type to add. */ + public void addEquipType(String equipType) { if (inNonEquip) { - nonequipTypes.add(type); + nonequipTypes.add(equipType); } else { - if (type.equals("SOCKETABLE") || type.contains(" EMBER")) { - isSocketable = true; - socketableTypes.add(type); - } else if (type.startsWith("ENCHANTER")) { - isEnchantment = true; - enchantSources.add(type.substring(10)); - } else if (type.equals("MONSTER") || type.equals("PLAYER")) { - isPerson = true; + if (equipType.equals("SOCKETABLE") || equipType.contains(" EMBER")) { + type = AffixType.SOCKETABLE; + socketableTypes.add(equipType); + } else if (equipType.startsWith("ENCHANTER")) { + type = AffixType.ENCHANTMENT; + enchantSources.add(equipType.substring(10)); + } else if (equipType.equals("MONSTER") || equipType.equals("PLAYER")) { + type = AffixType.PERSONAL; } else { - equipTypes.add(type); + equipTypes.add(equipType); } } } @@ -256,22 +201,71 @@ public class Affix { return intName; } - /** - * Print out the full details of this affix. + /** Print out a 'short-form' of this affix. + * + * @return The short form of this affix. */ + public String toShortString() { + StringBuilder sb = new StringBuilder(); + + sb.append(intName); + sb.append("\n"); + + if (affixSuffix != null) { + sb.append("\tSuffix: "); + sb.append(affixSuffix); + sb.append("\n"); + } + + if (affixPrefix != null) { + sb.append("\tPrefix: "); + sb.append(affixPrefix); + sb.append("\n"); + + } + + sb.append("\t"); + sb.append(spawnRange.toString()); + sb.append("\n"); + + sb.append("\tSpawn Weight: "); + sb.append(weight); + sb.append("\t"); + + if (slots == 0) { + sb.append("\tOccupies no slots\n"); + } else { + sb.append("\tSlots: "); + sb.append(slots); + sb.append("\n"); + } + + if (effects.size() != 0) { + sb.append("\tEffects: "); + for (Effect eft : effects) { + if (effects.size() > 1) sb.append("\n\t\t"); + sb.append(eft.toString()); + } + sb.append("\n"); + } + + return sb.toString(); + } + + /** Print out the full details of this affix. * - * @return The full details of the affix. - */ + * @return The full details of the affix. */ public String toLongString() { StringBuilder sb = new StringBuilder(); - if (isSocketable) { + + if (type == AffixType.SOCKETABLE) { sb.append("Socketable "); - } else if (isPerson || (intName != null && intName.startsWith("HERO_"))) { + } else if (type == AffixType.PERSONAL || (intName != null && intName.startsWith("HERO_"))) { sb.append("Personal "); } else if (intName != null & intName.startsWith("MAP_")) { sb.append("Area "); } - if (isEnchantment) { + if (type == AffixType.ENCHANTMENT) { sb.append("Enchantment: "); } else { sb.append("Affix: "); @@ -294,21 +288,7 @@ public class Affix { } sb.append("\t"); - if (minLevel <= 1 && maxLevel == 999) { - sb.append("No Level Range"); - } else if (minLevel != 1 && maxLevel != 999) { - sb.append("Level Range: "); - sb.append(minLevel); - sb.append("-"); - sb.append(maxLevel); - } else if (minLevel <= 1) { - sb.append("Max Level: "); - sb.append(maxLevel); - } else if (maxLevel == 999) { - sb.append("Minimum Level: "); - sb.append(minLevel); - } - + sb.append(spawnRange); sb.append("\n"); sb.append("\tSpawn Weight: "); @@ -324,18 +304,20 @@ public class Affix { } if (equipTypes.size() != 0) { - if (isSocketable) + if (type == AffixType.SOCKETABLE) { sb.append("\tSocketable Into: "); - else if (isEnchantment) + } else if (type == AffixType.ENCHANTMENT) { sb.append("\tEnchants Onto: "); - else + } else { sb.append("\tSpawns On: "); + } + sb.append(equipTypes); sb.append("\n"); } // Socketables & enchantments use this as a duplicate. - if (!isSocketable && !isEnchantment && nonequipTypes.size() != 0) { + if (type != AffixType.SOCKETABLE && type != AffixType.ENCHANTMENT && nonequipTypes.size() != 0) { sb.append("\tCan't Spawn On: "); sb.append(nonequipTypes); sb.append("\n"); @@ -362,6 +344,7 @@ public class Affix { sb.append("\n"); } + /* sb.append("Affix Group: "); String afxGroupName = getAffixGroupName(); sb.append(afxGroupName); @@ -369,36 +352,29 @@ public class Affix { sb.append(afxGroupName.hashCode()); sb.append(")"); sb.append("\n"); + */ return sb.toString(); } - /** - * Load an affix from an input source. + /** Load an affix from an input source. * - * @param scn - * The input source to load from. + * @param scn The input source to load from. * - * @param fName - * The name of the input source in question. + * @param fName The name of the input source in question. * - * @return The loaded affix. - */ + * @return The loaded affix. */ public static Affix loadAffix(Scanner scn, String fName) { return loadAffix(scn, fName, new ArrayList<>()); } - /** - * Load an affix from an input source. + /** Load an affix from an input source. * - * @param scn - * The input source to read from. - * @param scnName - * The name of the input source. - * @param errors - * A list to stick errors encountered during loading the affix. - * @return The affix, loaded from the file. - */ + * @param scn The input source to read from. + * @param scnName The name of the input source. + * @param errors A list to stick errors encountered during loading the affix. + * + * @return The affix, loaded from the file. */ public static Affix loadAffix(Scanner scn, String scnName, List<String> errors) { Affix afx = new Affix(); @@ -428,27 +404,32 @@ public class Affix { afx.affixPrefix = splits[1]; break; default: - errors.add( - String.format("Misformed affix translation: (%s) (%s) (%s)\n", - splits[0], splits[1], scnName)); + String msg = String.format( + "Misformed affix translation: (%s) (%s) (%s)\n", + splits[0], splits[1], scnName); + errors.add(msg); } } else if (ln.contains("MIN_SPAWN_RANGE")) { - afx.minLevel = Integer.parseInt(splits[1]); + afx.spawnRange.minLevel = Integer.parseInt(splits[1]); } else if (ln.contains("MAX_SPAWN_RANGE")) { - afx.maxLevel = Integer.parseInt(splits[1]); + afx.spawnRange.maxLevel = Integer.parseInt(splits[1]); } else if (ln.contains("WEIGHT:")) { afx.weight = Integer.parseInt(splits[1]); } else if (ln.contains("SLOTS_OCCUPY")) { afx.weight = Integer.parseInt(splits[1]); } else if (ln.contains("UNITTYPE") && !ln.contains("/")) { if (splits.length == 1) - errors.add(String.format("Malformed equip type: (%s) (%s)\n", + errors.add(String.format( + "Malformed equip type: (%s) (%s)\n", splits[0], scnName)); + afx.addEquipType(splits[1]); } else if (splits[0].equals("<STRING>NAME")) { if (splits.length == 1) - errors.add(String.format("Malformed name: (%s) (%s)\n", splits[0], - scnName)); + errors.add(String.format( + "Malformed name: (%s) (%s)\n", + splits[0], scnName)); + afx.intName = splits[1]; } else if (ln.contains("[EFFECT]")) { List<String> eftErrs = new ArrayList<>(); @@ -459,21 +440,21 @@ public class Affix { afx.effects.add(eft); } } + // Sort effects, so that they are in a stable order, even if specified out of // order afx.effects.sort(Comparator.comparingInt((val) -> val.hashCode())); long endTime = System.nanoTime(); if (doTiming) { - String fmt - = "\tProcessed affix %s from %s in %d nanoseconds (%.2f seconds)\n\n"; + String fmt = "\tProcessed affix %s from %s in %d nanoseconds (%.2f seconds)\n\n"; double seconds = ((double) (endTime - startTime) / 1000000000); - errors.add(String.format(fmt, afx.intName, scnName, endTime - startTime, - seconds)); + errors.add(String.format( + fmt, + afx.intName, scnName, endTime - startTime, seconds)); } return afx; } - } diff --git a/src/main/java/tlIItools/AffixGroup.java b/src/main/java/tlIItools/AffixGroup.java new file mode 100644 index 00000000..5835614d --- /dev/null +++ b/src/main/java/tlIItools/AffixGroup.java @@ -0,0 +1,130 @@ +package tlIItools; + +import java.util.*; + +import tlIItools.Affix.*; + +/** + * Represents a 'group' of related affixes. + * + * These are affixes that are do the same thing, but could be of varying levels; + * or have effects of differing intensity. + * + * @author Ben Culkin */ +public class AffixGroup implements Comparable<AffixGroup> { + public List<EffectGroup> effects; + /** The types of enchanters who can add this. */ + public List<String> enchantSources; + /** The types of equipment this can spawn on. */ + public List<String> equipTypes; + /** The types of equipment this cannot spawn on. */ + public List<String> nonequipTypes; + /** The types of equipment this can be socketed into on. */ + public List<String> socketableTypes; + + /** The type of thing this affix applies to. */ + public AffixType type = AffixType.ITEM; + + /** Create a new affix group. */ + public AffixGroup() { + effects = new ArrayList<>(); + enchantSources = new ArrayList<>(); + equipTypes = new ArrayList<>(); + nonequipTypes = new ArrayList<>(); + socketableTypes = new ArrayList<>(); + } + + /** Determine whether this affix group contains a particular affix. + * + * By 'affix group', what we mean is that it is essentially the same affix, with + * generally just differing levels/values. + * + * For instance, an affix that granted +2 strength, and one that granted +4 + * strength would be considered to be in the same affix group (assuming that + * both of those strength bonuses had the same effect name). + * + * @param afx The affix to check if it is in the affix group with. + * + * @return Whether or the specified affix is in this affix group. */ + public boolean contains(Affix afx) { + return afx.toAffixGroup().equals(this); + } + + public String groupSummary() { + StringBuilder sb = new StringBuilder(); + + sb.append("Affix Type: "); + sb.append(type); + sb.append("\n"); + sb.append("Effects: "); + if (effects.size() > 1) sb.append("\n"); + for (EffectGroup group : effects) { + if (effects.size() > 1) sb.append("\t"); + sb.append(group.summary()); + sb.append("\n"); + } + + if (type == AffixType.SOCKETABLE) { + sb.append("Affix can be socketed into: "); + sb.append(String.join(", ", equipTypes)); + sb.append("\nAffix can spawn on: "); + sb.append(String.join(", ", socketableTypes)); + sb.append("\n"); + } else { + sb.append("Affix can spawn on: "); + sb.append(String.join(", ", equipTypes)); + sb.append("\nAffix can't spawn on: "); + sb.append(String.join(", ", nonequipTypes)); + sb.append("\n"); + } + + if (type == AffixType.ENCHANTMENT) { + sb.append("Affix can be enchanted by: "); + sb.append(String.join(", ", socketableTypes)); + sb.append("\n"); + } + + return sb.toString(); + } + + @Override + public int compareTo(AffixGroup other) { + return toString().compareTo(other.toString()); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + for (EffectGroup group: effects) sb.append(group); + for (String enchantSource: enchantSources) sb.append(enchantSource); + for (String equipType: equipTypes) sb.append(equipType); + for (String nonEquipType: nonequipTypes) sb.append(nonEquipType); + for (String socketableType: socketableTypes) sb.append(socketableType); + + return sb.toString(); + } + + @Override + public int hashCode() { + return Objects.hash(effects, enchantSources, equipTypes, nonequipTypes, + socketableTypes, type); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AffixGroup other = (AffixGroup) obj; + return Objects.equals(effects, other.effects) + && Objects.equals(enchantSources, other.enchantSources) + && Objects.equals(equipTypes, other.equipTypes) + && Objects.equals(nonequipTypes, other.nonequipTypes) + && Objects.equals(socketableTypes, other.socketableTypes) + && type == other.type; + } +} diff --git a/src/main/java/tlIItools/AffixLister.java b/src/main/java/tlIItools/AffixLister.java index 3a096bd2..c9cce52a 100644 --- a/src/main/java/tlIItools/AffixLister.java +++ b/src/main/java/tlIItools/AffixLister.java @@ -5,79 +5,56 @@ import java.io.*; import java.util.*; import java.util.Map.Entry; -/** - * Lists randomly generated affixes for Torchlight II gear. +/** Lists randomly generated affixes for Torchlight II gear. * - * @author Ben Culkin - */ + * @author Ben Culkin */ public class AffixLister { - /* - * Count of effects this class has loaded. - */ + /* Count of effects this class has loaded. */ private static int effectCount = 0; - /** - * Should the class record timing data? - */ + /** Should the class record timing data? */ public static boolean doTiming = false; - /** - * Should the file name be attached to things? - */ + /** Should the file name be attached to things? */ public static boolean addFileName = false; - /* - * Output streams to use. - */ - /** - * The normal output to use. - */ + /* Output streams to use. */ + + /** The normal output to use. */ public static PrintStream normOut = System.out; - /** - * The error output to use. - */ + /** The error output to use. */ public static PrintStream errOut = System.err; + /** The output to write affix groups to. */ + public static PrintStream affixGroupDest = null; - /** - * Indicates how to treat affixes with regards to their names. - */ + /** Indicates how to treat affixes with regards to their names. */ public static enum NameMode { - /** - * Show all affixes. - */ + /** Show all affixes. */ ALL, - /** - * Show only unnamed affixes. - */ + /** Show only unnamed affixes. */ UNNAMED, - /** - * Show only named affixes. - */ + /** Show only named affixes. */ NAMED; } - /** - * Main method. + /** Main method. * - * @param args The names of the files to read affix data from. - */ + * @param args The names of the files to read affix data from. */ public static void main(String[] args) { listAffixes(args); } - /** - * Main method that actually does stuff. + /** Main method that actually does stuff. * - * @param args - * The names of the files to read affix data from. - */ + * @param args The names of the files to read affix data from. + * + * @return The listed affix set. */ + @SuppressWarnings("unused") public static AffixSet listAffixes(String[] args) { - AffixSet affixSetByName = new AffixSet(); + boolean doingArgs = true; - boolean doingArgs = true; - - boolean omitZeros = false; - boolean listZeros = false; + boolean omitZeros = false; + boolean listZeros = false; NameMode nameMode = NameMode.ALL; @@ -86,193 +63,164 @@ public class AffixLister { int zeroCount = 0; int groupCount = 0; - boolean outputAffixGroups = false; - OutputStream affixGroupDest = null; - - Map<String, Set<Affix>> groupContents = affixSetByName.affixGroups; + boolean outputAffixGroups = false; - Set<Affix> nonGroupContents = affixSetByName.ungroupedAffixes; + Map<String, Set<Affix>> groupContents = new HashMap<>(); + Set<Affix> nonGroupContents = new HashSet<>(); NameFileReader nfr = new NameFileReader(false); nfr.groupRx = ".*/mods/([^/]+)/*"; long startTime = System.nanoTime(); - for(int i = 0; i < args.length; i++) { + for (int i = 0; i < args.length; i++) { String fName = args[i]; if (doingArgs && fName.startsWith("-")) { boolean isArg = true; switch (fName) { - case "--": - doingArgs = false; - break; - - case "--omit-zero": - case "-z": - omitZeros = true; - break; - - case "--no-omit-zero": - case "-Z": - omitZeros = false; - break; - - case "--list-zero": - case "-l": - listZeros = true; - break; - - case "--no-list-zero": - case "-L": - listZeros = false; - break; - - case "--timing": - case "-t": - doTiming = true; - Effect.doTiming = true; + case "--": + doingArgs = false; + break; + case "--omit-zero": + case "-z": + omitZeros = true; + break; + case "--no-omit-zero": + case "-Z": + omitZeros = false; + break; + case "--list-zero": + case "-l": + listZeros = true; + break; + case "--no-list-zero": + case "-L": + listZeros = false; + break; + case "--timing": + case "-t": + doTiming = true; + Effect.doTiming = true; + break; + case "--no-timing": + case "-T": + doTiming = false; + Effect.doTiming = false; + break; + case "--file-names": + case "-f": + addFileName = true; + break; + case "--no-file-names": + case "-F": + addFileName = true; + break; + case "--name-mode": + case "-n": + if (i + 1 >= args.length) { + errOut.printf("ERROR: name mode argument requires the mode to use be specified (all, unnamed or named)\n"); break; + } - case "--no-timing": - case "-T": - doTiming = false; - Effect.doTiming = false; - break; - - case "--file-names": - case "-f": - addFileName = true; - break; - - case "--no-file-names": - case "-F": - addFileName = true; - break; - - case "--name-mode": - case "-n": - if (i + 1 >= args.length) { - errOut.printf("ERROR: name mode argument requires the mode to use be specified (all, unnamed or named)\n"); - break; - } - - nameMode = NameMode.valueOf(args[++i].toUpperCase()); - - break; - - case "--file-group": - case "-g": - if (i + 1 >= args.length) { - errOut.printf("ERROR: file group argument requires the group name to use be specified\n"); - break; - } - - nfr.swapGroup(args[++i]); - - break; - - case "--guess-groups": - nfr.guessGroups = true; - - break; - - case "--no-guess-groups": - nfr.guessGroups = false; - + nameMode = NameMode.valueOf(args[++i].toUpperCase()); + break; + case "--file-group": + case "-g": + if (i + 1 >= args.length) { + errOut.printf("ERROR: file group argument requires the group name to use be specified\n"); break; + } - case "--read-names-from-file": - case "-r": - if (i + 1 >= args.length) { - errOut.printf("ERROR: read name file argument requires the file to use be specified\n"); - break; - } - - nfr.readFrom(args[++i]); - + nfr.swapGroup(args[++i]); + break; + case "--guess-groups": + nfr.guessGroups = true; + break; + case "--no-guess-groups": + nfr.guessGroups = false; + break; + case "--read-names-from-file": + case "-r": + if (i + 1 >= args.length) { + errOut.printf("ERROR: read name file argument requires the file to use be specified\n"); break; + } - case "--output": - case "-o": - if (i + 1 >= args.length) { - errOut.printf("ERROR: output file argument requires the file to use be specified\n"); - break; - } - - try { - normOut = new PrintStream(args[++i]); - - nfr.normOut = normOut; - } catch (IOException ioex) { - errOut.printf("Could not open output file %s\n", args[i]); - - ioex.printStackTrace(errOut); - } - + nfr.readFrom(args[++i]); + break; + case "--output": + case "-o": + if (i + 1 >= args.length) { + errOut.printf("ERROR: output file argument requires the file to use be specified\n"); break; + } - case "--output-errors": - case "-e": - if (i + 1 >= args.length) { - errOut.printf("ERROR: error output file argument requires the file to use be specified\n"); - break; - } - - try { - errOut = new PrintStream(args[++i]); - - nfr.errOut = errOut; - } catch (IOException ioex) { - errOut.printf("Could not open error output file %s\n", args[i]); - - ioex.printStackTrace(errOut); - } + try { + normOut = new PrintStream(args[++i]); + nfr.normOut = normOut; + } catch (IOException ioex) { + errOut.printf("Could not open output file %s\n", args[i]); + ioex.printStackTrace(errOut); + } + break; + case "--output-errors": + case "-e": + if (i + 1 >= args.length) { + errOut.printf("ERROR: error output file argument requires the file to use be specified\n"); break; + } - case "--guess-regex": - if (i + 1 >= args.length) { - errOut.printf("ERROR: group regex argument requires the regex to use be specified\n"); - break; - } - - nfr.groupRx = args[++i]; + try { + errOut = new PrintStream(args[++i]); + nfr.errOut = errOut; + } catch (IOException ioex) { + errOut.printf("Could not open error output file %s\n", args[i]); + ioex.printStackTrace(errOut); + } + break; + case "--guess-regex": + if (i + 1 >= args.length) { + errOut.printf("ERROR: group regex argument requires the regex to use be specified\n"); break; - case "--output-affix-groups": - if (i + 1 >= args.length) { - errOut.printf("ERROR: to output affix-groups, must specify a file to output them to"); - break; - } - - try { - affixGroupDest = new PrintStream(args[++i]); - - outputAffixGroups = true; - } catch (IOException ioex) { - errOut.printf("ERROR: Couldn't open file %s to write affix groups to\n", affixGroupDest); - } + } + nfr.groupRx = args[++i]; + break; + case "--output-affix-groups": + if (i + 1 >= args.length) { + errOut.printf( + "ERROR: to output affix-groups, must specify a file to output them to"); break; - default: - isArg = false; - } + } - if (isArg) { - continue; + try { + affixGroupDest = new PrintStream(args[++i]); + outputAffixGroups = true; + } catch (IOException ioex) { + errOut.printf( + "ERROR: Couldn't open file %s to write affix groups to\n", + affixGroupDest); + } + break; + default: + isArg = false; } - nfr.addFile(fName); + if (isArg) continue; + else nfr.addFile(fName); } else { nfr.addFile(fName); } } AffixSet affixSetByContents = new AffixSet(); - + for (Entry<String, List<String>> fGroup : nfr.fNames.entrySet()) { if (fGroup.getValue().size() == 0) continue; + normOut.printf("\nFile Group '%s' starting\n", fGroup.getKey()); for (String fName : fGroup.getValue()) { try (FileReader fr = new FileReader(fName)) { @@ -280,7 +228,7 @@ public class AffixLister { Affix afx = Affix.loadAffix(sc, fName); affixSetByContents.addAffixByContents(afx); - + effectCount += afx.effects.size(); if (afx.intName != null && afx.weight != 0) { @@ -290,10 +238,12 @@ public class AffixLister { if (!groupContents.containsKey(groupName)) { groupCount += 1; - // errOut.printf("\tTRACE: Counted distinct group %s from %s\n", groupName, afx.intName); + // errOut.printf("\tTRACE: Counted distinct group %s from + // %s\n", groupName, afx.intName); if (hasGroup) { - // errOut.printf("\tTRACE: Counted actual group %s from %s\n", groupName, afx.intName); + // errOut.printf("\tTRACE: Counted actual group %s from + // %s\n", groupName, afx.intName); groupContents.put(groupName, new HashSet<>()); } else { @@ -309,58 +259,88 @@ public class AffixLister { if (afx.weight == 0) zeroCount += 1; if (afx.weight == 0 && !listZeros) { - if (!omitZeros) - normOut.printf("\nAffix %s has zero spawn weight\n", afx.intName); + if (!omitZeros) normOut.printf( + "\nAffix %s has zero spawn weight\n", + afx.intName); } else { - boolean isNamed = (afx.affixSuffix != null) || (afx.affixPrefix != null); + boolean isNamed = + (afx.affixSuffix != null) || (afx.affixPrefix != null); - if (isNamed) namedCount += 1; + if (isNamed) namedCount += 1; else unnamedCount += 1; - if (nameMode == NameMode.UNNAMED && isNamed) continue; + if (nameMode == NameMode.UNNAMED && isNamed) continue; if (nameMode == NameMode.NAMED && !isNamed) continue; normOut.printf("\n%s\n", afx.toLongString()); } } catch (Exception ex) { - errOut.printf("Something bad happened for file %s:%s\n", fName, ex.getMessage()); + errOut.printf( + "Something bad happened for file %s:%s\n", + fName, ex.getMessage()); ex.printStackTrace(errOut); - errOut.println(); } } + normOut.printf("\nFile Group '%s' ending\n", fGroup.getKey()); } errOut.println("\nGroup Contents: "); - for (Entry<String, Set<Affix>> ent: groupContents.entrySet()) { + + for (Entry<String, Set<Affix>> ent : groupContents.entrySet()) { errOut.printf("\t%s: %s\n", ent.getKey(), ent.getValue()); } + errOut.println(); errOut.println(); if (outputAffixGroups) { - for (Entry<String, Set<Affix>> ent : affixSetByContents.affixGroups.entrySet()) { - String groupName = ent.getKey(); - Set<Affix> affixes = ent.getValue(); - - boolean isFirstAfx = true; - for (Affix afx : affixes) { - if (isFirstAfx) { - // Print the header for this - // group - isFirstAfx = false; - } - // print this affix in the group format + for (Entry<AffixGroup, Set<Affix>> entry + : affixSetByContents.affixGroups.entrySet()) + { + AffixGroup group = entry.getKey(); + Set<Affix> affixes = entry.getValue(); + + // Skip one-affix groups + if (affixes.size() == 1) continue; + + List<Affix> affixList = new ArrayList<>(affixes); + Collections.sort(affixList, (lhs, rhs) -> lhs.spawnRange.compareTo(rhs.spawnRange)); + + boolean isFirstAfx = true; + for (Affix afx : affixList) { + // @TODO actually implement this -bculkin, 12/29/2020 + + // Print the header for this group + if (isFirstAfx) { + isFirstAfx = false; + affixGroupDest.printf("Group ID %s (%d affixes)\t", + group.hashCode(), affixes.size()); + affixGroupDest.print(group.groupSummary()); } + + affixGroupDest.print("\t"); + affixGroupDest.print(afx.toShortString().replaceAll("\n(?=.)", "\n\t")); + // print this affix in the group format } + affixGroupDest.println(); + } } long endTime = System.nanoTime(); - errOut.printf("\nProcessed %,d affixes (%,d named, %,d unnamed, %,d zero-weight) (%,d effects) (%,d distinct groups, %,d actual groups, %,d nongrouped affixes) out of %,d files (%,d groups) in %,d nanoseconds (%.2f seconds)\n", nfr.fCount, namedCount, unnamedCount, zeroCount, effectCount, groupCount, groupContents.size(), nonGroupContents.size(), nfr.fCount, nfr.fNames.size(), endTime - startTime, ((double)(endTime - startTime) / 1000000000)); - errOut.printf("\tOptions: Name Mode: %s, Special-case zero weight: %s, Noting zero-weight in special case: %s\n", nameMode, !listZeros, !omitZeros); - - return affixSetByName; + errOut.printf( + "\nProcessed %,d affixes (%,d named, %,d unnamed, %,d zero-weight) (%,d effects) (%,d distinct groups, %,d actual groups, %,d nongrouped affixes) out of %,d files (%,d groups) in %,d nanoseconds (%.2f seconds)\n", + nfr.fCount, namedCount, unnamedCount, zeroCount, effectCount, groupCount, + groupContents.size(), nonGroupContents.size(), nfr.fCount, + nfr.fNames.size(), endTime - startTime, + ((double) (endTime - startTime) / 1000000000)); + + errOut.printf( + "\tOptions: Name Mode: %s, Special-case zero weight: %s, Noting zero-weight in special case: %s\n", + nameMode, !listZeros, !omitZeros); + + return affixSetByContents; } } diff --git a/src/main/java/tlIItools/AffixSet.java b/src/main/java/tlIItools/AffixSet.java index d7f14211..fa5c8d19 100644 --- a/src/main/java/tlIItools/AffixSet.java +++ b/src/main/java/tlIItools/AffixSet.java @@ -2,65 +2,50 @@ package tlIItools; import java.util.*; -/** - * Container of a set of affixes. +/** Container of a set of affixes. * - * @author Ben Culkin - */ + * @author Ben Culkin */ public class AffixSet { private static class AffixComparator implements Comparator<Affix> { + @Override public int compare(Affix a1, Affix a2) { - if (a1.minLevel == a2.minLevel) { - return a1.maxLevel - a2.maxLevel; - } - - return a1.minLevel - a2.minLevel; + return a1.spawnRange.compareTo(a2.spawnRange); } } - /** - * All of the affix groups contained in this set. + /** All of the affix groups contained in this set. * * An affix group is a set of affixes that generally have the same or - * similar effects, but have different intensities or spawn levels. - */ - public Map<String, Set<Affix>> affixGroups; + * similar effects, but have different intensities or spawn levels. */ + public Map<AffixGroup, Set<Affix>> affixGroups; - /** - * All of the ungrouped affixes contained in this set. - */ + /** All of the ungrouped affixes contained in this set. */ public Set<Affix> ungroupedAffixes; - /** - * Create a new blank affix set. - */ + /** Create a new blank affix set. */ public AffixSet() { affixGroups = new TreeMap<>(); ungroupedAffixes = new TreeSet<>(new AffixComparator()); } - - /** - * Add an affix to this set. + + /** Add an affix to this set. * - * @param afx The affix to add. - */ + * @param afx The affix to add. */ public void addAffixByContents(Affix afx) { - String afxGroup = afx.getAffixGroupName(); - + AffixGroup group = afx.toAffixGroup(); + String afxGroup = group.toString(); + if (afxGroup.equals("")) { ungroupedAffixes.add(afx); } else { - affixGroups.compute(afxGroup, (key, val) -> { + affixGroups.compute(group, (key, val) -> { if (val == null) { Set<Affix> afxSet = new HashSet<>(); - afxSet.add(afx); - return afxSet; } else { val.add(afx); - return val; } }); diff --git a/src/main/java/tlIItools/Effect.java b/src/main/java/tlIItools/Effect.java index d641b112..fd7867d0 100644 --- a/src/main/java/tlIItools/Effect.java +++ b/src/main/java/tlIItools/Effect.java @@ -1,255 +1,139 @@ package tlIItools; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Scanner; +import java.util.*; -/** - * Represents an effect attached to an affix. +/** Represents an effect attached to an affix. * - * @author Ben Culkin - */ + * @author Ben Culkin */ public class Effect { - /** - * Count of all loaded effects. - */ + /** Count of all loaded effects. */ public static int effectCount = 0; - /** - * Do timing analysis when loading effects. - */ + /** Do timing analysis when loading effects. */ public static boolean doTiming; - /** - * The file name this effect came from. - */ + /** The file name this effect came from. */ public String fName; - - /** - * The name of the effect. - */ - public String name; - - /** - * The specific effect that happens. - */ - public String type; - - /** - * Damage type for the effect, if applicable. - */ - public String damageType = "physical"; - - /** - * Duration of the effect. - */ + /** Duration of the effect. */ public double duration; - /** - * Whether or not we have a duration or not. - */ - public boolean hasDuration; - - /** - * Minimum value for the effect. - */ + /** Minimum value for the effect. */ public double minValue; - /** - * Maximum value for the effect. - */ + /** Maximum value for the effect. */ public double maxValue; - /** - * The name of the stat that applies to this affect. - */ - public String statName; - /** - * The percent of the stat value to apply. - */ + /** The percent of the stat value to apply. */ public double statPercent; - /** - * Whether or not this stat is a bonus value. - */ - public boolean isStatBonus; - - /** - * Whether or not this uses the owners level to modify - * any applicable graph. - */ - public boolean ownerLevel; - - /** - * The graph to use instead of the default graph. - */ - public String graphOverride; - - /** - * Whether or not a graph is used for this effect. - */ - public boolean useGraph = true; - - /** - * Whether this effect can stack with itself. - */ - public boolean exclusive; - - /** - * The amount the targets armor is reduced by for this - * effect. - */ + /** The amount the targets armor is reduced by for this effect. */ public double soakScale = 1.0; - /** - * Level of the effect. - */ + /** Level of the effect. */ public int level = -1; - /** - * Whether or not this effect is a 'transfer' - * effect (Applied to the enemy on a hit). - */ - public boolean isTransfer; - - /** - * The amount to resist/do knockback by. - */ + /** The 'effect group' this effect belongs to. + * + * An 'effect group is essentially any other effect that is the same general sort of effect, just with different details. + * + * For instance, an effect that grants +4 strength would group with one granting +8 strength, + * assuming that most other details were equal. */ + public EffectGroup group = new EffectGroup(); + + /** The amount to resist/do knockback by. */ public double resist; - /** - * Minimum value per monster. - */ + /** Minimum value per monster. */ public double minPer; - /** - * Maximum value per monster. - */ + /** Maximum value per monster. */ public double maxPer; - /** - * Range for effect. - */ + /** Range for effect. */ public double range; - /** - * Maximum count of monsters. - */ + /** Maximum count of monsters. */ public double maxCount; - /** - * The rate at which the effect fires. - */ + /** The rate at which the effect fires. */ public double pulse; - /** - * Create a new blank effect. - */ + /** Create a new blank effect. */ public Effect() { } - - /** - * Gets the 'effect group' this effect belongs to. - * - * An 'effect group is essentially any other effect that is the same general sort of effect, just with different details. - * - * For instance, an effect that grants +4 strength would group with one granting +8 strength, - * assuming that most other details were equal. - * - * @return The 'effect group' this effect belongs to. - */ - public String getEffectGroup() { - StringBuilder sb = new StringBuilder(); - - sb.append(name); - sb.append(type); - sb.append(damageType); - sb.append(hasDuration); - sb.append(statName); - sb.append(isStatBonus); - sb.append(ownerLevel); - sb.append(graphOverride); - sb.append(useGraph); - sb.append(exclusive); - sb.append(isTransfer); - - return sb.toString(); - } @Override public String toString() { StringBuilder sb = new StringBuilder(); - if (isTransfer) { + if (group.isTransfer) { sb.append("Inflict on Hit: "); } - Map<String, String> detMap = hasDuration ? EffectRepo.timeDetals : EffectRepo.detals; + Map<String, String> detMap = group.hasDuration ? EffectRepo.timeDetals : EffectRepo.detals; - if (detMap.containsKey(type) || (hasDuration && !EffectRepo.timeDetals.containsKey(type) && EffectRepo.detals.containsKey(type))) { + if (detMap.containsKey(group.type) || + (group.hasDuration + && !EffectRepo.timeDetals.containsKey(group.type) + && EffectRepo.detals.containsKey(group.type))) + { String fmt; - if (hasDuration && !EffectRepo.timeDetals.containsKey(type) && EffectRepo.detals.containsKey(type)) { - AffixLister.errOut.printf("Improvised details for timed %s\n", type); - fmt = EffectRepo.detals.get(type) + "for <DUR> seconds"; + if (group.hasDuration + && !EffectRepo.timeDetals.containsKey(group.type) + && EffectRepo.detals.containsKey(group.type)) + { + AffixLister.errOut.printf("Improvised details for timed %s\n", group.type); + fmt = EffectRepo.detals.get(group.type) + "for <DUR> seconds"; } else { - fmt = detMap.get(type); + fmt = detMap.get(group.type); } // Expand aliases first. - for (ReplPair repl : EffectRepo.replList) { - fmt = fmt.replaceAll(repl.find, repl.replace); - } + for (ReplPair repl : EffectRepo.replList) fmt = fmt.replaceAll(repl.find, repl.replace); - if (minValue <= 0 && maxValue <= 0) { - fmt = fmt.replaceAll("<C\\|([^|>]+)\\|([^|>]+)>", "$1"); - } - - if (minValue >= 0 && maxValue >= 0) { - fmt = fmt.replaceAll("<C\\|([^|>]+)\\|([^|>]+)>", "$2"); - } - - if (minPer <= 0 && maxPer <= 0) { - fmt = fmt.replaceAll("<MC\\|(\\w+)\\|(\\w+)>", "$1"); - } - - if (minPer >= 0 && maxPer >= 0) { - fmt = fmt.replaceAll("<MC\\|([^|>]+)\\|([^|>]+)>", "$2"); - } + if (minValue <= 0 && maxValue <= 0) { fmt = fmt.replaceAll("<C\\|([^|>]+)\\|([^|>]+)>", "$1"); } + if (minValue >= 0 && maxValue >= 0) { fmt = fmt.replaceAll("<C\\|([^|>]+)\\|([^|>]+)>", "$2"); } + if (minPer <= 0 && maxPer <= 0) { fmt = fmt.replaceAll("<MC\\|(\\w+)\\|(\\w+)>", "$1"); } + if (minPer >= 0 && maxPer >= 0) { fmt = fmt.replaceAll("<MC\\|([^|>]+)\\|([^|>]+)>", "$2"); } if (fmt.contains("<") || fmt.contains(">")) { - AffixLister.errOut.printf("WARN: Details for effect %s are malformatted (contains < or >):\n\t%s\n", type, fmt); + AffixLister.errOut.printf("WARN: Details for effect %s are malformatted (contains < or >):\n\t%s\n", group.type, fmt); } - sb.append(String.format(fmt, Math.abs(minValue), Math.abs(maxValue), duration, damageType.toLowerCase(), level, resist, name, Math.abs(minPer), Math.abs(maxPer), range, maxCount, pulse)); + sb.append(String.format(fmt, + Math.abs(minValue), Math.abs(maxValue), + duration, group.damageType.toLowerCase(), level, resist, group.name, + Math.abs(minPer), Math.abs(maxPer), range, maxCount, pulse)); } else { sb.append("No effect details for effect "); - sb.append(type); - sb.append(String.format(" with parameters (min %.2f, max %.2f, dur %.2f, type %s, level %d)", minValue, maxValue, duration, damageType.toLowerCase(), level, name)); + sb.append(group.type); + sb.append(String.format( + " with parameters (min %.2f, max %.2f, dur %.2f, type %s, level %d)", + minValue, maxValue, duration, group.damageType.toLowerCase(), level, group.name)); if (AffixLister.addFileName) { sb.append(" from file "); sb.append(fName); } - if (hasDuration) AffixLister.errOut.print("TIMED: "); + if (group.hasDuration) AffixLister.errOut.print("TIMED: "); AffixLister.errOut.println(sb.toString()); } - if (name != null) { + if (group.name != null) { sb.append(" (named "); - sb.append(name); + sb.append(group.name); sb.append(")"); } - if (exclusive) sb.append(" (Exclusive)"); + if (group.exclusive) sb.append(" (Exclusive)"); - if (graphOverride != null) { + if (group.graphOverride != null) { sb.append(" (Uses "); - sb.append(graphOverride); + sb.append(group.graphOverride); sb.append(" graph)"); } - if (ownerLevel) { + if (group.ownerLevel) { sb.append(" (Uses owner level for graph)"); } @@ -265,154 +149,77 @@ public class Effect { sb.append(")"); } - if (statName != null) { - sb.append(String.format(" (%.2f of stat %s", statPercent, statName)); - if (isStatBonus) sb.append(" as bonus)"); + if (group.statName != null) { + sb.append(String.format(" (%.2f of stat %s", statPercent, group.statName)); + + if (group.isStatBonus) sb.append(" as bonus)"); else sb.append(")"); } - if (!useGraph) sb.append(" (Ignoring graph)"); + if (!group.useGraph) sb.append(" (Ignoring graph)"); return sb.toString(); } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((damageType == null) ? 0 : damageType.hashCode()); - long temp; - temp = Double.doubleToLongBits(duration); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + (exclusive ? 1231 : 1237); - result = prime * result - + ((graphOverride == null) ? 0 : graphOverride.hashCode()); - result = prime * result + (hasDuration ? 1231 : 1237); - result = prime * result + (isStatBonus ? 1231 : 1237); - result = prime * result + (isTransfer ? 1231 : 1237); - result = prime * result + level; - temp = Double.doubleToLongBits(maxCount); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(maxPer); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(maxValue); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(minPer); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(minValue); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + (ownerLevel ? 1231 : 1237); - temp = Double.doubleToLongBits(pulse); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(range); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(resist); - result = prime * result + (int) (temp ^ (temp >>> 32)); - temp = Double.doubleToLongBits(soakScale); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + ((statName == null) ? 0 : statName.hashCode()); - temp = Double.doubleToLongBits(statPercent); - result = prime * result + (int) (temp ^ (temp >>> 32)); - result = prime * result + ((type == null) ? 0 : type.hashCode()); - result = prime * result + (useGraph ? 1231 : 1237); - return result; - } @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Effect other = (Effect) obj; - if (damageType == null) { - if (other.damageType != null) - return false; - } else if (!damageType.equals(other.damageType)) - return false; - if (Double.doubleToLongBits(duration) != Double.doubleToLongBits(other.duration)) - return false; - if (exclusive != other.exclusive) - return false; - if (graphOverride == null) { - if (other.graphOverride != null) - return false; - } else if (!graphOverride.equals(other.graphOverride)) - return false; - if (hasDuration != other.hasDuration) - return false; - if (isStatBonus != other.isStatBonus) - return false; - if (isTransfer != other.isTransfer) - return false; - if (level != other.level) - return false; - if (Double.doubleToLongBits(maxCount) != Double.doubleToLongBits(other.maxCount)) - return false; - if (Double.doubleToLongBits(maxPer) != Double.doubleToLongBits(other.maxPer)) - return false; - if (Double.doubleToLongBits(maxValue) != Double.doubleToLongBits(other.maxValue)) - return false; - if (Double.doubleToLongBits(minPer) != Double.doubleToLongBits(other.minPer)) - return false; - if (Double.doubleToLongBits(minValue) != Double.doubleToLongBits(other.minValue)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (ownerLevel != other.ownerLevel) - return false; - if (Double.doubleToLongBits(pulse) != Double.doubleToLongBits(other.pulse)) - return false; - if (Double.doubleToLongBits(range) != Double.doubleToLongBits(other.range)) - return false; - if (Double.doubleToLongBits(resist) != Double.doubleToLongBits(other.resist)) - return false; - if (Double.doubleToLongBits(soakScale) - != Double.doubleToLongBits(other.soakScale)) - return false; - if (statName == null) { - if (other.statName != null) - return false; - } else if (!statName.equals(other.statName)) - return false; - if (Double.doubleToLongBits(statPercent) - != Double.doubleToLongBits(other.statPercent)) - return false; - if (type == null) { - if (other.type != null) - return false; - } else if (!type.equals(other.type)) - return false; - if (useGraph != other.useGraph) - return false; - return true; - } - - /** - * Parse an effect. + public int hashCode() { + return Objects.hash(duration, fName, group, level, maxCount, maxPer, maxValue, + minPer, minValue, pulse, range, resist, soakScale, statPercent); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Effect other = (Effect) obj; + return Double.doubleToLongBits(duration) + == Double.doubleToLongBits(other.duration) + && Objects.equals(fName, other.fName) + && Objects.equals(group, other.group) && level == other.level + && Double.doubleToLongBits(maxCount) + == Double.doubleToLongBits(other.maxCount) + && Double.doubleToLongBits(maxPer) + == Double.doubleToLongBits(other.maxPer) + && Double.doubleToLongBits(maxValue) + == Double.doubleToLongBits(other.maxValue) + && Double.doubleToLongBits(minPer) + == Double.doubleToLongBits(other.minPer) + && Double.doubleToLongBits(minValue) + == Double.doubleToLongBits(other.minValue) + && Double.doubleToLongBits(pulse) == Double.doubleToLongBits(other.pulse) + && Double.doubleToLongBits(range) == Double.doubleToLongBits(other.range) + && Double.doubleToLongBits(resist) + == Double.doubleToLongBits(other.resist) + && Double.doubleToLongBits(soakScale) + == Double.doubleToLongBits(other.soakScale) + && Double.doubleToLongBits(statPercent) + == Double.doubleToLongBits(other.statPercent); + } + + /** Parse an effect. + * * @param afx The affix the effect belongs to. * @param scn The scanner to read from. * @param scnSource The name of the scanner. + * * @return An effect, read from the scanner. */ public static Effect parseEffect(Affix afx, Scanner scn, String scnSource) { return parseEffect(afx, scn, scnSource, new ArrayList<>()); } - /** - * Parse an effect. + /** Parse an effect. + * * @param afx The affix the effect belongs to. * @param scn The scanner to read from. * @param scnSource The name of the scanner. * @param errs Repository for errors found while parsing. - * @return An effect, read from the scanner. - */ + * + * @return An effect, read from the scanner. */ public static Effect parseEffect(Affix afx, Scanner scn, String scnSource, List<String> errs) { Effect efct = new Effect(); @@ -432,11 +239,11 @@ public class Effect { if (splits.length == 1) continue; if (ln.contains("NAME")) { - efct.name = splits[1]; + efct.group.name = splits[1]; } else if (ln.contains("DAMAGE_TYPE")) { - efct.damageType = splits[1]; + efct.group.damageType = splits[1]; } else if (ln.contains("TYPE")) { - efct.type = splits[1]; + efct.group.type = splits[1]; } else if (ln.contains("ACTIVATION")) { switch (splits[1]) { case "DYNAMIC": @@ -446,31 +253,31 @@ public class Effect { // actual difference. break; case "TRANSFER": - efct.isTransfer = true; + efct.group.isTransfer = true; break; default: - errs.add(String.format("Malformed activation type: (%s) (%s) (%s)\n", splits[1], efct.name, afx.intName)); + errs.add(String.format("Malformed activation type: (%s) (%s) (%s)\n", splits[1], efct.group.name, afx.intName)); } } else if (ln.contains("DURATION")) { if (splits[1].equals("ALWAYS")) { - efct.hasDuration = false; + efct.group.hasDuration = false; efct.duration = Double.POSITIVE_INFINITY; } else if (splits[1].equals("INSTANT")) { - efct.hasDuration = false; + efct.group.hasDuration = false; efct.duration = Double.NaN; } else if (splits[1].equals("PERCENT")) { - efct.hasDuration = false; + efct.group.hasDuration = false; efct.duration = Double.NaN; errs.add(String.format("WARN: Punting on DURATION:PERCENT for %s\n", scnSource)); } else if (splits[1].equals("0")) { - efct.hasDuration = false; + efct.group.hasDuration = false; efct.duration = 0.0; } else { - efct.hasDuration = true; + efct.group.hasDuration = true; if (splits[1].equalsIgnoreCase("instant")) { efct.duration = -1; @@ -487,19 +294,19 @@ public class Effect { } else if (ln.contains("LEVEL:")) { efct.level = Integer.parseInt(splits[1]); } else if (ln.contains("EXCLUSIVE")) { - efct.exclusive = Boolean.parseBoolean(splits[1]); + efct.group.exclusive = Boolean.parseBoolean(splits[1]); } else if (ln.contains("GRAPHOVERRIDE")) { - efct.graphOverride = splits[1]; + efct.group.graphOverride = splits[1]; } else if (ln.contains("USEOWNERLEVEL")) { - efct.ownerLevel = Boolean.parseBoolean(splits[1]); + efct.group.ownerLevel = Boolean.parseBoolean(splits[1]); } else if (ln.contains("NOGRAPH")) { - efct.useGraph = Boolean.parseBoolean(splits[1]); + efct.group.useGraph = Boolean.parseBoolean(splits[1]); } else if (ln.contains("STATNAME")) { - efct.statName = splits[1]; + efct.group.statName = splits[1]; } else if (ln.contains("STATPERCENT")) { efct.statPercent = Double.parseDouble(splits[1]); } else if (ln.contains("STATMODIFIERISBONUS")) { - efct.isStatBonus = Boolean.parseBoolean(splits[1]); + efct.group.isStatBonus = Boolean.parseBoolean(splits[1]); } else if (ln.contains("RESISTANCE:")) { efct.resist = Double.parseDouble(splits[1]); } else if (ln.contains("FORCE:")) { @@ -525,13 +332,11 @@ public class Effect { String fmt = "\t\tProcessed effect %s from %s in %d nanoseconds (%.2f seconds)\n"; double seconds = (((endTime - startTime) / 1000000000)); - errs.add(String.format(fmt, efct.name, scnSource, endTime - startTime, seconds)); + errs.add(String.format(fmt, efct.group.name, scnSource, endTime - startTime, seconds)); } effectCount += 1; return efct; } - - } diff --git a/src/main/java/tlIItools/EffectGroup.java b/src/main/java/tlIItools/EffectGroup.java new file mode 100644 index 00000000..9f4ad49b --- /dev/null +++ b/src/main/java/tlIItools/EffectGroup.java @@ -0,0 +1,120 @@ +package tlIItools; + +import java.util.*; + +/** An 'effect group'. + * + * This groups similar effects together, the same way affix groups group affixs + * together. + * + * @author Ben Culkin */ +public class EffectGroup { + /** The name of the effect. */ + public String name; + /** The specific effect that happens. */ + public String type; + /** Damage type for the effect, if applicable. */ + public String damageType = "physical"; + /** Whether or not we have a duration or not. */ + public boolean hasDuration; + /** The name of the stat that applies to this affect. */ + public String statName; + /** Whether or not this stat is a bonus value. */ + public boolean isStatBonus; + /** Whether or not this uses the owners level to modify any applicable graph. */ + public boolean ownerLevel; + /** Whether or not a graph is used for this effect. */ + public boolean useGraph = true; + /** The graph to use instead of the default graph. */ + public String graphOverride; + /** Whether this effect can stack with itself. */ + public boolean exclusive; + /** Whether or not this effect is a 'transfer' effect (Applied to the enemy on a hit). */ + public boolean isTransfer; + + public String summary() { + StringBuilder sb = new StringBuilder(); + + if (isTransfer) sb.append("Transfer: "); + sb.append(type); + if (name != null && !name.equals("")) { + sb.append(" (named "); + sb.append(name); + sb.append(")"); + } + + if (hasDuration) sb.append(" (timed)"); + if (statName != null && !name.equals("")) { + sb.append(" (uses stat "); + sb.append(statName); + if (isStatBonus) sb.append(" as a bonus"); + sb.append(")"); + } + + if (ownerLevel) sb.append(" (uses owner level)"); + if (useGraph) { + sb.append(" (uses "); + if (graphOverride != null && !graphOverride.equals("")) sb.append(graphOverride); + else sb.append("default"); + sb.append(" graph)"); + } + + if (exclusive) sb.append(" (exclusive)"); + + // @TODO Ben Culkin 12/31/2020 :FancyEffectSummary + // + // EffectGroups should probably use something from EffectRepo to better + // output the summary for a particular group type + // String fmt = "%s (name %s, damageType %s, hasDuration %s, stat %s, isBonus %s, ownerLevel %s, useGraph %s, graphOverride %s, exclusive %s, isTransfer %s)"; + + // sb.append(String.format(fmt, type, name, damageType, hasDuration, statName, isStatBonus, ownerLevel, useGraph, graphOverride, exclusive, isTransfer)); + + return sb.toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + sb.append(name); + sb.append(type); + sb.append(damageType); + sb.append(hasDuration); + sb.append(statName); + sb.append(isStatBonus); + sb.append(ownerLevel); + sb.append(graphOverride); + sb.append(useGraph); + sb.append(exclusive); + sb.append(isTransfer); + + return sb.toString(); + } + + @Override + public int hashCode() { + return Objects.hash(damageType, exclusive, graphOverride, hasDuration, + isStatBonus, isTransfer, name, ownerLevel, statName, type, useGraph); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + + EffectGroup other = (EffectGroup) obj; + + return Objects.equals(damageType, other.damageType) + && Objects.equals(graphOverride, other.graphOverride) + && Objects.equals(name, other.name) + && Objects.equals(statName, other.statName) + && Objects.equals(type, other.type) + && exclusive == other.exclusive + && hasDuration == other.hasDuration + && isStatBonus == other.isStatBonus + && isTransfer == other.isTransfer + && ownerLevel == other.ownerLevel + && useGraph == other.useGraph; + } +} diff --git a/src/main/java/tlIItools/EffectRepo.java b/src/main/java/tlIItools/EffectRepo.java index f2f0d076..05151a48 100644 --- a/src/main/java/tlIItools/EffectRepo.java +++ b/src/main/java/tlIItools/EffectRepo.java @@ -1,40 +1,26 @@ package tlIItools; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; +import java.io.*; +import java.util.*; import java.util.Map.Entry; -/** - * Repository class for storing information needed for parsing/outputing +/** Repository class for storing information needed for parsing/outputing * effects. * - * @author Ben Culkin - * - */ + * @author Ben Culkin */ public class EffectRepo { // NOTE: consider making these use function accessors in the future? // --bculkin, 6/24/20 - /** - * The list of detail strings for skills. - */ + + /** The list of detail strings for skills. */ public static Map<String, String> detals; - /** - * The list of detail strings for timed skills. - */ + /** The list of detail strings for timed skills. */ public static Map<String, String> timeDetals; - /** - * The list of replacements for detail strings. - */ + /** The list of replacements for detail strings. */ public static List<ReplPair> replList; - /* - * Init. lists from files. - */ + /* Init. lists from files. */ static { try (FileReader detalReader = new FileReader("data/affix-detals.txt")) { detals = readDetails(new Scanner(detalReader)); @@ -42,8 +28,7 @@ public class EffectRepo { AffixLister.errOut.println("Error loading affix detail text"); } - try (FileReader timedDetalReader - = new FileReader("data/timed-affix-detals.txt")) { + try (FileReader timedDetalReader = new FileReader("data/timed-affix-detals.txt")) { timeDetals = readDetails(new Scanner(timedDetalReader)); } catch (IOException ioex) { AffixLister.errOut.println("Error loading timed affix detail text"); @@ -56,36 +41,31 @@ public class EffectRepo { } } - /** - * Read effect detail strings from an input source. + /** Read effect detail strings from an input source. + * + * @param scn The source to read from. * - * @param scn - * The source to read from. - * @return The map of effect details to use. - */ + * @return The map of effect details to use. */ public static Map<String, String> readDetails(Scanner scn) { Map<String, String> detalMap = new HashMap<>(); return readDetails(detalMap, scn); } - /** - * Read effect detail strings from an input source, adding to an existing set. + /** Read effect detail strings from an input source, adding to an existing set. + * + * @param detalMap The details to add to. + * @param scn The source to read from. * - * @param detalMap - * The details to add to. - * @param scn - * The source to read from. - * @return The map of effect details to use. - */ - public static Map<String, String> readDetails(Map<String, String> detalMap, - Scanner scn) { + * @return The map of effect details to use. */ + public static Map<String, String> readDetails( + Map<String, String> detalMap, Scanner scn) + { while (scn.hasNextLine()) { String name = scn.nextLine().trim(); - if (name.equals("")) - continue; - if (name.startsWith("#")) - continue; + + if (name.equals("")) continue; + if (name.startsWith("#")) continue; String body; do { @@ -98,18 +78,17 @@ public class EffectRepo { return detalMap; } - /** - * Sanity check the loaded format strings. - */ + /** Sanity check the loaded format strings. */ public static void sanityCheckFormats() { for (Entry<String, String> detal : detals.entrySet()) { String fmt = detal.getValue(); - AffixLister.errOut.printf("\tTRACE: Applying replacements for %s\n", - detal.getKey()); + AffixLister.errOut.printf("\tTRACE: Applying replacements for %s\n", detal.getKey()); + for (ReplPair repl : replList) { String tmp = fmt; fmt = fmt.replaceAll(repl.find, repl.replace); + if (!fmt.equals(tmp)) { String outFmt = "\t\tTRACE: Replaced %s with %s: \n\t\t%s\n\t\t%s\n"; @@ -118,8 +97,7 @@ public class EffectRepo { } if (fmt.contains("<") || fmt.contains(">")) { - String warnFmt - = "WARN: Details for effect %s are malformated (contains < or >):\n\t%s\n"; + String warnFmt = "WARN: Details for effect %s are malformated (contains < or >):\n\t%s\n"; AffixLister.errOut.printf(warnFmt, detal.getKey(), fmt); } @@ -133,8 +111,7 @@ public class EffectRepo { } if (fmt.contains("<") || fmt.contains(">")) { - String warnFmt - = "WARN: Details for timed effect %s are malformatted (contains < or >):\n\t%s\n"; + String warnFmt = "WARN: Details for timed effect %s are malformatted (contains < or >):\n\t%s\n"; AffixLister.errOut.printf(warnFmt, detal.getKey(), fmt); } } diff --git a/src/main/java/tlIItools/LevelRange.java b/src/main/java/tlIItools/LevelRange.java new file mode 100644 index 00000000..b0d620bf --- /dev/null +++ b/src/main/java/tlIItools/LevelRange.java @@ -0,0 +1,135 @@ +package tlIItools; + +import java.util.*; + +public class LevelRange implements Comparable<LevelRange> { + /* + * if (minLevel <= 1 && maxLevel == 999) { + * sb.append("No Level Range"); + * } else if (minLevel != 1 && maxLevel != 999) { + * sb.append("Level Range: "); + * sb.append(minLevel); + * sb.append("-"); + * sb.append(maxLevel); + * } else if (minLevel <= 1) { + * sb.append("Max Level: "); + * sb.append(maxLevel); + * } else if (maxLevel == 999) { + * sb.append("Minimum Level: "); + * sb.append(minLevel); + * } */ + + public int minLevel; + public int maxLevel; + + public LevelRange() { + minLevel = 1; + maxLevel = 999; + } + + public LevelRange(int minLevel, int maxLevel) { + this.minLevel = minLevel; + this.maxLevel = maxLevel; + } + + private void clamp() { + minLevel = Math.max(1, minLevel); + maxLevel = Math.min(999, maxLevel); + } + + public boolean isUnrestricted() { + return minLevel <= 1 && maxLevel >= 999; + } + + public boolean noLowerBound() { + return minLevel <= 1; + } + + public boolean noUpperBound() { + return maxLevel >= 999; + } + + @Override + public String toString() { + clamp(); + + StringBuilder sb = new StringBuilder(); + + if (minLevel <= 1 && maxLevel >= 999) { + sb.append("No Level Range"); + } else if (minLevel > 1 && maxLevel < 999) { + sb.append("Level Range: "); + sb.append(minLevel); + sb.append("-"); + sb.append(maxLevel); + } else if (minLevel <= 1) { + sb.append("Max Level: "); + sb.append(maxLevel); + } else if (maxLevel >= 999) { + sb.append("Minimum Level: "); + sb.append(minLevel); + } + + return sb.toString(); + } + + @Override + public int hashCode() { + clamp(); + + return Objects.hash(maxLevel, minLevel); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + + LevelRange other = (LevelRange) obj; + + clamp(); + other.clamp(); + + if (isUnrestricted() && other.isUnrestricted()) { + return true; + } else if (noLowerBound()) { + if (other.noLowerBound()) return maxLevel == other.maxLevel; + else return false; + } else if (noUpperBound()) { + if (other.noUpperBound()) return minLevel == other.minLevel; + else return false; + } else { + return maxLevel == other.maxLevel && minLevel == other.minLevel; + } + } + + @Override + public int compareTo(LevelRange other) { + clamp(); + other.clamp(); + + if (this.equals(other)) return 0; + + // Unrestricted ranges sort above all others + if (isUnrestricted()) return 1; + if (other.isUnrestricted()) return -1; + + if (noLowerBound()) { + if (other.noLowerBound()) { + return maxLevel - other.maxLevel; + } else { + return -1; + } + } else if (noUpperBound()) { + if (other.noUpperBound()) { + return minLevel - other.minLevel; + } else { + return 1; + } + } else { + if (minLevel == other.minLevel) return maxLevel - other.maxLevel; + else return minLevel - other.minLevel; + } + } +} diff --git a/src/main/java/tlIItools/Main.java b/src/main/java/tlIItools/Main.java index 234f0bd3..a4d09bff 100644 --- a/src/main/java/tlIItools/Main.java +++ b/src/main/java/tlIItools/Main.java @@ -1,6 +1,12 @@ package tlIItools; +/** Main method for TLIITools + * + * @author Ben Culkin */ public class Main { + /** Main method. + * + * @param args Unused CLI args. */ public static void main(String[] args) { // TODO implement this } diff --git a/src/main/java/tlIItools/NameFileReader.java b/src/main/java/tlIItools/NameFileReader.java index 87407162..a9646942 100644 --- a/src/main/java/tlIItools/NameFileReader.java +++ b/src/main/java/tlIItools/NameFileReader.java @@ -1,113 +1,71 @@ package tlIItools; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintStream; -import java.io.Reader; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Scanner; - -/** - * Reads in a list of file names to process. +import java.io.*; + +import java.util.*; + +/** Reads in a list of file names to process. * - * @author Ben Culkin - */ + * @author Ben Culkin */ public class NameFileReader { - /** - * Are we attempting to guess group names? - */ + /** Are we attempting to guess group names? */ public boolean guessGroups; - - /** - * Regex to use for guessing group names. - */ + /** Regex to use for guessing group names. */ public String groupRx; - - /** - * The default group to put files into. - */ + /** The default group to put files into. */ public String defGroup; - - /** - * The map of file groups. - */ + /** The map of file groups. */ public Map<String, List<String>> fNames; - /* - * The current group. - */ + /* The current group. */ private String curGroup; - /* - * The list of files for the current group. - */ + /* The list of files for the current group. */ private List<String> curList; - /** - * Counts the files read in. - */ + /** Counts the files read in. */ public int fCount; + /** Stream to write normal output to. */ public PrintStream normOut = System.out; + /** Stream to write error output to. */ public PrintStream errOut = System.err; - /** - * Create a new name reader using the default settings. + /** Create a new name reader using the default settings. * - * Guessing groups is disabled by default. - */ + * Guessing groups is disabled by default. */ public NameFileReader() { this(false); } - /** - * Create a new name reader using the default settings. + /** Create a new name reader using the default settings. * - * @param guessGroups - * Controls whether or not to try to guess file groups from file - * names. - */ + * @param guessGroups Controls whether or not to try to guess file groups from file names. */ public NameFileReader(boolean guessGroups) { this(new HashMap<>(), "default", guessGroups); } - /** - * Create a new name reader using the specified settings. - * - * @param fNames - * The set of groups to add files to. + /** Create a new name reader using the specified settings. * - * @param defGroup - * The name of the default file group. - * - * @param guessGroups - * Whether or not to attempt to guess group names. - */ + * @param fNames The set of groups to add files to. + * @param defGroup The name of the default file group. + * @param guessGroups Whether or not to attempt to guess group names. */ public NameFileReader(Map<String, List<String>> fNames, String defGroup, boolean guessGroups) { - if (!fNames.containsKey(defGroup)) - fNames.put(defGroup, new ArrayList<>()); + if (!fNames.containsKey(defGroup)) fNames.put(defGroup, new ArrayList<>()); this.fNames = fNames; - this.defGroup = defGroup; - + this.defGroup = defGroup; this.guessGroups = guessGroups; + this.curGroup = defGroup; - this.curGroup = defGroup; - this.curList = fNames.get(curGroup); + this.curList = fNames.get(curGroup); this.fCount = 0; } - /** - * Read in file names from a file. + /** Read in file names from a file. * - * @param from - * The name of the file to read from. - */ + * @param from The name of the file to read from. */ public void readFrom(String from) { try (FileReader fr = new FileReader(from)) { readFrom(fr); @@ -118,13 +76,9 @@ public class NameFileReader { } } - /** - * Read in file names from an input source. - * - * @param r - * The input source to read from. + /** Read in file names from an input source. * - */ + * @param r The input source to read from. */ public void readFrom(Reader r) { Scanner scn = new Scanner(r); @@ -153,12 +107,9 @@ public class NameFileReader { scn.close(); } - /** - * Swap to a new file group. + /** Swap to a new file group. * - * @param groupName - * The name of the group to swap to. - */ + * @param groupName The name of the group to swap to. */ public void swapGroup(String groupName) { curGroup = groupName; @@ -171,12 +122,19 @@ public class NameFileReader { } } + /** Add a file to this file reader. + * + * @param fName The file to add. */ public void addFile(String fName) { curList.add(fName); fCount += 1; } - + + /** Add a file to this file reader. + * + * @param groupName The group to add the file to. + * @param fName The file to add. */ public void addFile(String groupName, String fName) { fNames.computeIfAbsent(groupName, (key) -> new ArrayList<>()).add(fName); diff --git a/src/main/java/tlIItools/ReplPair.java b/src/main/java/tlIItools/ReplPair.java index 74012716..90717a0a 100644 --- a/src/main/java/tlIItools/ReplPair.java +++ b/src/main/java/tlIItools/ReplPair.java @@ -1,51 +1,31 @@ package tlIItools; -import java.util.ArrayList; -import java.util.List; -import java.util.Scanner; +import java.util.*; -/** - * String pairs for replacements. +/** String pairs for replacements. * - * @author Ben Culkin - */ + * @author Ben Culkin */ public class ReplPair implements Comparable<ReplPair> { - /** - * Represents an error encountered parsing ReplPairs + /** Represents an error encountered parsing ReplPairs * - * @author Ben Culkin - */ + * @author Ben Culkin */ public static class ReplError { - /** - * The line the error occured on. - */ + /** The line the error occured on. */ public int line; - /** - * The number of pairs we have processed so far. - */ + /** The number of pairs we have processed so far. */ public int numPairs; - /** - * The text of the line we errored on. - */ + /** The text of the line we errored on. */ public String txt; - /** - * The message of the error. - */ + /** The message of the error. */ public String msg; - /** - * Create a new ReplPair parse error. + /** Create a new ReplPair parse error. * - * @param lne - * The line the error occured on. - * @param nPairs - * The number of pairs processed up to this point. - * @param msg - * The message detailing the error. - * @param txt - * The text that caused the error. - */ + * @param lne The line the error occured on. + * @param nPairs The number of pairs processed up to this point. + * @param msg The message detailing the error. + * @param txt The text that caused the error. */ public ReplError(int lne, int nPairs, String msg, String txt) { line = lne; numPairs = nPairs; @@ -65,86 +45,56 @@ public class ReplPair implements Comparable<ReplPair> { } } - /** - * The priority for this replacement. - */ + /** The priority for this replacement. */ public int priority; - - /** - * The name of this replacement. + /** The name of this replacement. * - * Defaults to the 'find' string. - */ + * Defaults to the 'find' string. */ public String name; - /** - * The string to look for. - */ + /** The string to look for. */ public String find; - - /** - * The string to replace it with. - */ + /** The string to replace it with. */ public String replace; - /** - * Create a new blank replacement pair. - */ + /** Create a new blank replacement pair. */ public ReplPair() { this("", "", 1, null); } - /** - * Create a new replacement pair with a priority of 1. + /** Create a new replacement pair with a priority of 1. * - * @param f - * The string to find. - * @param r - * The string to replace. + * @param f The string to find. + * @param r The string to replace. */ public ReplPair(String f, String r) { this(f, r, 1); } - /** - * Create a new named replacement pair with a priority of 1. + /** Create a new named replacement pair with a priority of 1. * - * @param f - * The string to find. - * @param r - * The string to replace. - * @param n - * The name of the replacement pair. + * @param f The string to find. + * @param r The string to replace. + * @param n The name of the replacement pair. */ public ReplPair(String f, String r, String n) { this(f, r, 1, n); } - /** - * Create a new replacement pair with a set priority. + /** Create a new replacement pair with a set priority. * - * @param f - * The string to find. - * @param r - * The string to replace. - * @param p - * The priority for the replacement. - */ + * @param f The string to find. + * @param r The string to replace. + * @param p The priority for the replacement. */ public ReplPair(String f, String r, int p) { this(f, r, p, f); } - /** - * Create a new replacement pair with a set priority and name. + /** Create a new replacement pair with a set priority and name. * - * @param f - * The string to find. - * @param r - * The string to replace. - * @param n - * The name of the replacement pair. - * @param p - * The priority for the replacement. - */ + * @param f The string to find. + * @param r The string to replace. + * @param n The name of the replacement pair. + * @param p The priority for the replacement. */ public ReplPair(String f, String r, int p, String n) { find = f; replace = r; @@ -153,29 +103,23 @@ public class ReplPair implements Comparable<ReplPair> { priority = p; } - /** - * Read a list of replacement pairs from an input source. + + /** Read a list of replacement pairs from an input source. * - * @param scn - * The source to read the replacements from. - * @return - * The list of replacements. - */ + * @param scn The source to read the replacements from. + * + * @return The list of replacements. */ public static List<ReplPair> readList(Scanner scn) { return ReplPair.readList(new ArrayList<>(), scn); } - /** - * Read a list of replacement pairs from an input source, adding them to + /** Read a list of replacement pairs from an input source, adding them to * an existing list. * - * @param detals - * The list to add the replacements to. - * @param scn - * The source to read the replacements from. - * @return - * The list of replacements. - */ + * @param detals The list to add the replacements to. + * @param scn The source to read the replacements from. + * + * @return The list of replacements. */ public static List<ReplPair> readList(List<ReplPair> detals, Scanner scn) { List<ReplError> errList = new ArrayList<>(); @@ -186,25 +130,22 @@ public class ReplPair implements Comparable<ReplPair> { if (errList.size() == 0) errString = "An error"; else errString = "Errors"; - throw new IllegalArgumentException(String.format("%s occured parsing replacement pairs:\n%s", errString, errList)); + throw new IllegalArgumentException(String.format( + "%s occured parsing replacement pairs:\n%s", + errString, errList)); } return rplPar; } - /** - * Read a list of replacement pairs from an input source, adding them to + /** Read a list of replacement pairs from an input source, adding them to * an existing list. * - * @param detals - * The list to add the replacements to. - * @param scn - * The source to read the replacements from. - * @param errs - * The list to stick errors in. - * @return - * The list of replacements. - */ + * @param detals The list to add the replacements to. + * @param scn The source to read the replacements from. + * @param errs The list to stick errors in. + * + * @return The list of replacements. */ public static List<ReplPair> readList(List<ReplPair> detals, Scanner scn, List<ReplError> errs) { int lno = 0; int pno = 0; @@ -236,8 +177,7 @@ public class ReplPair implements Comparable<ReplPair> { // Read in the next uncommented line do { if (!scn.hasNextLine()) { - String msg = - "Ran out of input looking for replacement body for raw name " + name; + String msg = "Ran out of input looking for replacement body for raw name " + name; errs.add(new ReplError(lno, pno, msg, null)); break; @@ -247,7 +187,6 @@ public class ReplPair implements Comparable<ReplPair> { lno += 1; } while (body.startsWith("#")); - rp.replace = body; resList.add(rp); |
