Skip to content

Commit

Permalink
Table parsing improvements: async, table name detection improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
MrPrimate committed Mar 7, 2023
1 parent d053d8b commit c23ebb5
Show file tree
Hide file tree
Showing 18 changed files with 149 additions and 127 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* DDB Icon image selection was not always respected.
* Some monsters would cause the use SRD images copy to fail.
* Tables did not parse and link correctly during background, and some other parsing operations.

# 3.3.15

Expand Down
15 changes: 8 additions & 7 deletions src/muncher/backgrounds/backgrounds.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const BACKGROUND_TEMPLATE = {
"img": "icons/skills/trades/academics-book-study-purple.webp",
};

function buildBase(data) {
async function buildBase(data) {
let result = duplicate(BACKGROUND_TEMPLATE);
const bgData = generateBackground(data);
result.name = data.name;
Expand All @@ -45,14 +45,14 @@ function buildBase(data) {

result.system.source = DDBHelper.parseSource(data);
result.system.description.value = parseTags(result.system.description.value);
result.system.description.value = generateTable(result.name, result.system.description.value, true, "background");
result.system.description.value = await generateTable(result.name, result.system.description.value, true, "background");

return result;
}


function buildBackground(background) {
let result = buildBase(background);
async function buildBackground(background) {
let result = await buildBase(background);

return result;
}
Expand All @@ -66,11 +66,12 @@ export async function getBackgrounds(data) {

// console.warn(data);

data.forEach((background) => {
for (const background of data) {
logger.debug(`${background.name} background parsing started...`);
const parsedBackground = buildBackground(background);
// eslint-disable-next-line no-await-in-loop
const parsedBackground = await buildBackground(background);
backgrounds.push(parsedBackground);
});
}

// console.warn("backgrounds", backgrounds);

Expand Down
33 changes: 16 additions & 17 deletions src/muncher/classes/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ async function buildClass(klass, compendiumClassFeatures) {
let result = await buildBaseClass(klass);
result.system.description.value += await buildClassFeatures(klass, compendiumClassFeatures);
result.system.description.value = parseTags(result.system.description.value);
result.system.advancement.push(getHPAdvancement(), ...await generateFeatureAdvancements(klass, compendiumClassFeatures));
result.system.advancement.push(getHPAdvancement(), ...(await generateFeatureAdvancements(klass, compendiumClassFeatures)));
result.system.advancement = await addSRDAdvancements(result.system.advancement, result);
return result;
}
Expand All @@ -24,23 +24,22 @@ export async function getClasses(data) {
let klasses = [];
let classFeatures = [];

data.forEach((klass) => {
for (const klass of data) {
logger.debug(`${klass.name} feature parsing started...`);
klass.classFeatures
.sort((a, b) => a.requiredLevel - b.requiredLevel)
.forEach((feature) => {
const existingFeature = classFeatures.some((f) =>
f.flags.ddbimporter.featureName === feature.name
&& f.flags.ddbimporter.classId === klass.id
);
logger.debug(`${feature.name} feature starting...`);
if (!NO_TRAITS.includes(feature.name) && !existingFeature) {
const parsedFeature = getClassFeature(feature, klass);
classFeatures.push(parsedFeature);
results.push({ class: klass.name, subClass: "", feature: feature.name });
}
});
});
for (const feature of klass.classFeatures.sort((a, b) => a.requiredLevel - b.requiredLevel)) {
const existingFeature = classFeatures.some((f) =>
f.flags.ddbimporter.featureName === feature.name
&& f.flags.ddbimporter.classId === klass.id
);
logger.debug(`${feature.name} feature starting...`);
if (!NO_TRAITS.includes(feature.name) && !existingFeature) {
// eslint-disable-next-line no-await-in-loop
const parsedFeature = await getClassFeature(feature, klass);
classFeatures.push(parsedFeature);
results.push({ class: klass.name, subClass: "", feature: feature.name });
}
}
}

const fiddledClassFeatures = await srdFiddling(classFeatures, "features");
DDBMuncher.munchNote(`Importing ${fiddledClassFeatures.length} features!`, true);
Expand Down
7 changes: 4 additions & 3 deletions src/muncher/classes/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ export async function getClassOptions(data, className) {
id: classMatch.id,
};

data.forEach((feature) => {
for (const feature of data) {
const existingFeature = classFeatures.some((f) => f.name === feature.name);
logger.debug(`${feature.name} feature starting...`);
if (!NO_TRAITS.includes(feature.name.trim()) && !existingFeature) {
const parsedFeature = getClassFeature(feature, klass);
// eslint-disable-next-line no-await-in-loop
const parsedFeature = await getClassFeature(feature, klass);
classFeatures.push(parsedFeature);
results.push({ class: className, subClass: "", feature: feature.name });
}
});
}

const fiddledClassFeatures = await srdFiddling(classFeatures, "features");
DDBMuncher.munchNote(`Importing ${fiddledClassFeatures.length} options!`, true);
Expand Down
10 changes: 5 additions & 5 deletions src/muncher/classes/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ export const FEATURE_DUP = [
"Tool Proficiency",
];

function buildBase(data) {
async function buildBase(data) {
let result = duplicate(CLASS_TEMPLATE);
const updateExisting = game.settings.get("ddb-importer", "munching-policy-update-existing");

result.name = data.name;
const tableDescription = generateTable(data.name, data.description, updateExisting);
const tableDescription = await generateTable(data.name, data.description, updateExisting);
result.system.description.value += `${tableDescription}\n\n`;

result.flags.ddbimporter = {
Expand Down Expand Up @@ -177,10 +177,10 @@ export async function buildClassFeatures(klass, compendiumClassFeatures, ignoreI
return description;
}

export function getClassFeature(feature, klass, subClassName = "") {
export async function getClassFeature(feature, klass, subClassName = "") {
logger.debug("Class feature build started");

let result = buildBase(feature);
let result = await buildBase(feature);
result.flags.obsidian.source.text = klass.name;

const duplicateFeature = FEATURE_DUP.includes(feature.name);
Expand All @@ -207,7 +207,7 @@ export function getClassFeature(feature, klass, subClassName = "") {
}

export async function buildBaseClass(klass) {
let result = buildBase(klass);
let result = await buildBase(klass);
logger.debug(`Parsing ${klass.name}`);
result.flags.obsidian.source.text = klass.name;
result.type = "class";
Expand Down
29 changes: 15 additions & 14 deletions src/muncher/classes/subclasses.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ async function buildSubClass(klass, subclass, compendiumSubClassFeatures) {
const ignoreIds = klass.flags.ddbimporter.data.classFeatures.map((f) => f.id);
result.system.description.value += await buildClassFeatures(subclass, compendiumSubClassFeatures, ignoreIds);
result.system.description.value = parseTags(result.system.description.value);
result.system.advancement.push(...await generateFeatureAdvancements(subclass, compendiumSubClassFeatures, ignoreIds));
result.system.advancement.push(...(await generateFeatureAdvancements(subclass, compendiumSubClassFeatures, ignoreIds)));
return result;
}

Expand All @@ -106,26 +106,27 @@ export async function getSubClasses(data) {
let classFeatures = [];
let results = [];

data.forEach((subClass) => {
for (const subClass of data) {
const classMatch = CONFIG.DDB.classConfigurations.find((k) => k.id === subClass.parentClassId);
logger.debug(`${subClass.name} feature parsing started...`);
subClass.classFeatures
const filteredFeatures = subClass.classFeatures
.filter((feature) =>
!classFeatureIndex.some((i) => hasProperty(i, "flags.ddbimporter.classId")
&& hasProperty(i, "flags.ddbimporter.featureName")
&& feature.name === i.flags.ddbimporter.featureName
&& subClass.parentClassId === i.flags.ddbimporter.classId)
)
.forEach((feature) => {
const existingFeature = classFeatures.some((f) => f.name === feature.name);
logger.debug(`${feature.name} feature starting...`);
if (!NO_TRAITS.includes(feature.name.trim()) && !existingFeature) {
const parsedFeature = getClassFeature(feature, subClass, subClass.name);
classFeatures.push(parsedFeature);
results.push({ class: classMatch.name, subClass: subClass.name, feature: feature.name });
}
});
});
);
for (const feature of filteredFeatures) {
const existingFeature = classFeatures.some((f) => f.name === feature.name);
logger.debug(`${feature.name} feature starting...`);
if (!NO_TRAITS.includes(feature.name.trim()) && !existingFeature) {
// eslint-disable-next-line no-await-in-loop
const parsedFeature = await getClassFeature(feature, subClass, subClass.name);
classFeatures.push(parsedFeature);
results.push({ class: classMatch.name, subClass: subClass.name, feature: feature.name });
}
}
}

const fiddledClassFeatures = await srdFiddling(classFeatures, "features");
DDBMuncher.munchNote(`Importing ${fiddledClassFeatures.length} features!`, true);
Expand Down
65 changes: 39 additions & 26 deletions src/muncher/table.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { parseTable, getHeadings } from "../../vendor/parseTable.js";
import CompendiumHelper from "../lib/CompendiumHelper.js";
import utils from "../lib/utils.js";
import logger from "../logger.js";
import { updateCompendium } from "./import.js";
Expand Down Expand Up @@ -68,16 +69,15 @@ function guessTableName(parentName, htmlDocument, tableNum) {
}


function tableReplacer(htmlDocument, tableNum, compendiumTables) {
function tableReplacer(htmlDocument, tableNum, compendiumTables, compendiumLabel) {
// future enhancement - replace liks to DDB spells, monsters, items etc to munched compendium
const element = htmlDocument.querySelectorAll('table');
const tablePoint = element[tableNum];

if (tablePoint) {
const rollCompendiumLabel = game.settings.get("ddb-importer", "entity-table-compendium");
compendiumTables.slice().reverse().forEach((table) => {
logger.debug(`Updating table reference for: ${table.name}`);
tablePoint.insertAdjacentHTML("afterend", `<div id="table-link">@Compendium[${rollCompendiumLabel}.${table.name}]{Open RollTable ${table.name}}</div>`);
tablePoint.insertAdjacentHTML("afterend", `<div id="table-link">@Compendium[${compendiumLabel}.${table.name}]{Open RollTable ${table.name}}</div>`);
});
}

Expand Down Expand Up @@ -198,55 +198,69 @@ function buildTable(parsedTable, keys, diceKeys, tableName, parentName) {
return generatedTables;
}

export function generateTable(parentName, html, updateExisting, type = "") {
export async function generateTable(parentName, html, updateExisting, type = "") {
let name = `${parentName}`;
const document = utils.htmlToDoc(html);
const tableNodes = document.querySelectorAll("table");
let tablesMatched = [];
let updatedDocument = utils.htmlToDoc(html);
if (type === "background" && !parentName.startsWith("Background:")) {
parentName = `Background: ${parentName}`;
if (type === "background" && !name.startsWith("Background:")) {
name = `Background: ${name}`;
}
if (parentName.startsWith("Background:")) {
const parentNamesArray = parentName.split(":");
if (name.startsWith("Background:")) {
const namesArray = name.split(":");
// if (parentNamesArray.length > 2) parentNamesArray.pop();
parentName = parentNamesArray.join(":");
name = namesArray.join(":");
}

const tableCompendiumLabel = CompendiumHelper.getCompendiumLabel("tables");
let tableNum = 0;
tableNodes.forEach((node) => {
let foundTables = [];
for (const node of tableNodes) {
// for (let i = 0; i < tableNodes.length; i++) {
// const node = tableNodes[i];
const parsedTable = parseTable(node);
const keys = getHeadings(node);
const diceKeys = findDiceColumns(node);
let nameGuess = guessTableName(parentName, document, tableNum);
let nameGuess = guessTableName(name, document, tableNum);
if (nameGuess.split(" ").length > 5 && diceKeys.length === 1 && keys.length === 2) {
nameGuess = keys[1];
} else if (nameGuess.trim() === "") {
nameGuess = keys[1];
}
const finalName = `${parentName}: ${nameGuess}`;
const tableGenerated = (finalName in CONFIG.DDBI.TABLES);

logger.debug(`Table detection triggered for ${parentName}!`);
logger.debug(`Table: "${finalName}"`);
logger.debug(`Dice Keys: ${diceKeys.join(", ")}`);
logger.debug(`Keys: ${keys.join(", ")}`);
const finalName = `${name}: ${nameGuess}`;
// eslint-disable-next-line no-await-in-loop
const tableGenerated = await CompendiumHelper.queryCompendiumEntry(tableCompendiumLabel, finalName, true);

logger.debug(`Table detection triggered for ${name} (parentName: ${parentName})!`, {
finalName,
diceKeys,
keys,
node,
html,
parsedTable,
foundTables,
nameGuess,
tableGenerated,
});

const builtTables = tableGenerated
? CONFIG.DDBI.TABLES[finalName]
: buildTable(parsedTable, keys, diceKeys, finalName, parentName);
? [tableGenerated.toObject()]
: buildTable(parsedTable, keys, diceKeys, finalName, name);

if (builtTables.length > 0) {
// these updates are done async, and we continue. this is fine as we actually use the table name for linking
if (!tableGenerated) {
CONFIG.DDBI.TABLES[finalName] = builtTables;
logger.debug(`Generated table`, builtTables);
updateCompendium("tables", { tables: builtTables }, updateExisting);
// eslint-disable-next-line no-await-in-loop
await updateCompendium("tables", { tables: builtTables }, updateExisting);
}

let tableData = {
nameGuess,
finalName,
parentName,
name,
tableNum,
length: parsedTable.length,
keys: keys,
Expand All @@ -255,16 +269,15 @@ export function generateTable(parentName, html, updateExisting, type = "") {
multiDiceKeys: diceKeys.length > 1,
diceKeysNumber: diceKeys.length,
totalKeys: keys.length,
builtTables: CONFIG.DDBI.TABLES[finalName],
builtTables,
};
tablesMatched.push(tableData);
updatedDocument = tableReplacer(updatedDocument, tableNum, tableData.builtTables);
updatedDocument = tableReplacer(updatedDocument, tableNum, builtTables, tableCompendiumLabel);

}
tableNum++;
// }
});
}

return updatedDocument.body.innerHTML;

}
2 changes: 1 addition & 1 deletion src/parser/DDBMonster.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ export default class DDBMonster {
this._generateEnvironments();
this.npc.system.details.biography.value = this.source.characteristicsDescription;

this._generateFeatures();
await this._generateFeatures();

// Spellcasting
this._generateSpells();
Expand Down
2 changes: 1 addition & 1 deletion src/parser/companions/DDBCompanion.js
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ export default class DDBCompanion {
ddbMonster.abilities = ddbMonster.npc.system.abilities;
ddbMonster.proficiencyBonus = 0;
const featureFactory = new DDBFeatureFactory({ ddbMonster, hideDescription: false, updateExisting: false });
featureFactory.generateActions(text, type);
await featureFactory.generateActions(text, type);
logger.debug("Generating companion feature", { text, type, featureFactory });
const toHitRegex = /(your spell attack modifier to hit)/i;
if (toHitRegex.test(text)) {
Expand Down
2 changes: 1 addition & 1 deletion src/parser/features/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ export default async function parseActions(ddb, character) {
}
});

fixFeatures(actions);
await fixFeatures(actions);
const results = await addExtraEffects(ddb, actions, character);
return results;
}
2 changes: 1 addition & 1 deletion src/parser/features/features.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,6 @@ DDBCharacter.prototype._generateFeatures = async function _generateFeatures() {

logger.debug("Feature fixes");
setLevelScales(classes, items);
fixFeatures(items);
await fixFeatures(items);
this.raw.features = await addExtraEffects(ddb, items, character);
};
Loading

0 comments on commit c23ebb5

Please sign in to comment.