Spaces:
Running
Running
import fs from 'fs/promises' | |
import path from 'path' | |
const root = path.resolve(new URL(import.meta.url).pathname, '..', '..') | |
const publicDir = path.join(root, 'public', 'evaluations') | |
const dataDir = path.join(root, 'data', 'evaluations') | |
async function listFiles(dir){ | |
try{ const files = await fs.readdir(dir); return files.filter(f=>f.endsWith('.json')).map(f=>path.join(dir,f)) }catch(e){ return [] } | |
} | |
function chooseTarget(obj){ | |
// prefer B6, then B5 | |
if(!Object.prototype.hasOwnProperty.call(obj, 'B6')) return 'B6' | |
if(!Object.prototype.hasOwnProperty.call(obj, 'B5')) return 'B5' | |
// If both exist, choose B6 (we will try to merge by leaving existing and moving into B5) | |
return 'B5' | |
} | |
async function processFile(file){ | |
const txt = await fs.readFile(file,'utf8') | |
let json | |
try{ json = JSON.parse(txt) }catch(e){ return {file, error: 'invalid json'} } | |
const cats = json.categoryEvaluations || {} | |
let changed = false | |
const changes = [] | |
for(const [cat, obj] of Object.entries(cats)){ | |
// handle processAnswers | |
if(obj.processAnswers && Object.prototype.hasOwnProperty.call(obj.processAnswers, 'B8')){ | |
const target = chooseTarget(obj.processAnswers) | |
// if target exists, don't overwrite: move B8 value into an array / or leave both under target with suffix | |
if(!Object.prototype.hasOwnProperty.call(obj.processAnswers, target)){ | |
obj.processAnswers[target] = obj.processAnswers['B8'] | |
}else{ | |
// merge: if values differ, create array of unique | |
const existing = obj.processAnswers[target] | |
const incoming = obj.processAnswers['B8'] | |
if(Array.isArray(existing)){ | |
const arr = Array.from(new Set([...existing, ...(Array.isArray(incoming)?incoming:[incoming])])) | |
obj.processAnswers[target] = arr | |
}else{ | |
const arr = Array.from(new Set([existing, ...(Array.isArray(incoming)?incoming:[incoming])])) | |
obj.processAnswers[target] = arr | |
} | |
} | |
delete obj.processAnswers['B8'] | |
changed = true | |
changes.push({category:cat, section:'processAnswers', from:'B8', to:target}) | |
} | |
// handle processSources | |
if(obj.processSources && Object.prototype.hasOwnProperty.call(obj.processSources, 'B8')){ | |
const target = chooseTarget(obj.processSources) | |
if(!Object.prototype.hasOwnProperty.call(obj.processSources, target)){ | |
obj.processSources[target] = obj.processSources['B8'] | |
}else{ | |
// merge arrays | |
const existing = obj.processSources[target] | |
const incoming = obj.processSources['B8'] | |
const merged = Array.isArray(existing)? existing.concat(incoming || []) : [existing].concat(incoming || []) | |
// dedupe by JSON | |
const seen = new Map() | |
const dedup = [] | |
for(const item of merged){ | |
const key = JSON.stringify(item) | |
if(!seen.has(key)){ seen.set(key,true); dedup.push(item) } | |
} | |
obj.processSources[target] = dedup | |
} | |
delete obj.processSources['B8'] | |
changed = true | |
changes.push({category:cat, section:'processSources', from:'B8', to:target}) | |
} | |
} | |
if(changed){ | |
await fs.writeFile(file, JSON.stringify(json, null, 2), 'utf8') | |
} | |
return {file, changed, changes} | |
} | |
async function main(){ | |
const files = [ ...(await listFiles(publicDir)), ...(await listFiles(dataDir)) ] | |
const results = [] | |
for(const f of files){ | |
const r = await processFile(f) | |
results.push(r) | |
} | |
console.log(JSON.stringify(results, null, 2)) | |
} | |
main().catch(err=>{ console.error(err); process.exit(1) }) | |