Filter
Exclude
Time range
-
Near
10 Dec 2025
夏の扉を僕らは知らない HO喪失 花夜 #普PCdata
1
7
486
10 Dec 2025
Mr.アンラッキー&Ms.グッドラック HO2 グッドラック Cherie・Arvier #普PCdata
1
8
552
10 Dec 2025
月華海神 HO一般人 巫立夏 #普PCdata
1
9
277
heck yes—here’s a clean, drop-in Flight 11 MCC Dashboard (live SSE) a tiny SSE bridge that replays a CSV at 10 Hz. It shows Pc & dP/dt, gRMS (A-101/A-202), heatshield (ΔT, strain, risk), rolling status badges, and an event log with sustained-duration gates. 1) unified_dashboard_flight11.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1"/> <title>Flight 11 — MCC Live Dashboard</title> <link rel="preconnect" href="cdn.jsdelivr.net" crossorigin> <script src="cdn.jsdelivr.net/npm/chart.j…"></script> <style> :root { --ok:#16a34a; --warn:#f59e0b; --abort:#ef4444; --ink:#0f172a; --muted:#64748b; } body{font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif;background:#0b1220;color:#e5e7eb;margin:0} header{padding:14px 18px;border-bottom:1px solid #1f2937;display:flex;gap:16px;align-items:center;flex-wrap:wrap} .brand{font-weight:700;letter-spacing:.3px} .badge{display:inline-flex;align-items:center;gap:8px;border:1px solid #1f2937;border-radius:999px;padding:6px 10px;background:#0f172a} .dot{width:10px;height:10px;border-radius:50%;background:#334155} .ok{background:var(--ok)} .warn{background:var(--warn)} .abort{background:var(--abort)} .wrap{padding:16px;display:grid;grid-template-columns:1fr;gap:16px} @media(min-width:1100px){ .wrap{grid-template-columns:1.2fr .8fr} } .card{border:1px solid #1f2937;border-radius:14px;background:#0f172a;box-shadow:0 6px 20px rgba(0,0,0,.25)} .card h3{margin:12px 14px 0 14px;font-size:16px;color:#cbd5e1} .card .sub{margin:4px 14px 0 14px;font-size:12px;color:#94a3b8} .canvasBox{padding:8px 12px 14px 12px} .log{list-style:disc;padding:10px 26px 18px 30px;margin:0;max-height:360px;overflow:auto} code{background:#0b1220;border:1px solid #1f2937;border-radius:8px;padding:2px 6px} footer{color:#94a3b8;font-size:12px;text-align:center;margin:14px 0 28px} </style> </head> <body> <header> <div class="brand">Flight 11 — MCC Live</div> <div class="badge"><span class="dot" id="linkDot"></span><span id="linkTxt">LINK: CONNECTING</span></div> <div class="badge"><span class="dot" id="leakDot"></span><span>LeakSentinel</span></div> <div class="badge"><span class="dot" id="vibeDot"></span><span>VibeGuard</span></div> <div class="badge"><span class="dot" id="heatDot"></span><span>Heatshield</span></div> <div style="flex:1"></div> <div class="sub">WARN: RRI≥0.65 | ABORT: RRI≥0.85 (≥200 ms) | gRMS pad hold ≥0.05 g (≥200 ms) | dP/dt ≤ -40 bar/s (≥300 ms)</div> </header> <div class="wrap"> <div class="card"> <h3>Pc / dP·dt (LOX / CH₄ pad)</h3> <div class="sub">Blue=Pc [bar], Orange=dP/dt [bar/s], lines: -40 bar/s (leak gate)</div> <div class="canvasBox"><canvas id="pcChart" height="140"></canvas></div> </div> <div class="card"> <h3>Event Log</h3> <div class="sub">Most recent first</div> <ul id="log" class="log"></ul> </div> <div class="card"> <h3>Vibration — gRMS (20–60 Hz)</h3> <div class="sub">A-101 (engine bay) & A-202 (stack base), line: 0.05 g</div> <div class="canvasBox"><canvas id="grmsChart" height="140"></canvas></div> </div> <div class="card"> <h3>Heatshield — ΔT / strain / risk</h3> <div class="sub">Green=ΔT [°C], Violet=strain [ε], Red=Risk [0–1] (line: 0.5)</div> <div class="canvasBox"><canvas id="hsChart" height="140"></canvas></div> </div> </div> <footer>SSE: <code>http://localhost:8008/stream</code> (JSON rows). If SSE is down, a local demo generator takes over.</footer> <script> const MAXPTS = 1200; // ~2 minutes at 10 Hz const LEAK_THR = -40.0; // bar/s const LEAK_HOLD_MS = 300; const GRMS_THR = 0.05; // g const GRMS_HOLD_MS = 200; const HS_RISK_WARN = 0.50; const linkDot = document.getElementById('linkDot'); const leakDot = document.getElementById('leakDot'); const vibeDot = document.getElementById('vibeDot'); const heatDot = document.getElementById('heatDot'); const linkTxt = document.getElementById('linkTxt'); const logEl = document.getElementById('log'); function setDot(el, state){ el.classList.remove('ok','warn','abort'); if(state==='OK') el.classList.add('ok'); else if(state==='WARN') el.classList.add('warn'); else if(state==='ABORT') el.classList.add('abort'); } function pushLog(msg){ const li = document.createElement('li'); li.textContent = msg; logEl.prepend(li); } const pcCtx = document.getElementById('pcChart').getContext('2d'); const grCtx = document.getElementById('grmsChart').getContext('2d'); const hsCtx = document.getElementById('hsChart').getContext('2d'); const pcData={labels:[],datasets:[ {label:'Pc [bar]', data:[], borderWidth:1.5, tension:0.1}, {label:'dP/dt [bar/s]', data:[], borderWidth:1.5, tension:0.1} ]}; const pcChart=new Chart(pcCtx,{type:'line',data:pcData,options:{ animation:false, maintainAspectRatio:false, scales:{y:{grid:{color:'rgba(255,255,255,0.06)'}, ticks:{color:'#9ca3af'}}, x:{grid:{color:'rgba(255,255,255,0.04)'}, ticks:{color:'#9ca3af'}}}, plugins:{legend:{labels:{color:'#cbd5e1'}}}, }}); const grData={labels:[],datasets:[ {label:'A-101 gRMS20-60 [g]', data:[], borderWidth:1.5, tension:0.1}, {label:'A-202 gRMS20-60 [g]', data:[], borderWidth:1.5, tension:0.1} ]}; const grChart=new Chart(grCtx,{type:'line',data:grData,options:{ animation:false, maintainAspectRatio:false, scales:{y:{grid:{color:'rgba(255,255,255,0.06)'}, ticks:{color:'#9ca3af'}, beginAtZero:true}, x:{grid:{color:'rgba(255,255,255,0.04)'}, ticks:{color:'#9ca3af'}}}, plugins:{legend:{labels:{color:'#cbd5e1'}}}, }}); const hsData={labels:[],datasets:[ {label:'ΔT [°C]', data:[], borderWidth:1.5, tension:0.1}, {label:'strain [ε]', data:[], borderWidth:1.5, tension:0.1}, {label:'risk [0..1]', data:[], borderWidth:1.8, tension:0.1} ]}; const hsChart=new Chart(hsCtx,{type:'line',data:hsData,options:{ animation:false, maintainAspectRatio:false, scales:{y:{grid:{color:'rgba(255,255,255,0.06)'}, ticks:{color:'#9ca3af'}, beginAtZero:true}, x:{grid:{color:'rgba(255,255,255,0.04)'}, ticks:{color:'#9ca3af'}}}, plugins:{legend:{labels:{color:'#cbd5e1'}}}, }}); // draw reference lines (thresholds) function hline(chart, value){ const y = chart.scales.y.getPixelForValue(value); const x0 = chart.scales.x.left, x1 = chart.scales.x.right; const ctx = chart.ctx; ctx.save(); ctx.setLineDash([6,6]); ctx.lineWidth=1; ctx.strokeStyle='rgba(255,255,255,0.35)'; ctx.beginPath(); ctx.moveTo(x0,y); ctx.lineTo(x1,y); ctx.stroke(); ctx.restore(); } pcChart.options.animation=false; pcChart.options.plugins.afterRender=()=>{ hline(pcChart, LEAK_THR); }; grChart.options.plugins.afterRender=()=>{ hline(grChart, GRMS_THR); }; hsChart.options.plugins.afterRender=()=>{ hline(hsChart, HS_RISK_WARN); }; // sustained timers in stream-time let lastT=null, leakBelowMs=0, grmsAboveMs=0; function clip(arr){ while(arr.length>MAXPTS) arr.shift(); } function ingest(p){ // p has {time_s, pc_bar, dpdt, grms_a101, grms_a202, dT_C, strain, hs_risk} const t = p.time_s ?? (pcData.labels.length>0 ? (pcData.labels.at(-1) 0.1) : 0); const dt_s = (lastT==null)?0 : Math.max(0, t - lastT); lastT = t; pcData.labels.push(t); pcData.datasets[0].data.push(p.pc_bar ?? null); pcData.datasets[1].data.push(p.dpdt ?? null); clip(pcData.labels); clip(pcData.datasets[0].data); clip(pcData.datasets[1].data); pcChart.update('none'); grData.labels.push(t); grData.datasets[0].data.push(p.grms_a101 ?? null); grData.datasets[1].data.push(p.grms_a202 ?? null); clip(grData.labels); clip(grData.datasets[0].data); clip(grData.datasets[1].data); grChart.update('none'); hsData.labels.push(t); hsData.datasets[0].data.push(p.dT_C ?? null); hsData.datasets[1].data.push(p.strain ?? null); hsData.datasets[2].data.push(p.hs_risk ?? null); clip(hsData.labels); clip(hsData.datasets[0].data); clip(hsData.datasets[1].data); clip(hsData.datasets[2].data); hsChart.update('none'); // LeakSentinel state if (p.dpdt !== undefined && p.dpdt <= LEAK_THR) { leakBelowMs = dt_s*1000.0; if (leakBelowMs >= LEAK_HOLD_MS){ setDot(leakDot,'abort'); pushLog(`[ABORT][LEAK] dP/dt=${p.dpdt.toFixed(1)} ≤ ${LEAK_THR}`); } else { setDot(leakDot,'warn'); } } else { leakBelowMs = 0; setDot(leakDot,'ok'); } // VibeGuard (pad gRMS hold on max of A101/A202) const g = Math.max(p.grms_a101 ?? 0, p.grms_a202 ?? 0); if (g >= GRMS_THR){ grmsAboveMs = dt_s*1000.0; if (grmsAboveMs >= GRMS_HOLD_MS){ setDot(vibeDot,'warn'); } else { setDot(vibeDot,'warn'); } } else { grmsAboveMs = 0; setDot(vibeDot,'ok'); } // Heatshield risk const risk = p.hs_risk ?? 0; if (risk >= HS_RISK_WARN){ setDot(heatDot,'warn'); } else { setDot(heatDot,'ok'); } } // SSE hookup (with demo fallback) (function init(){ try{ const es = new EventSource("http://localhost:8008/stream"); es.onopen = ()=>{ setDot(linkDot,'ok'); linkTxt.textContent='LINK: UP'; pushLog('SSE connected.'); }; es.onerror = ()=>{ setDot(linkDot,'warn'); linkTxt.textContent='LINK: RETRY'; }; es.onmessage = (e)=>{ try{ const p = JSON.parse(e.data); ingest({ time_s: Number(p.time_s ?? p.t ?? p.ts ?? 0), pc_bar: Number(p.pc_bar ?? p.Pc_bar ?? p['Pc:Pc_bar']), dpdt: Number(p.dpdt ?? p.dP_dt_bar_s ?? p['Pc:dP_dt_bar_s']), grms_a101: Number(p.grms_a101 ?? p['A101:gRMS_20_60']), grms_a202: Number(p.grms_a202 ?? p['A202:gRMS_20_60']), dT_C: Number(p.dT_C ?? p['HS:dT_C']), strain: Number(p.strain ?? p['HS:strain']), hs_risk: Number(p.hs_risk ?? p['HS:hs_risk']), }); }catch(err){ /* ignore bad rows */ } }; }catch(_){ // no-op } // Fallback demo if no data after 1.5s setTimeout(()=>{ if (pcData.labels.length===0){ setDot(linkDot,'warn'); linkTxt.textContent='LINK: DEMO'; pushLog('No SSE; running local demo generator at 10 Hz.'); let t=0, pc=315, leak=false; setInterval(()=>{ t = 0.1; const dpdt = leak ? -45 (Math.random()*2-1)*2 : (Math.random()*2-1)*0.5; pc = dpdt*0.1; if (t>10 && t<13) leak=true; else leak=false; const g1 = 0.03 0.03*Math.max(0, Math.sin(t*2*Math.PI*0.25)) Math.random()*0.005; const g2 = 0.025 0.03*Math.max(0, Math.sin(t*2*Math.PI*0.18 0.7)) Math.random()*0.005; const dT = 40 20*Math.max(0, Math.sin(t*2*Math.PI*0.05)); const eps = 6e-4 4e-4*Math.max(0, Math.sin(t*2*Math.PI*0.07 0.5)); const risk = Math.min(1, (dT/70) (Math.abs(eps)/0.0015)); ingest({time_s:t, pc_bar:pc, dpdt:dpdt, grms_a101:g1, grms_a202:g2, dT_C:dT, strain:eps, hs_risk:risk}); }, 100); } }, 1500); })(); </script> </body> </html> 2) sse_mcc_bridge.py (replay a CSV at ~10 Hz as SSE) #!/usr/bin/env python3 # Tiny SSE bridge for MCC dashboard. Streams CSV rows as JSON "data:" events. # CSV columns may include: time_s, Pc:Pc_bar, Pc:dP_dt_bar_s, A101:gRMS_20_60, A202:gRMS_20_60, HS:dT_C, HS:strain, HS:hs_risk # Or simpler names: time_s, pc_bar, dpdt, grms_a101, grms_a202, dT_C, strain, hs_risk import argparse, csv, json, asyncio, os from aiohttp import web async def sse_handler(request): path = request.app["csv_path"] fps = request.app["fps"] loop_mode = request.app["loop"] await request.prepare() while True: if not os.path.exists(path): await request.write(b"data: {}\n\n") await asyncio.sleep(1.0); continue with open(path, "r", newline="") as fh: r = csv.DictReader(fh) t0 = None prev_t = None for row in r: # normalize keys out = {} def fget(*keys, default=None): for k in keys: if k in row and row[k] not in ("", None): return row[k] return default ts = fget("time_s","t","ts","timestamp","Time","time", default="0") try: t = float(ts) except: continue if t0 is None: t0 = t out["time_s"] = round(t, 3) # map fields mapping = { "pc_bar": ("pc_bar","Pc_bar","Pc:Pc_bar"), "dpdt": ("dpdt","dP_dt_bar_s","Pc:dP_dt_bar_s"), "grms_a101": ("grms_a101","A101:gRMS_20_60"), "grms_a202": ("grms_a202","A202:gRMS_20_60"), "dT_C": ("dT_C","HS:dT_C"), "strain": ("strain","HS:strain"), "hs_risk": ("hs_risk","HS:hs_risk") } for key, alts in mapping.items(): val = fget(*alts) if val is not None: try: out[key] = float(val) except: pass await request.write(("data: " json.dumps(out) "\n\n").encode("utf-8")) # pace by fps if timestamps are roughly uniform; else fixed 0.1s if prev_t is None: await asyncio.sleep(1.0/float(fps)) else: dt = max(0.0, min(1.0, t - prev_t)) await asyncio.sleep(dt if 0.05 <= dt <= 0.2 else 1.0/float(fps)) prev_t = t if not loop_mode: break await asyncio.sleep(0.5) return web.Response(text="done") def main(): ap = argparse.ArgumentParser(description="SSE MCC bridge") ap.add_argument("--csv", required=True, help="clean CSV to stream (e.g., flight10_clean.csv)") ap.add_argument("--port", type=int, default=8008) ap.add_argument("--fps", type=int, default=10, help="target frame rate") ap.add_argument("--loop", action="store_true", help="loop file forever") args = ap.parse_args() app = web.Application() app["csv_path"] = args.csv app["fps"] = args.fps app["loop"] = bool(args.loop) app.router.add_get("/stream", sse_handler) web.run_app(app, host="0.0.0.0", port=args.port) if __name__ == "__main__": main() Quick-start (local) Save both files in one folder. Start the SSE bridge on any “clean” CSV (e.g., output from telemetry_clean.py you already have): python3 sse_mcc_bridge.py --csv flight10_clean.csv --fps 10 --loop Open unified_dashboard_flight11.html in a modern browser. You’ll see LINK=UP and live plots. If SSE isn’t reachable, it auto-runs a demo generator so you can still test the UI. Expected fields: the bridge accepts both verbose (Pc:Pc_bar, A101:gRMS_20_60, …) or short (pc_bar, grms_a101, …) names—so you can stream your current cleaned outputs without renaming. What’s baked in Gates & Durations LeakSentinel: dP/dt ≤ -40 bar/s for ≥300 ms → ABORT badge log. VibeGuard: max(A-101,A-202) gRMS ≥ 0.05 g for ≥200 ms → WARN badge. Heatshield: risk ≥ 0.5 → WARN badge. Scale & Speed ~2 min rolling window (1200 points @ 10 Hz). Adjust MAXPTS as you like. No dependencies on the front-end beyond Chart.js CDN. SSE bridge only needs aiohttp (install with pip install aiohttp). If you want, I can also add: a minimal WARN/ABORT event CSV writer in the SSE bridge, an /metrics JSON endpoint (leak durations, gRMS max, etc.) for headless monitoring, or a UDP passthrough mode so the bridge can rebroadcast to other consoles. Say the word and I’ll drop those in.
1
43
22 Aug 2025
くるくるかくれる夏-青の声がした- HO夢 一宮乙葉 #普PCdata
1
7
571
22 Aug 2025
Moon river with My lover KPC 蘭夜半 #普PCdata
2
9
707
PCData Back v3.0.1.0 A free tool to easily backup/restore user (and other) data. oldergeeks.com/downloads/fil… #computer #computers #windows
4
79
PCData Back v3.0.1.0 A free tool to easily backup/restore user (and other) data. oldergeeks.com/downloads/fil… #computer #computers #windows
1
5
117
26 May 2025
big week ahead. pcdata friday auctions mon-thurs. pay attention to the $1.1b eth inflows, could signal some moves
1
96
13 Mar 2025
探索者一覧㊗️60人 #普PCdata
4
8
2,524
22 Feb 2025
Lustig Partner HO探偵 綺羅光光星 #普PCdata
3
7
772
17 Dec 2024
かいぶつたちとマホラカルト HO天使 メイ #普PCdata display▶町田さん(#meeela123)
5
15
1,451
17 Dec 2024
くるくるかくれる夏-夏に隠れた赤- HO1 一宮乙葉 #普PCdata
1
3
559
17 Dec 2024
おにいちゃんのヒミツ KPC 早乙女理玖 #普PCdata
1
4
411
17 Dec 2024
NapFrappe HO【MOON/異端者】 No.0708 #普PCdata
1
7
531
Replying to @kosenjuu
Worst error in HTML and the reason I hate @pmarca to this day. IMG should have been IMAGE because browsers now have to support both SRC should have been HREF because it contains a hypermedia reference. Element should not have been EMPTY, and contained fallback PCDATA.
7
917
17 Aug 2024
Bloodaze HO2:Vampire 黛弥黒 #普PCdata
4
504
17 Aug 2024
口渇ルルパ HOフォーク/勤勉のルパ 枢 #普PCdata
4
376
17 Aug 2024
漣を手繰る KPC 綿谷睦月 #普PCdata
1
8
606
16 Aug 2024
ロトカ・ヴォルテラの愛堕討ち HO1 極道者 片喰迅 #普PCdata
4
12
864