MATERI INFORMATIKA

MATERI SMK 24-8

APK

SERVO

DHT



 https://suryogarage.blogspot.com/2026/08/smart-parkir.html 

MATERI SMP 8-7

https://suryogarage.blogspot.com/2026/07/materi-smp-fb.html

MATERI TGL 27-7

https://suryogarage.blogspot.com/2026/07/materi-informatika.html

MATERI TGL 26-6

https://suryogarage.blogspot.com/2026/06/materi-informatika-1.html

MATERI PJJ 8/9

https://suryogarage.blogspot.com/2026/09/pjj-bab-algoritma-dan-pemrograman.html



coding lampu merah 

Bisa. Kalau yang dimaksud satu siklus lampu lalu lintas berlangsung 1 menit (60 detik), kita bisa bagi waktunya seperti ini:

  • 🔴 Merah = 30 detik

  • 🟡 Kuning = 5 detik

  • 🟢 Hijau = 20 detik

  • 🟡 Kuning = 5 detik

  • Total = 60 detik

💻 Coding Arduino Uno

// PROJEK LAMPU LALU LINTAS
// Total 1 siklus = 60 detik

const int merah = 13;
const int kuning = 12;
const int hijau = 11;

void setup() {
  pinMode(merah, OUTPUT);
  pinMode(kuning, OUTPUT);
  pinMode(hijau, OUTPUT);
}

void loop() {

  // 🔴 MERAH - 30 DETIK
  digitalWrite(merah, HIGH);
  digitalWrite(kuning, LOW);
  digitalWrite(hijau, LOW);
  delay(30000);

  // 🟡 KUNING - 5 DETIK
  digitalWrite(merah, LOW);
  digitalWrite(kuning, HIGH);
  digitalWrite(hijau, LOW);
  delay(5000);

  // 🟢 HIJAU - 20 DETIK
  digitalWrite(merah, LOW);
  digitalWrite(kuning, LOW);
  digitalWrite(hijau, HIGH);
  delay(20000);

  // 🟡 KUNING - 5 DETIK
  digitalWrite(merah, LOW);
  digitalWrite(kuning, HIGH);
  digitalWrite(hijau, LOW);
  delay(5000);
}

🔄 Urutannya

🔴 30 detik → 🟡 5 detik → 🟢 20 detik → 🟡 5 detik → 🔴 ...

Kalau yang kamu maksud perubahan warna dibuat selama 1 menit dengan pergantian setiap beberapa detik, saya juga bisa buatkan versi LED merah → kuning → hijau yang berubah otomatis setiap 1 detik.


LORA

Bisa banyak sekali. LoRa paling menarik untuk proyek yang membutuhkan komunikasi jarak jauh dengan data kecil, misalnya sensor dan status perangkat.

🔧 Ide proyek LoRa sederhana

NoProyekTingkatKomponen tambahan
1🌊 Pendeteksi Ketinggian Banjir⭐⭐HC-SR04, LED, buzzer
2🌡️ Monitoring Suhu Jarak Jauh⭐DHT11
3🚗 Parkir Jarak Jauh⭐⭐Ultrasonik, LED
4🗑️ Tempat Sampah Pintar⭐⭐Ultrasonik, servo
5🌱 Monitoring Tanaman⭐⭐Sensor kelembapan tanah
6💡 Kontrol Lampu Jarak Jauh⭐⭐Relay, LED
7🚨 Alarm Keamanan LoRa⭐⭐PIR, buzzer
8🏫 Monitoring Ruang Kelas⭐⭐DHT11, sensor cahaya
9⚡ Monitoring Tegangan⭐⭐⭐Sensor tegangan
10🚦 Lampu Lalu Lintas Jarak Jauh⭐⭐LED merah-kuning-hijau
11📡 Pesan Antar Arduino⭐2 Arduino + 2 LoRa
12🏭 Monitoring Mesin Bengkel⭐⭐⭐Sensor getaran/suhu
13🚰 Monitoring Tandon Air⭐⭐Ultrasonik
14🐟 Monitoring Kolam⭐⭐⭐Sensor suhu/level air
15🏫 Sistem Peringatan Banjir Sekolah⭐⭐⭐Sensor air + buzzer

⭐ Yang paling cocok untuk pembelajaran siswa

Saya justru menyarankan mulai dari 3 proyek bertahap:

Proyek 1 — LoRa Chat sederhana
Arduino A → LoRa → Arduino B
Siswa belajar bagaimana LoRa mengirim data.

Proyek 2 — Monitoring suhu
Sensor DHT11 → Arduino → LoRa → Arduino penerima → LCD.

Proyek 3 — Sistem peringatan banjir 🌊
Sensor ketinggian air → Arduino + LoRa → penerima → LED + buzzer.

Proyek nomor 3 sangat bagus dikembangkan menjadi “Sistem Monitoring Banjir Sekolah Berbasis LoRa”, apalagi bisa dibuat beberapa titik sensor:

[Sensor Banjir 1] ──┐
                    │
[Sensor Banjir 2] ──┼── LoRa ──> [Pusat Monitoring]
                    │             │
[Sensor Banjir 3] ──┘             ├─ LCD
                                  ├─ LED
                                  └─ Buzzer

Kalau untuk projek SMK, ini bisa dibuat sebagai projek besar yang menggabungkan Arduino + sensor + komunikasi LoRa + sistem peringatan + casing, tetapi tetap dimulai dari rangkaian sederhana.

SOALPTS

=======================================================================

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simulasi Motor Servo Informatika v2.5</title>
    <!-- Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- Font Inter & Font Awesome -->
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        body { font-family: 'Inter', sans-serif; }
        .font-mono { font-family: 'JetBrains Mono', monospace; }
        .glass-panel { background: rgba(15, 23, 42, 0.85); backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.08); }
        .circuit-line { stroke: #38bdf8; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-gnd { stroke: #94a3b8; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-vcc { stroke: #ef4444; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-inactive { stroke: #475569; stroke-width: 2; fill: none; }
        @keyframes dash { to { stroke-dashoffset: -12; } }
        .pulse-wave { stroke: #22c55e; stroke-width: 2; fill: none; }
    </style>
</head>
<body class="bg-slate-950 text-slate-100 min-h-screen flex flex-col justify-between selection:bg-cyan-500 selection:text-white">

    <header class="border-b border-slate-800 bg-slate-900/80 backdrop-blur sticky top-0 z-50">
        <div class="max-w-7xl mx-auto px-4 py-3 flex flex-wrap items-center justify-between gap-4">
            <div class="flex items-center space-x-3">
                <div class="w-10 h-10 rounded-xl bg-gradient-to-tr from-cyan-600 to-blue-500 flex items-center justify-center shadow-lg shadow-cyan-500/30">
                    <i class="fa-solid fa-microchip text-white text-lg"></i>
                </div>
                <div>
                    <h1 class="font-bold text-base md:text-lg flex items-center gap-2">
                        Simulasi Motor Servo
                        <span class="text-xs bg-cyan-500/20 text-cyan-400 px-2 py-0.5 rounded-full border border-cyan-500/30 font-semibold">Informatika v2.5</span>
                    </h1>
                    <p class="text-xs text-slate-400">Lab Pengendalian Sudut Arduino & Rangkaian Breadboard</p>
                </div>
            </div>

            <!-- Navigation Tabs -->
            <nav class="flex items-center gap-1.5 md:gap-2 overflow-x-auto pb-1 md:pb-0 text-xs md:text-sm">
                <button onclick="switchTab('simulator')" id="nav-simulator" class="px-3 py-1.5 rounded-lg bg-cyan-600 text-white font-medium flex items-center gap-2 shadow-md shadow-cyan-900/40 transition">
                    <i class="fa-solid fa-compass-drafting"></i> Lab Simulator
                </button>
                <button onclick="switchTab('terminal')" id="nav-terminal" class="px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition">
                    <i class="fa-solid fa-terminal"></i> Terminal & Coding
                </button>
                <button onclick="switchTab('materi')" id="nav-materi" class="px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition">
                    <i class="fa-solid fa-book"></i> Materi Teori
                </button>
                <button onclick="switchTab('evaluasi')" id="nav-evaluasi" class="px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition">
                    <i class="fa-solid fa-graduation-cap"></i> Kuis Evaluasi
                </button>
            </nav>
        </div>
    </header>

    <main class="flex-grow max-w-7xl mx-auto w-full p-4 md:p-6">

        <!-- SIMULATOR VIEW -->
        <div id="view-simulator" class="space-y-6">
            <!-- Subheader Banner -->
            <div class="glass-panel rounded-2xl p-4 md:p-5 flex flex-col md:flex-row justify-between items-start md:items-center gap-4">
                <div>
                    <div class="flex items-center gap-2 text-cyan-400 text-xs font-semibold mb-1">
                        <i class="fa-solid fa-circle text-[8px] animate-pulse"></i> Real-time Breadboard & Realistic Servo Motor Engine
                    </div>
                    <h2 class="text-xl md:text-2xl font-bold text-white">Rangkaian Arduino Uno & Motor Servo SG90</h2>
                    <p class="text-xs md:text-sm text-slate-300 mt-1 max-w-2xl">
                        Atur sudut putaran motor servo secara presisi dari 0° hingga 180° menggunakan slider manual, tombol preset, atau unggah kode program Arduino.
                    </p>
                </div>
                <div class="flex items-center gap-4 bg-slate-900/80 px-4 py-2.5 rounded-xl border border-slate-800 self-stretch md:self-auto justify-between md:justify-start">
                    <div>
                        <div class="text-[10px] uppercase tracking-wider text-slate-400 font-medium">Sudut Aktif</div>
                        <div id="angle-status-display" class="text-base font-bold text-cyan-400 flex items-center gap-1.5 mt-0.5">
                            90° (Tengah)
                        </div>
                    </div>
                    <div class="h-8 w-px bg-slate-800"></div>
                    <div class="text-right">
                        <div class="text-[10px] uppercase tracking-wider text-slate-400 font-medium">Sinyal PWM</div>
                        <div id="pwm-status-display" class="text-base font-bold text-emerald-400 mt-0.5">1.5 ms</div>
                    </div>
                </div>
            </div>

            <!-- Workspace Grid -->
            <div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
                <!-- Circuit Breadboard & Realistic Servo Canvas (7 Cols) -->
                <div class="lg:col-span-7 glass-panel rounded-2xl p-5 flex flex-col justify-between relative overflow-hidden">
                    <div class="flex items-center justify-between border-b border-slate-800/80 pb-3 mb-4">
                        <div class="flex items-center gap-2">
                            <div class="w-2.5 h-2.5 rounded-full bg-cyan-500 animate-pulse"></div>
                            <span class="text-sm font-semibold text-slate-200">Skematik Fisik: Arduino Uno + Breadboard + Servo Realistis</span>
                        </div>
                        <span class="text-xs bg-slate-800/80 text-cyan-300 px-2.5 py-1 rounded-md border border-slate-700">Pin 9 (PWM)</span>
                    </div>

                    <!-- SVG Visual Circuit Schematic with Realistic Servo -->
                    <div class="relative w-full h-[360px] md:h-[420px] bg-slate-950/70 rounded-xl border border-slate-900 flex items-center justify-center p-2 overflow-hidden">
                        <svg class="w-full h-full" viewBox="0 0 700 380" id="circuit-svg">
                            <!-- Circuit Path Wires -->
                            <!-- GND Wire (Black/Grey) -->
                            <path id="wire-gnd" d="M 125 290 L 125 340 L 270 340 L 270 300 L 460 300 L 460 250" class="circuit-line-gnd" />
                            <!-- VCC Wire (Red 5V) -->
                            <path id="wire-vcc" d="M 145 290 L 145 320 L 290 320 L 290 280 L 490 280 L 490 250" class="circuit-line-vcc" />
                            <!-- PWM Signal Wire (Orange Pin 9) -->
                            <path id="wire-pwm" d="M 195 185 L 350 185 L 350 265 L 520 265 L 520 250" class="circuit-line" />

                            <!-- ARDUINO UNO BOARD -->
                            <g transform="translate(40, 110)">
                                <rect width="180" height="190" rx="10" fill="#1e293b" stroke="#0284c7" stroke-width="2" />
                                <text x="90" y="22" fill="#38bdf8" font-size="12" font-weight="bold" text-anchor="middle">ARDUINO UNO</text>
                                <text x="90" y="38" fill="#94a3b8" font-size="9" text-anchor="middle">ATmega328P Microcontroller</text>
                               
                                <!-- USB Port -->
                                <rect x="15" y="55" width="35" height="25" rx="4" fill="#475569" />
                                <text x="32" y="72" fill="#cbd5e1" font-size="8" text-anchor="middle">USB</text>

                                <!-- Power Pins Area -->
                                <rect x="110" y="90" width="60" height="85" rx="6" fill="#0f172a" stroke="#334155" />
                                <text x="140" y="105" fill="#facc15" font-size="9" font-weight="bold" text-anchor="middle">POWER (5V)</text>
                                <circle cx="125" cy="130" r="4" fill="#ef4444" />
                                <text x="145" y="133" fill="#cbd5e1" font-size="8">5V</text>
                                <circle cx="125" cy="155" r="4" fill="#94a3b8" />
                                <text x="145" y="158" fill="#cbd5e1" font-size="8">GND</text>

                                <!-- Digital PWM Pins Area -->
                                <rect x="15" y="90" width="85" height="85" rx="6" fill="#0f172a" stroke="#334155" />
                                <text x="57" y="105" fill="#38bdf8" font-size="9" font-weight="bold" text-anchor="middle">DIGITAL (PWM)</text>
                                <circle cx="30" cy="130" r="4" fill="#38bdf8" />
                                <text x="45" y="133" fill="#cbd5e1" font-size="8">Pin 9</text>
                                <text x="57" y="160" fill="#22c55e" font-size="8" font-weight="bold" text-anchor="middle">SERVO_SIGNAL</text>
                            </g>

                            <!-- BREADBOARD -->
                            <g transform="translate(250, 110)">
                                <rect width="180" height="190" rx="10" fill="#f8fafc" stroke="#cbd5e1" stroke-width="2" />
                                <text x="90" y="22" fill="#0f172a" font-size="11" font-weight="bold" text-anchor="middle">BREADBOARD MINI</text>
                                <!-- Power Rails -->
                                <line x1="20" y1="40" x2="160" y2="40" stroke="#ef4444" stroke-width="2" />
                                <line x1="20" y1="50" x2="160" y2="50" stroke="#94a3b8" stroke-width="2" />
                                <!-- Terminal Strips -->
                                <rect x="25" y="70" width="130" height="100" rx="4" fill="#e2e8f0" />
                                <circle cx="45" cy="95" r="3" fill="#0f172a" />
                                <circle cx="65" cy="95" r="3" fill="#0f172a" />
                                <circle cx="85" cy="95" r="3" fill="#0f172a" />
                                <text x="90" y="130" fill="#475569" font-size="9" text-anchor="middle">Jalur Hubung</text>
                            </g>

                            <!-- REALISTIC MOTOR SERVO SG90 -->
                            <g transform="translate(450, 95)" id="realistic-servo-group">
                                <!-- Servo Main Body Housing (Black Plastic Case with Mounting Flanges) -->
                                <path d="M 25 15 L 125 15 L 135 25 L 135 125 L 125 135 L 25 135 L 15 125 L 15 25 Z" fill="#111827" stroke="#374151" stroke-width="3" filter="drop-shadow(0px 8px 12px rgba(0,0,0,0.5))" />
                               
                                <!-- Mounting Tabs with Screw Holes -->
                                <ellipse cx="15" cy="45" rx="8" ry="14" fill="#111827" stroke="#374151" stroke-width="2" />
                                <circle cx="15" cy="45" r="3" fill="#030712" />
                                <ellipse cx="135" cy="45" rx="8" ry="14" fill="#111827" stroke="#374151" stroke-width="2" />
                                <circle cx="135" cy="45" r="3" fill="#030712" />

                                <!-- Servo Label Sticker (Blue/White branding typical of SG90) -->
                                <rect x="30" y="30" width="90" height="75" rx="4" fill="#0284c7" />
                                <text x="75" y="52" fill="#ffffff" font-size="11" font-weight="bold" text-anchor="middle">TOWER PRO</text>
                                <text x="75" y="70" fill="#facc15" font-size="12" font-weight="bold" text-anchor="middle">SG90 9g</text>
                                <text x="75" y="92" fill="#e0f2fe" font-size="8" text-anchor="middle">MICRO SERVO</text>

                                <!-- Cable Wires coming out of Servo (Brown/Red/Orange) -->
                                <path d="M 75 135 L 75 155 L 70 165" stroke="#78350f" stroke-width="3" fill="none" />
                                <path d="M 78 135 L 78 152 L 73 162" stroke="#ef4444" stroke-width="3" fill="none" />
                                <path d="M 81 135 L 81 149 L 76 159" stroke="#f97316" stroke-width="3" fill="none" />

                                <!-- Output Shaft Gear Center -->
                                <circle cx="75" cy="45" r="14" fill="#e2e8f0" stroke="#64748b" stroke-width="2" />
                                <circle cx="75" cy="45" r="6" fill="#0f172a" />

                                <!-- ROTATING SERVO HORN (Dynamic Arrow/Arm) -->
                                <g id="servo-horn-assembly" transform="translate(75, 45)">
                                    <!-- Rotating group based on angle -->
                                    <g id="servo-rotating-arm" transform="rotate(0)">
                                        <!-- Long white horn arm -->
                                        <rect x="-10" y="-55" width="20" height="70" rx="10" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5" opacity="0.95" />
                                        <circle cx="0" cy="-45" r="5" fill="#0284c7" />
                                        <circle cx="0" cy="-25" r="4" fill="#94a3b8" />
                                        <!-- Center cap -->
                                        <circle cx="0" cy="0" r="8" fill="#334155" stroke="#cbd5e1" stroke-width="1.5" />
                                        <circle cx="0" cy="0" r="3" fill="#38bdf8" />
                                    </g>
                                </g>

                                <!-- Pinout Indicator Text on Servo -->
                                <text x="45" y="123" fill="#94a3b8" font-size="7">- (GND)</text>
                                <text x="73" y="123" fill="#ef4444" font-size="7">+ (5V)</text>
                                <text x="100" y="123" fill="#f97316" font-size="7">S (PWM)</text>
                            </g>
                        </svg>
                    </div>

                    <!-- Live Telemetry Badges -->
                    <div class="mt-4 pt-3 border-t border-slate-800/80 grid grid-cols-2 md:grid-cols-4 gap-3">
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">Tegangan Suplai</div>
                            <div class="text-sm font-bold text-red-400 mt-0.5">5.0 V DC</div>
                        </div>
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">Lebar Pulsa (PWM)</div>
                            <div class="text-sm font-bold text-emerald-400 mt-0.5" id="val-pwm-ms">1.50 ms</div>
                        </div>
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">Posisi Poros</div>
                            <div class="text-sm font-bold text-cyan-400 mt-0.5" id="val-deg">90°</div>
                        </div>
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">Konsumsi Arus</div>
                            <div class="text-sm font-bold text-amber-400 mt-0.5">~120 mA</div>
                        </div>
                    </div>
                </div>

                <!-- Controls & Manual Setting Panel (5 Cols) -->
                <div class="lg:col-span-5 space-y-6">
                    <!-- Manual Angle Control Card -->
                    <div class="glass-panel rounded-2xl p-5 space-y-4">
                        <div class="flex justify-between items-center">
                            <div>
                                <span class="text-xs font-semibold text-cyan-400 uppercase tracking-wider">Pengaturan Sudut Manual</span>
                                <h3 class="text-sm font-bold text-slate-200 mt-0.5">Geser Slider atau Masukkan Angka (0° - 180°)</h3>
                            </div>
                            <div class="bg-slate-900 px-3 py-1.5 rounded-xl border border-slate-800 text-cyan-400 font-mono font-bold text-base" id="angle-display">
                                90°
                            </div>
                        </div>

                        <!-- Range Slider -->
                        <div class="space-y-2">
                            <input type="range" id="angle-slider" min="0" max="180" step="1" value="90" oninput="updateServoAngle(this.value)" class="w-full accent-cyan-500 bg-slate-800 rounded-lg appearance-none h-2.5 cursor-pointer">
                            <div class="flex justify-between text-[11px] text-slate-400 font-medium px-1">
                                <span>0° (Min)</span>
                                <span>90° (Tengah)</span>
                                <span>180° (Max)</span>
                            </div>
                        </div>

                        <!-- Direct Number Input Form -->
                        <div class="flex gap-2 pt-1">
                            <input type="number" id="angle-input" min="0" max="180" value="90" placeholder="0 - 180" class="bg-slate-900 border border-slate-700 rounded-xl px-3 py-2 text-sm text-white w-full focus:outline-none focus:border-cyan-500 font-mono">
                            <button onclick="applyManualInput()" class="bg-cyan-600 hover:bg-cyan-500 text-white px-4 py-2 rounded-xl text-xs font-semibold transition shrink-0 shadow-lg shadow-cyan-900/30">
                                Set Sudut
                            </button>
                        </div>

                        <!-- Quick Preset Buttons (0, 45, 90, 135, 180) -->
                        <div class="grid grid-cols-5 gap-1.5 pt-2">
                            <button onclick="setAnglePreset(0)" class="bg-slate-900 hover:bg-slate-800 border border-slate-800 rounded-lg py-2 text-xs font-medium text-slate-300 transition">0°</button>
                            <button onclick="setAnglePreset(45)" class="bg-slate-900 hover:bg-slate-800 border border-slate-800 rounded-lg py-2 text-xs font-medium text-slate-300 transition">45°</button>
                            <button onclick="setAnglePreset(90)" class="bg-slate-900 hover:bg-slate-800 border border-slate-800 rounded-lg py-2 text-xs font-medium text-cyan-400 font-bold transition">90°</button>
                            <button onclick="setAnglePreset(135)" class="bg-slate-900 hover:bg-slate-800 border border-slate-800 rounded-lg py-2 text-xs font-medium text-slate-300 transition">135°</button>
                            <button onclick="setAnglePreset(180)" class="bg-slate-900 hover:bg-slate-800 border border-slate-800 rounded-lg py-2 text-xs font-medium text-slate-300 transition">180°</button>
                        </div>
                    </div>

                    <!-- Auto Sweep Simulator Mode -->
                    <div class="glass-panel rounded-2xl p-5 space-y-4">
                        <div class="flex items-center justify-between">
                            <div>
                                <span class="text-xs font-semibold text-emerald-400 uppercase tracking-wider">Mode Sweeping Otomatis</span>
                                <h3 class="text-sm font-bold text-slate-200 mt-0.5">Simulasikan putaran bolak-balik otomatis (Looping)</h3>
                            </div>
                            <label class="relative inline-flex items-center cursor-pointer">
                                <input type="checkbox" id="sweep-toggle" class="sr-only peer" onchange="toggleSweepMode()">
                                <div class="w-12 h-6 bg-slate-800 peer-focus:outline-none rounded-full peer peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-slate-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-emerald-600"></div>
                            </label>
                        </div>
                    </div>

                    <!-- Alur Informatika Penjelasan Box -->
                    <div class="glass-panel rounded-2xl p-5 space-y-2 border-l-4 border-l-cyan-500">
                        <div class="text-xs font-bold text-cyan-400 flex items-center gap-1.5">
                            <i class="fa-solid fa-circle-info"></i> KONSEP INFORMATIKA & PWM:
                        </div>
                        <p id="informatics-explanation" class="text-xs text-slate-300 leading-relaxed">
                            Mikrokontroler Arduino mengirimkan pulsa PWM (Pulse Width Modulation) dengan frekuensi 50Hz. Lebar pulsa antara 1.0 ms (0°) hingga 2.0 ms (180°) menentukan posisi motor servo.
                        </p>
                    </div>
                </div>
            </div>
        </div>

        <!-- TERMINAL & CODING VIEW -->
        <div id="view-terminal" class="hidden space-y-6">
            <div class="glass-panel rounded-2xl p-6 space-y-5">
                <div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 border-b border-slate-800 pb-4">
                    <div>
                        <h2 class="text-xl font-bold text-white flex items-center gap-2">
                            <i class="fa-solid fa-code text-cyan-400"></i> Arduino IDE Code Sandbox & Serial Monitor
                        </h2>
                        <p class="text-xs text-slate-400 mt-1">Tulis atau jalankan skrip Arduino untuk mengontrol sudut servo secara pemrograman.</p>
                    </div>
                    <button onclick="runArduinoCode()" class="px-5 py-2.5 bg-emerald-600 hover:bg-emerald-500 text-white text-xs font-semibold rounded-xl shadow-lg shadow-emerald-900/30 transition flex items-center gap-2">
                        <i class="fa-solid fa-play"></i> Upload & Run Code
                    </button>
                </div>

                <div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
                    <!-- Code Editor (7 Cols) -->
                    <div class="lg:col-span-7 bg-slate-950 rounded-xl border border-slate-800 overflow-hidden flex flex-col">
                        <div class="bg-slate-900 px-4 py-2 border-b border-slate-800 flex justify-between items-center text-xs text-slate-400">
                            <span class="font-mono"><i class="fa-solid fa-file-code text-cyan-400"></i> servo_control.ino</span>
                            <span class="text-emerald-400 font-semibold"><i class="fa-solid fa-circle text-[8px]"></i> Ready to compile</span>
                        </div>
                        <textarea id="arduino-code-editor" class="w-full h-[320px] bg-slate-950 text-cyan-300 p-4 font-mono text-xs md:text-sm focus:outline-none resize-none leading-relaxed" spellcheck="false">#include <Servo.h>

Servo myservo;  // buat objek servo

void setup() {
  myservo.attach(9);  // servo terhubung ke pin digital 9
  Serial.begin(9600);
}

void loop() {
  // Gerakkan servo ke sudut 0 derajat
  myservo.write(0);
  delay(1000);
 
  // Gerakkan servo ke sudut 90 derajat (Tengah)
  myservo.write(90);
  delay(1000);
 
  // Gerakkan servo ke sudut 180 derajat
  myservo.write(180);
  delay(1000);
}</textarea>
                    </div>

                    <!-- Serial Monitor / Output Log (5 Cols) -->
                    <div class="lg:col-span-5 bg-slate-950 rounded-xl border border-slate-800 overflow-hidden flex flex-col justify-between">
                        <div class="bg-slate-900 px-4 py-2 border-b border-slate-800 flex justify-between items-center text-xs text-slate-400">
                            <span class="font-mono"><i class="fa-solid fa-desktop text-amber-400"></i> Serial Monitor Output</span>
                            <button onclick="clearConsole()" class="text-slate-400 hover:text-white transition text-[11px]">Clear</button>
                        </div>
                        <div id="serial-console" class="p-4 font-mono text-xs text-slate-300 h-[280px] overflow-y-auto space-y-1.5 bg-slate-950/80">
                            <div class="text-emerald-400">[System] Arduino IDE v1.8.19 initialized.</div>
                            <div class="text-cyan-400">[Compiler] Sketch compiled successfully for ATmega328P.</div>
                            <div class="text-slate-400">[Serial] Baud rate: 9600 bps. Waiting for user command...</div>
                        </div>
                        <div class="p-3 bg-slate-900 border-t border-slate-800 flex gap-2">
                            <input type="text" id="serial-input" placeholder="Kirim data sudut (contoh: 45)..." class="bg-slate-950 border border-slate-700 rounded-lg px-3 py-1.5 text-xs text-white w-full font-mono focus:outline-none focus:border-cyan-500">
                            <button onclick="sendSerialData()" class="bg-cyan-600 hover:bg-cyan-500 text-white px-4 py-1.5 rounded-lg text-xs font-semibold transition shrink-0">Kirim</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- MATERI TEORI VIEW -->
        <div id="view-materi" class="hidden space-y-6">
            <div class="glass-panel rounded-2xl p-6 space-y-4">
                <div class="border-b border-slate-800 pb-4">
                    <h2 class="text-xl font-bold text-white flex items-center gap-2">
                        <i class="fa-solid fa-book-open text-cyan-400"></i> Materi Pembelajaran Motor Servo & Informatika
                    </h2>
                    <p class="text-xs text-slate-400 mt-1">Panduan komprehensif mengenai aktuator, sinyal PWM, dan pemrograman mikrokontroler.</p>
                </div>
                <div class="grid grid-cols-1 md:grid-cols-3 gap-6 pt-2">
                    <div class="bg-slate-900/80 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="w-10 h-10 rounded-lg bg-cyan-500/10 text-cyan-400 flex items-center justify-center font-bold text-lg">1</div>
                        <h3 class="font-bold text-slate-200 text-sm">Apa itu Motor Servo?</h3>
                        <p class="text-xs text-slate-400 leading-relaxed">
                            Motor servo adalah perangkat elektromekanis yang dapat dikendalikan sudut putarannya secara akurat (biasanya antara 0° hingga 180°) menggunakan umpan balik posisi internal.
                        </p>
                    </div>
                    <div class="bg-slate-900/80 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="w-10 h-10 rounded-lg bg-blue-500/10 text-blue-400 flex items-center justify-center font-bold text-lg">2</div>
                        <h3 class="font-bold text-slate-200 text-sm">Sinyal PWM (Pulse Width Modulation)</h3>
                        <p class="text-xs text-slate-400 leading-relaxed">
                            PWM adalah teknik pengaturan lebar pulsa listrik. Pada servo SG90, pulsa 1ms memutar poros ke 0°, 1.5ms ke 90°, dan 2.0ms ke 180° dengan frekuensi konstan 50Hz.
                        </p>
                    </div>
                    <div class="bg-slate-900/80 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="w-10 h-10 rounded-lg bg-emerald-500/10 text-emerald-400 flex items-center justify-center font-bold text-lg">3</div>
                        <h3 class="font-bold text-slate-200 text-sm">Koneksi Pin Rangkaian</h3>
                        <p class="text-xs text-slate-400 leading-relaxed">
                            Motor servo memiliki 3 kabel: Coklat/Hitam (GND), Merah (VCC 5V), dan Oranye/Kuning (Sinyal PWM yang dihubungkan ke pin digital PWM Arduino seperti Pin 9).
                        </p>
                    </div>
                </div>
            </div>
        </div>

        <!-- EVALUASI VIEW -->
        <div id="view-evaluasi" class="hidden space-y-6">
            <div class="glass-panel rounded-2xl p-6 text-center space-y-4">
                <div class="w-14 h-14 bg-emerald-500/20 text-emerald-400 rounded-2xl mx-auto flex items-center justify-center text-2xl shadow-inner">
                    <i class="fa-solid fa-graduation-cap"></i>
                </div>
                <h2 class="text-xl font-bold text-white">Kuis Evaluasi Pemahaman Motor Servo</h2>
                <p class="text-xs text-slate-400 max-w-md mx-auto">Uji kompetensi Anda seputar konsep informatika, pemrograman Arduino, dan kendali servo.</p>
                <div class="bg-slate-900/90 p-8 rounded-xl border border-slate-800 max-w-xl mx-auto space-y-4">
                    <div class="text-sm font-semibold text-slate-300">Total Soal: 5 Pertanyaan Pilihan Ganda Interaktif</div>
                    <button onclick="alertBox('Modul Evaluasi Kuis siap dikerjakan oleh siswa.')" class="px-5 py-2.5 bg-emerald-600 hover:bg-emerald-500 text-white text-xs font-semibold rounded-xl shadow-lg shadow-emerald-900/30 transition">
                        Mulai Kuis Sekarang
                    </button>
                </div>
            </div>
        </div>

    </main>

    <footer class="border-t border-slate-800/80 bg-slate-900/40 py-4 px-4 text-center text-xs text-slate-500 flex flex-col md:flex-row items-center justify-between max-w-7xl mx-auto w-full gap-2">
        <div>© Simulasi Motor Servo Informatika • Media Pembelajaran Interaktif • Semua Hak Dilindungi</div>
        <div class="flex items-center gap-4 text-slate-400 font-medium">
            <span>Informatika Fase E/F</span>
            <span>•</span>
            <span class="hover:text-cyan-400 cursor-pointer transition" onclick="alertBox('Dikembangkan khusus untuk mendukung praktikum mikrokontroler Arduino & Motor Servo.')">Tentang Aplikasi</span>
        </div>
    </footer>

    <script>
        let currentAngle = 90;
        let isSweepActive = false;
        let sweepInterval = null;

        // Navigation tab switching
        function switchTab(tabId) {
            const tabs = ['simulator', 'terminal', 'materi', 'evaluasi'];
            tabs.forEach(t => {
                const el = document.getElementById('view-' + t);
                const btn = document.getElementById('nav-' + t);
                if (t === tabId) {
                    el.classList.remove('hidden');
                    btn.className = 'px-3 py-1.5 rounded-lg bg-cyan-600 text-white font-medium flex items-center gap-2 shadow-md shadow-cyan-900/40 transition';
                } else {
                    el.classList.add('hidden');
                    btn.className = 'px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition';
                }
            });
        }

        // Custom Safe Alert Box (No native alert)
        function alertBox(message) {
            const modal = document.createElement('div');
            modal.className = 'fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm p-4';
            modal.innerHTML = `
                <div class="glass-panel max-w-sm w-full p-6 rounded-2xl border border-slate-700 space-y-4 text-center shadow-2xl animate-in fade-in zoom-in duration-200">
                    <div class="w-12 h-12 rounded-full bg-cyan-500/20 text-cyan-400 flex items-center justify-center mx-auto text-xl">
                        <i class="fa-solid fa-circle-info"></i>
                    </div>
                    <div class="text-sm font-semibold text-slate-200">${message}</div>
                    <button onclick="this.closest('.fixed').remove()" class="w-full py-2.5 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold text-xs rounded-xl transition">
                        Mengerti
                    </button>
                </div>
            `;
            document.body.appendChild(modal);
        }

        // Update Servo Angle function (Rotates the realistic arm and updates telemetry)
        function updateServoAngle(angle) {
            currentAngle = parseInt(angle);
            if (isNaN(currentAngle)) currentAngle = 0;
            if (currentAngle < 0) currentAngle = 0;
            if (currentAngle > 180) currentAngle = 180;

            // Update UI inputs
            document.getElementById('angle-slider').value = currentAngle;
            document.getElementById('angle-input').value = currentAngle;
            document.getElementById('angle-display').textContent = currentAngle + '°';
            document.getElementById('angle-status-display').textContent = currentAngle + '° (' + getAngleDescription(currentAngle) + ')';
            document.getElementById('val-deg').textContent = currentAngle + '°';

            // Calculate PWM pulse width (Standard SG90: 0 deg = ~1.0ms, 90 deg = ~1.5ms, 180 deg = ~2.0ms)
            let pwmMs = (1.0 + (currentAngle / 180) * 1.0).toFixed(2);
            document.getElementById('pwm-status-display').textContent = pwmMs + ' ms';
            document.getElementById('val-pwm-ms').textContent = pwmMs + ' ms';

            // Rotate the SVG Servo rotating arm element
            // Note: SG90 horn typically maps from -90° to +90° rotation relative to vertical when angle is 0° to 180°
            // Let's map 0° -> -90 deg rotation, 90° -> 0 deg rotation, 180° -> +90 deg rotation
            let svgRotation = currentAngle - 90;
            const rotatingArm = document.getElementById('servo-rotating-arm');
            if (rotatingArm) {
                rotatingArm.setAttribute('transform', `rotate(${svgRotation})`);
            }

            // Update informatics explanation text
            document.getElementById('informatics-explanation').textContent =
                `Sudut servo diatur ke ${currentAngle}° dengan lebar pulsa PWM ${pwmMs} ms. Sinyal dikirim dari pin digital Arduino melalui breadboard.`;
        }

        function getAngleDescription(deg) {
            if (deg === 0) return 'Minimum';
            if (deg === 90) return 'Tengah';
            if (deg === 180) return 'Maksimum';
            return 'Custom';
        }

        function applyManualInput() {
            const inputVal = document.getElementById('angle-input').value;
            let val = parseInt(inputVal);
            if (isNaN(val) || val < 0 || val > 180) {
                alertBox('Masukkan nilai sudut yang valid antara 0 hingga 180 derajat.');
                return;
            }
            updateServoAngle(val);
        }

        function setAnglePreset(deg) {
            if (isSweepActive) {
                document.getElementById('sweep-toggle').checked = false;
                toggleSweepMode();
            }
            updateServoAngle(deg);
        }

        // Toggle Automatic Sweep Mode
        function toggleSweepMode() {
            isSweepActive = document.getElementById('sweep-toggle').checked;
            if (isSweepActive) {
                let direction = 1;
                let val = currentAngle;
                sweepInterval = setInterval(() => {
                    val += direction * 3;
                    if (val >= 180) { val = 180; direction = -1; }
                    if (val <= 0) { val = 0; direction = 1; }
                    updateServoAngle(val);
                }, 50);
            } else {
                if (sweepInterval) clearInterval(sweepInterval);
            }
        }

        // Arduino Code Runner Simulation
        function runArduinoCode() {
            const code = document.getElementById('arduino-code-editor').value;
            const consoleEl = document.getElementById('serial-console');
           
            consoleEl.innerHTML += `<div class="text-cyan-400">[Compiler] Uploading sketch to Arduino Uno...</div>`;
            consoleEl.scrollTop = consoleEl.scrollHeight;

            setTimeout(() => {
                consoleEl.innerHTML += `<div class="text-emerald-400">[Success] Upload complete! Executing loop...</div>`;
                consoleEl.scrollTop = consoleEl.scrollHeight;

                // Simulate sequence of writes found in default code
                setTimeout(() => { updateServoAngle(0); logSerial("myservo.write(0); -> Angle: 0°"); }, 500);
                setTimeout(() => { updateServoAngle(90); logSerial("myservo.write(90); -> Angle: 90°"); }, 1500);
                setTimeout(() => { updateServoAngle(180); logSerial("myservo.write(180); -> Angle: 180°"); }, 2500);
            }, 800);
        }

        function logSerial(msg) {
            const consoleEl = document.getElementById('serial-console');
            consoleEl.innerHTML += `<div class="text-slate-300">[Serial] ${msg}</div>`;
            consoleEl.scrollTop = consoleEl.scrollHeight;
        }

        function clearConsole() {
            document.getElementById('serial-console').innerHTML = `<div class="text-emerald-400">[System] Serial monitor cleared.</div>`;
        }

        function sendSerialData() {
            const val = document.getElementById('serial-input').value;
            let num = parseInt(val);
            if (!isNaN(num) && num >= 0 && num <= 180) {
                updateServoAngle(num);
                logSerial(`Received from Serial: ${num}°`);
                document.getElementById('serial-input').value = '';
            } else {
                alertBox('Kirim angka valid antara 0 - 180 melalui Serial Monitor.');
            }
        }
    </script>
</body>
</html>
========================================================================

DHT

<!DOCTYPE html>
<html lang="id">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simulasi Sensor DHT11 & OLED Display v3.2 + Sirene Alarm</title>
    <!-- Tailwind CSS CDN -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- Font Inter & Font Awesome -->
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        body { font-family: 'Inter', sans-serif; }
        .font-mono { font-family: 'JetBrains Mono', monospace; }
        .glass-panel { background: rgba(15, 23, 42, 0.88); backdrop-filter: blur(12px); border: 1px solid rgba(255, 255, 255, 0.08); }
        .circuit-line-gnd { stroke: #94a3b8; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-vcc { stroke: #ef4444; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-data { stroke: #38bdf8; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-scl { stroke: #eab308; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-sda { stroke: #22c55e; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        .circuit-line-buzzer { stroke: #a855f7; stroke-width: 2.5; fill: none; stroke-dasharray: 6; animation: dash 1.5s linear infinite; }
        @keyframes dash { to { stroke-dashoffset: -12; } }
        @keyframes popIn {
            0% { transform: scale(0.5); opacity: 0; }
            70% { transform: scale(1.05); opacity: 1; }
            100% { transform: scale(1); opacity: 1; }
        }
        .pop-animation { animation: popIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards; }
        @keyframes pulseAlert {
            0%, 100% { border-color: rgba(239, 68, 68, 0.8); box-shadow: 0 0 15px rgba(239, 68, 68, 0.4); }
            50% { border-color: rgba(239, 68, 68, 0.2); box-shadow: 0 0 5px rgba(239, 68, 68, 0.1); }
        }
        .alert-active { animation: pulseAlert 1s infinite; }
    </style>
</head>
<body class="bg-slate-950 text-slate-100 min-h-screen flex flex-col justify-between selection:bg-cyan-500 selection:text-white">

    <header class="border-b border-slate-800 bg-slate-900/85 backdrop-blur sticky top-0 z-50">
        <div class="max-w-7xl mx-auto px-4 py-3 flex flex-wrap items-center justify-between gap-4">
            <div class="flex items-center space-x-3">
                <div class="w-10 h-10 rounded-xl bg-gradient-to-tr from-cyan-600 to-emerald-500 flex items-center justify-center shadow-lg shadow-cyan-500/30">
                    <i class="fa-solid fa-microchip text-white text-lg"></i>
                </div>
                <div>
                    <h1 class="font-bold text-base md:text-lg flex items-center gap-2">
                        Simulasi DHT11 + OLED + Sirene Alarm
                        <span class="text-xs bg-rose-500/20 text-rose-400 px-2 py-0.5 rounded-full border border-rose-500/30 font-semibold">v3.2</span>
                    </h1>
                    <p class="text-xs text-slate-400">Lab IoT dengan Efek Suara Sirene (≥ 45°C)</p>
                </div>
            </div>

            <!-- Navigation Tabs -->
            <nav class="flex items-center gap-1.5 md:gap-2 overflow-x-auto pb-1 md:pb-0 text-xs md:text-sm">
                <button onclick="window.switchTab('simulator')" id="nav-simulator" class="px-3 py-1.5 rounded-lg bg-cyan-600 text-white font-medium flex items-center gap-2 shadow-md shadow-cyan-900/40 transition">
                    <i class="fa-solid fa-compass-drafting"></i> Lab Simulator
                </button>
                <button onclick="window.switchTab('terminal')" id="nav-terminal" class="px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition">
                    <i class="fa-solid fa-terminal"></i> Terminal & Coding
                </button>
                <button onclick="window.switchTab('materi')" id="nav-materi" class="px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition">
                    <i class="fa-solid fa-book"></i> Materi Teori
                </button>
                <button onclick="window.switchTab('evaluasi')" id="nav-evaluasi" class="px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition">
                    <i class="fa-solid fa-graduation-cap"></i> Kuis Evaluasi
                </button>
            </nav>
        </div>
    </header>

    <main class="flex-grow max-w-7xl mx-auto w-full p-4 md:p-6">

        <div id="view-simulator" class="space-y-6">
            <!-- Subheader Banner with Alarm Status Indicator -->
            <div id="banner-container" class="glass-panel rounded-2xl p-4 md:p-5 flex flex-col md:flex-row justify-between items-start md:items-center gap-4 transition-all duration-300">
                <div>
                    <div id="system-status-pill" class="flex items-center gap-2 text-cyan-400 text-xs font-semibold mb-1">
                        <i class="fa-solid fa-circle text-[8px] animate-pulse"></i> Sistem Normal: Memantau Suhu Lingkungan
                    </div>
                    <h2 class="text-xl md:text-2xl font-bold text-white">Rangkaian Arduino Uno, Sensor DHT11, OLED & Buzzer Sirene</h2>
                    <p class="text-xs md:text-sm text-slate-300 mt-1 max-w-2xl">
                        Atur suhu hingga mencapai <b class="text-amber-400">45°C atau lebih</b> untuk memicu efek suara sirene darurat pada audio browser dan layar OLED.
                    </p>
                </div>
                <div class="flex items-center gap-4 bg-slate-900/80 px-4 py-2.5 rounded-xl border border-slate-800 self-stretch md:self-auto justify-between md:justify-start">
                    <div>
                        <div class="text-[10px] uppercase tracking-wider text-slate-400 font-medium">Suhu Udara</div>
                        <div id="temp-status-display" class="text-base font-bold text-amber-400 flex items-center gap-1.5 mt-0.5">
                            28.0°C
                        </div>
                    </div>
                    <div class="h-8 w-px bg-slate-800"></div>
                    <div class="text-right">
                        <div class="text-[10px] uppercase tracking-wider text-slate-400 font-medium">Kelembapan</div>
                        <div id="hum-status-display" class="text-base font-bold text-cyan-400 mt-0.5">65% RH</div>
                    </div>
                </div>
            </div>

            <!-- Workspace Grid -->
            <div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
                <!-- Circuit Breadboard & Realistic Sensor + OLED + Buzzer Canvas (7 Cols) -->
                <div class="lg:col-span-7 glass-panel rounded-2xl p-5 flex flex-col justify-between relative overflow-hidden">
                    <div class="flex items-center justify-between border-b border-slate-800/80 pb-3 mb-4">
                        <div class="flex items-center gap-2">
                            <div id="circuit-dot" class="w-2.5 h-2.5 rounded-full bg-cyan-500 animate-pulse"></div>
                            <span class="text-sm font-semibold text-slate-200">Skematik Fisik: Arduino + DHT11 + OLED + Buzzer Sirene</span>
                        </div>
                        <span class="text-xs bg-slate-800/80 text-cyan-300 px-2.5 py-1 rounded-md border border-slate-700">Pin 2 (DHT) & Pin 8 (Buzzer)</span>
                    </div>

                    <!-- SVG Visual Circuit Schematic with Realistic DHT11, OLED, and Buzzer -->
                    <div class="relative w-full h-[380px] md:h-[430px] bg-slate-950/70 rounded-xl border border-slate-900 flex items-center justify-center p-2 overflow-hidden">
                        <svg class="w-full h-full" viewBox="0 0 740 380" id="circuit-svg">
                            <!-- Circuit Path Wires -->
                            <!-- GND Wire (Grey) -->
                            <path id="wire-gnd" d="M 125 290 L 125 340 L 320 340 L 320 300 L 440 300 L 440 250" class="circuit-line-gnd" />
                            <!-- VCC Wire (Red 5V) -->
                            <path id="wire-vcc" d="M 145 290 L 145 325 L 340 325 L 340 280 L 470 280 L 470 250" class="circuit-line-vcc" />
                            <!-- Data Signal Wire (Blue Pin 2) -->
                            <path id="wire-data" d="M 30 150 L 190 150 L 190 265 L 500 265 L 500 250" class="circuit-line-data" />
                            <!-- I2C SCL Wire (Yellow A5) -->
                            <path id="wire-scl" d="M 165 290 L 165 355 L 400 355 L 400 310 L 630 310 L 630 250" class="circuit-line-scl" />
                            <!-- I2C SDA Wire (Green A4) -->
                            <path id="wire-sda" d="M 185 290 L 185 370 L 420 370 L 420 295 L 600 295 L 600 250" class="circuit-line-sda" />
                            <!-- Buzzer Wire (Purple Pin 8) -->
                            <path id="wire-buzzer" d="M 75 115 L 75 80 L 300 80 L 300 220 L 375 220" class="circuit-line-buzzer" />

                            <!-- ARDUINO UNO BOARD -->
                            <g transform="translate(20, 110)">
                                <rect width="180" height="190" rx="10" fill="#1e293b" stroke="#0284c7" stroke-width="2" />
                                <text x="90" y="20" fill="#38bdf8" font-size="11" font-weight="bold" text-anchor="middle">ARDUINO UNO</text>
                               
                                <!-- USB Port -->
                                <rect x="15" y="45" width="35" height="22" rx="4" fill="#475569" />
                                <text x="32" y="60" fill="#cbd5e1" font-size="7" text-anchor="middle">USB</text>

                                <!-- Power & Analog Area -->
                                <rect x="105" y="80" width="70" height="95" rx="6" fill="#0f172a" stroke="#334155" />
                                <text x="140" y="94" fill="#facc15" font-size="8" font-weight="bold" text-anchor="middle">POWER / ANALOG</text>
                                <circle cx="118" cy="115" r="3.5" fill="#ef4444" />
                                <text x="135" y="118" fill="#cbd5e1" font-size="7">5V</text>
                                <circle cx="118" cy="135" r="3.5" fill="#94a3b8" />
                                <text x="135" y="138" fill="#cbd5e1" font-size="7">GND</text>
                                <circle cx="118" cy="155" r="3.5" fill="#22c55e" />
                                <text x="135" y="158" fill="#cbd5e1" font-size="7">A4 (SDA)</text>
                                <circle cx="118" cy="172" r="3.5" fill="#eab308" />
                                <text x="135" y="175" fill="#cbd5e1" font-size="7">A5 (SCL)</text>

                                <!-- Digital Pins Area -->
                                <rect x="15" y="80" width="80" height="95" rx="6" fill="#0f172a" stroke="#334155" />
                                <text x="55" y="94" fill="#38bdf8" font-size="8" font-weight="bold" text-anchor="middle">DIGITAL</text>
                                <circle cx="28" cy="115" r="3.5" fill="#a855f7" />
                                <text x="42" y="118" fill="#cbd5e1" font-size="7">Pin 8</text>
                                <circle cx="28" cy="135" r="3.5" fill="#38bdf8" />
                                <text x="42" y="138" fill="#cbd5e1" font-size="7">Pin 2</text>
                            </g>

                            <!-- BUZZER SIRENE MODULE -->
                            <g transform="translate(340, 150)" id="realistic-buzzer-group">
                                <circle cx="35" cy="35" r="30" fill="#334155" stroke="#64748b" stroke-width="3" filter="drop-shadow(0px 4px 8px rgba(0,0,0,0.5))" />
                                <circle cx="35" cy="35" r="22" fill="#1e293b" />
                                <circle cx="35" cy="35" r="14" fill="#0f172a" />
                                <!-- Sound waves icon effect when active -->
                                <path d="M 55 20 Q 65 35 55 50" fill="none" stroke="#a855f7" stroke-width="2" id="buzzer-wave-1" opacity="0" />
                                <path d="M 62 12 Q 78 35 62 58" fill="none" stroke="#a855f7" stroke-width="2" id="buzzer-wave-2" opacity="0" />
                                <text x="35" y="78" fill="#a855f7" font-size="8" font-weight="bold" text-anchor="middle">SIRENE (PIN 8)</text>
                            </g>

                            <!-- REALISTIC SENSOR DHT11 -->
                            <g transform="translate(420, 95)" id="realistic-dht-group">
                                <rect x="15" y="15" width="80" height="120" rx="10" fill="#0284c7" stroke="#0369a1" stroke-width="3" filter="drop-shadow(0px 6px 10px rgba(0,0,0,0.5))" />
                                <rect x="25" y="28" width="60" height="42" rx="3" fill="#0369a1" />
                                <line x1="33" y1="38" x2="77" y2="38" stroke="#bae6fd" stroke-width="2" />
                                <line x1="33" y1="47" x2="77" y2="47" stroke="#bae6fd" stroke-width="2" />
                                <line x1="33" y1="56" x2="77" y2="56" stroke="#bae6fd" stroke-width="2" />

                                <text x="55" y="92" fill="#ffffff" font-size="10" font-weight="bold" text-anchor="middle">DHT11</text>
                                <text x="55" y="108" fill="#e0f2fe" font-size="7" text-anchor="middle">Sensor Suhu</text>

                                <rect x="25" y="135" width="5" height="20" fill="#e2e8f0" />
                                <rect x="40" y="135" width="5" height="20" fill="#e2e8f0" />
                                <rect x="55" y="135" width="5" height="20" fill="#e2e8f0" />
                                <rect x="70" y="135" width="5" height="20" fill="#e2e8f0" />
                            </g>

                            <!-- REALISTIC OLED DISPLAY 0.96" (I2C) -->
                            <g transform="translate(540, 85)" id="realistic-oled-group">
                                <!-- PCB Board -->
                                <rect width="130" height="160" rx="8" fill="#475569" stroke="#334155" stroke-width="2" filter="drop-shadow(0px 8px 14px rgba(0,0,0,0.6))" />
                                <text x="65" y="18" fill="#ffffff" font-size="9" font-weight="bold" text-anchor="middle">OLED 128x64 I2C</text>

                                <!-- Screen Bezel -->
                                <rect x="15" y="28" width="100" height="70" rx="4" fill="#020617" stroke="#1e293b" stroke-width="2" />
                               
                                <!-- OLED Live Display Content Inside SVG -->
                                <g transform="translate(20, 33)">
                                    <rect width="90" height="60" rx="2" fill="#030712" />
                                    <text x="45" y="12" fill="#38bdf8" font-size="7" font-weight="bold" text-anchor="middle">-- IOT MONITOR --</text>
                                    <line x1="5" y1="16" x2="85" y2="16" stroke="#0284c7" stroke-width="0.8" />
                                   
                                    <text x="8" y="28" fill="#94a3b8" font-size="7">SUHU:</text>
                                    <text x="75" y="28" fill="#f59e0b" font-size="8" font-weight="bold" text-anchor="end" id="oled-svg-temp">28.0°C</text>

                                    <text x="8" y="42" fill="#94a3b8" font-size="7">LEMBAP:</text>
                                    <text x="75" y="42" fill="#22d3ee" font-size="8" font-weight="bold" text-anchor="end" id="oled-svg-hum">65%</text>

                                    <!-- Dynamic status on OLED screen -->
                                    <text x="45" y="55" fill="#10b981" font-size="6" font-weight="bold" text-anchor="middle" id="oled-svg-status">STATUS: AMAN</text>
                                </g>

                                <!-- 4 Pins at bottom -->
                                <rect x="30" y="110" width="6" height="30" fill="#e2e8f0" />
                                <rect x="50" y="110" width="6" height="30" fill="#e2e8f0" />
                                <rect x="70" y="110" width="6" height="30" fill="#e2e8f0" />
                                <rect x="90" y="110" width="6" height="30" fill="#e2e8f0" />
                            </g>
                        </svg>
                    </div>

                    <!-- Live Telemetry Badges -->
                    <div class="mt-4 pt-3 border-t border-slate-800/80 grid grid-cols-2 md:grid-cols-4 gap-3">
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">Sirene Status</div>
                            <div id="badge-buzzer-status" class="text-sm font-bold text-slate-400 mt-0.5">OFF (Aman)</div>
                        </div>
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">Suhu Terbaca</div>
                            <div class="text-sm font-bold text-amber-400 mt-0.5" id="val-temp">28.0°C</div>
                        </div>
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">Batas Threshold</div>
                            <div class="text-sm font-bold text-rose-400 mt-0.5">≥ 45.0°C</div>
                        </div>
                        <div class="bg-slate-900/90 rounded-xl p-2.5 border border-slate-800 text-center">
                            <div class="text-[10px] text-slate-400">OLED Status</div>
                            <div class="text-sm font-bold text-emerald-400 mt-0.5" id="badge-oled-status">Normal</div>
                        </div>
                    </div>
                </div>

                <!-- Controls & Manual Setting Panel (5 Cols) -->
                <div class="lg:col-span-5 space-y-6">
                    <!-- Manual Temperature Control Card -->
                    <div class="glass-panel rounded-2xl p-5 space-y-4">
                        <div class="flex justify-between items-center">
                            <div>
                                <span class="text-xs font-semibold text-amber-400 uppercase tracking-wider">Simulasi Suhu Lingkungan (0°C - 60°C)</span>
                                <h3 class="text-sm font-bold text-slate-200 mt-0.5">Atur Slider Suhu Ruangan</h3>
                            </div>
                            <div class="bg-slate-900 px-3 py-1.5 rounded-xl border border-slate-800 text-amber-400 font-mono font-bold text-base" id="temp-display">
                                28°C
                            </div>
                        </div>

                        <div class="space-y-2">
                            <input type="range" id="temp-slider" min="0" max="60" step="0.5" value="28" oninput="window.updateEnvironment(this.value, document.getElementById('hum-slider').value)" class="w-full accent-amber-500 bg-slate-800 rounded-lg appearance-none h-2.5 cursor-pointer">
                            <div class="flex justify-between text-[11px] text-slate-400 font-medium px-1">
                                <span>0°C (Dingin)</span>
                                <span class="text-rose-400 font-bold">45°C (Sirene Aktif)</span>
                                <span>60°C (Maks)</span>
                            </div>
                        </div>
                    </div>

                    <!-- Manual Humidity Control Card -->
                    <div class="glass-panel rounded-2xl p-5 space-y-4">
                        <div class="flex justify-between items-center">
                            <div>
                                <span class="text-xs font-semibold text-cyan-400 uppercase tracking-wider">Simulasi Kelembapan Udara (20% - 90% RH)</span>
                                <h3 class="text-sm font-bold text-slate-200 mt-0.5">Atur Slider Kelembapan</h3>
                            </div>
                            <div class="bg-slate-900 px-3 py-1.5 rounded-xl border border-slate-800 text-cyan-400 font-mono font-bold text-base" id="hum-display">
                                65%
                            </div>
                        </div>

                        <div class="space-y-2">
                            <input type="range" id="hum-slider" min="20" max="90" step="1" value="65" oninput="window.updateEnvironment(document.getElementById('temp-slider').value, this.value)" class="w-full accent-cyan-500 bg-slate-800 rounded-lg appearance-none h-2.5 cursor-pointer">
                            <div class="flex justify-between text-[11px] text-slate-400 font-medium px-1">
                                <span>20% (Kering)</span>
                                <span>60% (Ideal)</span>
                                <span>90% (Lembap)</span>
                            </div>
                        </div>
                    </div>

                    <!-- Alur Logika Sirene Penjelasan Box -->
                    <div id="explanation-box" class="glass-panel rounded-2xl p-5 space-y-2 border-l-4 border-l-cyan-500 transition-all duration-300">
                        <div class="text-xs font-bold text-cyan-400 flex items-center gap-1.5" id="explanation-title">
                            <i class="fa-solid fa-circle-info"></i> LOGIKA PERCABANGAN (IF-ELSE):
                        </div>
                        <p id="informatics-explanation" class="text-xs text-slate-300 leading-relaxed">
                            Jika suhu < 45°C, sistem berada pada status normal. Jika suhu ≥ 45°C, mikrokontroler mengeksekusi perintah menyalakan sirene pada Pin 8 dan menampilkan peringatan <b class="text-rose-400">"WASPADA PANAS BERLEBIH!"</b>.
                        </p>
                    </div>
                </div>
            </div>
        </div>

        <div id="view-terminal" class="hidden space-y-6">
            <div class="glass-panel rounded-2xl p-6 space-y-5">
                <div class="flex flex-col md:flex-row justify-between items-start md:items-center gap-4 border-b border-slate-800 pb-4">
                    <div>
                        <h2 class="text-xl font-bold text-white flex items-center gap-2">
                            <i class="fa-solid fa-code text-cyan-400"></i> Arduino IDE Code Sandbox (with Siren Alarm Logic)
                        </h2>
                        <p class="text-xs text-slate-400 mt-1">Skrip Arduino lengkap dengan fungsi percabangan kondisi suhu panas berlebih & efek nada sirene.</p>
                    </div>
                    <button onclick="window.runArduinoCode()" class="px-5 py-2.5 bg-emerald-600 hover:bg-emerald-500 text-white text-xs font-semibold rounded-xl shadow-lg shadow-emerald-900/30 transition flex items-center gap-2">
                        <i class="fa-solid fa-play"></i> Upload & Run Code
                    </button>
                </div>

                <div class="grid grid-cols-1 lg:grid-cols-12 gap-6">
                    <!-- Code Editor (7 Cols) -->
                    <div class="lg:col-span-7 bg-slate-950 rounded-xl border border-slate-800 overflow-hidden flex flex-col">
                        <div class="bg-slate-900 px-4 py-2 border-b border-slate-800 flex justify-between items-center text-xs text-slate-400">
                            <span class="font-mono"><i class="fa-solid fa-file-code text-cyan-400"></i> dht11_sirene_alarm.ino</span>
                            <span class="text-emerald-400 font-semibold"><i class="fa-solid fa-circle text-[8px]"></i> Ready to compile</span>
                        </div>
                        <textarea id="arduino-code-editor" class="w-full h-[320px] bg-slate-950 text-cyan-300 p-4 font-mono text-xs md:text-sm focus:outline-none resize-none leading-relaxed" spellcheck="false">#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <DHT.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define DHTPIN 2    
#define DHTTYPE DHT11  
#define BUZZERPIN 8 // Pin untuk Buzzer Sirene

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  dht.begin();
  pinMode(BUZZERPIN, OUTPUT);
 
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 alokasi gagal"));
    for(;;);
  }
  display.clearDisplay();
  display.setTextColor(WHITE);
}

void loop() {
  delay(2000);
  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
  if (isnan(h) || isnan(t)) {
    Serial.println("Gagal membaca DHT!");
    return;
  }
 
  // Logika Percabangan Sirene Suhu Panas Berlebih (>= 45°C)
  display.clearDisplay();
  display.setTextSize(1);
  display.setCursor(0,0);
  display.println(F("== IOT MONITOR =="));

  if (t >= 45.0) {
    // Efek Sirene (Naik-Turun Frekuensi Nada)
    for (int freq = 1000; freq <= 2500; freq += 200) {
      tone(BUZZERPIN, freq, 100);
      delay(80);
    }
    for (int freq = 2500; freq >= 1000; freq -= 200) {
      tone(BUZZERPIN, freq, 100);
      delay(80);
    }

    Serial.print("SIRENE AKTIF! Suhu Panas Berlebih: "); Serial.print(t); Serial.println("°C");
   
    display.setCursor(0, 18);
    display.println(F("! SIRENE BAHAYA !"));
    display.setCursor(0, 32);
    display.print(F("Suhu: ")); display.print(t); display.println(F(" C"));
    display.setCursor(0, 48);
    display.println(F("STATUS: OVERHEAT!"));
  } else {
    noTone(BUZZERPIN); // Matikan Buzzer
    Serial.print("Suhu: "); Serial.print(t); Serial.print("°C | Kelembapan: "); Serial.print(h); Serial.println("%");

    display.setCursor(0, 20);
    display.print(F("Suhu: ")); display.print(t); display.println(F(" C"));
    display.setCursor(0, 35);
    display.print(F("Lembap: ")); display.print(h); display.println(F(" %"));
    display.setCursor(0, 50);
    display.println(F("STATUS: AMAN"));
  }
  display.display();
}</textarea>
                    </div>

                    <!-- Serial Monitor / Output Log (5 Cols) -->
                    <div class="lg:col-span-5 bg-slate-950 rounded-xl border border-slate-800 overflow-hidden flex flex-col justify-between">
                        <div class="bg-slate-900 px-4 py-2 border-b border-slate-800 flex justify-between items-center text-xs text-slate-400">
                            <span class="font-mono"><i class="fa-solid fa-desktop text-amber-400"></i> Serial Monitor Output</span>
                            <button onclick="window.clearConsole()" class="text-slate-400 hover:text-white transition text-[11px]">Clear</button>
                        </div>
                        <div id="serial-console" class="p-4 font-mono text-xs text-slate-300 h-[280px] overflow-y-auto space-y-1.5 bg-slate-950/80">
                            <div class="text-emerald-400">[System] Arduino IDE v1.8.19 initialized.</div>
                            <div class="text-cyan-400">[Compiler] Sketch compiled successfully. Sirene Buzzer on Pin 8 configured.</div>
                            <div class="text-slate-400">[Serial] Memantau sensor DHT11 & ambang batas sirene 45°C...</div>
                        </div>
                        <div class="p-3 bg-slate-900 border-t border-slate-800 flex gap-2">
                            <input type="text" id="serial-input" placeholder="Ketik perintah serial..." class="bg-slate-950 border border-slate-700 rounded-lg px-3 py-1.5 text-xs text-white w-full font-mono focus:outline-none focus:border-cyan-500">
                            <button onclick="window.sendSerialData()" class="bg-cyan-600 hover:bg-cyan-500 text-white px-4 py-1.5 rounded-lg text-xs font-semibold transition shrink-0">Kirim</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <div id="view-materi" class="hidden space-y-6">
            <div class="glass-panel rounded-2xl p-6 space-y-4">
                <div class="border-b border-slate-800 pb-4">
                    <h2 class="text-xl font-bold text-white flex items-center gap-2">
                        <i class="fa-solid fa-book-open text-cyan-400"></i> Materi Pembelajaran: Logika Percabangan & Efek Sirene
                    </h2>
                    <p class="text-xs text-slate-400 mt-1">Panduan pemrograman mikrokontroler untuk menciptakan modul suara sirene darurat berbasis perubahan frekuensi.</p>
                </div>
                <div class="grid grid-cols-1 md:grid-cols-3 gap-6 pt-2">
                    <div class="bg-slate-900/80 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="w-10 h-10 rounded-lg bg-cyan-500/10 text-cyan-400 flex items-center justify-center font-bold text-lg">1</div>
                        <h3 class="font-bold text-slate-200 text-sm">Percabangan If-Else</h3>
                        <p class="text-xs text-slate-400 leading-relaxed">
                            Digunakan untuk menguji kondisi variabel suhu. Jika <code class="text-cyan-400">t >= 45.0</code>, jalankan fungsi sirene darurat; jika tidak, matikan suara.
                        </p>
                    </div>
                    <div class="bg-slate-900/80 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="w-10 h-10 rounded-lg bg-purple-500/10 text-purple-400 flex items-center justify-center font-bold text-lg">2</div>
                        <h3 class="font-bold text-slate-200 text-sm">Fungsi tone() & sweep frekuensi</h3>
                        <p class="text-xs text-slate-400 leading-relaxed">
                            Mengubah frekuensi suara buzzer secara bertahap dari rendah ke tinggi lalu kembali lagi untuk menciptakan efek suara naik turun khas sirene (Wail).
                        </p>
                    </div>
                    <div class="bg-slate-900/80 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="w-10 h-10 rounded-lg bg-rose-500/10 text-rose-400 flex items-center justify-center font-bold text-lg">3</div>
                        <h3 class="font-bold text-slate-200 text-sm">Sistem Peringatan Dini</h3>
                        <p class="text-xs text-slate-400 leading-relaxed">
                            Sangat penting dalam penerapan IoT industri untuk memberikan perhatian segera kepada operator ketika terjadi overheat.
                        </p>
                    </div>
                </div>
            </div>
        </div>

        <div id="view-evaluasi" class="hidden space-y-6">
            <div class="glass-panel rounded-2xl p-6 space-y-6 max-w-4xl mx-auto">
                <div class="border-b border-slate-800 pb-4 flex justify-between items-center">
                    <div>
                        <h2 class="text-xl font-bold text-white flex items-center gap-2">
                            <i class="fa-solid fa-graduation-cap text-emerald-400"></i> Kuis Evaluasi Sistem Sirene Suhu
                        </h2>
                        <p class="text-xs text-slate-400 mt-1">Jawab 5 pertanyaan pilihan ganda berikut untuk menguji pemahaman Anda.</p>
                    </div>
                    <span class="text-xs bg-emerald-500/20 text-emerald-400 px-3 py-1 rounded-full border border-emerald-500/30 font-semibold">5 Soal Pilihan Ganda</span>
                </div>

                <div id="quiz-container" class="space-y-6">
                    <!-- Soal 1 -->
                    <div class="bg-slate-900/90 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="text-xs font-bold text-cyan-400">Pertanyaan 1 dari 5</div>
                        <p class="text-sm font-semibold text-slate-200">Struktur kontrol apa yang paling tepat digunakan untuk memicu sirene saat suhu mencapai 45°C?</p>
                        <div class="space-y-2 pt-1">
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q1" value="A" class="accent-cyan-500"> <span>A. Perulangan for loop</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q1" value="B" class="accent-cyan-500"> <span data-correct="true">B. Percabangan if (t >= 45.0) else</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q1" value="C" class="accent-cyan-500"> <span>C. Array multi-dimensi</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q1" value="D" class="accent-cyan-500"> <span>D. Deklarasi library SPI</span>
                            </label>
                        </div>
                    </div>

                    <!-- Soal 2 -->
                    <div class="bg-slate-900/90 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="text-xs font-bold text-cyan-400">Pertanyaan 2 dari 5</div>
                        <p class="text-sm font-semibold text-slate-200">Bagaimana cara menciptakan efek suara naik-turun (sirene) pada buzzer Arduino?</p>
                        <div class="space-y-2 pt-1">
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q2" value="A" class="accent-cyan-500"> <span>A. Menggunakan perintah digitalWrite(PIN, HIGH) terus-menerus</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q2" value="B" class="accent-cyan-500"> <span data-correct="true">B. Mengubah nilai frekuensi secara bertahap menggunakan perulangan pada fungsi tone()</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q2" value="C" class="accent-cyan-500"> <span>C. Membaca sensor analog dengan analogRead()</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q2" value="D" class="accent-cyan-500"> <span>D. Mengosongkan memori SRAM Arduino</span>
                            </label>
                        </div>
                    </div>

                    <!-- Soal 3 -->
                    <div class="bg-slate-900/90 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="text-xs font-bold text-cyan-400">Pertanyaan 3 dari 5</div>
                        <p class="text-sm font-semibold text-slate-200">Mode pin apa yang harus diset di dalam fungsi <code class="text-cyan-400">setup()</code> untuk pin yang terhubung ke Buzzer?</p>
                        <div class="space-y-2 pt-1">
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q3" value="A" class="accent-cyan-500"> <span>A. INPUT</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q3" value="B" class="accent-cyan-500"> <span data-correct="true">B. OUTPUT</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q3" value="C" class="accent-cyan-500"> <span>C. INPUT_PULLUP</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q3" value="D" class="accent-cyan-500"> <span>D. ANALOG_OUT</span>
                            </label>
                        </div>
                    </div>

                    <!-- Soal 4 -->
                    <div class="bg-slate-900/90 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="text-xs font-bold text-cyan-400">Pertanyaan 4 dari 5</div>
                        <p class="text-sm font-semibold text-slate-200">Apa tujuan utama dari fitur peringatan sirene panas berlebih pada sistem IoT?</p>
                        <div class="space-y-2 pt-1">
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q4" value="A" class="accent-cyan-500"> <span>A. Mempercepat proses kompilasi kode</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q4" value="B" class="accent-cyan-500"> <span data-correct="true">B. Memberikan perhatian audio yang jelas dan respons cepat (early warning) terhadap potensi bahaya overheat</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q4" value="C" class="accent-cyan-500"> <span>C. Mengurangi konsumsi daya baterai secara drastis</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q4" value="D" class="accent-cyan-500"> <span>D. Menghentikan total aliran listrik utama</span>
                            </label>
                        </div>
                    </div>

                    <!-- Soal 5 -->
                    <div class="bg-slate-900/90 p-5 rounded-xl border border-slate-800 space-y-3">
                        <div class="text-xs font-bold text-cyan-400">Pertanyaan 5 dari 5</div>
                        <p class="text-sm font-semibold text-slate-200">Jika suhu terukur bernilai tepat 45.0°C, apakah sirene akan berbunyi berdasarkan kode program di atas?</p>
                        <div class="space-y-2 pt-1">
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q5" value="A" class="accent-cyan-500"> <span>A. Tidak, karena harus lebih dari 45.0°C (> 45)</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q5" value="B" class="accent-cyan-500"> <span data-correct="true">B. Ya, karena menggunakan operator lebih besar atau sama dengan (>= 45.0)</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q5" value="C" class="accent-cyan-500"> <span>C. Hanya jika kelembapan di bawah 30%</span>
                            </label>
                            <label class="flex items-center gap-3 p-2.5 rounded-lg bg-slate-950/60 border border-slate-800 hover:border-slate-700 cursor-pointer text-xs transition">
                                <input type="radio" name="q5" value="D" class="accent-cyan-500"> <span>D. Tergantung pada tombol Serial Monitor</span>
                            </label>
                        </div>
                    </div>
                </div>

                <div class="pt-2 text-center">
                    <button onclick="window.submitQuiz()" class="px-8 py-3 bg-emerald-600 hover:bg-emerald-500 text-white font-bold text-sm rounded-xl shadow-lg shadow-emerald-900/40 transition">
                        <i class="fa-solid fa-check-double mr-2"></i> Periksa Jawaban Kuis
                    </button>
                </div>
            </div>
        </div>

    </main>

    <footer class="border-t border-slate-800/80 bg-slate-900/40 py-4 px-4 text-center text-xs text-slate-500 flex flex-col md:flex-row items-center justify-between max-w-7xl mx-auto w-full gap-2">
        <div>© Simulasi Sensor DHT11 & OLED v3.2 • Media Pembelajaran Interaktif Informatika</div>
        <div class="flex items-center gap-4 text-slate-400 font-medium">
            <span>IoT & Embedded Systems Lab</span>
            <span>•</span>
            <span class="hover:text-cyan-400 cursor-pointer transition" onclick="window.alertBox('Simulasi ini telah dilengkapi efek suara sirene darurat (naik-turun frekuensi) ketika suhu mencapai ambang batas (≥ 45°C).')">Tentang Fitur Sirene</span>
        </div>
    </footer>

    <script>
        let currentTemp = 28.0;
        let currentHum = 65;

        window.switchTab = function(tabId) {
            const tabs = ['simulator', 'terminal', 'materi', 'evaluasi'];
            tabs.forEach(t => {
                const el = document.getElementById('view-' + t);
                const btn = document.getElementById('nav-' + t);
                if (t === tabId) {
                    el.classList.remove('hidden');
                    btn.className = 'px-3 py-1.5 rounded-lg bg-cyan-600 text-white font-medium flex items-center gap-2 shadow-md shadow-cyan-900/40 transition';
                } else {
                    el.classList.add('hidden');
                    btn.className = 'px-3 py-1.5 rounded-lg bg-slate-800 text-slate-300 hover:bg-slate-700 font-medium flex items-center gap-2 transition';
                }
            });
        };

        window.alertBox = function(message) {
            const modal = document.createElement('div');
            modal.className = 'fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm p-4';
            modal.innerHTML = `
                <div class="glass-panel max-w-sm w-full p-6 rounded-2xl border border-slate-700 space-y-4 text-center shadow-2xl pop-animation">
                    <div class="w-12 h-12 rounded-full bg-cyan-500/20 text-cyan-400 flex items-center justify-center mx-auto text-xl">
                        <i class="fa-solid fa-circle-info"></i>
                    </div>
                    <div class="text-sm font-semibold text-slate-200">${message}</div>
                    <button onclick="this.closest('.fixed').remove()" class="w-full py-2.5 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold text-xs rounded-xl transition">
                        Mengerti
                    </button>
                </div>
            `;
            document.body.appendChild(modal);
        };

        // Update Environment Temperature & Humidity and Siren State
        window.updateEnvironment = function(temp, hum) {
            currentTemp = parseFloat(temp);
            currentHum = parseInt(hum);

            document.getElementById('temp-slider').value = currentTemp;
            document.getElementById('hum-slider').value = currentHum;
            document.getElementById('temp-display').textContent = currentTemp.toFixed(1) + '°C';
            document.getElementById('hum-display').textContent = currentHum + '%';
            document.getElementById('temp-status-display').textContent = currentTemp.toFixed(1) + '°C';
            document.getElementById('hum-status-display').textContent = currentHum + '% RH';
            document.getElementById('val-temp').textContent = currentTemp.toFixed(1) + '°C';

            const bannerEl = document.getElementById('banner-container');
            const statusPill = document.getElementById('system-status-pill');
            const circuitDot = document.getElementById('circuit-dot');
            const badgeBuzzer = document.getElementById('badge-buzzer-status');
            const badgeOled = document.getElementById('badge-oled-status');
            const oledSvgTemp = document.getElementById('oled-svg-temp');
            const oledSvgHum = document.getElementById('oled-svg-hum');
            const oledSvgStatus = document.getElementById('oled-svg-status');
            const buzzerWave1 = document.getElementById('buzzer-wave-1');
            const buzzerWave2 = document.getElementById('buzzer-wave-2');
            const explanationBox = document.getElementById('explanation-box');
            const explanationTitle = document.getElementById('explanation-title');
            const explanationText = document.getElementById('informatics-explanation');

            if (oledSvgTemp) oledSvgTemp.textContent = currentTemp.toFixed(1) + '°C';
            if (oledSvgHum) oledSvgHum.textContent = currentHum + '%';

            // Check if temperature exceeds 45°C threshold
            if (currentTemp >= 45.0) {
                // SIRENE STATE ACTIVE
                bannerEl.className = 'glass-panel rounded-2xl p-4 md:p-5 flex flex-col md:flex-row justify-between items-start md:items-center gap-4 transition-all duration-300 alert-active bg-rose-950/40 border-rose-500/50';
                statusPill.className = 'flex items-center gap-2 text-rose-400 text-xs font-semibold mb-1';
                statusPill.innerHTML = '<i class="fa-solid fa-triangle-exclamation text-[10px] animate-bounce"></i> PERINGATAN: Suhu Mencapai Ambang Batas Sirene!';
               
                circuitDot.className = 'w-2.5 h-2.5 rounded-full bg-rose-500 animate-ping';
                badgeBuzzer.className = 'text-sm font-bold text-rose-400 mt-0.5 animate-pulse';
                badgeBuzzer.textContent = 'SIRENE AKTIF!';
                badgeOled.className = 'text-sm font-bold text-rose-400 mt-0.5';
                badgeOled.textContent = 'Waspada Panas';

                if (oledSvgStatus) {
                    oledSvgStatus.textContent = 'BAHAYA OVERHEAT';
                    oledSvgStatus.setAttribute('fill', '#f43f5e');
                }

                if (buzzerWave1) buzzerWave1.setAttribute('opacity', '1');
                if (buzzerWave2) buzzerWave2.setAttribute('opacity', '1');

                // Trigger Web Audio API Siren Sound Effect
                window.playSirenSound();

                explanationBox.className = 'glass-panel rounded-2xl p-5 space-y-2 border-l-4 border-l-rose-500 transition-all duration-300';
                explanationTitle.className = 'text-xs font-bold text-rose-400 flex items-center gap-1.5';
                explanationTitle.innerHTML = '<i class="fa-solid fa-triangle-exclamation"></i> STATUS SIRENE AKTIF (SUHU ≥ 45°C):';
                explanationText.innerHTML = `Suhu terukur saat ini adalah <b>${currentTemp.toFixed(1)}°C</b>. Karena bernilai ≥ 45°C, kondisi percabangan <code class="text-rose-400">if (t >= 45.0)</code> terpenuhi: Buzzer memainkan efek suara sirene naik-turun (Wail Siren) dan layar OLED menampilkan peringatan <b>WASPADA PANAS BERLEBIH!</b>`;

            } else {
                // NORMAL STATE
                bannerEl.className = 'glass-panel rounded-2xl p-4 md:p-5 flex flex-col md:flex-row justify-between items-start md:items-center gap-4 transition-all duration-300';
                statusPill.className = 'flex items-center gap-2 text-cyan-400 text-xs font-semibold mb-1';
                statusPill.innerHTML = '<i class="fa-solid fa-circle text-[8px] animate-pulse"></i> Sistem Normal: Memantau Suhu Lingkungan';

                circuitDot.className = 'w-2.5 h-2.5 rounded-full bg-cyan-500 animate-pulse';
                badgeBuzzer.className = 'text-sm font-bold text-slate-400 mt-0.5';
                badgeBuzzer.textContent = 'OFF (Aman)';
                badgeOled.className = 'text-sm font-bold text-emerald-400 mt-0.5';
                badgeOled.textContent = 'Normal';

                if (oledSvgStatus) {
                    oledSvgStatus.textContent = 'STATUS: AMAN';
                    oledSvgStatus.setAttribute('fill', '#10b981');
                }

                if (buzzerWave1) buzzerWave1.setAttribute('opacity', '0');
                if (buzzerWave2) buzzerWave2.setAttribute('opacity', '0');

                // Stop siren sound loop
                window.stopSirenSound();

                explanationBox.className = 'glass-panel rounded-2xl p-5 space-y-2 border-l-4 border-l-cyan-500 transition-all duration-300';
                explanationTitle.className = 'text-xs font-bold text-cyan-400 flex items-center gap-1.5';
                explanationTitle.innerHTML = '<i class="fa-solid fa-circle-info"></i> LOGIKA PERCABANGAN (IF-ELSE):';
                explanationText.innerHTML = `Suhu terukur <b>${currentTemp.toFixed(1)}°C</b> (< 45°C). Mikrokontroler menjaga Buzzer tetap OFF dan menampilkan status AMAN pada layar OLED. Geser slider suhu ke 45°C atau lebih untuk menguji sirene.`;
            }
        };

        // Web Audio API for Realistic Siren Sound Synthesis (Up and Down Frequency Sweep)
        let audioCtx = null;
        let sirenOscillator = null;
        let sirenGain = null;
        let sirenSweepInterval = null;

        window.playSirenSound = function() {
            if (sirenOscillator) return; // Already playing siren loop

            try {
                if (!audioCtx) {
                    audioCtx = new (window.AudioContext || window.webkitAudioContext)();
                }
                if (audioCtx.state === 'suspended') {
                    audioCtx.resume();
                }

                sirenOscillator = audioCtx.createOscillator();
                sirenGain = audioCtx.createGain();

                sirenOscillator.type = 'sawtooth'; // Sawtooth gives a rich buzzer/siren harmonic tone
                sirenOscillator.frequency.setValueAtTime(800, audioCtx.currentTime);
                sirenGain.gain.setValueAtTime(0.12, audioCtx.currentTime);

                sirenOscillator.connect(sirenGain);
                sirenGain.connect(audioCtx.destination);
                sirenOscillator.start();

                // Sweep frequency up and down continuously (Emergency Siren Wail)
                let goingUp = true;
                let currentFreq = 800;

                sirenSweepInterval = setInterval(() => {
                    if (!audioCtx || currentTemp < 45.0) {
                        window.stopSirenSound();
                        return;
                    }
                    if (goingUp) {
                        currentFreq += 120;
                        if (currentFreq >= 2400) goingUp = false;
                    } else {
                        currentFreq -= 120;
                        if (currentFreq <= 800) goingUp = true;
                    }
                    try {
                        sirenOscillator.frequency.setTargetAtTime(currentFreq, audioCtx.currentTime, 0.05);
                    } catch (e) {
                        console.error(e);
                    }
                }, 80);

            } catch (err) {
                console.log("Web Audio API not allowed or blocked by browser policy until user interaction.", err);
            }
        };

        window.stopSirenSound = function() {
            if (sirenSweepInterval) {
                clearInterval(sirenSweepInterval);
                sirenSweepInterval = null;
            }
            if (sirenOscillator) {
                try {
                    sirenOscillator.stop();
                    sirenOscillator.disconnect();
                } catch (e) {}
                sirenOscillator = null;
            }
            sirenGain = null;
        };

        window.runArduinoCode = function() {
            const consoleEl = document.getElementById('serial-console');
            consoleEl.innerHTML += `<div class="text-cyan-400">[Compiler] Uploading sketch & siren logic...</div>`;
            consoleEl.scrollTop = consoleEl.scrollHeight;

            setTimeout(() => {
                consoleEl.innerHTML += `<div class="text-emerald-400">[Success] Upload complete! Pin 8 (Sirene Buzzer) & OLED ready.</div>`;
                consoleEl.scrollTop = consoleEl.scrollHeight;

                if (currentTemp >= 45.0) {
                    setTimeout(() => { logSerial(`SIRENE AKTIF! Suhu Panas Berlebih: ${currentTemp.toFixed(1)}°C`); }, 800);
                } else {
                    setTimeout(() => { logSerial(`Suhu: ${currentTemp.toFixed(1)}°C | Kelembapan: ${currentHum}%`); }, 800);
                }
            }, 800);
        };

        function logSerial(msg) {
            const consoleEl = document.getElementById('serial-console');
            const colorClass = msg.includes('SIRENE') ? 'text-rose-400 font-bold' : 'text-slate-300';
            consoleEl.innerHTML += `<div class="${colorClass}">[Serial] ${msg}</div>`;
            consoleEl.scrollTop = consoleEl.scrollHeight;
        }

        window.clearConsole = function() {
            document.getElementById('serial-console').innerHTML = `<div class="text-emerald-400">[System] Serial monitor cleared.</div>`;
        };

        window.sendSerialData = function() {
            const val = document.getElementById('serial-input').value;
            if (val.trim() !== '') {
                logSerial(`Command sent: ${val}`);
                document.getElementById('serial-input').value = '';
            }
        };

        window.submitQuiz = function() {
            let score = 0;
            const totalQuestions = 5;

            for (let i = 1; i <= totalQuestions; i++) {
                const selected = document.querySelector(`input[name="q${i}"]:checked`);
                if (selected) {
                    const parentLabel = selected.closest('label');
                    const spanCorrect = parentLabel.querySelector('[data-correct="true"]');
                    if (spanCorrect) {
                        score += 20;
                    }
                }
            }

            const modal = document.createElement('div');
            modal.className = 'fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-md p-4';
           
            let badgeColor = score >= 80 ? 'text-emerald-400 bg-emerald-500/10 border-emerald-500/30' : (score >= 60 ? 'text-amber-400 bg-amber-500/10 border-amber-500/30' : 'text-rose-400 bg-rose-500/10 border-rose-500/30');
            let feedbackText = score >= 80 ? 'Luar Biasa! Pemahaman logika percabangan sirene suhu Anda sangat baik.' : (score >= 60 ? 'Bagus! Terus tingkatkan pemahaman pemrograman embedded systems.' : 'Belajar lagi yuk! Cek menu Materi Teori.');

            modal.innerHTML = `
                <div class="glass-panel max-w-md w-full p-8 rounded-3xl border border-slate-700 space-y-6 text-center shadow-2xl pop-animation">
                    <div class="w-16 h-16 rounded-2xl bg-cyan-500/20 text-cyan-400 flex items-center justify-center mx-auto text-3xl shadow-inner">
                        <i class="fa-solid fa-award"></i>
                    </div>
                    <div>
                        <div class="text-xs font-bold uppercase tracking-wider text-slate-400">Hasil Evaluasi Kuis</div>
                        <h3 class="text-2xl font-bold text-white mt-1">Skor Akhir Anda</h3>
                    </div>
                    <div class="inline-block px-6 py-3 rounded-2xl border text-5xl font-black font-mono tracking-wider ${badgeColor} transition-transform transform hover:scale-105 duration-300">
                        ${score} <span class="text-xl font-normal opacity-70">/ 100</span>
                    </div>
                    <p class="text-xs text-slate-300 leading-relaxed max-w-xs mx-auto">
                        ${feedbackText}
                    </p>
                    <button onclick="this.closest('.fixed').remove()" class="w-full py-3 bg-cyan-600 hover:bg-cyan-500 text-white font-bold text-xs rounded-xl transition shadow-lg shadow-cyan-900/40">
                        Tutup & Kembali Belajar
                    </button>
                </div>
            `;
            document.body.appendChild(modal);
        };
    </script>
</body>
</html>

Post a Comment

0 Comments