Files
dwroller/scripts/normalize-bestiary.js
Alex caf8a03553 feat: Add scripts for upserting and validating bestiary data
- Implemented `upsert-allewis-from-5001.js` to fetch and update Allewis data from API.
- Created `upsert-missing-movement-from-5001.js` to fill missing movement and wounds data from API.
- Developed `upsert-missing-movement-from-pdfs.js` to extract movement and wounds from PDF text.
- Added `upsert-missing-profiles-from-pdfs.js` to fill missing profiles from PDF data.
- Introduced `upsert-missing-wounds-from-pdfs.js` to update wounds data from PDF sources.
- Created `validate-bestiary.js` to validate the structure of the bestiary JSON.
- Updated `BestiaryTab.jsx` component to display bestiary data with improved structure and search functionality.
- Added tests for `BestiaryTab` to ensure proper rendering and functionality.
2025-08-17 16:21:00 +02:00

68 lines
1.9 KiB
JavaScript

const fs = require('fs');
const path = require('path');
function backup(filePath) {
const ts = Date.now();
const bakPath = filePath + `.backup.${ts}.json`;
fs.copyFileSync(filePath, bakPath);
return bakPath;
}
function normalizeFile(filePath) {
const raw = fs.readFileSync(filePath, 'utf8');
const data = JSON.parse(raw);
if (!Array.isArray(data.results)) {
console.error('No results array in', filePath);
return { updated: 0, total: 0 };
}
const total = data.results.length;
let updated = 0;
const mapped = data.results.map((e) => {
const out = Object.assign({}, e);
if (e.stats && typeof e.stats === 'object') {
const s = e.stats;
const fields = ['profile','wounds','movement','toughness','skills','talents','traits','armour','weapons','gear','snippet'];
let any = false;
fields.forEach(f => {
if (s[f] !== undefined && out[f] === undefined) {
out[f] = s[f];
any = true;
}
});
if (any) updated++;
}
return out;
});
// update count if present
if (typeof data.count === 'number') data.count = mapped.length;
data.results = mapped;
const bak = backup(filePath);
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
console.log(`Normalized ${filePath}: ${updated}/${total} entries updated. Backup created at ${bak}`);
return { updated, total, backup: bak };
}
function main() {
const repoRoot = path.resolve(__dirname, '..');
const targets = [
path.join(repoRoot, 'database', 'deathwatch-bestiary-extracted.json'),
path.join(repoRoot, 'public', 'deathwatch-bestiary-extracted.json'),
];
targets.forEach(tp => {
if (fs.existsSync(tp)) {
try {
normalizeFile(tp);
} catch (err) {
console.error('Error normalizing', tp, err);
}
} else {
console.warn('File not found, skipping:', tp);
}
});
}
main();