everydaytok commited on
Commit
f3748f0
·
verified ·
1 Parent(s): 7502fa3

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +207 -404
index.html CHANGED
@@ -1,416 +1,219 @@
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Topological Engine Lab</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script src="https://cdn.plot.ly/plotly-2.24.1.min.js"></script>
9
- <style>
10
- body { background: #06090e; color: #cbd5e1; font-family: monospace; overflow: hidden; }
11
- .glass { background: rgba(15,23,42,0.96); border: 1px solid #334155; }
12
- #drawer { transition: transform 0.28s ease-in-out; z-index: 100; }
13
- .drawer-hidden { transform: translateY(100%); }
14
- .panel-title { letter-spacing: .18em; text-transform: uppercase; }
15
- .btn { border-radius: 10px; padding: 10px 12px; font-weight: 700; }
16
- </style>
17
  </head>
18
  <body class="flex flex-col h-screen overflow-hidden">
19
 
20
- <header class="glass p-3 flex justify-between items-center z-10">
21
- <div>
22
- <h1 id="logic-label" class="text-blue-400 font-bold text-xs uppercase">TOPOLOGICAL ENGINE</h1>
23
- <div id="sub-label" class="text-[10px] text-slate-500 mt-1">Ready</div>
24
- </div>
25
- <button onclick="toggleDrawer()" class="bg-blue-600 px-4 py-1 rounded text-white text-xs font-bold">⚙️ SYSTEM DIALS</button>
26
- </header>
27
 
28
- <aside id="drawer" class="fixed inset-x-0 bottom-0 drawer-hidden glass p-5 flex flex-col gap-4 z-50 max-h-[92vh] overflow-y-auto">
29
- <div class="flex justify-between items-center border-b border-slate-700 pb-2">
30
- <span class="text-orange-400 font-bold panel-title text-xs">LAB CONTROLS</span>
31
- <button onclick="toggleDrawer()" class="text-slate-400 text-2xl">✕</button>
32
- </div>
33
-
34
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
35
- <section class="bg-slate-900 border border-blue-900 p-3 rounded">
36
- <h3 class="text-blue-400 font-bold text-[10px] mb-2 panel-title">ARCHITECTURE</h3>
37
- <select id="architecture" class="w-full bg-black border border-slate-700 p-2 text-white rounded">
38
- <option value="additive">Additive</option>
39
- <option value="multiplicative">Multiplicative</option>
40
- <option value="affine">Affine</option>
41
- <option value="gated">Gated</option>
42
- </select>
43
-
44
- <select id="coeff_mode" class="w-full mt-2 bg-black border border-slate-700 p-2 text-white rounded">
45
- <option value="single_k">Single K</option>
46
- <option value="triple_k">Triple K</option>
47
- </select>
48
-
49
- <select id="topology" class="w-full mt-2 bg-black border border-slate-700 p-2 text-white rounded">
50
- <option value="single_cell">Single Cell</option>
51
- <option value="chain">Chain</option>
52
- <option value="mesh">Mesh</option>
53
- </select>
54
-
55
- <select id="mode" class="w-full mt-2 bg-black border border-slate-700 p-2 text-white rounded">
56
- <option value="training">Training</option>
57
- <option value="inference">Inference</option>
58
- </select>
59
-
60
- <div class="grid grid-cols-2 gap-2 mt-2">
61
- <input id="num_cells" type="number" min="1" value="4" class="bg-black border border-slate-700 p-2 text-white rounded" />
62
- <input id="batch_count" type="number" min="1" value="24" class="bg-black border border-slate-700 p-2 text-white rounded" />
63
- </div>
64
-
65
- <div class="grid grid-cols-3 gap-2 mt-2">
66
- <input id="learning_rate" type="number" step="0.001" value="0.01" class="bg-black border border-slate-700 p-2 text-white rounded" />
67
- <input id="coupling" type="number" step="0.001" value="0.05" class="bg-black border border-slate-700 p-2 text-white rounded" />
68
- <input id="damping" type="number" step="0.001" value="0.08" class="bg-black border border-slate-700 p-2 text-white rounded" />
69
- </div>
70
-
71
- <button onclick="applyConfig()" class="btn w-full bg-blue-700 mt-3 text-white">APPLY PHYSICS</button>
72
- </section>
73
-
74
- <section class="bg-slate-900 border border-purple-900 p-3 rounded">
75
- <h3 class="text-purple-400 font-bold text-[10px] mb-2 panel-title">DATASET</h3>
76
- <select id="dataset_family" class="w-full bg-black border border-slate-700 p-2 text-white rounded">
77
- <option value="housing">Housing</option>
78
- <option value="subtraction">Subtraction</option>
79
- <option value="multiplication">Multiplication</option>
80
- <option value="symbolic">Symbolic</option>
81
- <option value="mixed">Mixed</option>
82
- </select>
83
-
84
- <button onclick="previewExample()" class="btn w-full bg-purple-700 mt-3 text-white">GENERATE EXAMPLE</button>
85
- <button onclick="startBatch()" class="btn w-full bg-indigo-700 mt-2 text-white">START BATCH</button>
86
-
87
- <div class="mt-3 p-3 rounded border border-slate-700 bg-black/40 text-[11px] space-y-1">
88
- <div class="text-slate-400 panel-title text-[10px]">EXAMPLE PREVIEW</div>
89
- <div id="example-view" class="text-slate-300">No sample loaded.</div>
90
- </div>
91
- </section>
92
-
93
- <section class="bg-slate-900 border border-cyan-900 p-3 rounded">
94
- <h3 class="text-cyan-400 font-bold text-[10px] mb-2 panel-title">CUSTOM INPUTS</h3>
95
- <div class="grid grid-cols-3 gap-2">
96
- <input id="custom_a" type="number" step="0.01" value="7" class="bg-black border border-slate-700 p-2 text-white rounded" placeholder="A" />
97
- <input id="custom_b" type="number" step="0.01" value="8" class="bg-black border border-slate-700 p-2 text-white rounded" placeholder="B" />
98
- <input id="custom_c" type="number" step="0.01" class="bg-black border border-slate-700 p-2 text-white rounded" placeholder="C target" />
99
- </div>
100
- <button onclick="runCustom()" class="btn w-full bg-cyan-700 mt-3 text-white">RUN CUSTOM</button>
101
- </section>
102
-
103
- <section class="bg-slate-900 border border-red-900 p-3 rounded flex flex-col justify-between">
104
- <h3 class="text-red-400 font-bold text-[10px] mb-2 panel-title">CONTROL</h3>
105
- <button onclick="halt()" class="btn w-full border border-red-500 text-red-400">HALT ENGINE</button>
106
- <div class="mt-3 text-[11px] text-slate-500">
107
- Every click updates the status line immediately.
108
- </div>
109
- </section>
110
- </div>
111
- </aside>
112
-
113
- <main class="flex-grow flex flex-col min-h-0">
114
- <div class="flex flex-col xl:flex-row flex-grow min-h-0">
115
- <div class="flex-1 min-h-[320px]" id="plot"></div>
116
-
117
- <div class="xl:w-[36rem] w-full glass border-l border-slate-800 p-4 overflow-y-auto">
118
- <div class="flex justify-between items-center mb-3 border-b border-slate-800 pb-2">
119
- <div>
120
- <div class="text-blue-300 text-[10px] font-bold panel-title">LIVE STATUS</div>
121
- <div id="status-line" class="text-[11px] text-slate-400 mt-1">Waiting...</div>
122
- </div>
123
- <div id="error-val" class="text-sm font-bold text-red-400">ERR: 0.000</div>
124
  </div>
125
-
126
- <div id="summary-box" class="grid grid-cols-2 gap-2 text-[11px] mb-4"></div>
127
-
128
- <div class="mb-4">
129
- <div class="text-[10px] text-slate-500 panel-title mb-2">CELL STATE</div>
130
- <div id="cells-ui" class="space-y-2 text-[11px] font-mono"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131
  </div>
132
-
133
- <div class="mb-4">
134
- <div class="text-[10px] text-slate-500 panel-title mb-2">LOSS HISTORY</div>
135
- <div id="loss-plot" class="h-56"></div>
 
 
 
 
 
 
 
 
136
  </div>
137
-
138
- <div>
139
- <div class="text-[10px] text-slate-500 panel-title mb-2">LOGS</div>
140
- <div id="logs" class="mt-auto pt-2 border-t border-slate-800 text-[10px] text-slate-500 h-44 overflow-y-auto space-y-1"></div>
141
- </div>
142
- </div>
143
- </div>
144
- </main>
145
-
146
- <script>
147
- const appState = { topPlotted: false, lossPlotted: false };
148
-
149
- function toggleDrawer() {
150
- document.getElementById('drawer').classList.toggle('drawer-hidden');
151
- }
152
-
153
- function readConfig() {
154
- return {
155
- architecture: document.getElementById('architecture').value,
156
- coeff_mode: document.getElementById('coeff_mode').value,
157
- topology: document.getElementById('topology').value,
158
- dataset_family: document.getElementById('dataset_family').value,
159
- mode: document.getElementById('mode').value,
160
- num_cells: parseInt(document.getElementById('num_cells').value || '1', 10),
161
- batch_size: parseInt(document.getElementById('batch_count').value || '24', 10),
162
- learning_rate: parseFloat(document.getElementById('learning_rate').value || '0.01'),
163
- coupling: parseFloat(document.getElementById('coupling').value || '0.05'),
164
- damping: parseFloat(document.getElementById('damping').value || '0.08'),
165
- };
166
- }
167
-
168
- function setHeader(cfg) {
169
- document.getElementById('logic-label').innerText =
170
- `TOPOLOGICAL ENGINE | ${cfg.architecture.toUpperCase()} | ${cfg.coeff_mode.toUpperCase()} | ${cfg.topology.toUpperCase()}`;
171
- document.getElementById('sub-label').innerText =
172
- `${cfg.dataset_family.toUpperCase()} / ${cfg.mode.toUpperCase()}`;
173
- }
174
-
175
- function setStatus(msg) {
176
- document.getElementById('status-line').innerText = msg;
177
- }
178
-
179
- function fmt(v) {
180
- if (v === null || v === undefined || Number.isNaN(v)) return '';
181
- return Number(v).toFixed(4);
182
- }
183
-
184
- async function api(path, body) {
185
- const res = await fetch(path, {
186
- method: 'POST',
187
- headers: { 'Content-Type': 'application/json' },
188
- body: JSON.stringify(body || {})
189
- });
190
- return await res.json();
191
- }
192
-
193
- async function applyConfig() {
194
- const cfg = readConfig();
195
- setHeader(cfg);
196
- setStatus('Applying config...');
197
- const out = await api('/config', cfg);
198
- setStatus(out.message || 'Config applied.');
199
- await previewExample(false);
200
- toggleDrawer();
201
- }
202
-
203
- async function previewExample(fillInputs = true) {
204
- const cfg = readConfig();
205
- const sample = await api('/example', { dataset_family: cfg.dataset_family });
206
-
207
- document.getElementById('example-view').innerHTML = `
208
- <div class="text-slate-200">a: <b>${sample.a.toFixed(3)}</b></div>
209
- <div class="text-slate-200">b: <b>${sample.b.toFixed(3)}</b></div>
210
- <div class="text-slate-200">c: <b>${sample.c.toFixed(3)}</b></div>
211
- <div class="text-slate-400">label: ${sample.label}</div>
212
- `;
213
-
214
- if (fillInputs) {
215
- document.getElementById('custom_a').value = sample.a.toFixed(3);
216
- document.getElementById('custom_b').value = sample.b.toFixed(3);
217
- document.getElementById('custom_c').value = sample.c.toFixed(3);
218
- }
219
- setStatus('Example generated.');
220
- }
221
-
222
- async function startBatch() {
223
- const cfg = readConfig();
224
- setStatus('Starting batch...');
225
- await api('/config', cfg);
226
- const out = await api('/generate_batch', { count: cfg.batch_size });
227
- setStatus(out.message || 'Batch started.');
228
- toggleDrawer();
229
- }
230
-
231
- async function runCustom() {
232
- const a = document.getElementById('custom_a').value;
233
- const b = document.getElementById('custom_b').value;
234
- const c = document.getElementById('custom_c').value;
235
- setStatus('Running custom input...');
236
- const out = await api('/test_custom', { a, b, c: c === '' ? null : c });
237
- setStatus(out.message || 'Custom input loaded.');
238
- toggleDrawer();
239
- }
240
-
241
- async function halt() {
242
- setStatus('Halting...');
243
- const out = await api('/halt', {});
244
- setStatus(out.message || 'Engine halted.');
245
- toggleDrawer();
246
- }
247
-
248
- function renderSummary(d) {
249
- const cfg = d.config || {};
250
- const sample = d.current_sample || {};
251
- const items = [
252
- ['Mode', cfg.mode || '—'],
253
- ['Arch', cfg.architecture || '—'],
254
- ['Coeffs', cfg.coeff_mode || '—'],
255
- ['Topology', cfg.topology || '—'],
256
- ['Dataset', cfg.dataset_family || '—'],
257
- ['Batch left', String(d.batch_remaining ?? '—')],
258
- ['Iteration', String(d.iteration ?? '—')],
259
- ['Error', fmt(d.current_error)],
260
- ['Loss', fmt(d.current_loss)],
261
- ['A', sample.a !== undefined ? fmt(sample.a) : '—'],
262
- ['B', sample.b !== undefined ? fmt(sample.b) : '—'],
263
- ['C', sample.c !== undefined && sample.c !== null ? fmt(sample.c) : '—']
264
- ];
265
-
266
- document.getElementById('summary-box').innerHTML = items.map(([k, v]) => `
267
- <div class="bg-black/40 border border-slate-800 rounded p-2">
268
- <div class="text-[9px] text-slate-500 panel-title">${k}</div>
269
- <div class="text-[12px] text-slate-100 mt-1">${v}</div>
270
- </div>
271
- `).join('');
272
- }
273
-
274
- function renderCells(d) {
275
- const cells = d.cells || [];
276
- document.getElementById('cells-ui').innerHTML = cells.map(cell => `
277
- <div class="border border-slate-800 rounded p-3 bg-black/30">
278
- <div class="flex justify-between items-center mb-1">
279
- <div class="text-sky-300 font-bold">CELL ${cell.id} ${cell.anchored ? '[ANCHORED]' : '[DRIFTING]'}</div>
280
- <div class="text-slate-400">label: ${cell.label || '—'}</div>
281
- </div>
282
- <div class="grid grid-cols-2 gap-x-3 gap-y-1">
283
- <div>A: <span class="text-white">${fmt(cell.a)}</span></div>
284
- <div>B: <span class="text-white">${fmt(cell.b)}</span></div>
285
- <div>C: <span class="text-white">${fmt(cell.c)}</span></div>
286
- <div>T: <span class="text-white">${cell.target !== null && cell.target !== undefined ? fmt(cell.target) : '—'}</span></div>
287
- <div>P: <span class="text-white">${fmt(cell.prediction)}</span></div>
288
- <div>E: <span class="text-white">${fmt(cell.error)}</span></div>
289
- <div>L: <span class="text-white">${fmt(cell.loss)}</span></div>
290
- <div>F: <span class="text-white">${fmt(cell.force)}</span></div>
291
- </div>
292
- <div class="mt-2 flex gap-3 text-[10px] text-purple-300">
293
- <div>k: ${fmt(cell.k)}</div>
294
- <div>ka: ${fmt(cell.ka)}</div>
295
- <div>kb: ${fmt(cell.kb)}</div>
296
- <div>kc: ${fmt(cell.kc)}</div>
297
- </div>
298
- </div>
299
- `).join('');
300
- }
301
-
302
- function renderLogs(d) {
303
- document.getElementById('logs').innerHTML = (d.logs || []).map(l => `<div>${l}</div>`).join('');
304
- }
305
-
306
- function renderTopPlot(d) {
307
- const cells = d.cells || [];
308
- const x1 = cells.map(c => c.prediction);
309
- const y1 = cells.map(c => c.id);
310
- const z1 = cells.map(c => c.error);
311
- const text1 = cells.map(c => `cell ${c.id}`);
312
-
313
- const x2 = cells.map(c => c.target !== null && c.target !== undefined ? c.target : null).filter(v => v !== null);
314
- const y2 = cells.map(c => c.target !== null && c.target !== undefined ? c.id : null).filter(v => v !== null);
315
- const z2 = x2.map(() => 0);
316
-
317
- const t1 = {
318
- type: 'scatter3d',
319
- mode: 'lines+markers+text',
320
- x: x1,
321
- y: y1,
322
- z: z1,
323
- text: text1,
324
- textposition: 'top center',
325
- marker: { size: 7 },
326
- line: { width: 3 }
327
- };
328
-
329
- const t2 = {
330
- type: 'scatter3d',
331
- mode: 'markers',
332
- x: x2,
333
- y: y2,
334
- z: z2,
335
- marker: { size: 5 }
336
- };
337
-
338
- const layout = {
339
- margin: { l: 0, r: 0, t: 0, b: 0 },
340
- paper_bgcolor: 'transparent',
341
- scene: {
342
- xaxis: { title: 'Prediction / C', color: '#475569', gridcolor: '#1e293b' },
343
- yaxis: { title: 'Cell', color: '#475569', gridcolor: '#1e293b' },
344
- zaxis: { title: 'Error', color: '#475569', gridcolor: '#1e293b' },
345
- camera: { eye: { x: 0.9, y: -1.7, z: 0.8 } }
346
- },
347
- showlegend: false
348
- };
349
-
350
- if (!appState.topPlotted) {
351
- Plotly.newPlot('plot', [t1, t2], layout, { displayModeBar: false, responsive: true });
352
- appState.topPlotted = true;
353
- } else {
354
- Plotly.react('plot', [t1, t2], layout, { displayModeBar: false, responsive: true });
355
- }
356
- }
357
-
358
- function renderLossPlot(d) {
359
- const loss = d.loss_history || [];
360
- const err = d.error_history || [];
361
- const x = loss.map((_, i) => i);
362
-
363
- const t1 = { type: 'scatter', mode: 'lines', x, y: loss, name: 'loss' };
364
- const t2 = { type: 'scatter', mode: 'lines', x, y: err, name: 'error' };
365
-
366
- const layout = {
367
- margin: { l: 35, r: 10, t: 10, b: 30 },
368
- paper_bgcolor: 'transparent',
369
- plot_bgcolor: 'transparent',
370
- xaxis: { color: '#94a3b8', gridcolor: '#1e293b' },
371
- yaxis: { color: '#94a3b8', gridcolor: '#1e293b' },
372
- showlegend: true,
373
- legend: { orientation: 'h' }
374
- };
375
-
376
- if (!appState.lossPlotted) {
377
- Plotly.newPlot('loss-plot', [t1, t2], layout, { displayModeBar: false, responsive: true });
378
- appState.lossPlotted = true;
379
- } else {
380
- Plotly.react('loss-plot', [t1, t2], layout, { displayModeBar: false, responsive: true });
381
- }
382
- }
383
-
384
- async function tick() {
385
- try {
386
- const res = await fetch('/state');
387
- const d = await res.json();
388
-
389
- const err = Math.abs(d.current_error || 0);
390
- document.getElementById('error-val').innerText = 'ERR: ' + fmt(d.current_error);
391
- document.getElementById('error-val').className = err < 0.05 ? 'text-green-400 font-bold' : 'text-red-400 font-bold';
392
-
393
- document.getElementById('status-line').innerText = d.running ? 'Engine running...' : 'Engine idle.';
394
- renderSummary(d);
395
- renderCells(d);
396
- renderLogs(d);
397
- renderTopPlot(d);
398
- renderLossPlot(d);
399
- } catch (e) {
400
- document.getElementById('status-line').innerText = 'Disconnected.';
401
- }
402
- }
403
-
404
- window.addEventListener('error', (e) => {
405
- setStatus('JS error: ' + e.message);
406
- });
407
-
408
- (async () => {
409
- setHeader(readConfig());
410
- await previewExample(false);
411
- await tick();
412
- setInterval(tick, 180);
413
- })();
414
- </script>
415
  </body>
416
  </html>
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Topological Engine Lab</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.plot.ly/plotly-2.24.1.min.js"></script>
9
+ <style>
10
+ body { background: #06090e; color: #cbd5e1; font-family: monospace; overflow: hidden; }
11
+ .glass { background: rgba(15,23,42,0.95); border: 1px solid #334155; }
12
+ #drawer { transition: transform 0.3s ease-in-out; z-index: 100; }
13
+ .drawer-hidden { transform: translateY(100%); }
14
+ </style>
 
 
15
  </head>
16
  <body class="flex flex-col h-screen overflow-hidden">
17
 
18
+ <header class="glass p-3 flex justify-between items-center z-10 shadow-lg">
19
+ <h1 class="text-blue-400 font-bold text-xs uppercase">MULTICELLULAR TOPOLOGY</h1>
20
+ <button onclick="toggleDrawer()" class="bg-blue-600 px-4 py-1 rounded text-white text-xs font-bold shadow hover:bg-blue-500">⚙️ DIALS & TESTING</button>
21
+ </header>
 
 
 
22
 
23
+ <aside id="drawer" class="fixed inset-x-0 bottom-0 drawer-hidden glass p-5 flex flex-col gap-4 z-50 max-h-[90vh] overflow-y-auto shadow-2xl">
24
+ <div class="flex justify-between items-center border-b border-slate-700 pb-2">
25
+ <span class="text-orange-400 font-bold">LABORATORY CONTROLS</span>
26
+ <button onclick="toggleDrawer()" class="text-slate-400 text-2xl">✕</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  </div>
28
+
29
+ <div class="space-y-4">
30
+ <!-- 1. TOPOLOGY ARCHITECTURE -->
31
+ <section class="bg-slate-900 border border-blue-900 p-3 rounded">
32
+ <h3 class="text-blue-400 font-bold text-[10px] mb-2 uppercase">1. Mesh Topology & Physics</h3>
33
+
34
+ <label class="text-[9px] text-slate-500">PHYSICS BASE</label>
35
+ <select id="architecture" class="w-full bg-black border border-slate-700 p-2 text-white mb-2 text-xs">
36
+ <option value="additive">Additive Base[(A) + (B) = C]</option>
37
+ <option value="multiplicative">Multiplicative Base[(A) * (B) = C]</option>
38
+ </select>
39
+
40
+ <div class="grid grid-cols-2 gap-2 mb-2">
41
+ <div>
42
+ <label class="text-[9px] text-slate-500">MESH DEPTH (CELLS)</label>
43
+ <input type="number" id="depth" value="1" min="1" max="5" class="w-full bg-black border border-slate-700 p-2 text-white text-xs text-center">
44
+ </div>
45
+ <div>
46
+ <label class="text-[9px] text-slate-500">STIFFNESS (K-COEFFICIENTS)</label>
47
+ <select id="k_mode" class="w-full bg-black border border-slate-700 p-2 text-white text-xs">
48
+ <option value="individual">Individual K per Node</option>
49
+ <option value="uniform">Uniform (1 Global K)</option>
50
+ </select>
51
+ </div>
52
+ </div>
53
+
54
+ <select id="mode" class="w-full bg-black border border-slate-700 p-2 text-white text-xs">
55
+ <option value="training">TRAINING PHASE (Adapt K Factors)</option>
56
+ <option value="inference">INFERENCE PHASE (Predict C)</option>
57
+ </select>
58
+ <button onclick="applyConfig()" class="w-full bg-blue-700 mt-2 py-2 font-bold text-xs rounded hover:bg-blue-600">APPLY & REBUILD MESH</button>
59
+ </section>
60
+
61
+ <!-- 2. DATASET INJECTOR -->
62
+ <section class="bg-slate-900 border border-purple-900 p-3 rounded">
63
+ <h3 class="text-purple-400 font-bold text-[10px] mb-2 uppercase">2. Dataset Environment</h3>
64
+ <select id="dataset" class="w-full bg-black border border-slate-700 p-2 text-white text-xs">
65
+ <option value="housing">Housing Data (Weight: A*2.5, B*1.2)</option>
66
+ <option value="subtraction">Subtraction Data (Weight: A*1.0, B*-1.0)</option>
67
+ <option value="multiplication">Factorization Data</option>
68
+ </select>
69
+ <button onclick="genData()" class="w-full bg-purple-700 mt-2 py-2 font-bold text-xs rounded hover:bg-purple-600">START TRAINING BATCH</button>
70
+ </section>
71
+
72
+ <!-- 3. MANUAL TESTING -->
73
+ <section class="bg-slate-900 border border-emerald-900 p-3 rounded">
74
+ <h3 class="text-emerald-400 font-bold text-[10px] mb-2 uppercase">3. Manual Prediction Test</h3>
75
+ <button onclick="loadExample()" class="w-full bg-slate-800 border border-slate-600 text-slate-300 py-1 mb-2 text-[10px] rounded hover:bg-slate-700">Auto-Fill Example for Selected Dataset</button>
76
+ <div class="grid grid-cols-2 gap-2 mb-2">
77
+ <input type="number" id="test_a" placeholder="Input A" class="w-full bg-black border border-slate-700 p-2 text-white text-center text-xs">
78
+ <input type="number" id="test_b" placeholder="Input B" class="w-full bg-black border border-slate-700 p-2 text-white text-center text-xs">
79
+ </div>
80
+ <button onclick="runManual()" class="w-full bg-emerald-700 py-2 font-bold text-xs rounded hover:bg-emerald-600 text-white">TEST FORWARD PASS</button>
81
+ </section>
82
+
83
+ <button onclick="halt()" class="w-full border border-red-500 text-red-500 py-2 rounded font-bold text-xs hover:bg-red-900">HALT / RESET SYSTEM</button>
84
  </div>
85
+ </aside>
86
+
87
+ <main class="flex-grow flex flex-col min-h-0 relative">
88
+ <div id="plot" class="flex-grow z-0"></div>
89
+
90
+ <div class="h-48 glass border-t border-slate-700 p-3 flex flex-col z-10">
91
+ <div class="flex justify-between items-center mb-1 border-b border-slate-800 pb-1">
92
+ <h4 class="text-blue-300 text-[10px] font-bold tracking-widest">NETWORK TENSION & STIFFNESS</h4>
93
+ <div id="error-val" class="text-sm font-bold text-red-400">ERR: 0.000</div>
94
+ </div>
95
+ <!-- Dynamic Grid for K Values -->
96
+ <div id="nodes-ui" class="text-[10px] font-mono mt-1 flex-grow overflow-y-auto space-y-1"></div>
97
  </div>
98
+ </main>
99
+
100
+ <script>
101
+ function toggleDrawer() { document.getElementById('drawer').classList.toggle('drawer-hidden'); }
102
+
103
+ async function applyConfig() {
104
+ await fetch('/config', {
105
+ method: 'POST', headers: {'Content-Type': 'application/json'},
106
+ body: JSON.stringify({
107
+ mode: document.getElementById('mode').value,
108
+ architecture: document.getElementById('architecture').value,
109
+ dataset: document.getElementById('dataset').value,
110
+ k_mode: document.getElementById('k_mode').value,
111
+ depth: document.getElementById('depth').value
112
+ })
113
+ });
114
+ window.plotted = false; // Force Plotly Redraw
115
+ toggleDrawer();
116
+ }
117
+
118
+ async function genData() {
119
+ await fetch('/generate', { method: 'POST' });
120
+ toggleDrawer();
121
+ }
122
+
123
+ function loadExample() {
124
+ const ds = document.getElementById('dataset').value;
125
+ if (ds === 'housing') { document.getElementById('test_a').value = 4; document.getElementById('test_b').value = 5; } // Target = 16
126
+ if (ds === 'subtraction') { document.getElementById('test_a').value = 20; document.getElementById('test_b').value = 8; } // Target = 12
127
+ if (ds === 'multiplication') { document.getElementById('test_a').value = 6; document.getElementById('test_b').value = 7; } // Target = 42
128
+ }
129
+
130
+ async function runManual() {
131
+ const a = document.getElementById('test_a').value;
132
+ const b = document.getElementById('test_b').value;
133
+ if (!a || !b) return alert("Please fill A and B");
134
+ await fetch('/test_manual', {
135
+ method: 'POST', headers: {'Content-Type':'application/json'},
136
+ body: JSON.stringify({ a: a, b: b })
137
+ });
138
+ toggleDrawer();
139
+ }
140
+
141
+ async function halt() { await fetch('/halt', {method: 'POST'}); toggleDrawer(); }
142
+
143
+ setInterval(async () => {
144
+ try {
145
+ const res = await fetch('/state');
146
+ const d = await res.json();
147
+
148
+ const err = Math.abs(d.error);
149
+ document.getElementById('error-val').innerText = "TENSION: " + d.error.toFixed(4);
150
+ document.getElementById('error-val').className = err < 0.05 ? "text-green-400 font-bold" : "text-red-400 font-bold";
151
+
152
+ let ui = "";
153
+ if (d.k_mode === 'uniform') {
154
+ ui += `<div class="bg-purple-900/40 p-1 mb-2 text-center text-purple-300 font-bold rounded">UNIFORM GLOBAL STIFFNESS (K): ${d.global_k.toFixed(4)}</div>`;
155
+ }
156
+
157
+ // Plotly Line generation (The Mesh Web)
158
+ let px=[], py=[], pz=[], ids=[];
159
+ let path_a_x = [], path_a_y = [], path_a_z =[];
160
+ let path_b_x = [], path_b_y = [], path_b_z =[];
161
+
162
+ // Format Node Readouts
163
+ Object.keys(d.nodes).sort().forEach(id => {
164
+ const n = d.nodes[id];
165
+ let k_display = d.k_mode === 'individual' ? `K: ${n.k.toFixed(3)}` : `(Global K)`;
166
+ ui += `<div class="flex justify-between border-b border-slate-900 pb-0.5">
167
+ <span class="${n.anchored ? 'text-red-300' : 'text-sky-300'}">NODE ${id}: <b class="text-white">${n.x.toFixed(2)}</b></span>
168
+ <span class="text-slate-500">${k_display}</span>
169
+ </div>`;
170
+
171
+ // Route points for Line Tracing
172
+ if(id === 'A') { path_a_x.push(n.x); path_a_y.push(n.y); path_a_z.push(n.z); px.push(n.x); py.push(n.y); pz.push(n.z); ids.push(id); }
173
+ if(id === 'B') { path_b_x.push(n.x); path_b_y.push(n.y); path_b_z.push(n.z); px.push(n.x); py.push(n.y); pz.push(n.z); ids.push(id); }
174
+ if(id.startsWith('Ha_')) { path_a_x.push(n.x); path_a_y.push(n.y); path_a_z.push(n.z); px.push(n.x); py.push(n.y); pz.push(n.z); ids.push(id); }
175
+ if(id.startsWith('Hb_')) { path_b_x.push(n.x); path_b_y.push(n.y); path_b_z.push(n.z); px.push(n.x); py.push(n.y); pz.push(n.z); ids.push(id); }
176
+ });
177
+
178
+ // Add C to both paths to close the web
179
+ path_a_x.push(d.nodes['C'].x); path_a_y.push(d.nodes['C'].y); path_a_z.push(d.nodes['C'].z);
180
+ path_b_x.push(d.nodes['C'].x); path_b_y.push(d.nodes['C'].y); path_b_z.push(d.nodes['C'].z);
181
+ px.push(d.nodes['C'].x); py.push(d.nodes['C'].y); pz.push(d.nodes['C'].z); ids.push('C');
182
+
183
+ document.getElementById('nodes-ui').innerHTML = ui;
184
+
185
+ // Creating the Multicellular Web Traces
186
+ const traces =[
187
+ { type: 'scatter3d', mode: 'markers+text', x: px, y: py, z: pz, text: ids, marker: {size: 6, color:'#38bdf8'}, name: 'Nodes' },
188
+ { type: 'scatter3d', mode: 'lines', x: path_a_x, y: path_a_y, z: path_a_z, line: {color:'#475569', width:3}, name: 'Path A' },
189
+ { type: 'scatter3d', mode: 'lines', x: path_b_x, y: path_b_y, z: path_b_z, line: {color:'#475569', width:3}, name: 'Path B' }
190
+ ];
191
+
192
+ // Add Cross-links if Multicellular to make it a "Mesh"
193
+ if (d.depth > 1) {
194
+ for(let i=0; i < d.depth - 1; i++) {
195
+ traces.push({
196
+ type: 'scatter3d', mode: 'lines',
197
+ x: [d.nodes[`Ha_${i}`].x, d.nodes[`Hb_${i}`].x],
198
+ y: [d.nodes[`Ha_${i}`].y, d.nodes[`Hb_${i}`].y],
199
+ z: [d.nodes[`Ha_${i}`].z, d.nodes[`Hb_${i}`].z],
200
+ line: {color:'rgba(71,85,105,0.4)', width:1}, showlegend: false
201
+ });
202
+ }
203
+ }
204
+
205
+ const layout = {
206
+ margin:{l:0,r:0,t:0,b:0}, paper_bgcolor:'transparent', showlegend: false,
207
+ scene:{
208
+ xaxis:{color:'#475569'}, yaxis:{range:[-3,3], visible:false}, zaxis:{range:[-1,1], visible:false},
209
+ camera: {eye:{x:0, y:-1.5, z:0.5}}
210
+ }
211
+ };
212
+ if(!window.plotted){ Plotly.newPlot('plot', traces, layout, {displayModeBar:false}); window.plotted=true; }
213
+ else { Plotly.react('plot', traces, layout); }
214
+
215
+ } catch(e){}
216
+ }, 200);
217
+ </script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
218
  </body>
219
  </html>