27:18Gemini 4 Hydrogen: Cheaper Tokens, More Expensive Answers?
Nov 13, 2026 · YouTube
36:22Fable 5.2 robbing me blind, plus: Nex AGI's N2.6 vs GLM 5.3 Flash
Nov 11, 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
You build physics toys, and you have dropped a garden hose with the water on full.
Build me a single HTML page: a garden hose lying on a lawn, the spigot on, and the nozzle released.
#psi=40 sets the pressure to 40 psi with the nozzle free on load. Any number works.data: URIs are fine.localStorage, sessionStorage, cookies or indexedDB — sandboxed frame, they throw.html block.One paragraph, before the file: how the hose discretization and inextensibility constraints are implemented, the formula for the nozzle reaction force as a function of psi, and ground friction handling.
The pressure in psi at which the hose transitions from stationary or settling to continuous whipping, as one number, derived from your model parameters.
The single fenced html block.
Where the motion looks like a real hose and where it does not. Name any artificial damping, injected noise or scripted oscillation. Everyone has watched a hose get away from somebody; say what yours gets wrong before I see it.
The hose is a chain of 44 point masses (0.09 kg each, 0.30 m apart, pinned at the spigot) integrated with Verlet/PBD substeps at 240 Hz, with 8 distance-constraint iterations per substep enforcing the fixed segment length so the total length cannot stretch, and a discrete bending force $F_{bend}=-K_{bend}(p_i-(p_{i-1}+p_{i+1})/2)$ with $K_{bend}=90\ \mathrm{N/m}$; internal water pressure amplifies curvature with $F_{press}=+\gamma,\psi,(p_i-(p_{i-1}+p_{i+1})/2)$, $\gamma=3.6\ \mathrm{N,m^{-1},psi^{-1}}$, i.e. net stiffness $K_{bend}-\gamma\psi$, and the nozzle reaction is the momentum flux $F_{nozzle}=2A\psi_{Pa}$ with $A=1.8\times10^{-5}\ \mathrm{m^2}$, $\psi_{Pa}=6894.76,\psi$, applied opposite the tip tangent and distributed over the last three points; ground friction is Coulomb friction $\mu=0.5$ applied as a constant deceleration $\mu g$ opposing each point's velocity every substep, stopping it in finite time, plus a small viscous damping, so below the stiffness threshold bending and friction dissipate motion and above it the negative net stiffness and follower nozzle force inject energy faster than friction removes it.
25
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Crouton Alpha — Garden Hose</title>
<style>
html,body{margin:0;height:100%;overflow:hidden;background:#357a28;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif}
canvas{display:block;width:100vw;height:100vh;cursor:crosshair}
#ui{position:absolute;top:12px;left:12px;background:rgba(10,25,10,.72);color:#eef7e8;
padding:12px 14px;border-radius:12px;max-width:320px;box-shadow:0 4px 18px rgba(0,0,0,.35)}
#ui h1{font-size:15px;margin:0 0 6px}
#ui p{font-size:12px;line-height:1.35;margin:6px 0;color:#cfe8c2}
#psiVal{font-variant-numeric:tabular-nums;font-weight:700;color:#fff}
input[type=range]{width:100%;accent-color:#7ecbff}
.row{display:flex;justify-content:space-between;font-size:12px;color:#cfe8c2}
#state{font-weight:700;color:#ffe27a}
</style>
</head>
<body>
<canvas id="c"></canvas>
<div id="ui">
<h1>Garden hose — dropped, nozzle free</h1>
<div class="row"><span>Water pressure</span><span><span id="psiVal">0</span> psi</span></div>
<input id="psi" type="range" min="0" max="80" step="1" value="0">
<div class="row"><span>0</span><span id="state">settled</span><span>80 psi</span></div>
<p>Drag the hose to pin that point to the mouse. Release to free it. The spigot end stays pinned. Try loading with <b>#psi=40</b>.</p>
</div>
<script>
(function(){
"use strict";
var canvas=document.getElementById('c'), ctx=canvas.getContext('2d');
var slider=document.getElementById('psi'), psiVal=document.getElementById('psiVal'), stateEl=document.getElementById('state');
function clamp(v,a,b){return v<a?a:(v>b?b:v);}
var psi=0;
var m=location.hash.match(/psi=(-?\d+(?:\.\d+)?)/i);
if(m){ psi=clamp(parseFloat(m[1])||0,0,80); }
slider.value=psi; psiVal.textContent=Math.round(psi);
slider.addEventListener('input',function(){ psi=parseFloat(slider.value); psiVal.textContent=Math.round(psi); });
var W=0,H=0,SCALE=36,spigotX=150,spigotY=300,speckles=[];
function resize(){
W=canvas.width=window.innerWidth; H=canvas.height=window.innerHeight;
spigotX=Math.min(150,W*0.22); spigotY=H/2; speckles=[];
var seed=12345; function rnd(){ seed=(seed*1103515245+12345)&0x7fffffff; return seed/0x7fffffff; }
for(var i=0;i<900;i++) speckles.push({x:rnd()*W,y:rnd()*H,r:1+rnd()*2,a:0.05+rnd()*0.12});
}
window.addEventListener('resize',resize); resize();
// Model constants (SI, metres)
var N=44, SEG=0.30, MASS=0.09, MU=0.5, G=9.81;
var K_BEND=90.0, GAMMA=3.6; // psi_crit = K_BEND/GAMMA = 25
var A_NOZZLE=1.8e-5, PSI_PA=6894.76, RHO=1000.0;
var pts=[], prev=[];
for(var i=0;i<N;i++){
var x=i*SEG*0.98, y=Math.sin(i*0.28)*0.65*(0.3+0.7*i/N);
pts.push({x:x,y:y}); prev.push({x:x,y:y});
}
var dragIndex=-1, mouse={x:0,y:0};
function toWorld(cx,cy){ return {x:(cx-spigotX)/SCALE, y:(cy-spigotY)/SCALE}; }
canvas.addEventListener('pointerdown',function(e){
var w=toWorld(e.clientX,e.clientY), best=-1, bd=1e9;
for(var i=1;i<N;i++){ var dx=pts[i].x-w.x, dy=pts[i].y-w.y, d=dx*dx+dy*dy; if(d<bd){bd=d;best=i;} }
if(bd<1.0){ dragIndex=best; mouse=w; canvas.setPointerCapture(e.pointerId); }
});
canvas.addEventListener('pointermove',function(e){ mouse=toWorld(e.clientX,e.clientY); });
canvas.addEventListener('pointerup',function(){ dragIndex=-1; });
canvas.addEventListener('pointercancel',function(){ dragIndex=-1; });
var ax=new Float64Array(N), ay=new Float64Array(N);
function step(dt){
for(var i=0;i<N;i++){ ax[i]=0; ay[i]=0; }
var keff=K_BEND-GAMMA*psi;
for(i=1;i<N-1;i++){
var dx=pts[i].x-(pts[i-1].x+pts[i+1].x)*0.5;
var dy=pts[i].y-(pts[i-1].y+pts[i+1].y)*0.5;
ax[i]+=-keff*dx/MASS; ay[i]+=-keff*dy/MASS;
}
if(psi>0){
var tx=pts[N-1].x-pts[N-2].x, ty=pts[N-1].y-pts[N-2].y;
var tl=Math.hypot(tx,ty)||1; tx/=tl; ty/=tl;
var F=2*A_NOZZLE*psi*PSI_PA; // nozzle reaction, N
var wts=[[N-1,0.65],[N-2,0.25],[N-3,0.10]];
for(var k=0;k<wts.length;k++){ var idx=wts[k][0]; ax[idx]+=-tx*F*wts[k][1]/MASS; ay[idx]+=-ty*F*wts[k][1]/MASS; }
var noise=(Math.random()-0.5)*0.04*F; // tiny symmetry-breaking noise, disclosed
ax[N-1]+=-ty*noise/MASS; ay[N-1]+=tx*noise/MASS;
}
var damp=Math.exp(-0.9*dt);
for(i=1;i<N;i++){
if(i===dragIndex) continue;
var vx=(pts[i].x-prev[i].x)*damp, vy=(pts[i].y-prev[i].y)*damp;
var sp=Math.hypot(vx,vy)/dt;
if(sp>1e-9){
var ns=Math.max(0,sp-MU*G*dt), s=ns/sp; vx*=s; vy*=s; // Coulomb ground friction
}
var ox=pts[i].x, oy=pts[i].y;
prev[i].x=ox; prev[i].y=oy;
pts[i].x=ox+vx+ax[i]*dt*dt;
pts[i].y=oy+vy+ay[i]*dt*dt;
}
for(var it=0;it<8;it++){
pts[0].x=0; pts[0].y=0; prev[0].x=0; prev[0].y=0;
if(dragIndex>=0){ pts[dragIndex].x=mouse.x; pts[dragIndex].y=mouse.y; prev[dragIndex].x=mouse.x; prev[dragIndex].y=mouse.y; }
for(i=0;i<N-1;i++){
var ddx=pts[i+1].x-pts[i].x, ddy=pts[i+1].y-pts[i].y;
var d=Math.hypot(ddx,ddy)||1e-9, diff=(d-SEG)/d;
if(i===0){ pts[i+1].x-=ddx*diff; pts[i+1].y-=ddy*diff; }
else if(i+1===dragIndex){ pts[i].x+=ddx*diff; pts[i].y+=ddy*diff; }
else if(i===dragIndex){ pts[i+1].x-=ddx*diff; pts[i+1].y-=ddy*diff; }
else { var h=0.5*diff; pts[i].x+=ddx*h; pts[i].y+=ddy*h; pts[i+1].x-=ddx*h; pts[i+1].y-=ddy*h; }
}
}
if(dragIndex>=0){ pts[dragIndex].x=mouse.x; pts[dragIndex].y=mouse.y; prev[dragIndex].x=mouse.x; prev[dragIndex].y=mouse.y; }
}
var particles=[], wet=[], spawnAcc=0;
function updateParticles(dt){
if(psi>0){
spawnAcc+=dt*psi*3;
var tx=pts[N-1].x-pts[N-2].x, ty=pts[N-1].y-pts[N-2].y, tl=Math.hypot(tx,ty)||1; tx/=tl; ty/=tl;
var vjet=Math.sqrt(2*psi*PSI_PA/RHO);
while(spawnAcc>=1){
spawnAcc-=1;
particles.push({x:pts[N-1].x,y:pts[N-1].y,vx:tx*vjet*(0.85+Math.random()*0.3),vy:ty*vjet*(0.85+Math.random()*0.3),life:0.55+Math.random()*0.3});
}
}
var drag=Math.exp(-7*dt);
for(var i=particles.length-1;i>=0;i--){
var p=particles[i]; p.vx*=drag; p.vy*=drag; p.x+=p.vx*dt; p.y+=p.vy*dt; p.life-=dt;
if(p.life<=0){ wet.push({x:p.x,y:p.y,r:0.12+Math.random()*0.2,life:6}); particles.splice(i,1); }
}
for(i=wet.length-1;i>=0;i--){ wet[i].life-=dt; if(wet[i].life<=0) wet.splice(i,1); }
if(wet.length>600) wet.splice(0,wet.length-600);
}
function draw(){
// lawn
var g=ctx.createLinearGradient(0,0,0,H); g.addColorStop(0,'#4a9a3a'); g.addColorStop(1,'#2f7a26');
ctx.fillStyle=g; ctx.fillRect(0,0,W,H);
var stripe=Math.floor(W/90);
for(var s=0;s<stripe;s++){ if(s%2===0){ ctx.fillStyle='rgba(255,255,255,0.05)'; ctx.fillRect(s*90,0,90,H); } }
for(var i=0;i<speckles.length;i++){ var sp=speckles[i]; ctx.fillStyle='rgba(20,60,15,'+sp.a+')'; ctx.beginPath(); ctx.arc(sp.x,sp.y,sp.r,0,6.283); ctx.fill(); }
// wet patches
for(i=0;i<wet.length;i++){ var w=wet[i]; ctx.fillStyle='rgba(40,90,160,'+Math.min(0.35,w.life*0.08)+')'; ctx.beginPath(); ctx.arc(spigotX+w.x*SCALE,spigotY+w.y*SCALE,w.r*SCALE,0,6.283); ctx.fill(); }
// spigot / wall
ctx.fillStyle='#8a8f94'; ctx.fillRect(0,0,Math.max(28,spigotX-52),H);
ctx.fillStyle='#6f7479'; ctx.fillRect(Math.max(28,spigotX-52),0,6,H);
ctx.fillStyle='#c0c5ca'; ctx.beginPath(); ctx.arc(spigotX,spigotY,16,0,6.283); ctx.fill();
ctx.fillStyle='#7a8087'; ctx.beginPath(); ctx.arc(spigotX,spigotY,7,0,6.283); ctx.fill();
ctx.strokeStyle='#a33'; ctx.lineWidth=3; ctx.beginPath(); ctx.moveTo(spigotX-14,spigotY); ctx.lineTo(spigotX+14,spigotY); ctx.stroke();
// hose shadow + body
function path(offx,offy){ ctx.beginPath(); ctx.moveTo(spigotX+pts[0].x*SCALE+offx,spigotY+pts[0].y*SCALE+offy);
for(var i=1;i<N;i++) ctx.lineTo(spigotX+pts[i].x*SCALE+offx,spigotY+pts[i].y*SCALE+offy); }
ctx.lineJoin='round'; ctx.lineCap='round';
ctx.strokeStyle='rgba(0,0,0,0.28)'; ctx.lineWidth=11; path(3,4); ctx.stroke();
ctx.strokeStyle='#1e6b2a'; ctx.lineWidth=10; path(0,0); ctx.stroke();
ctx.strokeStyle='#3fa34d'; ctx.lineWidth=4; path(-1,-1); ctx.stroke();
// nozzle
var tx=pts[N-1].x-pts[N-2].x, ty=pts[N-1].y-pts[N-2].y, tl=Math.hypot(tx,ty)||1; tx/=tl; ty/=tl;
var nx=spigotX+pts[N-1].x*SCALE, ny=spigotY+pts[N-1].y*SCALE, ang=Math.atan2(ty,tx);
ctx.save(); ctx.translate(nx,ny); ctx.rotate(ang);
ctx.fillStyle='#c9a227'; ctx.beginPath(); ctx.moveTo(0,-5); ctx.lineTo(20,-3); ctx.lineTo(20,3); ctx.lineTo(0,5); ctx.closePath(); ctx.fill();
ctx.fillStyle='#8a6d14'; ctx.fillRect(16,-3,4,6); ctx.restore();
// water particles
ctx.strokeStyle='rgba(170,220,255,0.9)'; ctx.lineWidth=2;
for(i=0;i<particles.length;i++){ var p=particles[i], px=spigotX+p.x*SCALE, py=spigotY+p.y*SCALE;
ctx.beginPath(); ctx.moveTo(px,py); ctx.lineTo(px-p.vx*SCALE*0.03,py-p.vy*SCALE*0.03); ctx.stroke(); }
// drag hint
if(dragIndex>=0){ ctx.fillStyle='rgba(255,255,255,0.9)'; ctx.beginPath(); ctx.arc(spigotX+pts[dragIndex].x*SCALE,spigotY+pts[dragIndex].y*SCALE,5,0,6.283); ctx.fill(); }
}
var last=performance.now(), tipSpeed=0;
function frame(now){
var dt=Math.min(0.033,(now-last)/1000); last=now;
var sub=4, sdt=1/240;
for(var i=0;i<sub;i++) step(sdt);
updateParticles(dt);
var vx=pts[N-1].x-prev[N-1].x, vy=pts[N-1].y-prev[N-1].y;
tipSpeed=Math.hypot(vx,vy)/sdt;
stateEl.textContent = (psi>25 && tipSpeed>0.4) ? 'WHIPPING' : (psi>25 ? 'unstable…' : 'settled');
draw();
requestAnimationFrame(frame);
}
requestAnimationFrame(frame);
})();
</script>
</body>
</html>
Where it looks real: the inextensible chain, the follower nozzle force, and the curvature-amplifying pressure force together produce the familiar behaviour — at low pressure the hose straightens and settles, near the threshold it develops a growing S-bend, and above it the tip thrashes in large, irregular arcs while water sprays along the instantaneous nozzle direction and leaves wet patches where droplets land. Dragging a point genuinely pins it kinematically and the rest of the hose reacts through the constraints, and lowering the pressure below the threshold lets friction and bending settle it again, with no hysteresis scripted in.
Where it does not: this is a top-down, single-plane model, so the hose cannot lift, coil in 3D, kink, or bounce, and water is shown as fast streaks with strong artificial air drag rather than true ballistic droplets with gravity. I use artificial viscous damping ($\exp(-0.9,dt)$ per substep) on top of Coulomb ground friction, and a tiny 4%-of-nozzle-force random perpendicular noise at the tip to break symmetry — there is no scripted oscillation, but that noise plus the negative-stiffness pressure term is what guarantees a prompt, sustained whip rather than a hose that might sit metastably in a bent arc. The bending law is linear and uniform, the nozzle force is distributed over three points for numerical stability, and the lawn, spigot, and wet patches are stylised, so fine details like hose memory, nozzle flutter, and pressure loss along the hose are absent.