Skip to content

Commit

Permalink
🐛 Restore spell class/subclass lists; fix subclass index
Browse files Browse the repository at this point in the history
  • Loading branch information
ebullient committed May 14, 2023
1 parent 238cedf commit 2fcf744
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 68 deletions.
23 changes: 23 additions & 0 deletions src/main/java/dev/ebullient/convert/config/TtrpgConfig.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
package dev.ebullient.convert.config;

import java.io.File;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.NullNode;

import dev.ebullient.convert.io.Tui;
import io.quarkus.runtime.annotations.RegisterForReflection;
Expand Down Expand Up @@ -59,6 +63,21 @@ public static Map<String, String> imageFallbackPaths() {
return activeConfig().fallbackImagePaths;
}

public static JsonNode readIndex(String key) {
String file = activeConfig().indexes.get(key);
Optional<Path> root = file == null ? Optional.empty() : tui.resolvePath(Path.of(file));
if (root.isEmpty()) {
return NullNode.getInstance();
}
File indexFile = root.get().resolve(file).toFile();
try {
return Tui.MAPPER.readTree(indexFile);
} catch (Exception e) {
tui.errorf("Failed to read index file %s: %s", indexFile, e.getMessage());
return NullNode.getInstance();
}
}

public static JsonNode activeGlobalConfig(String key) {
return activeConfig().data.get(key);
}
Expand Down Expand Up @@ -114,6 +133,7 @@ protected static void readSystemConfig(JsonNode node) {
config.fallbackImagePaths.putAll(ConfigKeys.fallbackImage.getAsMap(config5e));
config.markerFiles.addAll(ConfigKeys.markerFiles.getAsList(config5e));
config.sources.addAll(ConfigKeys.sources.getAsList(config5e));
config.indexes.putAll(ConfigKeys.indexes.getAsKeyLowerMap(config5e));

Map<String, List<Fix>> fixes = ConfigKeys.fixes.getAs(config5e, FIXES);
if (fixes != null) {
Expand All @@ -129,6 +149,7 @@ protected static void readSystemConfig(JsonNode node) {
config.fallbackImagePaths.putAll(ConfigKeys.fallbackImage.getAsMap(configPf2e));
config.markerFiles.addAll(ConfigKeys.markerFiles.getAsList(configPf2e));
config.sources.addAll(ConfigKeys.sources.getAsList(configPf2e));
config.indexes.putAll(ConfigKeys.indexes.getAsKeyLowerMap(configPf2e));

Map<String, List<Fix>> fixes = ConfigKeys.fixes.getAs(configPf2e, FIXES);
if (fixes != null) {
Expand All @@ -144,6 +165,7 @@ static class DatasourceConfig {
final Map<String, String> longToAbv = new HashMap<>();
final Map<String, String> fallbackImagePaths = new HashMap<>();
final Map<String, List<Fix>> fixes = new HashMap<>();
final Map<String, String> indexes = new HashMap<>();
final List<String> sources = new ArrayList<>();
final List<String> markerFiles = new ArrayList<>();

Expand Down Expand Up @@ -171,6 +193,7 @@ enum ConfigKeys {
config5e,
configPf2e,
fixes,
indexes,
markerFiles,
srdEntries,
properties,
Expand Down
14 changes: 11 additions & 3 deletions src/main/java/dev/ebullient/convert/io/Tui.java
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,16 @@ public static String slugify(String s) {
return slugifier().slugify(s);
}

public Optional<Path> resolvePath(Path path) {
if (path == null) {
return Optional.empty();
}
// find the right source root (there could be several)
return inputRoot.stream()
.filter(x -> x.resolve(path).toFile().exists())
.findFirst();
}

public void copyImages(Collection<ImageRef> images, Map<String, String> fallbackPaths) {
for (ImageRef image : images) {
Path targetPath = output.resolve(image.targetFilePath());
Expand All @@ -275,9 +285,7 @@ public void copyImages(Collection<ImageRef> images, Map<String, String> fallback
}

// find the right source root (there could be several)
Optional<Path> sourceRoot = inputRoot.stream()
.filter(x -> x.resolve(image.sourcePath()).toFile().exists())
.findFirst();
Optional<Path> sourceRoot = resolvePath(image.sourcePath());

// adjust basePath for relocated image
Path relativeImagePath = image.sourcePath();
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/dev/ebullient/convert/tools/NodeReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -102,6 +103,20 @@ default Iterable<JsonNode> iterableEntries(JsonNode source) {
return () -> entries.elements();
}

default Iterable<Entry<String, JsonNode>> iterableFields(JsonNode source) {
if (source == null) {
return List.of();
}
return () -> source.fields();
}

default Iterable<String> iterableFieldNames(JsonNode source) {
if (source == null) {
return List.of();
}
return () -> source.fieldNames();
}

default String join(String joiner, Collection<String> list) {
if (list == null || list.isEmpty()) {
return "";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.JsonNode;

Expand All @@ -26,7 +27,8 @@ protected QuteBase buildQuteResource() {
SchoolEnum school = getSchool();
String level = node.get("level").asText();

Collection<String> classes = spellClasses(school);
Set<String> classes = indexedSpellClasses();
classes.addAll(spellClasses(school)); // legacy

List<String> tags = new ArrayList<>(sources.getSourceTags());

Expand Down Expand Up @@ -210,6 +212,25 @@ String spellCastingTime() {
time.get("unit").asText());
}

Set<String> indexedSpellClasses() {
Collection<String> list = index().classesForSpell(this.sources.getKey());

return list.stream()
.filter(k -> index().isIncluded(k))
.map(k -> {
Tools5eSources sources = Tools5eSources.findSources(k);
Tools5eIndexType type = Tools5eIndexType.getTypeFromKey(k);
if (type == Tools5eIndexType.subclass) {
JsonNode subclassNode = index().getOrigin(k);
return String.format("%s (%s)",
subclassNode.get("className").asText().trim(),
sources.getName());
}
return sources.getName();
})
.collect(Collectors.toCollection(TreeSet::new));
}

Collection<String> spellClasses(SchoolEnum school) {
JsonNode classesNode = node.get("classes");
if (classesNode == null || classesNode.isNull()) {
Expand Down Expand Up @@ -238,7 +259,8 @@ Collection<String> spellClasses(SchoolEnum school) {
}
String classSource = s.get("class").get("source").asText();
String subclassName = s.get("subclass").get("name").asText();
if (includeSubclass(className, classSource, subclassName)) {
String subclassSource = s.get("subclass").get("source").asText();
if (includeSubclass(className, classSource, subclassName, subclassSource)) {
classes.add(String.format("%s (%s)", className, subclassName));
}
});
Expand All @@ -254,12 +276,13 @@ Collection<String> spellClasses(SchoolEnum school) {
}

private boolean includeClass(String className, String classSource) {
String finalKey = index().getClassKey(className, classSource);
String finalKey = Tools5eIndexType.classtype.createKey(className, classSource);
return index().isIncluded(finalKey);
}

private boolean includeSubclass(String className, String classSource, String subclassName) {
String finalKey = index().getSubclassKey(subclassName.trim(), className.trim(), classSource.trim());
private boolean includeSubclass(String className, String classSource, String subclassName, String subclassSource) {
String finalKey = Tools5eIndexType.getSubclassKey(subclassName.trim(), className.trim(), classSource.trim(),
subclassSource.trim());
return index().isIncluded(finalKey);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ JsonNode handleCopy(Tools5eIndexType type, JsonNode jsonSource) {
// is the copy a copy?
baseNode = handleCopy(type, baseNode);
try {
String originKey = index().getKey(type, jsonSource);
String originKey = type.createKey(jsonSource);
jsonSource = mergeNodes(originKey, baseNode, jsonSource);
} catch (IllegalStateException | StackOverflowError e) {
throw new IllegalStateException("Unable to resolve copy " + _copy.toPrettyString());
Expand Down Expand Up @@ -213,7 +213,7 @@ JsonNode mergeNodes(String originKey, JsonNode baseNode, JsonNode overlayNode) {
}

if (_trait != null) {
String key = index.getKey(Tools5eIndexType.trait, _trait);
String key = Tools5eIndexType.trait.createKey(_trait);
JsonNode trait = index.getOrigin(key);
if (trait == null) {
tui().warn("Unable to find trait for " + key);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -419,29 +419,20 @@ default String linkifyClass(String match) {
// {@class artificer|uaartificer} can have sources added with a pipe,
// {@class fighter|phb|optional link text added with another pipe},
// {@class fighter|phb|subclasses added|Eldritch Knight} with another pipe,
// {@class fighter|phb|and class feature added|Eldritch Knight|phb|2-0} with
// another pipe
// {@class fighter|phb|and class feature added|Eldritch Knight|phb|2-0} with another pipe
// (first number is level index (0-19), second number is feature index (0-n)).",
// {@class Barbarian|phb|Path of the Ancestral Guardian|Ancestral Guardian|xge}
// {@class Fighter|phb|Samurai|Samurai|xge}
String[] parts = match.split("\\|");
String className = parts[0];
String classSource = "phb";
String linkText = className;
String subclass = null;

if (parts.length > 3) {
subclass = parts[3];
}
if (parts.length > 2) {
linkText = parts[2];
}
if (parts.length > 1) {
classSource = parts[1];
}
String classSource = parts.length < 2 || parts[1].isEmpty() ? "phb" : parts[1];
String linkText = parts.length < 3 || parts[2].isEmpty() ? className : parts[2];
String subclass = parts.length < 4 || parts[3].isEmpty() ? null : parts[3];
String subclassSource = parts.length < 5 || parts[4].isEmpty() ? classSource : parts[4];

if (subclass != null) {
String key = index().getAliasOrDefault(Tools5eIndexType.getSubclassKey(subclass, className, classSource));
String key = index()
.getAliasOrDefault(Tools5eIndexType.getSubclassKey(subclass, className, classSource, subclassSource));
// "subclass|path of wild magic|barbarian|phb|"
int first = key.indexOf('|');
int second = key.indexOf('|', first + 1);
Expand Down Expand Up @@ -525,14 +516,16 @@ default String linkifySubclassFeature(String match) {
// {@subclassFeature Blessed Strikes|Cleric||Life||8|UAClassFeatureVariants}, --> "-domain"
// {@subclassFeature Blessed Strikes|Cleric|PHB|Twilight|TCE|8|TCE}
// {@subclassFeature Path of the Berserker|Barbarian||Berserker||3||optional display text}.
// Class source is assumed to be PHB. Subclass source is assumed to be PHB.
// Class source is assumed to be PHB.
// Subclass source is assumed to be PHB.
// Subclass feature source is assumed to be the same as subclass source.",

String[] parts = match.split("\\|");
String linkText = parts[0];
String className = parts[1];
String classSource = parts[2].isBlank() ? "phb" : parts[2];
String subclass = parts[3];
String subclassSource = parts[4].isBlank() ? classSource : parts[4];
String level = parts[5];

if (parts.length > 7) {
Expand All @@ -548,8 +541,9 @@ default String linkifySubclassFeature(String match) {

// look up alias for subclass so link is correct, e.g.
// "subclass|redemption|paladin|phb|" : "subclass|oath of redemption|paladin|phb|",
// "subclass|twilight|cleric|phb|" : "subclass|twilight domain|cleric|phb|"
String subclassKey = index().getAliasOrDefault(Tools5eIndexType.getSubclassKey(subclass, className, classSource));
// "subclass|twilight|cleric|phb|tce" : "subclass|twilight domain|cleric|phb|tce"
String subclassKey = index()
.getAliasOrDefault(Tools5eIndexType.getSubclassKey(subclass, className, classSource, subclassSource));
int first = subclassKey.indexOf('|');
subclass = subclassKey.substring(first + 1, subclassKey.indexOf('|', first + 1));

Expand Down
Loading

0 comments on commit 2fcf744

Please sign in to comment.