diff --git a/docs/factory-console.html b/docs/factory-console.html index d79966f..9223493 100644 --- a/docs/factory-console.html +++ b/docs/factory-console.html @@ -115,12 +115,12 @@ document.documentElement.setAttribute("data-theme",t);})(); .ok { color: var(--ok); } .bad { color: var(--bad); } .warn { color: var(--warn); } /* presses */ - .presses { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(262px, 100%), 1fr)); gap: 12px; } + .presses { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(262px, 100%), 1fr)); gap: 12px; } .pcard { display: flex; flex-direction: column; gap: 9px; background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 12px 14px; color: var(--ink); text-decoration: none; min-width: 0; position: relative; } .pcard:hover { border-color: var(--stroke); text-decoration: none; } .pc-h { display: flex; align-items: center; gap: 8px; } .pc-h b { font-family: var(--mono); font-size: 15px; } - .pc-h .mute { font-size: 12px; } + .pc-h .mute { font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; } .pst { margin-left: auto; font-size: 11.5px; font-weight: 700; padding: 1px 8px; border-radius: 99px; background: var(--card2); color: var(--mute); white-space: nowrap; } .lamp { width: 9px; height: 9px; border-radius: 50%; background: var(--faint); flex: none; } .s-run .lamp { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-s); animation: pulse 1.6s ease-in-out infinite; } @@ -343,7 +343,7 @@ document.documentElement.setAttribute("data-theme",t);})();
@@ -425,7 +425,8 @@ const NOW0=(()=>{const d=new Date();d.setHours(10,5,0,0);return d.getTime();})() const S={t:NOW0-60*DAY,speed:20,run:true,warm:true,orders:[],byId:{},presses:[],lots:[],use:{black:null,clear:null},pend:{black:0,clear:0},regrind:[],feed:[],aud:[],led:[],ledN:0,day:{k:0},days:[],nextArr:0,seq:{o:1040,p:300,lot:2400,rg:880}, ui:{view:"factory",fpage:"floor",arg:null,fhash:"floor",filter:"active",q:"",cust:null}}; function mkPress(id,sys,kind){return {id,sys,kind,st:"off",next:0,until:0,order:null,set:null,since:0,why:"",tel:[],lc:30000,op:"",res:0};} -S.presses=[mkPress("D1-A","Duplex 1","duplex"),mkPress("D1-B","Duplex 1","duplex"),mkPress("D2-A","Duplex 2","duplex"),mkPress("D2-B","Duplex 2","duplex"),mkPress("C1","Classic","classic")]; +/* demo fleet for now: one Duplex system (two presses on one extruder set) and one Classic */ +S.presses=[mkPress("D1-A","Duplex","duplex"),mkPress("D1-B","Duplex","duplex"),mkPress("C1","Classic","classic")]; const pById=id=>S.presses.find(p=>p.id===id); /* ================= ledger: append-only, hash-chained ================= */ @@ -635,7 +636,7 @@ function arrivals(t){ while(S.nextArr<=t){ const at=S.nextArr;newOrder(at); const queued=S.orders.reduce((a,o)=>a+((o.si===SI.queue||o.si===SI.run)?o.qty-o.good:0),0); - S.nextArr=at-Math.log(1-rnd())*(DAY/3.6)*(queued>18000?2.6:1); + S.nextArr=at-Math.log(1-rnd())*(DAY/2.2)*(queued>11000?2.6:1); } } function step(t){dayRoll(t);advanceLots(t);for(const p of S.presses)pressAdvance(p,t);advanceOrders(t);arrivals(t);S.t=t;} @@ -794,7 +795,7 @@ function pressCard(p){
Stamper set ${set?set.n:"-"}: ${set?fI(set.plays):0} of ${set?fI(set.life):0} plays${bar(set?set.plays/set.life:0,set&&set.plays/set.life>0.9?"warn":"")}
`; else body=`
${p.st==="off"?"Off for the night.":"No order mounted."}
`; const stats=p.st==="run"&&tl?`${f1(tl.cyc)} s cycle${Math.round(3600/tl.cyc)} an hoursteam ${Math.round(tl.steam)} °C`:`${esc(pstate(p))}`; - return `
${p.id}${p.kind==="duplex"?"Newbilt "+p.sys:"Newbilt Classic"}${PST[p.st]}
${body}
${stats}
`; + return `
${p.id}${p.kind==="duplex"?"Newbilt Duplex, press "+p.id.slice(-1):"Newbilt Classic"}${PST[p.st]}
${body}
${stats}
`; } function alerts(){const A=[]; for(const p of S.presses){if(p.st==="stop")A.push(["bad",`${p.id} stopped: ${p.why}`,`Back in about ${dur(p.until-S.t)}. Logged by the press PLC.`,"press="+p.id]); @@ -818,7 +819,7 @@ const PAGES={}; PAGES.floor={ layout:()=>`
Factory console

Press floor, live

-

Presses

The launch fleet in the plan: two Newbilt Duplex systems and one Classic
+

Presses

One Newbilt Duplex system (two HRP 12 presses) and one Newbilt Classic

Optical inspection, every record

record key: stamper · press · cycle time

Needs attention

@@ -901,7 +902,7 @@ PAGES.press={ const o=p.order,tel=p.tel,last=tel[tel.length-1],bp=S.day.bp[p.id]||{g:0,r:0}; const tl=(lbl,key,unit,lo,hi,fmt)=>`
${lbl}${last?fmt(last[key])+" "+unit:"-"}
${spark(tel.map(x=>x[key]),lo,hi)}
`; return { - prH:`
${p.kind==="duplex"?"Newbilt "+p.sys+", HRP 12 press":"Newbilt Classic, automatic"}

${p.id} ${PST[p.st]}

${esc(pstate(p))}${p.op?" · "+p.op:""}

`, + prH:`
${p.kind==="duplex"?"Newbilt Duplex, HRP 12 press "+p.id.slice(-1):"Newbilt Classic, automatic"}

${p.id} ${PST[p.st]}

${esc(pstate(p))}${p.op?" · "+p.op:""}

`, prG:`

Mounted

${o?`${o.id}`:""}
${o?`
${discSVG(o,54,false)}
${esc(o.title)}
${esc(o.artist)}
${esc(fmtS(o))}
Progress
${fI(o.good)} good of ${fI(o.qty)}, ${fI(o.rej)} rejected
Stampers
${p.set?p.set.st.map(s=>s.id).join(" / "):"-"}
Plays
${p.set?fI(p.set.plays)+" of "+fI(p.set.life)+" expected life":"-"}
Compound
${o.lots.slice(-1)[0]||"-"}
Labels
${o.labelLot||"-"}
`:'

Nothing mounted.

'}

Today on this press

${fI(bp.g)}good
${fI(bp.r)}rejected
${f1(pct(bp.r,bp.g+bp.r))} %reject rate

${p.kind==="duplex"?"Cycle about 30 s (Newbilt): load by hand 4 to 6.5 s, close, steam, cool, open, eject.":"Cycle 28 s (Newbilt Classic flyer), fully automatic."} Unplanned stops average one per four running hours in this simulation.

Telemetry, last ${tel.length} cycles

values simulated around the plan's 10 bar / 180 °C steam
${tl("Cycle time","cyc","s",26,34,f1)}${tl("Steam temperature","steam","°C",176,184,f1)}${tl("Steam pressure","bar","bar",9.5,10.5,f2)}${tl("Cooling water supply","cool","°C",15,21,f1)}${tl("Cake weight","cake","g",o?cakeW(o)-5:140,o?cakeW(o)+5:160,f1)}
diff --git a/site/public/index.html b/site/public/index.html index 4788d3b..8f320da 100644 --- a/site/public/index.html +++ b/site/public/index.html @@ -117,8 +117,8 @@ document.documentElement.setAttribute("data-theme",t);})();
  • Factory console and order status (investor demo) - The factory application on a simulated plant day: five - presses with live counters, every record through optical + The factory application on a simulated plant day: a Newbilt + Duplex system and a Classic with live counters, every record through optical inspection, audio samples, the material lab gate, stamper metrology and the hash-chained event log. Switch to the customer portal to follow the same orders: steps and approvals, copies