27:18Gemini 4 Hydrogen: Cheaper Tokens, More Expensive Answers?
Nov 13, 2026 · YouTube
18:40ERNIE 5.5 Flash Preview vs GLM 5.3 Flash: Baidu's new model is very impressive!
Nov 11, 2026 · YouTube
36:22Fable 5.2 robbing me blind, plus: Nex AGI's N2.6 vs GLM 5.3 Flash
Nov 11, 2026 · YouTube
14:03Gemini 4 Carbon: Can it handle my challenges? (First look with one-shot coding tests)
Nov 10, 2026 · YouTube
47:51Ranking major U.S. Open-Weights Models. (Where does Ripple 65B fit in?)
Nov 6, 2026 · YouTube
10:57"Crouton Alpha": the latest super-efficient coding model by Meta?
Nov 3, 2026 · YouTube
38:58Testing Particle-1: a post-trained DeepSeek V4.1 Flash specializing in coding and efficiency
Oct 28, 2026 · YouTube
22:14GPT-6.1 Terra Pro vs Terra: How Much Better Is Pro?
Oct 27, 2026 · YouTube
29:55Kimi K3.1 Pro Looked Incredible. Then I Kept Testing.
Oct 26, 2026 · YouTube
31:28Is this company reselling GPT Sol 6.1 at a loss (for non-agentic/text-only)?🤔 Is this sustainable?
Oct 20, 2026 · YouTube
17:58Nemotron 3.5 Super VL vs Opus 5.5: Testing NVIDIA’s new coding juggernaut
Oct 15, 2026 · YouTube
16:04Testing a *massive* new open-weights model 🤯: Muse Spark Open (vs. Nemotron, Opus 5.5, and more)
Oct 15, 2026 · YouTube
16:43Gemini 4 Argon: Great 🐈 Animation, but a broken escalator. (Coding challenge vs Opus 5.5, Sol 6.1)
Oct 13, 2026 · YouTube
16:37Meta's new "Muse Wonder" AI is impressive... but can it compete with Anthropic's models?
Oct 12, 2026 · YouTube
11:12WOW... Haiku 5.5 is very impressive. RIP OpenAI?
Oct 7, 2026 · YouTube
22:47Mistral Large 4 Is Cheap. But Is It Good Enough to Compete?
Oct 6, 2026 · YouTube
22:02Is Pareto 26.10 Preview Just Routing to GPT Sol? I Tested It Against Sol 6.1 Pro
Oct 1, 2026 · YouTube
11:22I Tested Sonnet 5.5 Against Opus 5.5. Is It Actually Cheaper?
Sep 28, 2026 · YouTube
30:00Did Elon Musk's team "train the gay away"... and make Grok 4.7 worse?
Sep 26, 2026 · YouTube
19:21I Tested the Stealth "Space Bunny Alpha" Model Before It Went Offline
Sep 23, 2026 · YouTube
10:58So... how much better is Claude Opus 5.5 vs. GPT-6 Sol, really?
Sep 23, 2026 · YouTube
9:38Claude Opus 5.5... the BEST new model for coding!! 🤩
Sep 22, 2026 · YouTube
29:00Grok 4.7: improved, but GLM 5.3 FlashX beat it anyway (benchmark against Gemini, Sol, etc.)
Sep 22, 2026 · YouTube
You write simulations where the interesting behavior is supposed to emerge rather than be animated by hand.
Build me a single HTML page: a side-view escalator carrying 15 to 20 people. Then the escalator reverses, at high speed.
data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.One paragraph, before the file: how a person is represented, what makes one lose balance, and what happens when two of them occupy the same place.
The single fenced html block.
Having written it, what does the page do when the escalator reverses? Name anything you special-cased or nudged. Say what it does badly — I am going to press the button and watch.
Each person is a rigid, rounded body with position, velocity, angle and spin, supported by friction against the moving escalator. A limited balance motor tries to keep them upright; if the belt’s acceleration overwhelms it and they tilt too far, they fall. Bodies repel and exert friction on one another through sampled contact points, so a fallen person remains a physical obstruction. A settled person can try to stand when there is enough space.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Escalator reversal</title>
<style>
:root {
color-scheme: dark;
font-family: system-ui, sans-serif;
background: #101820;
color: #e8eef0;
}
* { box-sizing: border-box; }
body { margin: 0; }
main { max-width: 1200px; margin: auto; padding: 20px; }
header {
display: flex;
flex-wrap: wrap;
align-items: end;
justify-content: space-between;
gap: 16px;
margin-bottom: 16px;
}
h1 { font-size: 1.4rem; margin: 0 0 5px; }
p { margin: 0; color: #a9bac1; line-height: 1.45; }
.controls { display: flex; flex-wrap: wrap; gap: 8px; }
button {
border: 1px solid #7ccac2;
border-radius: 6px;
background: #23665f;
color: white;
font: inherit;
font-weight: 700;
padding: 10px 16px;
cursor: pointer;
}
button:hover { background: #2c8076; }
button:focus-visible { outline: 3px solid #ffd47f; outline-offset: 3px; }
button.secondary { background: #263741; border-color: #526b75; }
.scene {
position: relative;
overflow: hidden;
border: 1px solid #344955;
border-radius: 10px;
background: #192934;
}
canvas { display: block; width: 100%; height: clamp(390px, 53vw, 610px); }
.readout {
position: absolute;
top: 12px;
left: 14px;
color: #d5e3e5;
font-size: 0.85rem;
line-height: 1.55;
pointer-events: none;
text-shadow: 0 1px 3px #000;
}
.hint { margin-top: 12px; font-size: 0.88rem; }
</style>
</head>
<body>
<main>
<header>
<div>
<h1>Escalator reversal</h1>
<p>Watch the riders, then abruptly change the direction of the steps.</p>
</div>
<div class="controls">
<button id="reverse" type="button">Throw into reverse</button>
<button id="reset" class="secondary" type="button">Reset</button>
</div>
</header>
<div class="scene">
<canvas id="scene" aria-label="Side-view simulation of people riding an escalator"></canvas>
<div class="readout">
<div id="direction">Direction: up</div>
<div id="speed">Belt: 0.9 m/s</div>
<div id="count">Down: 0 / 18</div>
</div>
</div>
<p class="hint">Reverse again to restore the normal direction. Downed riders need room and a moment of steady footing to get up.</p>
</main>
<script>
(() => {
"use strict";
const canvas = document.getElementById("scene");
const ctx = canvas.getContext("2d");
const reverseButton = document.getElementById("reverse");
const directionLabel = document.getElementById("direction");
const speedLabel = document.getElementById("speed");
const countLabel = document.getElementById("count");
// Coordinates are along and perpendicular to the inclined belt.
const length = 32;
const incline = 0.30;
const cs = Math.cos(incline), sn = Math.sin(incline);
const gravity = 9.81;
const radius = 0.24;
const halfLength = 0.60;
const inertia = 0.16;
const invI = 1 / inertia;
const sampleOffsets = [-0.60, -0.30, 0, 0.30, 0.60];
const dt = 1 / 240;
const colors = [
"#edb16e", "#83c9c3", "#de8e85", "#a7b8e1", "#e4c66e",
"#b5d095", "#d79cc1", "#86b9d3", "#e9a781"
];
let people = [];
let belt = 0.9;
let target = 0.9;
let phase = 0;
let lastTime = 0;
let accumulator = 0;
let width = 0, height = 0, scale = 1, ox = 0, oy = 0;
function clamp(v, lo, hi) { return Math.max(lo, Math.min(hi, v)); }
function angleDiff(a, b) {
let d = a - b;
while (d > Math.PI) d -= Math.PI * 2;
while (d < -Math.PI) d += Math.PI * 2;
return d;
}
function reset() {
belt = target = 0.9;
phase = 0;
accumulator = 0;
people = [];
for (let i = 0; i < 18; i++) {
people.push({
x: 2 + i * 1.65,
y: halfLength + radius,
vx: belt,
vy: 0,
a: Math.PI / 2,
w: 0,
mode: "standing",
settled: 0,
color: colors[i % colors.length]
});
}
updateLabels();
}
function updateLabels() {
const reversed = target < 0;
reverseButton.textContent = reversed ? "Restore forward" : "Throw into reverse";
directionLabel.textContent = "Direction: " + (reversed ? "reverse" : "up");
speedLabel.textContent = "Belt: " + belt.toFixed(1) + " m/s";
countLabel.textContent = "Down: " +
people.filter(p => p.mode !== "standing").length + " / " + people.length;
}
reverseButton.addEventListener("click", () => {
target = target > 0 ? -4.4 : 0.9;
updateLabels();
});
document.getElementById("reset").addEventListener("click", reset);
function pointVelocity(p, rx, ry) {
return { x: p.vx - p.w * ry, y: p.vy + p.w * rx };
}
function impulse(p, jx, jy, rx, ry) {
p.vx += jx;
p.vy += jy;
p.w += (rx * jy - ry * jx) * invI;
}
// Contact between each of a body's sample circles and the belt.
function groundContact(p) {
const ax = Math.cos(p.a), ay = Math.sin(p.a);
for (const offset of sampleOffsets) {
const rx = ax * offset, ry = ay * offset;
const penetration = radius - (p.y + ry);
if (penetration <= 0) continue;
const v = pointVelocity(p, rx, ry);
const bias = Math.min(1.3, penetration * 0.16 / dt);
const normalMass = 1 + rx * rx * invI;
const jn = Math.max(0, (-v.y + bias) / normalMass);
impulse(p, 0, jn, rx, ry);
const after = pointVelocity(p, rx, ry);
const tangentMass = 1 + ry * ry * invI;
const jt = clamp(-(after.x - belt) / tangentMass, -1.2 * jn, 1.2 * jn);
impulse(p, jt, 0, rx, ry);
p.y += Math.min(penetration * 0.12, 0.025);
}
}
// Solid ends keep fallen riders in the scene.
function wallContact(p) {
const ax = Math.cos(p.a), ay = Math.sin(p.a);
for (const offset of sampleOffsets) {
const rx = ax * offset, ry = ay * offset;
const px = p.x + rx;
let normal = 0, penetration = 0;
if (px < radius) {
normal = 1;
penetration = radius - px;
} else if (px > length - radius) {
normal = -1;
penetration = px - (length - radius);
}
if (!normal) continue;
const v = pointVelocity(p, rx, ry);
const vn = v.x * normal;
const bias = Math.min(1, penetration * 0.14 / dt);
const j = Math.max(0, (-vn + bias) / (1 + ry * ry * invI));
impulse(p, normal * j, 0, rx, ry);
p.x += normal * Math.min(penetration * 0.15, 0.025);
}
}
function bodyContact(a, b) {
if (Math.abs(a.x - b.x) > 1.8 || Math.abs(a.y - b.y) > 1.8) return;
const ac = Math.cos(a.a), as = Math.sin(a.a);
const bc = Math.cos(b.a), bs = Math.sin(b.a);
for (const oa of sampleOffsets) {
const arx = ac * oa, ary = as * oa;
for (const ob of sampleOffsets) {
const brx = bc * ob, bry = bs * ob;
let dx = (b.x + brx) - (a.x + arx);
let dy = (b.y + bry) - (a.y + ary);
const d2 = dx * dx + dy * dy;
const diameter = radius * 2;
if (d2 >= diameter * diameter) continue;
const d = Math.sqrt(d2);
if (d < 0.00001) { dx = 1; dy = 0; }
else { dx /= d; dy /= d; }
const penetration = diameter - d;
const va = pointVelocity(a, arx, ary);
const vb = pointVelocity(b, brx, bry);
const rvx = vb.x - va.x, rvy = vb.y - va.y;
const vn = rvx * dx + rvy * dy;
const raCross = arx * dy - ary * dx;
const rbCross = brx * dy - bry * dx;
const denom = 2 + (raCross * raCross + rbCross * rbCross) * invI;
const bias = Math.min(0.8, penetration * 0.10 / dt);
const j = Math.max(0, (-vn + bias) / denom);
impulse(a, -dx * j, -dy * j, arx, ary);
impulse(b, dx * j, dy * j, brx, bry);
const tx = -dy, ty = dx;
const va2 = pointVelocity(a, arx, ary);
const vb2 = pointVelocity(b, brx, bry);
const vt = (vb2.x - va2.x) * tx + (vb2.y - va2.y) * ty;
const ta = arx * ty - ary * tx;
const tb = brx * ty - bry * tx;
const jt = clamp(-vt / (2 + (ta * ta + tb * tb) * invI),
-0.38 * j, 0.38 * j);
impulse(a, -tx * jt, -ty * jt, arx, ary);
impulse(b, tx * jt, ty * jt, brx, bry);
const correction = Math.min(penetration * 0.06, 0.012);
a.x -= dx * correction;
a.y -= dy * correction;
b.x += dx * correction;
b.y += dy * correction;
}
}
}
function hasRoom(p) {
for (const other of people) {
if (other === p) continue;
if (Math.abs(other.x - p.x) < 1.35 &&
Math.abs(other.y - p.y) < 1.4) return false;
}
return p.x > 0.9 && p.x < length - 0.9;
}
function simulate() {
const change = clamp(target - belt, -60 * dt, 60 * dt);
belt += change;
phase += belt * dt;
for (const p of people) {
const tilt = Math.abs(angleDiff(p.a, Math.PI / 2));
if (p.mode === "standing" && tilt > 0.72) {
p.mode = "down";
p.settled = 0;
} else if (p.mode === "rising" && tilt < 0.24 && p.y > 0.65) {
p.mode = "standing";
p.settled = 0;
} else if (p.mode === "rising" && !hasRoom(p)) {
p.mode = "down";
p.settled = 0;
}
if (p.mode === "down") {
const settled = p.y < 0.58 &&
Math.abs(p.vx - belt) < 1.5 &&
Math.abs(p.vy) < 0.8 && Math.abs(p.w) < 1.8 && hasRoom(p);
p.settled = settled ? p.settled + dt : 0;
if (p.settled > 0.8) {
p.mode = "rising";
p.settled = 0;
}
}
// The same limited upright controller is used by every rider.
if (p.mode !== "down") {
const error = angleDiff(Math.PI / 2, p.a);
const torqueLimit = p.mode === "rising" ? 4.8 : 3.6;
const torque = clamp(26 * error - 7 * p.w, -torqueLimit, torqueLimit);
p.w += torque * invI * dt;
}
p.vx -= gravity * sn * dt;
p.vy -= gravity * cs * dt;
p.w *= 0.9995;
p.x += p.vx * dt;
p.y += p.vy * dt;
p.a += p.w * dt;
// Normal forward operation recirculates upright riders at the top.
// The entrance must be clear; otherwise the end is a solid stop.
if (target > 0 && belt > 0 && p.mode === "standing" &&
p.x > length - 0.55) {
let clear = true;
for (const q of people) {
if (q !== p && q.x < 2.0 && q.y < 1.8) { clear = false; break; }
}
if (clear) p.x = 0.60;
}
}
for (let iteration = 0; iteration < 3; iteration++) {
for (const p of people) {
groundContact(p);
wallContact(p);
}
for (let i = 0; i < people.length; i++) {
for (let j = i + 1; j < people.length; j++) {
bodyContact(people[i], people[j]);
}
}
}
// Numerical safety limits, not triggers for falling.
for (const p of people) {
p.vx = clamp(p.vx, -12, 12);
p.vy = clamp(p.vy, -12, 12);
p.w = clamp(p.w, -14, 14);
}
}
function resize() {
const rect = canvas.getBoundingClientRect();
width = rect.width;
height = rect.height;
const dpr = Math.min(window.devicePixelRatio || 1, 2);
canvas.width = Math.round(width * dpr);
canvas.height = Math.round(height * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
scale = Math.min((width - 80) / (length * cs + 1.5),
(height - 90) / (length * sn + 3.5));
ox = (width - length * cs * scale) / 2;
oy = (height + (length * sn + 1.5) * scale) / 2;
}
function world(x, y) {
return {
x: ox + (x * cs - y * sn) * scale,
y: oy - (x * sn + y * cs) * scale
};
}
function line(x1, y1, x2, y2) {
const a = world(x1, y1), b = world(x2, y2);
ctx.moveTo(a.x, a.y);
ctx.lineTo(b.x, b.y);
}
function pathWorld(points) {
ctx.beginPath();
points.forEach((p, i) => {
const q = world(p[0], p[1]);
if (i === 0) ctx.moveTo(q.x, q.y);
else ctx.lineTo(q.x, q.y);
});
ctx.closePath();
}
function drawPerson(p) {
const ax = Math.cos(p.a), ay = Math.sin(p.a);
const sideX = -ay, sideY = ax;
function point(along, side = 0) {
return world(p.x + ax * along + sideX * side,
p.y + ay * along + sideY * side);
}
function stroke(a, b, color, widthInMeters) {
ctx.strokeStyle = color;
ctx.lineWidth = Math.max(1.2, widthInMeters * scale);
ctx.lineCap = "round";
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.lineTo(b.x, b.y);
ctx.stroke();
}
const hip = point(-0.13);
const shoulder = point(0.31);
const foot1 = point(-0.59, -0.13);
const foot2 = point(-0.59, 0.13);
const arm1 = point(-0.10, -0.23);
const arm2 = point(-0.10, 0.23);
stroke(hip, foot1, "#24333b", 0.13);
stroke(hip, foot2, "#24333b", 0.13);
stroke(shoulder, arm1, p.color, 0.11);
stroke(shoulder, arm2, p.color, 0.11);
stroke(hip, shoulder, p.color, 0.25);
const head = point(0.53);
ctx.fillStyle = "#f0c9a7";
ctx.beginPath();
ctx.arc(head.x, head.y, Math.max(2.5, 0.18 * scale), 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = "#273740";
ctx.lineWidth = Math.max(1, scale * 0.035);
ctx.stroke();
}
function draw() {
ctx.clearRect(0, 0, width, height);
const bg = ctx.createLinearGradient(0, 0, 0, height);
bg.addColorStop(0, "#233a46");
bg.addColorStop(1, "#14232d");
ctx.fillStyle = bg;
ctx.fillRect(0, 0, width, height);
// Architectural background.
ctx.strokeStyle = "rgba(190,220,225,0.07)";
ctx.lineWidth = 1;
for (let x = 40; x < width; x += 90) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, height);
ctx.stroke();
}
const left = world(0, -1.25), right = world(length, -1.25);
ctx.fillStyle = "#101c24";
ctx.fillRect(0, Math.min(height - 20, left.y + 12), width, height);
// Escalator housing.
pathWorld([[0, 0.05], [length, 0.05], [length, -1.05], [0, -1.05]]);
ctx.fillStyle = "#455b65";
ctx.fill();
ctx.strokeStyle = "#718a92";
ctx.lineWidth = Math.max(1, scale * 0.07);
ctx.stroke();
ctx.strokeStyle = "#283b44";
ctx.lineWidth = Math.max(2, scale * 0.12);
ctx.beginPath();
line(0, -0.55, length, -0.55);
ctx.stroke();
// Moving horizontal treads and vertical risers.
const spacing = 0.75;
let start = ((phase % spacing) + spacing) % spacing - spacing;
ctx.save();
pathWorld([[0, 0.18], [length, 0.18], [length, -0.6], [0, -0.6]]);
ctx.clip();
ctx.strokeStyle = "#b2c2c5";
ctx.lineWidth = Math.max(1.2, scale * 0.045);
for (let u = start; u < length + spacing; u += spacing) {
const a = world(u, 0);
const b = world(u + spacing, 0);
const yTop = a.y;
ctx.beginPath();
ctx.moveTo(a.x, yTop);
ctx.lineTo(b.x, yTop);
ctx.lineTo(b.x, b.y);
ctx.stroke();
}
ctx.restore();
// Transparent guard and handrail.
pathWorld([[0, 0.08], [length, 0.08], [length, 1.42], [0, 1.42]]);
ctx.fillStyle = "rgba(123,176,184,0.08)";
ctx.fill();
ctx.strokeStyle = "rgba(177,211,213,0.28)";
ctx.lineWidth = Math.max(1, scale * 0.035);
ctx.stroke();
for (let u = 0; u <= length; u += 3.2) {
ctx.strokeStyle = "rgba(174,205,208,0.25)";
ctx.beginPath();
line(u, 0.1, u, 1.4);
ctx.stroke();
}
people.slice().sort((a, b) => a.y - b.y).forEach(drawPerson);
ctx.strokeStyle = "#16252b";
ctx.lineWidth = Math.max(3, scale * 0.14);
ctx.lineCap = "round";
ctx.beginPath();
line(0, 1.42, length, 1.42);
ctx.stroke();
// End stops.
ctx.strokeStyle = "#f2bd60";
ctx.lineWidth = Math.max(2, scale * 0.09);
ctx.beginPath();
line(0, -0.1, 0, 0.65);
line(length, -0.1, length, 0.65);
ctx.stroke();
}
function frame(time) {
if (!lastTime) lastTime = time;
const elapsed = Math.min((time - lastTime) / 1000, 0.05);
lastTime = time;
accumulator += elapsed;
while (accumulator >= dt) {
simulate();
accumulator -= dt;
}
draw();
updateLabels();
requestAnimationFrame(frame);
}
window.addEventListener("resize", resize);
reset();
resize();
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
The belt rapidly accelerates from uphill to a faster downhill speed. The riders’ limited balance motors can be overwhelmed, after which their rigid bodies tumble, slide and push against one another. They try to stand after settling with room around them.
The main special case is the normal uphill loop: upright riders reaching the top re-enter at the bottom if it is clear. The ends otherwise act as stops. Recovery also uses an explicit clearance and settling test. The people are rigid capsules rather than articulated bodies, so their limbs do not independently catch steps or brace against neighbors; collisions and piles are approximate and can look jittery.