Danielchris145 commited on
Commit
d4f5acb
·
verified ·
1 Parent(s): f321e64

Automated deployment via API

Browse files
Files changed (2) hide show
  1. app.py +1 -1
  2. templates/index.html +280 -208
app.py CHANGED
@@ -311,7 +311,7 @@ def upload_data():
311
  if file.filename == '':
312
  return jsonify({'error': 'No selected file'}), 400
313
 
314
- if file and file.filename.endswith('.csv'):
315
  df = pd.read_csv(file)
316
 
317
  # Validation
 
311
  if file.filename == '':
312
  return jsonify({'error': 'No selected file'}), 400
313
 
314
+ if file and file.filename.lower().endswith('.csv'):
315
  df = pd.read_csv(file)
316
 
317
  # Validation
templates/index.html CHANGED
@@ -1,33 +1,36 @@
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>🔥 Forge Intelligence - AI Molten Iron Monitoring</title>
7
-
8
  <!-- Google Fonts - Luxury Tech -->
9
- <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Rajdhani:wght@400;500;700&family=Inter:wght@100;300;400;500;700&display=swap" rel="stylesheet">
10
-
 
 
11
  <!-- Icons -->
12
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
13
-
14
  <!-- Chart.js -->
15
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
16
-
17
  <!-- Socket.IO -->
18
  <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
19
-
20
  <style>
21
  /* ============================================================================
22
  QUANTUM-INSPIRED LUXURY UI - FORGE INTELLIGENCE
23
  ============================================================================ */
24
-
25
  * {
26
  margin: 0;
27
  padding: 0;
28
  box-sizing: border-box;
29
  }
30
-
31
  :root {
32
  /* 🌌 Quantum Palette */
33
  --quantum-black: #0A0A0A;
@@ -40,17 +43,17 @@
40
  --neon-green: #39FF14;
41
  --glass-white: #F8F9FA;
42
  --thermal-gold: #FFD700;
43
-
44
  /* Gradients */
45
  --gradient-molten: linear-gradient(135deg, #FF4500 0%, #FFD700 50%, #00BFFF 100%);
46
  --gradient-forge: linear-gradient(180deg, #0A0A0A 0%, #1A1A2E 50%, #16213E 100%);
47
  --gradient-thermal: linear-gradient(135deg, #DC143C 0%, #FF4500 100%);
48
-
49
  /* Fonts */
50
  --font-luxury: 'Orbitron', sans-serif;
51
  --font-tech: 'Rajdhani', sans-serif;
52
  --font-modern: 'Inter', sans-serif;
53
-
54
  /* Effects */
55
  --blur-glass: 12px;
56
  --glow-molten: 0 0 30px rgba(255, 69, 0, 0.6);
@@ -58,22 +61,22 @@
58
  --shadow-deep: 0 20px 60px rgba(0, 0, 0, 0.8);
59
  --shadow-glow: 0 0 40px rgba(255, 69, 0, 0.4);
60
  }
61
-
62
  html {
63
  scroll-behavior: smooth;
64
  }
65
-
66
  body {
67
  background: var(--gradient-forge);
68
  color: var(--glass-white);
69
  font-family: var(--font-modern);
70
  overflow-x: hidden;
71
  }
72
-
73
  /* ============================================================================
74
  1. HEADER - LUXURY NAV
75
  ============================================================================ */
76
-
77
  header {
78
  position: fixed;
79
  top: 0;
@@ -85,7 +88,7 @@
85
  padding: 1.5rem 2rem;
86
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
87
  }
88
-
89
  .header-container {
90
  display: flex;
91
  justify-content: space-between;
@@ -93,7 +96,7 @@
93
  max-width: 1400px;
94
  margin: 0 auto;
95
  }
96
-
97
  .logo {
98
  font-family: var(--font-luxury);
99
  font-size: 1.5rem;
@@ -106,23 +109,30 @@
106
  gap: 0.8rem;
107
  letter-spacing: 2px;
108
  }
109
-
110
  .logo-icon {
111
  font-size: 2rem;
112
  animation: pulse-glow 2s infinite;
113
  }
114
-
115
  @keyframes pulse-glow {
116
- 0%, 100% { text-shadow: 0 0 10px rgba(255, 69, 0, 0.5); }
117
- 50% { text-shadow: 0 0 30px rgba(255, 69, 0, 0.8); }
 
 
 
 
 
 
 
118
  }
119
-
120
  nav {
121
  display: flex;
122
  gap: 3rem;
123
  align-items: center;
124
  }
125
-
126
  nav a {
127
  color: rgba(248, 249, 250, 0.7);
128
  text-decoration: none;
@@ -133,7 +143,7 @@
133
  position: relative;
134
  letter-spacing: 1px;
135
  }
136
-
137
  nav a::after {
138
  content: '';
139
  position: absolute;
@@ -144,19 +154,19 @@
144
  background: var(--gradient-molten);
145
  transition: width 0.3s ease;
146
  }
147
-
148
  nav a:hover {
149
  color: var(--molten-orange);
150
  }
151
-
152
  nav a:hover::after {
153
  width: 100%;
154
  }
155
-
156
  /* ============================================================================
157
  2. HERO SECTION - FUTURISTIC
158
  ============================================================================ */
159
-
160
  .hero {
161
  margin-top: 100px;
162
  padding: 4rem 2rem;
@@ -168,7 +178,7 @@
168
  align-items: center;
169
  justify-content: center;
170
  }
171
-
172
  .hero::before {
173
  content: '';
174
  position: absolute;
@@ -180,7 +190,7 @@
180
  animation: float 8s ease-in-out infinite;
181
  z-index: 0;
182
  }
183
-
184
  .hero::after {
185
  content: '';
186
  position: absolute;
@@ -192,12 +202,19 @@
192
  animation: float 10s ease-in-out infinite reverse;
193
  z-index: 0;
194
  }
195
-
196
  @keyframes float {
197
- 0%, 100% { transform: translateY(0px) rotate(0deg); }
198
- 50% { transform: translateY(-80px) rotate(20deg); }
 
 
 
 
 
 
 
199
  }
200
-
201
  .hero-content {
202
  position: relative;
203
  z-index: 1;
@@ -205,18 +222,19 @@
205
  margin: 0 auto;
206
  animation: fade-in 1s ease;
207
  }
208
-
209
  @keyframes fade-in {
210
  from {
211
  opacity: 0;
212
  transform: translateY(50px);
213
  }
 
214
  to {
215
  opacity: 1;
216
  transform: translateY(0);
217
  }
218
  }
219
-
220
  .hero h1 {
221
  font-family: var(--font-luxury);
222
  font-size: 4.5rem;
@@ -229,7 +247,7 @@
229
  letter-spacing: 2px;
230
  text-shadow: 0 0 40px rgba(255, 69, 0, 0.2);
231
  }
232
-
233
  .hero-tagline {
234
  font-size: 1.4rem;
235
  color: rgba(248, 249, 250, 0.85);
@@ -239,14 +257,14 @@
239
  letter-spacing: 3px;
240
  text-transform: uppercase;
241
  }
242
-
243
  .hero-buttons {
244
  display: flex;
245
  gap: 2rem;
246
  justify-content: center;
247
  flex-wrap: wrap;
248
  }
249
-
250
  .btn-primary {
251
  padding: 1.2rem 3.5rem;
252
  background: var(--gradient-molten);
@@ -263,7 +281,7 @@
263
  overflow: hidden;
264
  letter-spacing: 1px;
265
  }
266
-
267
  .btn-primary::before {
268
  content: '';
269
  position: absolute;
@@ -274,17 +292,17 @@
274
  background: rgba(255, 255, 255, 0.2);
275
  transition: left 0.3s ease;
276
  }
277
-
278
  .btn-primary:hover {
279
  transform: translateY(-8px);
280
  box-shadow: 0 0 60px rgba(255, 69, 0, 0.9);
281
  letter-spacing: 2px;
282
  }
283
-
284
  .btn-primary:hover::before {
285
  left: 100%;
286
  }
287
-
288
  .btn-secondary {
289
  padding: 1.2rem 3.5rem;
290
  background: transparent;
@@ -298,34 +316,34 @@
298
  transition: all 0.3s ease;
299
  letter-spacing: 1px;
300
  }
301
-
302
  .btn-secondary:hover {
303
  background: rgba(255, 69, 0, 0.15);
304
  box-shadow: 0 0 40px rgba(255, 69, 0, 0.6);
305
  transform: translateY(-8px);
306
  }
307
-
308
  /* ============================================================================
309
  3. MAIN DASHBOARD
310
  ============================================================================ */
311
-
312
  .dashboard {
313
  max-width: 1400px;
314
  margin: 4rem auto;
315
  padding: 0 2rem 4rem;
316
  }
317
-
318
  .dashboard-grid {
319
  display: grid;
320
  grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
321
  gap: 2rem;
322
  margin-bottom: 3rem;
323
  }
324
-
325
  /* ============================================================================
326
  4. QUANTUM CARD - THERMAL MONITORING
327
  ============================================================================ */
328
-
329
  .quantum-card {
330
  background: rgba(26, 26, 46, 0.6);
331
  backdrop-filter: blur(12px);
@@ -336,7 +354,7 @@
336
  position: relative;
337
  overflow: hidden;
338
  }
339
-
340
  .quantum-card::before {
341
  content: '';
342
  position: absolute;
@@ -348,19 +366,19 @@
348
  opacity: 0;
349
  transition: opacity 0.4s ease;
350
  }
351
-
352
  .quantum-card:hover {
353
  border-color: rgba(255, 69, 0, 0.5);
354
  box-shadow: 0 0 50px rgba(255, 69, 0, 0.35),
355
- inset 0 1px 20px rgba(255, 69, 0, 0.1);
356
  transform: translateY(-15px);
357
  background: rgba(26, 26, 46, 0.8);
358
  }
359
-
360
  .quantum-card:hover::before {
361
  opacity: 1;
362
  }
363
-
364
  .card-header {
365
  display: flex;
366
  justify-content: space-between;
@@ -369,7 +387,7 @@
369
  position: relative;
370
  z-index: 1;
371
  }
372
-
373
  .card-title {
374
  font-family: var(--font-luxury);
375
  font-size: 1.4rem;
@@ -379,22 +397,22 @@
379
  gap: 0.8rem;
380
  letter-spacing: 1px;
381
  }
382
-
383
  .card-icon {
384
  font-size: 1.8rem;
385
  background: var(--gradient-molten);
386
  -webkit-background-clip: text;
387
  -webkit-text-fill-color: transparent;
388
  }
389
-
390
  /* ============================================================================
391
  5. TEMPERATURE DISPLAY - HERO METRIC
392
  ============================================================================ */
393
-
394
  .temp-container {
395
  grid-column: 1 / -1;
396
  }
397
-
398
  .temp-display {
399
  text-align: center;
400
  padding: 4rem 3rem;
@@ -402,9 +420,9 @@
402
  border-radius: 24px;
403
  border: 1px solid rgba(255, 69, 0, 0.3);
404
  box-shadow: 0 0 50px rgba(255, 69, 0, 0.2),
405
- inset 0 1px 20px rgba(255, 69, 0, 0.05);
406
  }
407
-
408
  .temp-value {
409
  font-family: var(--font-luxury);
410
  font-size: 5.5rem;
@@ -417,12 +435,19 @@
417
  margin-bottom: 1rem;
418
  letter-spacing: 2px;
419
  }
420
-
421
  @keyframes pulse-temp {
422
- 0%, 100% { transform: scale(1); }
423
- 50% { transform: scale(1.08); }
 
 
 
 
 
 
 
424
  }
425
-
426
  .temp-status {
427
  font-family: var(--font-tech);
428
  font-size: 1.4rem;
@@ -436,7 +461,7 @@
436
  text-transform: uppercase;
437
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.3);
438
  }
439
-
440
  .thermal-bar {
441
  height: 16px;
442
  background: rgba(255, 255, 255, 0.1);
@@ -446,7 +471,7 @@
446
  border: 1px solid rgba(255, 69, 0, 0.3);
447
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.4);
448
  }
449
-
450
  .thermal-fill {
451
  height: 100%;
452
  background: var(--gradient-molten);
@@ -454,16 +479,23 @@
454
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.8);
455
  border-radius: 12px;
456
  }
457
-
458
  @keyframes thermal-wave {
459
- 0%, 100% { width: 65%; }
460
- 50% { width: 80%; }
 
 
 
 
 
 
 
461
  }
462
-
463
  /* ============================================================================
464
  6. METRIC BOXES - PREMIUM STATS
465
  ============================================================================ */
466
-
467
  .metric-box {
468
  background: linear-gradient(135deg, rgba(255, 69, 0, 0.12) 0%, rgba(0, 191, 255, 0.08) 100%);
469
  padding: 1.8rem;
@@ -473,12 +505,12 @@
473
  z-index: 1;
474
  transition: all 0.3s ease;
475
  }
476
-
477
  .metric-box:hover {
478
  border-color: rgba(255, 69, 0, 0.5);
479
  background: linear-gradient(135deg, rgba(255, 69, 0, 0.18) 0%, rgba(0, 191, 255, 0.12) 100%);
480
  }
481
-
482
  .metric-label {
483
  font-family: var(--font-tech);
484
  font-size: 0.85rem;
@@ -488,7 +520,7 @@
488
  letter-spacing: 2px;
489
  font-weight: 600;
490
  }
491
-
492
  .metric-value {
493
  font-family: var(--font-luxury);
494
  font-size: 2.8rem;
@@ -498,11 +530,11 @@
498
  -webkit-text-fill-color: transparent;
499
  letter-spacing: 1px;
500
  }
501
-
502
  /* ============================================================================
503
  7. CHAT INTERFACE - CONVERSATIONAL AI
504
  ============================================================================ */
505
-
506
  .chat-section {
507
  grid-column: 1 / -1;
508
  background: rgba(22, 33, 62, 0.6);
@@ -510,20 +542,20 @@
510
  padding: 2.5rem;
511
  border: 1px solid rgba(0, 191, 255, 0.25);
512
  box-shadow: 0 0 40px rgba(0, 191, 255, 0.15),
513
- inset 0 1px 20px rgba(0, 191, 255, 0.05);
514
  }
515
-
516
  .chat-header {
517
  margin-bottom: 2rem;
518
  }
519
-
520
  .chat-container {
521
  display: flex;
522
  flex-direction: column;
523
  height: 550px;
524
  gap: 1.5rem;
525
  }
526
-
527
  .chat-messages {
528
  flex: 1;
529
  overflow-y: auto;
@@ -532,7 +564,7 @@
532
  gap: 1.2rem;
533
  padding-right: 1rem;
534
  }
535
-
536
  .message {
537
  max-width: 75%;
538
  padding: 1.2rem 1.8rem;
@@ -542,18 +574,19 @@
542
  font-size: 0.95rem;
543
  line-height: 1.6;
544
  }
545
-
546
  @keyframes slide-in {
547
  from {
548
  opacity: 0;
549
  transform: translateY(30px);
550
  }
 
551
  to {
552
  opacity: 1;
553
  transform: translateY(0);
554
  }
555
  }
556
-
557
  .message.user {
558
  align-self: flex-end;
559
  background: var(--gradient-molten);
@@ -563,7 +596,7 @@
563
  margin-left: auto;
564
  margin-right: 0;
565
  }
566
-
567
  .message.agent {
568
  align-self: flex-start;
569
  background: rgba(0, 191, 255, 0.15);
@@ -572,26 +605,26 @@
572
  color: rgba(248, 249, 250, 0.95);
573
  box-shadow: 0 0 20px rgba(0, 191, 255, 0.2);
574
  }
575
-
576
  .chat-messages::-webkit-scrollbar {
577
  width: 6px;
578
  }
579
-
580
  .chat-messages::-webkit-scrollbar-track {
581
  background: transparent;
582
  }
583
-
584
  .chat-messages::-webkit-scrollbar-thumb {
585
  background: rgba(255, 69, 0, 0.5);
586
  border-radius: 3px;
587
  }
588
-
589
  .chat-input-area {
590
  display: flex;
591
  gap: 1rem;
592
  margin-top: 1.5rem;
593
  }
594
-
595
  .chat-input {
596
  flex: 1;
597
  padding: 1.2rem 1.8rem;
@@ -603,19 +636,19 @@
603
  font-size: 0.95rem;
604
  transition: all 0.3s ease;
605
  }
606
-
607
  .chat-input::placeholder {
608
  color: rgba(248, 249, 250, 0.4);
609
  }
610
-
611
  .chat-input:focus {
612
  outline: none;
613
  background: rgba(255, 255, 255, 0.12);
614
  border-color: var(--cyber-blue);
615
  box-shadow: 0 0 30px rgba(0, 191, 255, 0.4),
616
- inset 0 1px 10px rgba(0, 191, 255, 0.1);
617
  }
618
-
619
  .btn-send {
620
  padding: 1rem 2.5rem;
621
  background: var(--gradient-molten);
@@ -629,27 +662,27 @@
629
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.5);
630
  letter-spacing: 1px;
631
  }
632
-
633
  .btn-send:hover {
634
  transform: scale(1.08);
635
  box-shadow: 0 0 50px rgba(255, 69, 0, 0.8);
636
  }
637
-
638
  .btn-send:active {
639
  transform: scale(0.95);
640
  }
641
-
642
  /* ============================================================================
643
  8. ANALYTICS DASHBOARD
644
  ============================================================================ */
645
-
646
  .analytics {
647
  grid-column: 1 / -1;
648
  display: grid;
649
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
650
  gap: 2rem;
651
  }
652
-
653
  .chart-card {
654
  background: rgba(26, 26, 46, 0.6);
655
  backdrop-filter: blur(12px);
@@ -659,110 +692,112 @@
659
  min-height: 380px;
660
  transition: all 0.3s ease;
661
  }
662
-
663
  .chart-card:hover {
664
  border-color: rgba(255, 69, 0, 0.4);
665
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.2);
666
  transform: translateY(-5px);
667
  }
668
-
669
  /* ============================================================================
670
  9. RESPONSIVE DESIGN
671
  ============================================================================ */
672
-
673
  @media (max-width: 1024px) {
674
  .hero h1 {
675
  font-size: 3.5rem;
676
  }
677
-
678
  .dashboard-grid {
679
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
680
  }
681
  }
682
-
683
  @media (max-width: 768px) {
684
  header {
685
  padding: 1rem;
686
  }
687
-
688
  .header-container {
689
  flex-direction: column;
690
  gap: 1rem;
691
  }
692
-
693
  nav {
694
  gap: 1.5rem;
695
  font-size: 0.85rem;
696
  }
697
-
698
  .hero {
699
  margin-top: 180px;
700
  padding: 2rem 1rem;
701
  }
702
-
703
  .hero h1 {
704
  font-size: 2.5rem;
705
  }
706
-
707
  .hero-tagline {
708
  font-size: 1rem;
709
  letter-spacing: 1px;
710
  }
711
-
712
  .hero-buttons {
713
  flex-direction: column;
714
  gap: 1rem;
715
  }
716
-
717
- .btn-primary, .btn-secondary {
 
718
  width: 100%;
719
  }
720
-
721
  .dashboard-grid {
722
  grid-template-columns: 1fr;
723
  }
724
-
725
  .temp-value {
726
  font-size: 3.5rem;
727
  }
728
-
729
  .message {
730
  max-width: 85%;
731
  }
732
-
733
  .quantum-card {
734
  padding: 1.5rem;
735
  }
736
-
737
  .chat-container {
738
  height: 400px;
739
  }
740
  }
741
-
742
  @media (max-width: 480px) {
743
  .logo {
744
  font-size: 1.2rem;
745
  }
746
-
747
  nav {
748
  display: none;
749
  }
750
-
751
  .hero h1 {
752
  font-size: 2rem;
753
  line-height: 1.2;
754
  }
755
-
756
  .temp-value {
757
  font-size: 2.5rem;
758
  }
759
-
760
  .metric-value {
761
  font-size: 2rem;
762
  }
763
  }
764
  </style>
765
  </head>
 
766
  <body>
767
  <!-- ========== HEADER ========== -->
768
  <header>
@@ -799,7 +834,7 @@
799
  <!-- ========== MAIN DASHBOARD ========== -->
800
  <main class="dashboard" id="dashboard">
801
  <div class="dashboard-grid">
802
-
803
  <!-- TEMPERATURE HERO CARD -->
804
  <div class="quantum-card temp-container">
805
  <div class="temp-display">
@@ -876,14 +911,17 @@
876
  <div style="display: flex; gap: 1rem; flex-wrap: wrap;">
877
  <input type="file" id="csvFile" accept=".csv" class="chat-input" style="flex: 1;">
878
  <button class="btn-send" onclick="uploadData()">Analyze Data</button>
879
- <button class="btn-secondary" onclick="exportData()" style="padding: 1rem 2rem; border-radius: 50px;">Export Report</button>
 
880
  </div>
881
  <div id="upload-results" style="margin-top: 1.5rem; display: none;">
882
  <div class="metric-box" style="margin-bottom: 1rem;">
883
  <div class="metric-label">Analysis Summary</div>
884
- <div id="upload-summary" style="font-family: var(--font-modern); margin-top: 0.5rem; line-height: 1.6;"></div>
 
885
  </div>
886
- <div style="max-height: 200px; overflow-y: auto; background: rgba(0,0,0,0.2); border-radius: 12px; padding: 1rem;">
 
887
  <table style="width: 100%; border-collapse: collapse; color: #eee; font-size: 0.9rem;">
888
  <thead>
889
  <tr style="border-bottom: 1px solid rgba(255,255,255,0.1); text-align: left;">
@@ -912,17 +950,14 @@
912
  <div class="chat-messages" id="chat-messages">
913
  <div class="message agent">
914
  <strong>🤖 Forge AI:</strong><br>
915
- Greetings! I'm your foundry intelligence agent. Real-time monitoring active. Ask me about pouring readiness, energy optimization, or safety alerts.
 
916
  </div>
917
  </div>
918
  <div class="chat-input-area">
919
- <input
920
- type="text"
921
- class="chat-input"
922
- id="chat-input"
923
  placeholder="Ask me about pouring, energy, or safety..."
924
- onkeypress="handleChatKeypress(event)"
925
- >
926
  <button class="btn-send" onclick="sendChatMessage()">Send</button>
927
  </div>
928
  </div>
@@ -939,7 +974,7 @@
939
  </div>
940
  <canvas id="tempChart" height="100"></canvas>
941
  </div>
942
-
943
  <div class="chart-card">
944
  <div class="card-header">
945
  <div class="card-title">
@@ -982,144 +1017,180 @@
982
  // ============================================================================
983
  // SOCKET.IO & REAL-TIME UPDATES
984
  // ============================================================================
985
-
986
  const socket = io();
987
-
988
  let tempChart, energyChart;
989
  const tempData = [];
990
  const energyData = [];
991
  const maxDataPoints = 50;
992
-
993
  socket.on('connect', () => {
994
  console.log('✅ Connected to Forge Intelligence');
995
  updateThermalSimulation();
996
  });
997
-
998
  socket.on('temp_update', (data) => {
999
  updateTemperature(data.temp);
1000
  logSystemEvent(`Temp Update: ${data.temp}°C | Risk: ${data.quantum_risk}`);
1001
- if(data.anomaly) logSystemEvent(`⚠️ ANOMALY DETECTED`, 'error');
1002
  });
1003
 
1004
- function logSystemEvent(msg, type='info') {
1005
  const logs = document.getElementById('system-logs');
1006
- if(!logs) return;
1007
  const div = document.createElement('div');
1008
  const time = new Date().toLocaleTimeString();
1009
  div.textContent = `[${time}] ${msg}`;
1010
- if(type === 'error') div.style.color = '#ff3333';
1011
  logs.appendChild(div);
1012
  logs.scrollTop = logs.scrollHeight;
1013
  }
1014
-
1015
  // ============================================================================
1016
  // TEMPERATURE UPDATE
1017
  // ============================================================================
1018
-
1019
  function updateTemperature(temp) {
1020
  document.getElementById('current-temp').textContent = Math.round(temp) + '°C';
1021
  tempData.push(temp);
1022
  if (tempData.length > maxDataPoints) tempData.shift();
1023
-
1024
  if (tempChart) {
1025
  tempChart.data.datasets[0].data = tempData;
1026
  tempChart.update('none');
1027
  }
1028
  }
1029
-
1030
  // ============================================================================
1031
  // THERMAL SIMULATION
1032
  // ============================================================================
1033
-
1034
  function updateThermalSimulation() {
1035
  setInterval(() => {
1036
  const temp = 1450 + Math.sin(Date.now() / 3000) * 25 + (Math.random() - 0.5) * 8;
1037
  updateTemperature(Math.round(temp));
1038
  }, 2000);
1039
  }
1040
-
1041
  // ============================================================================
1042
  // CHAT FUNCTIONALITY
1043
  // ============================================================================
1044
-
1045
  function sendChatMessage() {
1046
  const input = document.getElementById('chat-input');
1047
  const message = input.value.trim();
1048
-
1049
  if (!message) return;
1050
-
1051
  addChatMessage('user', message);
1052
  input.value = '';
1053
-
1054
  // Real Backend Call
1055
  fetch('/api/chat', {
1056
  method: 'POST',
1057
- headers: {'Content-Type': 'application/json'},
1058
- body: JSON.stringify({query: message})
1059
- })
1060
- .then(r => r.json())
1061
- .then(data => {
1062
- addChatMessage('agent', data.response);
1063
- logSystemEvent(`[AI] Response generated (${data.confidence*100}% confidence)`);
1064
  })
1065
- .catch(e => {
1066
- addChatMessage('agent', "⚠️ Connection lost to AI Core.");
1067
- logSystemEvent(`[AI] Connection Error: ${e}`, 'error');
1068
- });
 
 
 
 
 
1069
  }
1070
 
1071
  // CSV Upload Logic
1072
  function uploadData() {
1073
  const input = document.getElementById('csvFile');
1074
- if(input.files.length === 0) {
1075
  alert('Please select a CSV file first');
1076
  return;
1077
  }
1078
-
1079
  const formData = new FormData();
1080
  formData.append('file', input.files[0]);
1081
-
1082
  logSystemEvent(`[UPLOAD] Processing ${input.files[0].name}...`);
1083
-
 
 
 
 
1084
  fetch('/api/upload_data', {
1085
  method: 'POST',
1086
  body: formData
1087
  })
1088
- .then(r => r.json())
1089
- .then(data => {
1090
- if(data.error) {
1091
- alert('Error: ' + data.error);
1092
- return;
1093
- }
1094
-
1095
- document.getElementById('upload-results').style.display = 'block';
1096
- document.getElementById('upload-summary').innerHTML =
1097
- `Processed <strong>${data.rows_processed}</strong> rows.<br>` +
1098
- `Anomalies Found: <span style="color:var(--neon-green)">${data.summary.anomalies_found}</span><br>` +
1099
- `Avg Temp: ${data.summary.avg_temp}°C`;
1100
-
1101
- const tbody = document.getElementById('results-table-body');
1102
- tbody.innerHTML = '';
1103
- data.predictions.forEach(row => {
1104
- const tr = document.createElement('tr');
1105
- tr.innerHTML = `
1106
- <td style="padding:0.5rem">${row.id}</td>
1107
- <td style="padding:0.5rem">${row.temperature}</td>
1108
- <td style="padding:0.5rem">${row.energy}</td>
1109
- <td style="padding:0.5rem; color:#0f0">${row.predicted_next}</td>
1110
- <td style="padding:0.5rem; color:${row.is_anomaly ? 'red' : 'inherit'}">${row.risk_score}</td>
 
1111
  `;
1112
- tbody.appendChild(tr);
 
 
 
 
 
 
 
 
 
 
 
 
 
1113
  });
1114
-
1115
- logSystemEvent(`[UPLOAD] Analysis Complete. ${data.summary.anomalies_found} anomalies.`);
1116
- })
1117
- .catch(e => {
1118
- console.error(e);
1119
- alert('Upload failed');
 
 
 
 
 
 
 
 
1120
  });
 
 
 
 
 
 
 
 
 
 
1121
  }
1122
-
1123
  function addChatMessage(type, text) {
1124
  const container = document.getElementById('chat-messages');
1125
  const msgDiv = document.createElement('div');
@@ -1128,37 +1199,37 @@
1128
  container.appendChild(msgDiv);
1129
  container.scrollTop = container.scrollHeight;
1130
  }
1131
-
1132
  function handleChatKeypress(e) {
1133
  if (e.key === 'Enter') sendChatMessage();
1134
  }
1135
-
1136
  // ============================================================================
1137
  // BUTTON HANDLERS
1138
  // ============================================================================
1139
-
1140
  function startMonitoring() {
1141
  alert('🔥 Real-time monitoring activated!');
1142
  }
1143
-
1144
  function activateAI() {
1145
  document.getElementById('chat-input').focus();
1146
  }
1147
-
1148
  // ============================================================================
1149
  // CHARTS INITIALIZATION
1150
  // ============================================================================
1151
-
1152
  window.addEventListener('load', () => {
1153
  initCharts();
1154
  });
1155
-
1156
  function initCharts() {
1157
  const ctx1 = document.getElementById('tempChart').getContext('2d');
1158
  tempChart = new Chart(ctx1, {
1159
  type: 'line',
1160
  data: {
1161
- labels: Array.from({length: maxDataPoints}, (_, i) => i),
1162
  datasets: [{
1163
  label: 'Temperature (°C)',
1164
  data: tempData,
@@ -1193,7 +1264,7 @@
1193
  }
1194
  }
1195
  });
1196
-
1197
  const ctx2 = document.getElementById('energyChart').getContext('2d');
1198
  energyChart = new Chart(ctx2, {
1199
  type: 'bar',
@@ -1231,4 +1302,5 @@
1231
  }
1232
  </script>
1233
  </body>
1234
- </html>
 
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
+
4
  <head>
5
  <meta charset="UTF-8">
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
  <title>🔥 Forge Intelligence - AI Molten Iron Monitoring</title>
8
+
9
  <!-- Google Fonts - Luxury Tech -->
10
+ <link
11
+ href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Rajdhani:wght@400;500;700&family=Inter:wght@100;300;400;500;700&display=swap"
12
+ rel="stylesheet">
13
+
14
  <!-- Icons -->
15
  <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
16
+
17
  <!-- Chart.js -->
18
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
19
+
20
  <!-- Socket.IO -->
21
  <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
22
+
23
  <style>
24
  /* ============================================================================
25
  QUANTUM-INSPIRED LUXURY UI - FORGE INTELLIGENCE
26
  ============================================================================ */
27
+
28
  * {
29
  margin: 0;
30
  padding: 0;
31
  box-sizing: border-box;
32
  }
33
+
34
  :root {
35
  /* 🌌 Quantum Palette */
36
  --quantum-black: #0A0A0A;
 
43
  --neon-green: #39FF14;
44
  --glass-white: #F8F9FA;
45
  --thermal-gold: #FFD700;
46
+
47
  /* Gradients */
48
  --gradient-molten: linear-gradient(135deg, #FF4500 0%, #FFD700 50%, #00BFFF 100%);
49
  --gradient-forge: linear-gradient(180deg, #0A0A0A 0%, #1A1A2E 50%, #16213E 100%);
50
  --gradient-thermal: linear-gradient(135deg, #DC143C 0%, #FF4500 100%);
51
+
52
  /* Fonts */
53
  --font-luxury: 'Orbitron', sans-serif;
54
  --font-tech: 'Rajdhani', sans-serif;
55
  --font-modern: 'Inter', sans-serif;
56
+
57
  /* Effects */
58
  --blur-glass: 12px;
59
  --glow-molten: 0 0 30px rgba(255, 69, 0, 0.6);
 
61
  --shadow-deep: 0 20px 60px rgba(0, 0, 0, 0.8);
62
  --shadow-glow: 0 0 40px rgba(255, 69, 0, 0.4);
63
  }
64
+
65
  html {
66
  scroll-behavior: smooth;
67
  }
68
+
69
  body {
70
  background: var(--gradient-forge);
71
  color: var(--glass-white);
72
  font-family: var(--font-modern);
73
  overflow-x: hidden;
74
  }
75
+
76
  /* ============================================================================
77
  1. HEADER - LUXURY NAV
78
  ============================================================================ */
79
+
80
  header {
81
  position: fixed;
82
  top: 0;
 
88
  padding: 1.5rem 2rem;
89
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5);
90
  }
91
+
92
  .header-container {
93
  display: flex;
94
  justify-content: space-between;
 
96
  max-width: 1400px;
97
  margin: 0 auto;
98
  }
99
+
100
  .logo {
101
  font-family: var(--font-luxury);
102
  font-size: 1.5rem;
 
109
  gap: 0.8rem;
110
  letter-spacing: 2px;
111
  }
112
+
113
  .logo-icon {
114
  font-size: 2rem;
115
  animation: pulse-glow 2s infinite;
116
  }
117
+
118
  @keyframes pulse-glow {
119
+
120
+ 0%,
121
+ 100% {
122
+ text-shadow: 0 0 10px rgba(255, 69, 0, 0.5);
123
+ }
124
+
125
+ 50% {
126
+ text-shadow: 0 0 30px rgba(255, 69, 0, 0.8);
127
+ }
128
  }
129
+
130
  nav {
131
  display: flex;
132
  gap: 3rem;
133
  align-items: center;
134
  }
135
+
136
  nav a {
137
  color: rgba(248, 249, 250, 0.7);
138
  text-decoration: none;
 
143
  position: relative;
144
  letter-spacing: 1px;
145
  }
146
+
147
  nav a::after {
148
  content: '';
149
  position: absolute;
 
154
  background: var(--gradient-molten);
155
  transition: width 0.3s ease;
156
  }
157
+
158
  nav a:hover {
159
  color: var(--molten-orange);
160
  }
161
+
162
  nav a:hover::after {
163
  width: 100%;
164
  }
165
+
166
  /* ============================================================================
167
  2. HERO SECTION - FUTURISTIC
168
  ============================================================================ */
169
+
170
  .hero {
171
  margin-top: 100px;
172
  padding: 4rem 2rem;
 
178
  align-items: center;
179
  justify-content: center;
180
  }
181
+
182
  .hero::before {
183
  content: '';
184
  position: absolute;
 
190
  animation: float 8s ease-in-out infinite;
191
  z-index: 0;
192
  }
193
+
194
  .hero::after {
195
  content: '';
196
  position: absolute;
 
202
  animation: float 10s ease-in-out infinite reverse;
203
  z-index: 0;
204
  }
205
+
206
  @keyframes float {
207
+
208
+ 0%,
209
+ 100% {
210
+ transform: translateY(0px) rotate(0deg);
211
+ }
212
+
213
+ 50% {
214
+ transform: translateY(-80px) rotate(20deg);
215
+ }
216
  }
217
+
218
  .hero-content {
219
  position: relative;
220
  z-index: 1;
 
222
  margin: 0 auto;
223
  animation: fade-in 1s ease;
224
  }
225
+
226
  @keyframes fade-in {
227
  from {
228
  opacity: 0;
229
  transform: translateY(50px);
230
  }
231
+
232
  to {
233
  opacity: 1;
234
  transform: translateY(0);
235
  }
236
  }
237
+
238
  .hero h1 {
239
  font-family: var(--font-luxury);
240
  font-size: 4.5rem;
 
247
  letter-spacing: 2px;
248
  text-shadow: 0 0 40px rgba(255, 69, 0, 0.2);
249
  }
250
+
251
  .hero-tagline {
252
  font-size: 1.4rem;
253
  color: rgba(248, 249, 250, 0.85);
 
257
  letter-spacing: 3px;
258
  text-transform: uppercase;
259
  }
260
+
261
  .hero-buttons {
262
  display: flex;
263
  gap: 2rem;
264
  justify-content: center;
265
  flex-wrap: wrap;
266
  }
267
+
268
  .btn-primary {
269
  padding: 1.2rem 3.5rem;
270
  background: var(--gradient-molten);
 
281
  overflow: hidden;
282
  letter-spacing: 1px;
283
  }
284
+
285
  .btn-primary::before {
286
  content: '';
287
  position: absolute;
 
292
  background: rgba(255, 255, 255, 0.2);
293
  transition: left 0.3s ease;
294
  }
295
+
296
  .btn-primary:hover {
297
  transform: translateY(-8px);
298
  box-shadow: 0 0 60px rgba(255, 69, 0, 0.9);
299
  letter-spacing: 2px;
300
  }
301
+
302
  .btn-primary:hover::before {
303
  left: 100%;
304
  }
305
+
306
  .btn-secondary {
307
  padding: 1.2rem 3.5rem;
308
  background: transparent;
 
316
  transition: all 0.3s ease;
317
  letter-spacing: 1px;
318
  }
319
+
320
  .btn-secondary:hover {
321
  background: rgba(255, 69, 0, 0.15);
322
  box-shadow: 0 0 40px rgba(255, 69, 0, 0.6);
323
  transform: translateY(-8px);
324
  }
325
+
326
  /* ============================================================================
327
  3. MAIN DASHBOARD
328
  ============================================================================ */
329
+
330
  .dashboard {
331
  max-width: 1400px;
332
  margin: 4rem auto;
333
  padding: 0 2rem 4rem;
334
  }
335
+
336
  .dashboard-grid {
337
  display: grid;
338
  grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
339
  gap: 2rem;
340
  margin-bottom: 3rem;
341
  }
342
+
343
  /* ============================================================================
344
  4. QUANTUM CARD - THERMAL MONITORING
345
  ============================================================================ */
346
+
347
  .quantum-card {
348
  background: rgba(26, 26, 46, 0.6);
349
  backdrop-filter: blur(12px);
 
354
  position: relative;
355
  overflow: hidden;
356
  }
357
+
358
  .quantum-card::before {
359
  content: '';
360
  position: absolute;
 
366
  opacity: 0;
367
  transition: opacity 0.4s ease;
368
  }
369
+
370
  .quantum-card:hover {
371
  border-color: rgba(255, 69, 0, 0.5);
372
  box-shadow: 0 0 50px rgba(255, 69, 0, 0.35),
373
+ inset 0 1px 20px rgba(255, 69, 0, 0.1);
374
  transform: translateY(-15px);
375
  background: rgba(26, 26, 46, 0.8);
376
  }
377
+
378
  .quantum-card:hover::before {
379
  opacity: 1;
380
  }
381
+
382
  .card-header {
383
  display: flex;
384
  justify-content: space-between;
 
387
  position: relative;
388
  z-index: 1;
389
  }
390
+
391
  .card-title {
392
  font-family: var(--font-luxury);
393
  font-size: 1.4rem;
 
397
  gap: 0.8rem;
398
  letter-spacing: 1px;
399
  }
400
+
401
  .card-icon {
402
  font-size: 1.8rem;
403
  background: var(--gradient-molten);
404
  -webkit-background-clip: text;
405
  -webkit-text-fill-color: transparent;
406
  }
407
+
408
  /* ============================================================================
409
  5. TEMPERATURE DISPLAY - HERO METRIC
410
  ============================================================================ */
411
+
412
  .temp-container {
413
  grid-column: 1 / -1;
414
  }
415
+
416
  .temp-display {
417
  text-align: center;
418
  padding: 4rem 3rem;
 
420
  border-radius: 24px;
421
  border: 1px solid rgba(255, 69, 0, 0.3);
422
  box-shadow: 0 0 50px rgba(255, 69, 0, 0.2),
423
+ inset 0 1px 20px rgba(255, 69, 0, 0.05);
424
  }
425
+
426
  .temp-value {
427
  font-family: var(--font-luxury);
428
  font-size: 5.5rem;
 
435
  margin-bottom: 1rem;
436
  letter-spacing: 2px;
437
  }
438
+
439
  @keyframes pulse-temp {
440
+
441
+ 0%,
442
+ 100% {
443
+ transform: scale(1);
444
+ }
445
+
446
+ 50% {
447
+ transform: scale(1.08);
448
+ }
449
  }
450
+
451
  .temp-status {
452
  font-family: var(--font-tech);
453
  font-size: 1.4rem;
 
461
  text-transform: uppercase;
462
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.3);
463
  }
464
+
465
  .thermal-bar {
466
  height: 16px;
467
  background: rgba(255, 255, 255, 0.1);
 
471
  border: 1px solid rgba(255, 69, 0, 0.3);
472
  box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.4);
473
  }
474
+
475
  .thermal-fill {
476
  height: 100%;
477
  background: var(--gradient-molten);
 
479
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.8);
480
  border-radius: 12px;
481
  }
482
+
483
  @keyframes thermal-wave {
484
+
485
+ 0%,
486
+ 100% {
487
+ width: 65%;
488
+ }
489
+
490
+ 50% {
491
+ width: 80%;
492
+ }
493
  }
494
+
495
  /* ============================================================================
496
  6. METRIC BOXES - PREMIUM STATS
497
  ============================================================================ */
498
+
499
  .metric-box {
500
  background: linear-gradient(135deg, rgba(255, 69, 0, 0.12) 0%, rgba(0, 191, 255, 0.08) 100%);
501
  padding: 1.8rem;
 
505
  z-index: 1;
506
  transition: all 0.3s ease;
507
  }
508
+
509
  .metric-box:hover {
510
  border-color: rgba(255, 69, 0, 0.5);
511
  background: linear-gradient(135deg, rgba(255, 69, 0, 0.18) 0%, rgba(0, 191, 255, 0.12) 100%);
512
  }
513
+
514
  .metric-label {
515
  font-family: var(--font-tech);
516
  font-size: 0.85rem;
 
520
  letter-spacing: 2px;
521
  font-weight: 600;
522
  }
523
+
524
  .metric-value {
525
  font-family: var(--font-luxury);
526
  font-size: 2.8rem;
 
530
  -webkit-text-fill-color: transparent;
531
  letter-spacing: 1px;
532
  }
533
+
534
  /* ============================================================================
535
  7. CHAT INTERFACE - CONVERSATIONAL AI
536
  ============================================================================ */
537
+
538
  .chat-section {
539
  grid-column: 1 / -1;
540
  background: rgba(22, 33, 62, 0.6);
 
542
  padding: 2.5rem;
543
  border: 1px solid rgba(0, 191, 255, 0.25);
544
  box-shadow: 0 0 40px rgba(0, 191, 255, 0.15),
545
+ inset 0 1px 20px rgba(0, 191, 255, 0.05);
546
  }
547
+
548
  .chat-header {
549
  margin-bottom: 2rem;
550
  }
551
+
552
  .chat-container {
553
  display: flex;
554
  flex-direction: column;
555
  height: 550px;
556
  gap: 1.5rem;
557
  }
558
+
559
  .chat-messages {
560
  flex: 1;
561
  overflow-y: auto;
 
564
  gap: 1.2rem;
565
  padding-right: 1rem;
566
  }
567
+
568
  .message {
569
  max-width: 75%;
570
  padding: 1.2rem 1.8rem;
 
574
  font-size: 0.95rem;
575
  line-height: 1.6;
576
  }
577
+
578
  @keyframes slide-in {
579
  from {
580
  opacity: 0;
581
  transform: translateY(30px);
582
  }
583
+
584
  to {
585
  opacity: 1;
586
  transform: translateY(0);
587
  }
588
  }
589
+
590
  .message.user {
591
  align-self: flex-end;
592
  background: var(--gradient-molten);
 
596
  margin-left: auto;
597
  margin-right: 0;
598
  }
599
+
600
  .message.agent {
601
  align-self: flex-start;
602
  background: rgba(0, 191, 255, 0.15);
 
605
  color: rgba(248, 249, 250, 0.95);
606
  box-shadow: 0 0 20px rgba(0, 191, 255, 0.2);
607
  }
608
+
609
  .chat-messages::-webkit-scrollbar {
610
  width: 6px;
611
  }
612
+
613
  .chat-messages::-webkit-scrollbar-track {
614
  background: transparent;
615
  }
616
+
617
  .chat-messages::-webkit-scrollbar-thumb {
618
  background: rgba(255, 69, 0, 0.5);
619
  border-radius: 3px;
620
  }
621
+
622
  .chat-input-area {
623
  display: flex;
624
  gap: 1rem;
625
  margin-top: 1.5rem;
626
  }
627
+
628
  .chat-input {
629
  flex: 1;
630
  padding: 1.2rem 1.8rem;
 
636
  font-size: 0.95rem;
637
  transition: all 0.3s ease;
638
  }
639
+
640
  .chat-input::placeholder {
641
  color: rgba(248, 249, 250, 0.4);
642
  }
643
+
644
  .chat-input:focus {
645
  outline: none;
646
  background: rgba(255, 255, 255, 0.12);
647
  border-color: var(--cyber-blue);
648
  box-shadow: 0 0 30px rgba(0, 191, 255, 0.4),
649
+ inset 0 1px 10px rgba(0, 191, 255, 0.1);
650
  }
651
+
652
  .btn-send {
653
  padding: 1rem 2.5rem;
654
  background: var(--gradient-molten);
 
662
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.5);
663
  letter-spacing: 1px;
664
  }
665
+
666
  .btn-send:hover {
667
  transform: scale(1.08);
668
  box-shadow: 0 0 50px rgba(255, 69, 0, 0.8);
669
  }
670
+
671
  .btn-send:active {
672
  transform: scale(0.95);
673
  }
674
+
675
  /* ============================================================================
676
  8. ANALYTICS DASHBOARD
677
  ============================================================================ */
678
+
679
  .analytics {
680
  grid-column: 1 / -1;
681
  display: grid;
682
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
683
  gap: 2rem;
684
  }
685
+
686
  .chart-card {
687
  background: rgba(26, 26, 46, 0.6);
688
  backdrop-filter: blur(12px);
 
692
  min-height: 380px;
693
  transition: all 0.3s ease;
694
  }
695
+
696
  .chart-card:hover {
697
  border-color: rgba(255, 69, 0, 0.4);
698
  box-shadow: 0 0 30px rgba(255, 69, 0, 0.2);
699
  transform: translateY(-5px);
700
  }
701
+
702
  /* ============================================================================
703
  9. RESPONSIVE DESIGN
704
  ============================================================================ */
705
+
706
  @media (max-width: 1024px) {
707
  .hero h1 {
708
  font-size: 3.5rem;
709
  }
710
+
711
  .dashboard-grid {
712
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
713
  }
714
  }
715
+
716
  @media (max-width: 768px) {
717
  header {
718
  padding: 1rem;
719
  }
720
+
721
  .header-container {
722
  flex-direction: column;
723
  gap: 1rem;
724
  }
725
+
726
  nav {
727
  gap: 1.5rem;
728
  font-size: 0.85rem;
729
  }
730
+
731
  .hero {
732
  margin-top: 180px;
733
  padding: 2rem 1rem;
734
  }
735
+
736
  .hero h1 {
737
  font-size: 2.5rem;
738
  }
739
+
740
  .hero-tagline {
741
  font-size: 1rem;
742
  letter-spacing: 1px;
743
  }
744
+
745
  .hero-buttons {
746
  flex-direction: column;
747
  gap: 1rem;
748
  }
749
+
750
+ .btn-primary,
751
+ .btn-secondary {
752
  width: 100%;
753
  }
754
+
755
  .dashboard-grid {
756
  grid-template-columns: 1fr;
757
  }
758
+
759
  .temp-value {
760
  font-size: 3.5rem;
761
  }
762
+
763
  .message {
764
  max-width: 85%;
765
  }
766
+
767
  .quantum-card {
768
  padding: 1.5rem;
769
  }
770
+
771
  .chat-container {
772
  height: 400px;
773
  }
774
  }
775
+
776
  @media (max-width: 480px) {
777
  .logo {
778
  font-size: 1.2rem;
779
  }
780
+
781
  nav {
782
  display: none;
783
  }
784
+
785
  .hero h1 {
786
  font-size: 2rem;
787
  line-height: 1.2;
788
  }
789
+
790
  .temp-value {
791
  font-size: 2.5rem;
792
  }
793
+
794
  .metric-value {
795
  font-size: 2rem;
796
  }
797
  }
798
  </style>
799
  </head>
800
+
801
  <body>
802
  <!-- ========== HEADER ========== -->
803
  <header>
 
834
  <!-- ========== MAIN DASHBOARD ========== -->
835
  <main class="dashboard" id="dashboard">
836
  <div class="dashboard-grid">
837
+
838
  <!-- TEMPERATURE HERO CARD -->
839
  <div class="quantum-card temp-container">
840
  <div class="temp-display">
 
911
  <div style="display: flex; gap: 1rem; flex-wrap: wrap;">
912
  <input type="file" id="csvFile" accept=".csv" class="chat-input" style="flex: 1;">
913
  <button class="btn-send" onclick="uploadData()">Analyze Data</button>
914
+ <button class="btn-secondary" onclick="exportData()"
915
+ style="padding: 1rem 2rem; border-radius: 50px;">Export Report</button>
916
  </div>
917
  <div id="upload-results" style="margin-top: 1.5rem; display: none;">
918
  <div class="metric-box" style="margin-bottom: 1rem;">
919
  <div class="metric-label">Analysis Summary</div>
920
+ <div id="upload-summary"
921
+ style="font-family: var(--font-modern); margin-top: 0.5rem; line-height: 1.6;"></div>
922
  </div>
923
+ <div
924
+ style="max-height: 200px; overflow-y: auto; background: rgba(0,0,0,0.2); border-radius: 12px; padding: 1rem;">
925
  <table style="width: 100%; border-collapse: collapse; color: #eee; font-size: 0.9rem;">
926
  <thead>
927
  <tr style="border-bottom: 1px solid rgba(255,255,255,0.1); text-align: left;">
 
950
  <div class="chat-messages" id="chat-messages">
951
  <div class="message agent">
952
  <strong>🤖 Forge AI:</strong><br>
953
+ Greetings! I'm your foundry intelligence agent. Real-time monitoring active. Ask me about
954
+ pouring readiness, energy optimization, or safety alerts.
955
  </div>
956
  </div>
957
  <div class="chat-input-area">
958
+ <input type="text" class="chat-input" id="chat-input"
 
 
 
959
  placeholder="Ask me about pouring, energy, or safety..."
960
+ onkeypress="handleChatKeypress(event)">
 
961
  <button class="btn-send" onclick="sendChatMessage()">Send</button>
962
  </div>
963
  </div>
 
974
  </div>
975
  <canvas id="tempChart" height="100"></canvas>
976
  </div>
977
+
978
  <div class="chart-card">
979
  <div class="card-header">
980
  <div class="card-title">
 
1017
  // ============================================================================
1018
  // SOCKET.IO & REAL-TIME UPDATES
1019
  // ============================================================================
1020
+
1021
  const socket = io();
1022
+
1023
  let tempChart, energyChart;
1024
  const tempData = [];
1025
  const energyData = [];
1026
  const maxDataPoints = 50;
1027
+
1028
  socket.on('connect', () => {
1029
  console.log('✅ Connected to Forge Intelligence');
1030
  updateThermalSimulation();
1031
  });
1032
+
1033
  socket.on('temp_update', (data) => {
1034
  updateTemperature(data.temp);
1035
  logSystemEvent(`Temp Update: ${data.temp}°C | Risk: ${data.quantum_risk}`);
1036
+ if (data.anomaly) logSystemEvent(`⚠️ ANOMALY DETECTED`, 'error');
1037
  });
1038
 
1039
+ function logSystemEvent(msg, type = 'info') {
1040
  const logs = document.getElementById('system-logs');
1041
+ if (!logs) return;
1042
  const div = document.createElement('div');
1043
  const time = new Date().toLocaleTimeString();
1044
  div.textContent = `[${time}] ${msg}`;
1045
+ if (type === 'error') div.style.color = '#ff3333';
1046
  logs.appendChild(div);
1047
  logs.scrollTop = logs.scrollHeight;
1048
  }
1049
+
1050
  // ============================================================================
1051
  // TEMPERATURE UPDATE
1052
  // ============================================================================
1053
+
1054
  function updateTemperature(temp) {
1055
  document.getElementById('current-temp').textContent = Math.round(temp) + '°C';
1056
  tempData.push(temp);
1057
  if (tempData.length > maxDataPoints) tempData.shift();
1058
+
1059
  if (tempChart) {
1060
  tempChart.data.datasets[0].data = tempData;
1061
  tempChart.update('none');
1062
  }
1063
  }
1064
+
1065
  // ============================================================================
1066
  // THERMAL SIMULATION
1067
  // ============================================================================
1068
+
1069
  function updateThermalSimulation() {
1070
  setInterval(() => {
1071
  const temp = 1450 + Math.sin(Date.now() / 3000) * 25 + (Math.random() - 0.5) * 8;
1072
  updateTemperature(Math.round(temp));
1073
  }, 2000);
1074
  }
1075
+
1076
  // ============================================================================
1077
  // CHAT FUNCTIONALITY
1078
  // ============================================================================
1079
+
1080
  function sendChatMessage() {
1081
  const input = document.getElementById('chat-input');
1082
  const message = input.value.trim();
1083
+
1084
  if (!message) return;
1085
+
1086
  addChatMessage('user', message);
1087
  input.value = '';
1088
+
1089
  // Real Backend Call
1090
  fetch('/api/chat', {
1091
  method: 'POST',
1092
+ headers: { 'Content-Type': 'application/json' },
1093
+ body: JSON.stringify({ query: message })
 
 
 
 
 
1094
  })
1095
+ .then(r => r.json())
1096
+ .then(data => {
1097
+ addChatMessage('agent', data.response);
1098
+ logSystemEvent(`[AI] Response generated (${data.confidence * 100}% confidence)`);
1099
+ })
1100
+ .catch(e => {
1101
+ addChatMessage('agent', "⚠️ Connection lost to AI Core.");
1102
+ logSystemEvent(`[AI] Connection Error: ${e}`, 'error');
1103
+ });
1104
  }
1105
 
1106
  // CSV Upload Logic
1107
  function uploadData() {
1108
  const input = document.getElementById('csvFile');
1109
+ if (input.files.length === 0) {
1110
  alert('Please select a CSV file first');
1111
  return;
1112
  }
1113
+
1114
  const formData = new FormData();
1115
  formData.append('file', input.files[0]);
1116
+
1117
  logSystemEvent(`[UPLOAD] Processing ${input.files[0].name}...`);
1118
+
1119
+ const btn = document.querySelector('button[onclick="uploadData()"]');
1120
+ btn.textContent = 'Analyzing...';
1121
+ btn.disabled = true;
1122
+
1123
  fetch('/api/upload_data', {
1124
  method: 'POST',
1125
  body: formData
1126
  })
1127
+ .then(r => r.json())
1128
+ .then(data => {
1129
+ if (data.error) {
1130
+ alert('Error: ' + data.error);
1131
+ return;
1132
+ }
1133
+
1134
+ document.getElementById('upload-results').style.display = 'block';
1135
+ document.getElementById('upload-summary').innerHTML =
1136
+ `Processed <strong>${data.rows_processed}</strong> rows.<br>` +
1137
+ `Anomalies Found: <span style="color:var(--neon-green)">${data.summary.anomalies_found}</span><br>` +
1138
+ `Avg Temp: ${data.summary.avg_temp}°C`;
1139
+
1140
+ const tbody = document.getElementById('results-table-body');
1141
+ tbody.innerHTML = '';
1142
+ data.predictions.forEach(row => {
1143
+ const tr = document.createElement('tr');
1144
+ tr.style.borderBottom = '1px solid rgba(255,255,255,0.05)';
1145
+ tr.innerHTML = `
1146
+ <td style="padding:0.8rem">${row.id}</td>
1147
+ <td style="padding:0.8rem">${row.temperature}</td>
1148
+ <td style="padding:0.8rem">${row.energy}</td>
1149
+ <td style="padding:0.8rem; color:#0f0">${row.predicted_next}</td>
1150
+ <td style="padding:0.8rem; color:${row.is_anomaly ? 'red' : 'inherit'}">${row.risk_score}</td>
1151
  `;
1152
+ tbody.appendChild(tr);
1153
+ });
1154
+
1155
+ logSystemEvent(`[UPLOAD] Analysis Complete. ${data.summary.anomalies_found} anomalies.`);
1156
+ })
1157
+ .catch(e => {
1158
+ console.error(e);
1159
+ alert('Upload failed: ' + e);
1160
+ logSystemEvent(`[UPLOAD] Failed: ${e}`, 'error');
1161
+ })
1162
+ .finally(() => {
1163
+ const btn = document.querySelector('button[onclick="uploadData()"]');
1164
+ btn.textContent = 'Analyze Data';
1165
+ btn.disabled = false;
1166
  });
1167
+ }
1168
+
1169
+ function exportData() {
1170
+ const tbody = document.getElementById('results-table-body');
1171
+ if (!tbody || tbody.children.length === 0) {
1172
+ alert('No data to export. Please analyze a CSV first.');
1173
+ return;
1174
+ }
1175
+
1176
+ let csvContent = "data:text/csv;charset=utf-8,ID,Temperature,Energy,Predicted,Risk\n";
1177
+
1178
+ Array.from(tbody.children).forEach(row => {
1179
+ const cols = Array.from(row.children).map(td => td.textContent);
1180
+ csvContent += cols.join(",") + "\r\n";
1181
  });
1182
+
1183
+ const encodedUri = encodeURI(csvContent);
1184
+ const link = document.createElement("a");
1185
+ link.setAttribute("href", encodedUri);
1186
+ link.setAttribute("download", "prediction_report.csv");
1187
+ document.body.appendChild(link);
1188
+ link.click();
1189
+ document.body.removeChild(link);
1190
+
1191
+ logSystemEvent(`[SYSTEM] Report exported successfully.`);
1192
  }
1193
+
1194
  function addChatMessage(type, text) {
1195
  const container = document.getElementById('chat-messages');
1196
  const msgDiv = document.createElement('div');
 
1199
  container.appendChild(msgDiv);
1200
  container.scrollTop = container.scrollHeight;
1201
  }
1202
+
1203
  function handleChatKeypress(e) {
1204
  if (e.key === 'Enter') sendChatMessage();
1205
  }
1206
+
1207
  // ============================================================================
1208
  // BUTTON HANDLERS
1209
  // ============================================================================
1210
+
1211
  function startMonitoring() {
1212
  alert('🔥 Real-time monitoring activated!');
1213
  }
1214
+
1215
  function activateAI() {
1216
  document.getElementById('chat-input').focus();
1217
  }
1218
+
1219
  // ============================================================================
1220
  // CHARTS INITIALIZATION
1221
  // ============================================================================
1222
+
1223
  window.addEventListener('load', () => {
1224
  initCharts();
1225
  });
1226
+
1227
  function initCharts() {
1228
  const ctx1 = document.getElementById('tempChart').getContext('2d');
1229
  tempChart = new Chart(ctx1, {
1230
  type: 'line',
1231
  data: {
1232
+ labels: Array.from({ length: maxDataPoints }, (_, i) => i),
1233
  datasets: [{
1234
  label: 'Temperature (°C)',
1235
  data: tempData,
 
1264
  }
1265
  }
1266
  });
1267
+
1268
  const ctx2 = document.getElementById('energyChart').getContext('2d');
1269
  energyChart = new Chart(ctx2, {
1270
  type: 'bar',
 
1302
  }
1303
  </script>
1304
  </body>
1305
+
1306
+ </html>