// Cross-engine oracle: executes the unmodified pinned upstream engine in Node/V8.
const fs=require('node:fs'),vm=require('node:vm'),path=require('node:path');
const root=path.resolve(__dirname,'..'),source=path.join(root,'XFEEDToolBox.Core/Outfitting/Edsy');
const context={window:{location:{protocol:'https:',host:'edsy.org',pathname:'/'}},document:{title:'EDSY headless oracle'}};
vm.createContext(context);
for(const file of ['eddb.js','edsy.js'])vm.runInContext(fs.readFileSync(path.join(source,file),'utf8'),context,{filename:file});
if(process.argv[2]==='--generate'){
const fixtures=[];
for(const [id,ship] of Object.entries(context.eddb.ship)){
const build=new context.window.edsy.Build(id,true);
fixtures.push({name:ship.name,hash:build.getHash(),ship:ship.fdname.toLowerCase(),loadout:build.exportJournal()});
}
const build=new context.window.edsy.Build(6,true);
build.setName('XFE Test - 42');build.setNameTag('XF-42');build.setPowerDist(6,4,2);build.setCrewDist(1,0,0);
for(const [group,slots] of Object.entries(build.slots)){
if(group==='ship')continue;
for(const slot of slots){
if(!slot.getModule())continue;
const type=context.eddb.mtype[slot.getModule().mtype];
if(type.blueprints?.length)slot.setBlueprint(type.blueprints[0],3,.435);
if(type.expeffects?.length)slot.setExpeffectID(type.expeffects[0]);
slot.setPowered(false);slot.setPriority(3);
}
}
fixtures.push({name:'engineered-custom-metadata',hash:build.getHash(),ship:'anaconda',loadout:build.exportJournal()});
fs.writeFileSync(path.join(root,'XFEEDToolBox.Test/Fixtures/edsy-oracle.json'),JSON.stringify(fixtures,null,2));
console.log(JSON.stringify({fixtures:fixtures.length,ships:Object.keys(context.eddb.ship).length}));
}else{
const input=JSON.parse(fs.readFileSync(process.argv[2],'utf8').replace(/^\uFEFF/,''));
const results=input.map(item=>{
const errors=[],hash=item.url.split('#/L=')[1],build=context.window.edsy.Build.fromHash(hash,errors);
if(!build||errors.length)throw new Error(JSON.stringify(errors));
if(item.expected){
const module=build.exportJournal().Modules.find(m=>m.Slot===item.expected.slot);
if(!module||module.Engineering?.BlueprintName!==item.expected.blueprint||module.Engineering?.Level!==item.expected.grade||module.Engineering?.ExperimentalEffect!==item.expected.effect)
throw new Error('Engineering mismatch for '+item.name);
}
return {name:item.name,url:item.url,canonical:build.getHash()===hash,loadout:build.exportJournal()};
});
fs.writeFileSync(process.argv[3],JSON.stringify(results,null,2));
console.log(JSON.stringify({decoded:results.length,canonical:results.every(r=>r.canonical),engine:'Node/V8 + upstream EDSY'}));
}
// Cross-engine oracle: executes the unmodified pinned upstream engine in Node/V8.
const fs=require('node:fs'),vm=require('node:vm'),path=require('node:path');
const root=path.resolve(__dirname,'..'),source=path.join(root,'XFEEDToolBox.Core/Outfitting/Edsy');
const context={window:{location:{protocol:'https:',host:'edsy.org',pathname:'/'}},document:{title:'EDSY headless oracle'}};
vm.createContext(context);
for(const file of ['eddb.js','edsy.js'])vm.runInContext(fs.readFileSync(path.join(source,file),'utf8'),context,{filename:file});
if(process.argv[2]==='--generate'){
const fixtures=[];
for(const [id,ship] of Object.entries(context.eddb.ship)){
const build=new context.window.edsy.Build(id,true);
fixtures.push({name:ship.name,hash:build.getHash(),ship:ship.fdname.toLowerCase(),loadout:build.exportJournal()});
}
const build=new context.window.edsy.Build(6,true);
build.setName('XFE Test - 42');build.setNameTag('XF-42');build.setPowerDist(6,4,2);build.setCrewDist(1,0,0);
for(const [group,slots] of Object.entries(build.slots)){
if(group==='ship')continue;
for(const slot of slots){
if(!slot.getModule())continue;
const type=context.eddb.mtype[slot.getModule().mtype];
if(type.blueprints?.length)slot.setBlueprint(type.blueprints[0],3,.435);
if(type.expeffects?.length)slot.setExpeffectID(type.expeffects[0]);
slot.setPowered(false);slot.setPriority(3);
}
}
fixtures.push({name:'engineered-custom-metadata',hash:build.getHash(),ship:'anaconda',loadout:build.exportJournal()});
fs.writeFileSync(path.join(root,'XFEEDToolBox.Test/Fixtures/edsy-oracle.json'),JSON.stringify(fixtures,null,2));
console.log(JSON.stringify({fixtures:fixtures.length,ships:Object.keys(context.eddb.ship).length}));
}else{
const input=JSON.parse(fs.readFileSync(process.argv[2],'utf8').replace(/^\uFEFF/,''));
const results=input.map(item=>{
const errors=[],hash=item.url.split('#/L=')[1],build=context.window.edsy.Build.fromHash(hash,errors);
if(!build||errors.length)throw new Error(JSON.stringify(errors));
if(item.expected){
const module=build.exportJournal().Modules.find(m=>m.Slot===item.expected.slot);
if(!module||module.Engineering?.BlueprintName!==item.expected.blueprint||module.Engineering?.Level!==item.expected.grade||module.Engineering?.ExperimentalEffect!==item.expected.effect)
throw new Error('Engineering mismatch for '+item.name);
}
return {name:item.name,url:item.url,canonical:build.getHash()===hash,loadout:build.exportJournal()};
});
fs.writeFileSync(process.argv[3],JSON.stringify(results,null,2));
console.log(JSON.stringify({decoded:results.length,canonical:results.every(r=>r.canonical),engine:'Node/V8 + upstream EDSY'}));
}