4492b4106a
1. 新增怀旧弹珠台、人性与投资、穿越三体、四维空间四个思想实验室项目 2. 为私有剪贴板添加业务层授权校验,优化上传进度显示与鉴权失败处理 3. 新增多个调试与单元测试脚本,覆盖三体积分、弹珠台物理、集成测试等场景 4. 补全穿越三体项目的完整HTML页面资源
71 lines
2.7 KiB
JavaScript
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) + ')')
|