Spaces:
Runtime error
Runtime error
Download frontend/src/lib/edge/simulator.ts from IDKHowToCodeFr/tinyml-backend: direct link, hf CLI and curl.
- Browser
- Download file 3.94 kB
-
https://huggingface.co/spaces/IDKHowToCodeFr/tinyml-backend/resolve/main/frontend/src/lib/edge/simulator.ts
- Command line
-
hf download hf://spaces/IDKHowToCodeFr/tinyml-backend/frontend/src/lib/edge/simulator.ts
-
curl -L -o simulator.ts https://huggingface.co/spaces/IDKHowToCodeFr/tinyml-backend/resolve/main/frontend/src/lib/edge/simulator.ts
3.94 kB
| import { PatientVitals, TelemetryPacket } from "./types"; | |
| import { evaluateEdge } from "./inference"; | |
| type PatientState = "normal" | "asthma" | "hypertension" | "heart_disease" | "diabetes"; | |
| export class BrowserTelemetrySimulator { | |
| private hr = 75.0; | |
| private spo2 = 98.0; | |
| private sys_bp = 120.0; | |
| private dia_bp = 80.0; | |
| private temp = 37.0; | |
| private target_hr = 75.0; | |
| private target_spo2 = 98.0; | |
| private target_sys = 120.0; | |
| private target_dia = 80.0; | |
| private timer: NodeJS.Timeout | null = null; | |
| private listeners: ((packet: TelemetryPacket) => void)[] = []; | |
| constructor() {} | |
| private shiftState() { | |
| // 8% chance every tick to shift patient state | |
| if (Math.random() < 0.08) { | |
| const states: PatientState[] = [ | |
| "normal", "normal", "normal", "asthma", "hypertension", "heart_disease", "diabetes" | |
| ]; | |
| const state = states[Math.floor(Math.random() * states.length)]; | |
| if (state === "normal") { | |
| this.target_hr = 75.0; this.target_spo2 = 98.0; this.target_sys = 120.0; this.target_dia = 80.0; | |
| } else if (state === "asthma") { | |
| this.target_hr = 115.0; this.target_spo2 = 88.0; this.target_sys = 135.0; this.target_dia = 85.0; | |
| } else if (state === "hypertension") { | |
| this.target_hr = 90.0; this.target_spo2 = 97.0; this.target_sys = 175.0; this.target_dia = 105.0; | |
| } else if (state === "heart_disease") { | |
| this.target_hr = 135.0; this.target_spo2 = 91.0; this.target_sys = 150.0; this.target_dia = 95.0; | |
| } else if (state === "diabetes") { | |
| this.target_hr = 85.0; this.target_spo2 = 96.0; this.target_sys = 140.0; this.target_dia = 90.0; | |
| } | |
| } | |
| } | |
| private stepPhysics() { | |
| // Interpolate towards target with noise | |
| this.hr += (this.target_hr - this.hr) * 0.12 + (Math.random() * 4 - 2); | |
| this.spo2 += (this.target_spo2 - this.spo2) * 0.12 + (Math.random() * 0.8 - 0.4); | |
| this.sys_bp += (this.target_sys - this.sys_bp) * 0.12 + (Math.random() * 2 - 1); | |
| this.dia_bp += (this.target_dia - this.dia_bp) * 0.12 + (Math.random() * 2 - 1); | |
| this.temp = Math.max(36.0, Math.min(39.2, this.temp + (Math.random() * 0.2 - 0.1))); | |
| // Clamping to physiologically valid ranges | |
| this.hr = Math.max(50.0, Math.min(180.0, this.hr)); | |
| this.spo2 = Math.max(78.0, Math.min(100.0, this.spo2)); | |
| this.sys_bp = Math.max(85.0, Math.min(210.0, this.sys_bp)); | |
| this.dia_bp = Math.max(55.0, Math.min(130.0, this.dia_bp)); | |
| } | |
| public getSnapshot(): PatientVitals { | |
| return { | |
| Heart_Rate: Number(this.hr.toFixed(1)), | |
| SpO2_Level: Number(this.spo2.toFixed(1)), | |
| Systolic_BP: Number(this.sys_bp.toFixed(1)), | |
| Diastolic_BP: Number(this.dia_bp.toFixed(1)), | |
| Body_Temp: Number(this.temp.toFixed(1)) | |
| }; | |
| } | |
| public tick(): TelemetryPacket { | |
| this.shiftState(); | |
| this.stepPhysics(); | |
| const sensor_data = this.getSnapshot(); | |
| const prediction = evaluateEdge(sensor_data); | |
| const packet: TelemetryPacket = { | |
| sensor_data, | |
| prediction: { | |
| is_at_risk: prediction.is_at_risk, | |
| label: prediction.label, | |
| confidence: prediction.confidence, | |
| disease_probs: prediction.disease_probs, | |
| inference_latency_us: prediction.latency_us | |
| }, | |
| runtime_mode: "EDGE_WASM_BROWSER" | |
| }; | |
| return packet; | |
| } | |
| public subscribe(fn: (packet: TelemetryPacket) => void) { | |
| this.listeners.push(fn); | |
| if (!this.timer && typeof window !== "undefined") { | |
| this.timer = setInterval(() => { | |
| const p = this.tick(); | |
| this.listeners.forEach(cb => cb(p)); | |
| }, 1000); | |
| } | |
| return () => { | |
| this.listeners = this.listeners.filter(cb => cb !== fn); | |
| if (this.listeners.length === 0 && this.timer) { | |
| clearInterval(this.timer); | |
| this.timer = null; | |
| } | |
| }; | |
| } | |
| } | |
| // Global singleton instance for the browser | |
| export const globalSimulator = new BrowserTelemetrySimulator(); | |