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

665 lines
25 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>思想实验室 · 穿越三体</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@300;500&display=swap');
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
background-color: #020205;
color: #ddd;
font-family: 'Noto Serif SC', serif;
overflow: hidden;
user-select: none;
}
#stage {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
.overlay {
position: absolute;
z-index: 10;
pointer-events: none;
box-sizing: border-box;
}
/* 顶部/底部叙事框 */
#narrative-box {
bottom: 50px;
left: 50%;
transform: translateX(-50%);
width: 60%;
max-width: 800px;
background: rgba(10, 15, 25, 0.85);
border: 1px solid rgba(100, 150, 255, 0.3);
padding: 25px 35px;
border-radius: 8px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.8);
font-size: 1.1rem;
line-height: 1.8;
letter-spacing: 1px;
text-align: justify;
min-height: 120px;
text-shadow: 0 0 5px rgba(255,255,255,0.2);
}
/* 侧边信息栏 */
.info-panel {
top: 50px;
width: 260px;
background: rgba(5, 5, 10, 0.7);
border: 1px solid rgba(255, 255, 255, 0.1);
padding: 20px;
border-radius: 5px;
backdrop-filter: blur(5px);
font-family: sans-serif;
font-size: 0.9rem;
line-height: 1.5;
}
#science-panel { left: 30px; border-top: 3px solid #4a90e2; }
#fiction-panel { right: 30px; border-top: 3px solid #e24a4a; }
.info-panel h3 {
margin-top: 0;
margin-bottom: 15px;
font-size: 1.1rem;
text-align: center;
letter-spacing: 2px;
}
#science-panel h3 { color: #4a90e2; }
#fiction-panel h3 { color: #e24a4a; }
.info-panel ul {
margin: 0;
padding-left: 20px;
}
.info-panel li { margin-bottom: 12px; color: #ccc; }
/* 控件 */
#controls {
bottom: 50px;
right: 50px;
display: flex;
gap: 15px;
pointer-events: auto;
}
button {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.3);
color: #fff;
padding: 10px 20px;
cursor: pointer;
font-family: 'Noto Serif SC', serif;
transition: all 0.3s;
border-radius: 4px;
}
button:hover { background: rgba(255, 255, 255, 0.2); }
button:disabled { opacity: 0.3; cursor: not-allowed; }
/* 场景标题 */
#scene-title {
top: 40px;
left: 50%;
transform: translateX(-50%);
font-size: 1.5rem;
letter-spacing: 4px;
color: rgba(255,255,255,0.9);
text-shadow: 0 0 10px rgba(255,255,255,0.5);
text-align: center;
}
#intro {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
background: #000;
z-index: 100;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
transition: opacity 1s;
}
#intro h1 { font-size: 3rem; letter-spacing: 10px; margin-bottom: 20px; font-weight: 300;}
#intro p { font-size: 1.2rem; color: #888; }
#start-btn { margin-top: 40px; font-size: 1.2rem; padding: 10px 40px; pointer-events: auto;}
</style>
</head>
<body>
<canvas id="stage"></canvas>
<div id="intro">
<h1>思想实验室 · 穿越三体</h1>
<p>一场基于物理与想象的第一人称视觉实验</p>
<button id="start-btn">启程</button>
</div>
<div id="scene-title" class="overlay"></div>
<div id="science-panel" class="overlay info-panel">
<h3>真实科学</h3>
<ul id="science-list"></ul>
</div>
<div id="fiction-panel" class="overlay info-panel">
<h3>小说想象</h3>
<ul id="fiction-list"></ul>
</div>
<div id="narrative-box" class="overlay">
<span id="narrative-text"></span><span class="cursor">_</span>
</div>
<div id="controls" class="overlay">
<button id="prev-btn" disabled>上一跃迁</button>
<button id="next-btn">下一跃迁</button>
</div>
<script>
/**
* 核心逻辑:画布与渲染
*/
const canvas = document.getElementById('stage');
const ctx = canvas.getContext('2d');
let width, height;
function resize() {
width = window.innerWidth;
height = window.innerHeight;
canvas.width = width;
canvas.height = height;
}
window.addEventListener('resize', resize);
resize();
// 宇宙背景星空
const stars = Array.from({length: 300}, () => ({
x: Math.random() * 2000,
y: Math.random() * 2000,
r: Math.random() * 1.5,
alpha: Math.random(),
speed: Math.random() * 0.05
}));
function drawBackground() {
ctx.fillStyle = '#020205';
ctx.fillRect(0, 0, width, height);
stars.forEach(star => {
star.alpha += star.speed;
let a = Math.abs(Math.sin(star.alpha));
ctx.fillStyle = `rgba(255, 255, 255, ${a})`;
ctx.beginPath();
ctx.arc(star.x % width, star.y % height, star.r, 0, Math.PI*2);
ctx.fill();
});
}
/**
* 打字机效果管理器
*/
let typeWriterTimer = null;
function typeWriter(text, elementId, speed = 40) {
const el = document.getElementById(elementId);
el.innerHTML = "";
if(typeWriterTimer) clearInterval(typeWriterTimer);
let i = 0;
typeWriterTimer = setInterval(() => {
if(i < text.length) {
el.innerHTML += text.charAt(i);
i++;
} else {
clearInterval(typeWriterTimer);
}
}, speed);
}
/**
* 场景定义与逻辑
*/
const scenes = [
{
title: "第一幕:红岸的回声",
narrative: "我凝视着夜空,那是一块深邃的黑天鹅绒。这里的海拔很高,风中带着寒意。红岸基地的巨型抛物面天线在缓慢转动。4.37光年外的星光刚刚抵达我的视网膜。我收到了一条无声的警告:『不要回答。』但我知道,文明的孤岛已被打破,我将化身幽灵,沿着电波的轨迹,去见证那场跨越数百个世纪的史诗。",
science: [
"半人马座α星是距离太阳系最近的恒星系统,距离约 4.37 光年(约 41.3 万亿公里)。",
"电磁波在真空中的传播速度为光速(约 300,000 km/s),信号一来一回需近9年。"
],
fiction: [
"太阳可以作为超级天线,利用恒星大气的等离子体将电波信号放大亿倍进行星际广播。",
"三体文明截获了广播,其监听员发出了警告。"
],
state: { earthR: 200, alpha: 1 },
init() { this.state.earthR = Math.min(width, height) * 0.4; this.state.alpha = 1; },
draw(ctx, width, height) {
// 画一个巨大的地球边缘
let cx = width / 2;
let cy = height + this.state.earthR * 0.5;
let grd = ctx.createRadialGradient(cx, cy, this.state.earthR * 0.8, cx, cy, this.state.earthR);
grd.addColorStop(0, "rgba(10, 30, 80, 1)");
grd.addColorStop(0.8, "rgba(40, 100, 200, 0.8)");
grd.addColorStop(1, "rgba(0, 0, 0, 0)");
ctx.fillStyle = grd;
ctx.beginPath();
ctx.arc(cx, cy, this.state.earthR, 0, Math.PI*2);
ctx.fill();
// 雷达红点
this.state.alpha = 0.5 + 0.5 * Math.sin(Date.now() / 300);
ctx.fillStyle = `rgba(255, 50, 50, ${this.state.alpha})`;
ctx.beginPath();
ctx.arc(cx, cy - this.state.earthR * 0.95, 3, 0, Math.PI*2);
ctx.fill();
// 发射波纹
ctx.strokeStyle = `rgba(255, 255, 255, ${this.state.alpha * 0.5})`;
ctx.lineWidth = 1;
let time = Date.now() / 1000;
for(let i=1; i<=3; i++) {
ctx.beginPath();
ctx.arc(cx, cy - this.state.earthR * 0.95, (time * 50 % 100) * i, Math.PI*1.2, Math.PI*1.8);
ctx.stroke();
}
}
},
{
title: "第二幕:乱纪元的炼狱 (三体问题)",
narrative: "经过漫长的意识跃迁,我坠入了这片毫无规律的炼狱。三颗巨大的恒星像狂舞的巨兽,在牛顿引力定律的诅咒下做着永不重复的混沌运动。刚刚还是飞星不动的三日凌空,瞬间又被撕裂成极寒的漫漫长夜。这里的文明在恒纪元与乱纪元的交替中痛苦轮回,而它们唯一的生路,就是逃离。",
science: [
"三体问题(Three-body problem):三个质量、初始位置和初始速度都是任意的天体,在相互之间万有引力的作用下的运动规律问题。",
"庞加莱已证明,三体问题没有一般解析解,其系统具备极端的混沌性对初始条件极度敏感。",
"注:背景动画采用纯粹的 RK4 (龙格-库塔) 数值积分实时演算,并非预设动画。"
],
fiction: [
"在一个如此极度不稳定的混沌星系中,居然存在一颗未被吞噬或甩出的行星。",
"该行星上诞生了能够脱水复苏,并进化出高度发达科技的三体文明。"
],
state: { bodies: [], trails: [] },
init() {
// 初始化三个恒星 (位置,速度,质量,颜色)
this.state.bodies = [
{x: -150, y: 50, vx: 0, vy: -30, m: 3000, color: '#ff4d4d', r: 15},
{x: 150, y: -50, vx: 0, vy: 30, m: 3000, color: '#fdb813', r: 15},
{x: 0, y: 0, vx: 20, vy: 0, m: 2500, color: '#4da6ff', r: 12}
];
this.state.trails = [[], [], []];
},
// RK4 引力积分演算核心
calculateAccelerations(bodies) {
const G = 10; // 引力常数调节
const softening = 20; // 软化参数防止奇点爆炸
let accels = bodies.map(() => ({ax: 0, ay: 0}));
for(let i=0; i<bodies.length; i++) {
for(let j=0; j<bodies.length; j++) {
if(i===j) continue;
let dx = bodies[j].x - bodies[i].x;
let dy = bodies[j].y - bodies[i].y;
let distSq = dx*dx + dy*dy + softening*softening;
let dist = Math.sqrt(distSq);
let force = (G * bodies[j].m) / (distSq * dist);
accels[i].ax += force * dx;
accels[i].ay += force * dy;
}
}
return accels;
},
draw(ctx, width, height) {
const dt = 0.05; // 时间步长
let b = this.state.bodies;
// RK4 步骤
// k1
let a1 = this.calculateAccelerations(b);
let k1 = b.map((body, i) => ({vx: a1[i].ax*dt, vy: a1[i].ay*dt, x: body.vx*dt, y: body.vy*dt}));
// k2
let b2 = b.map((body, i) => ({x: body.x + k1[i].x/2, y: body.y + k1[i].y/2, m: body.m}));
let a2 = this.calculateAccelerations(b2);
let k2 = b.map((body, i) => ({vx: a2[i].ax*dt, vy: a2[i].ay*dt, x: (body.vx + k1[i].vx/2)*dt, y: (body.vy + k1[i].vy/2)*dt}));
// k3
let b3 = b.map((body, i) => ({x: body.x + k2[i].x/2, y: body.y + k2[i].y/2, m: body.m}));
let a3 = this.calculateAccelerations(b3);
let k3 = b.map((body, i) => ({vx: a3[i].ax*dt, vy: a3[i].ay*dt, x: (body.vx + k2[i].vx/2)*dt, y: (body.vy + k2[i].vy/2)*dt}));
// k4
let b4 = b.map((body, i) => ({x: body.x + k3[i].x, y: body.y + k3[i].y, m: body.m}));
let a4 = this.calculateAccelerations(b4);
let k4 = b.map((body, i) => ({vx: a4[i].ax*dt, vy: a4[i].ay*dt, x: (body.vx + k3[i].vx)*dt, y: (body.vy + k3[i].vy)*dt}));
// 更新状态
for(let i=0; i<b.length; i++) {
b[i].x += (k1[i].x + 2*k2[i].x + 2*k3[i].x + k4[i].x)/6;
b[i].y += (k1[i].y + 2*k2[i].y + 2*k3[i].y + k4[i].y)/6;
b[i].vx += (k1[i].vx + 2*k2[i].vx + 2*k3[i].vx + k4[i].vx)/6;
b[i].vy += (k1[i].vy + 2*k2[i].vy + 2*k3[i].vy + k4[i].vy)/6;
this.state.trails[i].push({x: b[i].x, y: b[i].y});
if(this.state.trails[i].length > 150) this.state.trails[i].shift();
}
// 寻找中心点用于摄像机跟随
let cx = width/2, cy = height/2;
let sumX = 0, sumY = 0;
b.forEach(body => { sumX += body.x; sumY += body.y; });
let comX = sumX/3, comY = sumY/3;
ctx.save();
ctx.translate(cx - comX, cy - comY);
// 绘制轨迹和恒星
for(let i=0; i<b.length; i++) {
ctx.beginPath();
ctx.strokeStyle = b[i].color;
ctx.lineWidth = 1.5;
let tr = this.state.trails[i];
for(let j=0; j<tr.length; j++) {
ctx.globalAlpha = j / tr.length; // 轨迹渐隐
if(j===0) ctx.moveTo(tr[j].x, tr[j].y);
else ctx.lineTo(tr[j].x, tr[j].y);
}
ctx.stroke();
ctx.globalAlpha = 1;
ctx.beginPath();
ctx.arc(b[i].x, b[i].y, b[i].r, 0, Math.PI*2);
ctx.fillStyle = b[i].color;
ctx.shadowColor = b[i].color;
ctx.shadowBlur = 30;
ctx.fill();
}
ctx.restore();
}
},
{
title: "第三幕:绝对光滑 (水滴)",
narrative: "它静静地悬浮在太空中,完美得不包含任何瑕疵。这是一种无法用人类语言描述的美,表面绝对光滑,全反射着周围深邃的宇宙。它就像是一滴死神的眼泪,没有任何温度。我眼睁睁看着这颗长约三米的水滴,在瞬间撕碎了人类两千艘恒星级战舰。在物理学的铁壁面前,傲慢付出了最惨痛的代价。",
science: [
"强相互作用力:自然界四大基本力中最强的一种,负责将质子和中子结合在原子核中。作用距离极短(飞米级)。",
"绝对零度与全反射:微观粒子热运动几乎停止,若表面粗糙度低于光波长,可呈现高反射率。"
],
fiction: [
"水滴(探测器)的材料是由强相互作用力锁死的物质,这使得它的原子像被钉死般排列,坚不可摧。",
"在宏观层面运用强相互作用力,使其硬度远超自然界任何常规物质,并能进行锐角转向无工质推进。"
],
state: { angle: 0 },
init() { this.state.angle = 0; },
draw(ctx, width, height) {
this.state.angle += 0.01;
let cx = width / 2;
let cy = height / 2;
ctx.save();
ctx.translate(cx, cy);
// 微弱的上下浮动
let floatY = Math.sin(this.state.angle * 2) * 10;
ctx.translate(0, floatY);
// 绘制水滴 (贝塞尔曲线)
let w = 200;
let h = 80;
// 建立金属渐变反射
let grd = ctx.createLinearGradient(-w/2, -h, w/2, h);
grd.addColorStop(0, "#fff");
grd.addColorStop(0.2, "#88aaff");
grd.addColorStop(0.5, "#112244");
grd.addColorStop(0.8, "#5577aa");
grd.addColorStop(1, "#000");
ctx.beginPath();
// 左侧尾部
ctx.moveTo(-w/2, 0);
// 上半部分弧线
ctx.bezierCurveTo(-w/4, -h/2, w/4, -h/2, w/2, 0);
// 下半部分弧线
ctx.bezierCurveTo(w/4, h/2, -w/4, h/2, -w/2, 0);
ctx.closePath();
ctx.fillStyle = grd;
ctx.shadowColor = 'rgba(150, 180, 255, 0.5)';
ctx.shadowBlur = 20;
ctx.fill();
// 高光
ctx.beginPath();
ctx.moveTo(-w/2 + 20, -5);
ctx.bezierCurveTo(-w/4, -h/2 + 10, w/4, -h/2 + 10, w/2 - 20, -5);
ctx.strokeStyle = "rgba(255,255,255,0.7)";
ctx.lineWidth = 3;
ctx.filter = 'blur(2px)';
ctx.stroke();
ctx.restore();
}
},
{
title: "第四幕:梵高的星空 (二向箔)",
narrative: "一张明信片大小的纸条,剥夺了整个太阳系的深度。我绝望地看着前方的空间本身开始坍塌。木星、地球、逃亡的飞船……所有宏大的3D结构无可挽回地跌落,被死死地压在了一个二维的平面上。信息的细节在降维展开中铺陈,星海失去了深邃,变成了一幅绚丽而死寂的无边画卷,宛如梵高的《星月夜》。毁灭你,与你何干。",
science: [
"维度与空间:弦理论预测宇宙包含更多维度,但宏观上我们只体验到三维空间加一维时间。",
"热力学第二定律:孤立系统熵增(混乱度增加)。任何物理降维过程都会释放惊人的能量与信息。"
],
fiction: [
"将降维(从三维降至二维)作为一种宇宙规律武器,使得卷曲的维度展开。",
"逃逸降维打击的唯一方法是达到光速(即需要曲率驱动飞船)。二维化后的世界呈现出内部结构的完全平面展示。"
],
state: { radius: 10, planets: [] },
init() {
this.state.radius = 10;
this.state.planets = [
{x: 200, y: 100, r: 40, col: '#3498db'}, // 地球
{x: -150, y: -80, r: 60, col: '#e67e22'}, // 木星
{x: -50, y: 150, r: 25, col: '#bdc3c7'} // 飞船/月球
];
},
draw(ctx, width, height) {
let cx = width / 2;
let cy = height / 2;
// 扩张的二维化光环
this.state.radius += 2.5;
let r = this.state.radius;
ctx.save();
ctx.translate(cx, cy);
// 绘制尚未被吞噬的 3D 星球
this.state.planets.forEach(p => {
let dist = Math.sqrt(p.x*p.x + p.y*p.y);
if(dist > r) {
// 3D 效果
let grd = ctx.createRadialGradient(p.x - p.r/3, p.y - p.r/3, p.r/10, p.x, p.y, p.r);
grd.addColorStop(0, p.col);
grd.addColorStop(1, '#000');
ctx.fillStyle = grd;
ctx.beginPath();
ctx.arc(p.x, p.y, p.r, 0, Math.PI*2);
ctx.fill();
} else {
// 二维化效果:摊大、同心环状结构、纯色无光影
ctx.strokeStyle = p.col;
ctx.lineWidth = 1;
ctx.globalAlpha = 0.5;
for(let i=1; i<=5; i++) {
ctx.beginPath();
ctx.arc(p.x, p.y, p.r * 1.5 * i/3, 0, Math.PI*2);
ctx.stroke();
}
ctx.globalAlpha = 1;
}
});
// 降维打击的边界 (二向箔边缘)
ctx.beginPath();
ctx.arc(0, 0, r, 0, Math.PI*2);
ctx.strokeStyle = 'rgba(255, 255, 255, 0.8)';
ctx.lineWidth = 2;
ctx.shadowColor = '#fff';
ctx.shadowBlur = 15;
ctx.stroke();
// 二维区内部网格 (失去深度的象征)
ctx.clip();
ctx.strokeStyle = 'rgba(0, 255, 255, 0.1)';
ctx.lineWidth = 1;
ctx.shadowBlur = 0;
for(let i=-r; i<r; i+=20) {
ctx.beginPath(); ctx.moveTo(i, -r); ctx.lineTo(i, r); ctx.stroke();
ctx.beginPath(); ctx.moveTo(-r, i); ctx.lineTo(r, i); ctx.stroke();
}
ctx.restore();
}
},
{
title: "最终幕:时间闭环 (小宇宙)",
narrative: "几百亿年,又或者只是一瞬。在宇宙大撕裂的边缘,我推开了那扇第647号小宇宙的门。智子在一旁静静地泡着茶。我留下了一封信,一个装有五公斤生态的小球。我知道,为了大宇宙的重生,必须归还所有的质量。伴随着引力的坍缩,一切都回到了起点。时间闭环,我又看到了那颗蓝色的水球。一切都结束了,一切又将重新开始。",
science: [
"宇宙终局理论:大坍缩(Big Crunch)或热寂(Heat Death)。如果宇宙总质量超过临界值,引力最终会使其坍缩为一个奇点。",
"物质与质量守恒:在宏观闭合系统中,总质能是守恒的。"
],
fiction: [
"超级文明能够创造独立于大宇宙之外的『小宇宙』以躲避大爆炸或大坍缩。",
"回归运动声明书呼吁所有小宇宙归还质量,以便大宇宙能够收缩并引发新的大爆炸。"
],
state: { size: 0 },
init() { this.state.size = 0; },
draw(ctx, width, height) {
let cx = width / 2;
let cy = height / 2;
this.state.size += (1 - this.state.size) * 0.02; // 缓动展开
ctx.save();
ctx.translate(cx, cy);
// 小宇宙的门
let doorWidth = 120 * this.state.size;
let doorHeight = 200 * this.state.size;
ctx.fillStyle = "#fff";
ctx.shadowColor = "#fff";
ctx.shadowBlur = 50;
ctx.fillRect(-doorWidth/2, -doorHeight/2, doorWidth, doorHeight);
// 门中的微型新地球
if (this.state.size > 0.8) {
ctx.shadowBlur = 0;
ctx.fillStyle = "#3498db";
ctx.beginPath();
ctx.arc(0, 0, 30, 0, Math.PI*2);
ctx.fill();
// 生态球光晕
ctx.strokeStyle = "rgba(100, 255, 100, 0.8)";
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(0, 0, 40, 0, Math.PI*2);
ctx.stroke();
}
ctx.restore();
}
}
];
let currentSceneIndex = 0;
function updatePanels() {
const scene = scenes[currentSceneIndex];
document.getElementById('scene-title').innerText = scene.title;
// 渲染科学与想象列表
const sList = document.getElementById('science-list');
sList.innerHTML = scene.science.map(item => `<li>${item}</li>`).join('');
const fList = document.getElementById('fiction-list');
fList.innerHTML = scene.fiction.map(item => `<li>${item}</li>`).join('');
// 打字机叙事
typeWriter(scene.narrative, 'narrative-text');
// 按钮状态
document.getElementById('prev-btn').disabled = currentSceneIndex === 0;
const nextBtn = document.getElementById('next-btn');
if (currentSceneIndex === scenes.length - 1) {
nextBtn.innerText = "重新循环";
} else {
nextBtn.innerText = "下一跃迁";
}
scene.init();
}
/**
* 主循环
*/
function loop() {
drawBackground();
// 渲染当前场景
scenes[currentSceneIndex].draw(ctx, width, height);
requestAnimationFrame(loop);
}
/**
* 交互控制
*/
document.getElementById('start-btn').addEventListener('click', () => {
document.getElementById('intro').style.opacity = 0;
setTimeout(() => {
document.getElementById('intro').style.display = 'none';
updatePanels();
loop();
}, 1000);
});
document.getElementById('next-btn').addEventListener('click', () => {
if (currentSceneIndex < scenes.length - 1) {
currentSceneIndex++;
} else {
currentSceneIndex = 0; // 循环
}
updatePanels();
});
document.getElementById('prev-btn').addEventListener('click', () => {
if (currentSceneIndex > 0) {
currentSceneIndex--;
updatePanels();
}
});
// 键盘支持
window.addEventListener('keydown', (e) => {
if(document.getElementById('intro').style.display !== 'none') return;
if(e.key === 'ArrowRight' || e.key === 'Space') {
document.getElementById('next-btn').click();
} else if(e.key === 'ArrowLeft') {
document.getElementById('prev-btn').click();
}
});
</script>
</body>
</html>