Files
Toolbox/dev_test_scripts/debug/debug_retro_pinball_launch.js
yangxiangyuan 4492b4106a feat: 新增3个思想实验室项目,完善私有剪贴板授权与上传功能,添加配套测试脚本
1. 新增怀旧弹珠台、人性与投资、穿越三体、四维空间四个思想实验室项目
2. 为私有剪贴板添加业务层授权校验,优化上传进度显示与鉴权失败处理
3. 新增多个调试与单元测试脚本,覆盖三体积分、弹珠台物理、集成测试等场景
4. 补全穿越三体项目的完整HTML页面资源
2026-08-07 17:49:24 +08:00

71 lines
2.7 KiB
JavaScript

/**
* 调试:retro_pinball 满力发射轨迹追踪
* 目的:定位能量增益 bug(理论上满力发射到不了顶部,实测 minY=28)
* 运行:node dev_test_scripts/debug/debug_retro_pinball_launch.js
*/
'use strict'
const fs = require('fs')
const path = require('path')
const vm = require('vm')
const HTML_PATH = path.join(__dirname, '..', '..', 'public', 'tools', 'thought_lab', 'labs', 'retro_pinball', 'index.html')
const html = fs.readFileSync(HTML_PATH, 'utf-8')
const grab = (a, b) => {
const s = html.indexOf(a), e = html.indexOf(b)
if (s < 0 || e < 0 || e <= s) throw new Error('未找到标记块: ' + a)
return html.slice(s, e)
}
const code =
grab('/* ==PHYSICS_CORE_START== */', '/* ==PHYSICS_CORE_END== */') + '\n' +
grab('/* ==TABLE_GEOM_START== */', '/* ==TABLE_GEOM_END== */')
const sandbox = { Math, console }
vm.createContext(sandbox)
vm.runInContext(code, sandbox)
const PC = sandbox.PhysicsCore
const { BALL_R, G_PX, SPRING_X, SPRING_TOP, buildTableStatics } = sandbox
const DT = 1 / 360
function defaultParams() {
return {
g: G_PX * Math.sin(14 * Math.PI / 180),
e: 0.55, mu: 0.12, airK: 0.02, rollR: 0.25,
restV: 50, iterations: 8, slop: 0.3, correction: 0.8, maxV: 4200
};
}
const gEff = G_PX * Math.sin(14 * Math.PI / 180)
console.log('g_eff =', gEff.toFixed(1), 'px/s^2')
const table = buildTableStatics(5, 1)
const b = PC.createBall(SPRING_X, SPRING_TOP - BALL_R, BALL_R)
b.vy = -2900
b.vx = 5
const balls = [b]
let maxSp = 0, maxSpAt = ''
let minY = 1e9, minYAt = ''
let maxEnergy = -1e9, maxEnergyAt = ''
const startEnergy = 0.5 * (b.vx * b.vx + b.vy * b.vy) + gEff * b.y
console.log('初始动能+势能基准 E0 =', startEnergy.toFixed(0))
for (let i = 0; i < 360 * 3; i++) {
PC.stepWorld(balls, table.statics, defaultParams(), DT)
const sp = Math.hypot(b.vx, b.vy)
const t = ((i + 1) / 360).toFixed(2)
// 机械能 = 动能 + 势能(y 向下为正,势能取 g*y,越高 y 越小能量越小)
const E = 0.5 * sp * sp + gEff * b.y
if (sp > maxSp) { maxSp = sp; maxSpAt = `t=${t} pos=(${b.x.toFixed(1)},${b.y.toFixed(1)})` }
if (b.y < minY) { minY = b.y; minYAt = `t=${t} pos=(${b.x.toFixed(1)},${b.y.toFixed(1)}) sp=${sp.toFixed(0)}` }
if (E > maxEnergy) { maxEnergy = E; maxEnergyAt = `t=${t} pos=(${b.x.toFixed(1)},${b.y.toFixed(1)}) sp=${sp.toFixed(0)}` }
if (i % 36 === 0) {
console.log(`t=${t} pos=(${b.x.toFixed(1)},${b.y.toFixed(1)}) v=(${b.vx.toFixed(0)},${b.vy.toFixed(0)}) sp=${sp.toFixed(0)} E=${E.toFixed(0)}`)
}
}
console.log('----')
console.log('maxSp =', maxSp.toFixed(1), '@', maxSpAt)
console.log('minY =', minY.toFixed(1), '@', minYAt)
console.log('maxE =', maxEnergy.toFixed(0), '@', maxEnergyAt, '(E0=' + startEnergy.toFixed(0) + ')')