- Full manager sim: 28 orgs / 168 players, calendar, transfers, youth scouting, loans, training, board confidence - Simulation Mode with real-time micro-engine (live.js): A* pathfinding on map geometry, raycast ballistics (spread/falloff/armor/headshots), smokes/flashes/HE that matter, plant/defuse/retake AI, clutch detection - Canvas renderer (viz.js): follow/radar cameras, HP bars, CS2-style kill feed, callouts, synthesized Web-Audio SFX, speed x1-x3, AUTO-SPECTATE hands-free series playback - Round results flow from the firefight back into the career engine (score, economy, box score, MVP) - Playwright + Node VM test suites included (test/, plus external pwtest harness)
22 lines
1.0 KiB
JavaScript
22 lines
1.0 KiB
JavaScript
'use strict';
|
|
const fs=require('fs'),path=require('path'),vm=require('vm');
|
|
const ctx={console,Math,Date,JSON,Object,Array,Set,Map,Number,String,Boolean,RegExp,parseInt,parseFloat};
|
|
ctx.globalThis=ctx;vm.createContext(ctx);
|
|
const dir=path.join(__dirname,'..','js');
|
|
for(const f of ['util.js','data.js','game.js','match.js'])vm.runInContext(fs.readFileSync(path.join(dir,f),'utf8'),ctx,{filename:f});
|
|
vm.runInContext(`
|
|
Game.newWorld('normal');
|
|
// rating distribution over many head-to-head sims between similar teams
|
|
const ids=Object.keys(G.teams);
|
|
let all=[];
|
|
for(let i=0;i<40;i++){
|
|
const a=ids[i%ids.length], b=ids[(i+7)%ids.length];
|
|
const m={id:'x'+i,a,b,bo:1,day:G.day};
|
|
MatchEngine.simulate(m,null);
|
|
Object.entries(m.box).forEach(([pid,st])=>all.push((st.ratingSum||0)/Math.max(st.mapsN||1,1)));
|
|
}
|
|
all.sort((x,y)=>x-y);
|
|
console.log('n='+all.length,'min',all[0].toFixed(2),'p10',all[Math.floor(all.length*.1)].toFixed(2),
|
|
'median',all[Math.floor(all.length/2)].toFixed(2),'p90',all[Math.floor(all.length*.9)].toFixed(2),'max',all.at(-1).toFixed(2));
|
|
`,ctx);
|