Files

84 lines
8.1 KiB
JavaScript

/* Original conceptual teaching scenes. No operational or engineering model. */
(function () {
'use strict';
window.industryRenderers ??= {};
const C={bg:'#101d30',panel:'#182b42',line:'#667c95',ink:'#edf5ff',muted:'#aec1d7',cyan:'#57d4ed',green:'#85e0ad',amber:'#ffd178',red:'#ff8c8c'};
function scene(svg,config,kit,title,subtitle,phases,note){
const {anime,el}=kit, duration=Math.max(3000,Number(config.duration)||6000), unit=duration/6;
const tl=anime.createTimeline({autoplay:false,defaults:{ease:'linear'}});
const E=(tag,a={},text='',p=svg)=>el(tag,a,text,p);
const rect=(x,y,w,h,fill=C.panel,p=svg,extra={})=>E('rect',{x,y,width:w,height:h,rx:8,fill,...extra},'',p);
const text=(x,y,t,size=18,fill=C.ink,p=svg,extra={})=>E('text',{x,y,fill,'font-size':size,'font-family':'system-ui, sans-serif',style:`fill:${fill};font-size:${size}px;font-family:system-ui,sans-serif`,...extra},t,p);
const path=(d,color=C.line,width=3,p=svg,extra={})=>E('path',{d,fill:'none',stroke:color,'stroke-width':width,'stroke-linecap':'round','stroke-linejoin':'round',...extra},'',p);
const circle=(cx,cy,r,fill=C.cyan,p=svg,extra={})=>E('circle',{cx,cy,r,fill,...extra},'',p);
const group=()=>E('g');
const add=(target,props,at=0,len=.75)=>tl.add(target,{...props,duration:unit*len},unit*at);
const reveal=(target,at)=>{target.setAttribute('opacity','0.12');add(target,{opacity:[.12,1]},at);return target;};
const draw=(d,at,color=C.cyan,width=4)=>{const p=path(d,color,width);p.setAttribute('pathLength','1');p.setAttribute('stroke-dasharray','1');p.setAttribute('stroke-dashoffset','1');add(p,{'stroke-dashoffset':[1,0]},at);return p;};
rect(0,0,960,540,C.bg,svg,{rx:0}); text(32,39,title,26);text(32,69,subtitle,17,C.muted);
path('M32 88 H928',C.line,1);
phases.forEach((label,i)=>{const x=32+i*181;rect(x,440,172,44);const bar=rect(x,440,172,4,C.cyan,svg,{rx:0});add(bar,{opacity:[.15,1]},i,.65);text(x+10,469,`${i+1} ${label}`,16);});
text(32,516,note,16,C.muted);
const clock=E('g',{'data-clock':'finite'});add(clock,{opacity:[1,1]},0,6);
return {svg,config,tl,E,rect,text,path,circle,group,add,reveal,draw,C};
}
window.industryRenderers["infrastructure-bridge-inspection"] = function(svg, config, kit) {
const s=scene(svg,config,kit,'BRIDGE / LOAD PATH AND ACCESS CONTROL','Illustrate where load travels, then separate an inspection finding from a repair decision.',
['Apply load','Trace path','Inspect','Close lane','Review repair'],'Conceptual only — NOT structural analysis, load rating, inspection instruction or engineering advice.');
const {rect,text,path,circle,group,add,reveal,draw,C}=s;
// River, abutments, bridge piers and a recognizable truss deck.
path('M40 371 Q140 354 240 371 T440 371 T640 371 T840 371 H920', '#315f7a',14);
[99,456,813].forEach(x=>{rect(x,281,47,96,'#3b4c60');path(`M${x-13} 381 H${x+60}`,C.muted,7);});
rect(72,264,809,18,'#718296',svg,{rx:2});path('M104 254 H851 M104 254 V161 H851 V254 M104 161 L229 254 L354 161 L479 254 L604 161 L729 254 L851 161',C.muted,5);
path('M229 161 V254 M354 161 V254 M479 161 V254 M604 161 V254 M729 161 V254',C.line,3);
text(59,415,'Abutment',16,C.muted);text(426,415,'Support / ground',16,C.muted);text(791,415,'Abutment',16,C.muted);
// Vehicle load and explicit directional load arrows, intentionally unscaled.
const loadX=Math.min(420,Math.max(300,Number(config.loadX)||385));
const vehicle=group();rect(332,220,79,33,'#375676',vehicle);path('M411 233 H430 L441 252 H411 Z',C.cyan,3,vehicle);circle(349,257,7,C.bg,vehicle);circle(423,257,7,C.bg,vehicle);vehicle.setAttribute('transform',`translate(${loadX-385} 0)`);reveal(vehicle,0);
draw(`M${loadX} 112 V211 M${loadX-8} 201 L${loadX} 211 L${loadX+8} 201`,0,C.amber,4);text(440,126,'Illustrative load',17,C.amber);
draw(`M${loadX} 281 H479 V366 M471 357 L479 366 L487 357`,1,C.cyan,5);
draw('M355 267 L229 164 L119 267 V366 M111 357 L119 366 L127 357',1.2,C.cyan,4);
text(197,324,'Deck → members → supports',17,C.cyan);
// Inspected member, magnifier and review card. The crack is a symbolic finding.
const finding=group();path('M603 196 L595 207 L606 213 L599 224',C.amber,4,finding);circle(601,210,25,'none',finding,{stroke:C.amber,'stroke-width':3});path('M621 229 L642 250',C.amber,5,finding);reveal(finding,2);
const inspect=group();rect(519,300,273,104,'#3d382e',inspect);text(533,327,'Finding → qualified review',17,C.amber,inspect);text(533,352,'Access restricted locally',16,C.ink,inspect);text(533,377,'Repair / reopen not assumed',16,C.ink,inspect);reveal(inspect,2.4);
// Local closure barrier; physical access marker rather than alleged calculated failure.
const closure=group();[648,765].forEach(x=>{path(`M${x} 228 V263`,C.amber,5,closure);});rect(633,223,148,17,'#503e2d',closure,{rx:1,stroke:C.amber});for(let i=0;i<6;i++)path(`M${639+i*24} 238 L${651+i*24} 225`,C.amber,4,closure);text(668,205,'Lane closed',16,C.amber,closure);reveal(closure,3);
const repair=group();text(680,125,'Review before reopening',17,C.green,repair);path('M682 136 H902',C.green,2,repair);reveal(repair,4);
return s.tl;
};
window.industryRenderers["infrastructure-construction-resequence"] = function(svg, config, kit) {
const s=scene(svg,config,kit,'CONSTRUCTION / MOVE WORK, NOT THE GATE','Off-site work can advance during a permit hold; the dependent lift still waits for release.',
['Baseline','Permit hold','Identify float','Resequence','Gate lift'],'Illustrative schedule • amber = blocking dependency • green = resequenced work • no date promises');
const {rect,text,path,circle,group,add,reveal,draw,C}=s;
// Site section with footing, steel frame and tower crane.
path('M42 373 H347',C.muted,4);rect(66,350,90,23,'#44566b');path('M86 348 V258 H280 V348 M86 304 H280 M183 258 V350 M280 258 V350',C.line,6);
path('M316 350 V130 H51 M316 148 H100 L316 130 L337 148 H316 M316 180 L335 202 L316 224 L335 246 L316 268 L335 290 L316 312',C.amber,3);path('M335 148 V350 M112 132 V207',C.line,3);path('M103 207 Q112 225 120 208',C.amber,3);
text(51,404,'Site assembly waits for lift clearance',16,C.muted);
// A true time-axis schedule, not a generic process-box flow.
text(392,125,'Dependency schedule • illustrative time →',18);
const x0=535;[0,1,2,3,4,5].forEach(i=>{path(`M${x0+i*70} 144 V396`,C.line,1,svg,{'stroke-dasharray':'3 7'});text(x0+i*70-4,420,String(i),16,C.muted);});
const rows=[['Foundation',166],['Permit review',214],['Fabricate',262],['Site lift',310],['Envelope',358]];
rows.forEach(([name,y])=>text(390,y+20,name,16));
rect(535,166,98,27,'#316255');rect(535,214,140,27,'#59513d');
const baseline=rect(675,262,140,27,'none',svg,{stroke:C.line,'stroke-dasharray':'5 4'});
const advance=Math.min(2,Math.max(.5,Number(config.advanceSlots)||1.5))*70;
const fabrication=rect(675,262,140,27,C.green);add(fabrication,{x:[675,675-advance]},3,1);
text(684,282,'Off-site',16,C.bg); // label follows the moved bar using explicit x tween.
const label=svg.lastChild;add(label,{x:[684,684-advance]},3,1);
rect(745,310,70,27,'#32516d');rect(815,358,70,27,'#32516d');
path('M633 180 H724 V323 H740 M675 228 H727 V323 H740 M815 276 H824 V300 H780 V306 M815 323 H831 V353',C.line,2);
// A permit stop-sign interrupts the direct prerequisite, which never disappears.
const hold=group();s.E('polygon',{points:'685,204 701,204 712,215 712,231 701,242 685,242 674,231 674,215',fill:'#583e31',stroke:C.amber,'stroke-width':2},'',hold);text(687,231,'!',22,C.amber,hold);reveal(hold,1);
draw('M712 228 H727 V323 H741',1.3,C.amber,4);
const opportunity=group();path('M573 251 H810 M581 245 L573 251 L581 257',C.green,3,opportunity);text(612,201,'Use available float',16,C.green,opportunity);reveal(opportunity,2);
const staged=group();rect(168,321,97,26,'#345e46',staged,{rx:1});path('M179 320 L197 292 L217 320 L239 292 L255 320',C.green,3,staged);text(60,244,'Modules staged off-site',16,C.green,staged);reveal(staged,3.4);
const gateNote=group();rect(39,91,311,29,'#493e2d',gateNote);text(49,111,'Lift remains gated until permit release',16,C.amber,gateNote);reveal(gateNote,4);
return s.tl;
};
})();