Last active
April 13, 2026 14:10
-
-
Save ardzz/7cec74d76e8aed543c28ac375f36611d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ | |
| IoT Quiz Auto-Answer via Chrome DevTools Protocol (CDP) | |
| Prerequisite: | |
| pip install websockets | |
| Usage: | |
| 1. Launch Edge/Chrome with remote debugging enabled: | |
| microsoft-edge-stable --remote-debugging-port=9222 | |
| 2. Open the Google Forms quiz in that browser | |
| 3. Run this script: | |
| python quiz_apatuh.py | |
| The script auto-discovers the correct tab via CDP and fills all 50 answers. | |
| """ | |
| import json, asyncio, sys | |
| try: | |
| import websockets | |
| except ImportError: | |
| print("Missing dependency. Install with: pip install websockets") | |
| sys.exit(1) | |
| CDP_HOST = "localhost" | |
| CDP_PORT = 9222 | |
| SCRIPT = """ | |
| (async () => { | |
| const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); | |
| const ANSWERS = [ | |
| ["Apa definisi terbaik dari IoT", "Penggunaan internet untuk menghubungkan benda-benda agar bisa dimonitor dari jauh"], | |
| ["yang bukan merupakan bagian dari aspek device", "Aplikasi Android"], | |
| ["yang bukan merupakan contoh dari aspek network", "MBG"], | |
| ["Contoh implementasi IoT", "Monitoring tempat sampah jarak jauh menggunakan Wi-Fi"], | |
| ["yang bukan termasuk contoh aplikasi IoT", "Aplikasi akuntansi perusahaan"], | |
| ["Yang bukan merupakan contoh platform IoT", "Google Drive"], | |
| ["fase revolusi industri kedua", "Salah"], | |
| ["istilah yang maknanya mirip dengan IoT", "Denial of Service"], | |
| ["kota cerdas (smart city), kecuali", "Smart money"], | |
| ["Penggunaan CCTV dalam IoT", "Semua benar"], | |
| ["Fungsi sensor dalam IoT adalah", "Menangkap fenomena alam dan mengubah jadi sinyal listrik"], | |
| ["Sensor suhu yang sering digunakan di IoT", "DHT11"], | |
| ["fungsi utama dari cloud dalam sistem IoT", "Menyimpan dan memproses data"], | |
| ["perangkat yang berfungsi sebagai sensor dalam sistem IoT", "DHT22"], | |
| ["yang termasuk aktuator adalah", "Servo motor"], | |
| ["untuk mendeteksi gerakan adalah", "PIR sensor"], | |
| ["untuk mengukur jarak dalam IoT", "Ultrasonic sensor"], | |
| ["Fungsi utama relay dalam sistem IoT", "Mengontrol perangkat listrik"], | |
| ["termasuk Low Power Wide Area Network", "LoRa"], | |
| ["Keunggulan utama LoRaWAN", "Jangkauan luas dan hemat energi"], | |
| ["yang cocok untuk jarak dekat adalah", "Bluetooth"], | |
| ["topologi jaringan yang umum digunakan", "Star"], | |
| ["NB-IoT termasuk dalam kategori jaringan", "LPWAN berbasis seluler"], | |
| ["konektivitas IoT dengan jarak pendek (short range)", "Palmboom"], | |
| ["paling cocok untuk smart home dengan konsumsi daya rendah", "Zigbee"], | |
| ["Konsumsi daya WiFi lebih boros daripada Bluetooth", "Benar"], | |
| ["komunikasi jarak jauh dengan konsumsi daya rendah", "LoRaWAN"], | |
| ["penghubung antara jaringan lokal IoT dan internet", "Gateway"], | |
| ["microcontroller ESP32, terdapat modul komunikasi", "WiFi"], | |
| ["menjangkau tengah hutan dan tengah laut", "Satelit"], | |
| ["Pernyataan yang salah menurut anda", "Konektivitas IoT yang cocok untuk lokasi tanpa catu daya adalah 4G"], | |
| ["Pernyataan yang benar menurut anda", "IoT akan meningkatkan produktivitas perusahaan"], | |
| ["Layanan IoT pada cloud umumnya berfungsi", "Mengelola device IoT"], | |
| ["Protokol yang umum digunakan untuk komunikasi IoT", "MQTT"], | |
| ["melihat daftar file dalam direktori", "ls"], | |
| ["bisa menghapus seluruh isi direktori", "rm -rf"], | |
| ["fungsi utama platform adalah", "Menghubungkan, menyimpan, dan memproses data"], | |
| ["Fungsi utama dari setup() dalam program Arduino", "Menjalankan kode sekali saat pertama kali program dijalankan"], | |
| ["Apa yang terjadi pada LED", "LED menyala terus"], | |
| ["bukan termasuk perintah loop dalam bahasa C", "if"], | |
| ["Port default untuk SSH adalah", "22"], | |
| ["Format data yang paling umum digunakan dalam API IoT", "JSON"], | |
| ["menampilkan data suhu dari sensor secara real-time", "User Interface"], | |
| ["Week 3 - Internet of Things", "Java"], | |
| ["Week 5 - Internet of Things", "Node-Red"], | |
| ["Week 7 - Internet of Things", "Classes & Members"], | |
| ["Week 2 - Internet of Things", "Sigfox"], | |
| ["Apa perbedaan LoRa dan NB-IoT", "LoRaWAN merupakan konektivitas tanpa lisensi, NB-IoT menggunakan lisensi operator"], | |
| ["Fungsi utama dari gateway dalam sistem IoT", "Menghubungkan perangkat IoT ke jaringan/cloud"], | |
| ["D-N-P-A dalam value chain IoT", "Device - Network - Platform - Application"], | |
| ]; | |
| const headings = document.querySelectorAll('div[role="heading"][aria-level="3"]'); | |
| let clicked = 0; | |
| let correct = 0; | |
| let corrected = 0; | |
| let skipped = 0; | |
| const log = []; | |
| for (let i = 0; i < ANSWERS.length; i++) { | |
| const [questionText, answer] = ANSWERS[i]; | |
| const qNum = i + 1; | |
| let questionBlock = null; | |
| for (const h of headings) { | |
| if (h.textContent.includes(questionText)) { | |
| questionBlock = h.closest('.geS5n'); | |
| break; | |
| } | |
| } | |
| if (!questionBlock) { | |
| skipped++; | |
| log.push('Q' + qNum + ': SKIP - heading not found'); | |
| await sleep(1000); | |
| continue; | |
| } | |
| const radios = questionBlock.querySelectorAll('div[role="radio"]'); | |
| let targetRadio = null; | |
| let currentChecked = null; | |
| for (const radio of radios) { | |
| if (radio.getAttribute('data-value') === answer) { | |
| targetRadio = radio; | |
| } | |
| if (radio.getAttribute('aria-checked') === 'true') { | |
| currentChecked = radio.getAttribute('data-value'); | |
| } | |
| } | |
| if (!targetRadio) { | |
| skipped++; | |
| log.push('Q' + qNum + ': FAIL - radio not found'); | |
| await sleep(1000); | |
| continue; | |
| } | |
| if (targetRadio.getAttribute('aria-checked') === 'true') { | |
| correct++; | |
| log.push('Q' + qNum + ': OK (already correct)'); | |
| await sleep(1000); | |
| continue; | |
| } | |
| if (currentChecked) { | |
| log.push('Q' + qNum + ': CORRECTING "' + currentChecked.substring(0, 30) + '" -> "' + answer.substring(0, 30) + '"'); | |
| corrected++; | |
| } else { | |
| log.push('Q' + qNum + ': CLICKED - ' + answer.substring(0, 50)); | |
| } | |
| targetRadio.click(); | |
| clicked++; | |
| await sleep(1000); | |
| } | |
| return JSON.stringify({ clicked, correct, corrected, skipped, log }); | |
| })() | |
| """ | |
| async def discover_ws_url(): | |
| from urllib.request import urlopen | |
| url = f"http://{CDP_HOST}:{CDP_PORT}/json" | |
| try: | |
| resp = urlopen(url, timeout=5) | |
| tabs = json.loads(resp.read()) | |
| except Exception as e: | |
| print(f"Cannot connect to CDP at {url}") | |
| print( | |
| f"Make sure the browser is running with: --remote-debugging-port={CDP_PORT}" | |
| ) | |
| print(f"Error: {e}") | |
| sys.exit(1) | |
| forms_tabs = [t for t in tabs if "docs.google.com/forms" in t.get("url", "")] | |
| if forms_tabs: | |
| ws = forms_tabs[0]["webSocketDebuggerUrl"] | |
| print(f"Found Google Forms tab: {forms_tabs[0]['title']}") | |
| return ws | |
| page_tabs = [t for t in tabs if t.get("type") == "page"] | |
| if not page_tabs: | |
| print("No open tabs found via CDP.") | |
| sys.exit(1) | |
| print("No Google Forms tab found. Available tabs:") | |
| for i, t in enumerate(page_tabs): | |
| print(f" [{i}] {t['title'][:60]} - {t['url'][:80]}") | |
| choice = input("Select tab number: ").strip() | |
| try: | |
| return page_tabs[int(choice)]["webSocketDebuggerUrl"] | |
| except (ValueError, IndexError): | |
| print("Invalid selection.") | |
| sys.exit(1) | |
| async def run(): | |
| ws_url = await discover_ws_url() | |
| print(f"Connecting to: {ws_url}\n") | |
| async with websockets.connect(ws_url, max_size=10 * 1024 * 1024) as ws: | |
| cmd = { | |
| "id": 1, | |
| "method": "Runtime.evaluate", | |
| "params": { | |
| "expression": SCRIPT, | |
| "awaitPromise": True, | |
| "returnByValue": True, | |
| }, | |
| } | |
| await ws.send(json.dumps(cmd)) | |
| resp = json.loads(await ws.recv()) | |
| result_val = resp.get("result", {}).get("result", {}) | |
| if "value" not in result_val: | |
| print("Script execution failed:") | |
| print(json.dumps(resp, indent=2)) | |
| sys.exit(1) | |
| data = json.loads(result_val["value"]) | |
| print( | |
| f"Clicked: {data['clicked']} | Already correct: {data['correct']} | Corrected: {data['corrected']} | Skipped: {data['skipped']}" | |
| ) | |
| print() | |
| for line in data["log"]: | |
| print(line) | |
| asyncio.run(run()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment