Selasa, 25 November 2025

Bank Soal 600 Soal

import React, { useState, useEffect, useRef } from 'react'; import { ArrowRight, ArrowLeft, Thermometer, PieChart, Divide, Box, Triangle, BarChart2, CheckCircle, XCircle, Calculator, Brain, Lock, Unlock, Key, HelpCircle, List, Edit3, Link, CheckSquare, FileText, ChevronRight, Home, User, Award, Star, TrendingUp, Filter, RefreshCw } from 'lucide-react'; // --- KONFIGURASI --- const TEACHER_PIN = "1234"; const TOTAL_QUESTIONS_PER_CHAPTER = 100; // --- UTILS --- const playSound = (type) => { try { const ctx = new (window.AudioContext || window.webkitAudioContext)(); const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.connect(gain); gain.connect(ctx.destination); const now = ctx.currentTime; if (type==='correct' || type==='step_success') { osc.type='sine'; osc.frequency.setValueAtTime(600, now); osc.frequency.exponentialRampToValueAtTime(1000, now+0.1); gain.gain.setValueAtTime(0.3, now); gain.gain.linearRampToValueAtTime(0, now+0.5); } else if (type==='wrong') { osc.type='sawtooth'; osc.frequency.setValueAtTime(300, now); gain.gain.setValueAtTime(0.3, now); gain.gain.linearRampToValueAtTime(0, now+0.5); } else { osc.type='triangle'; osc.frequency.setValueAtTime(800, now); gain.gain.setValueAtTime(0.05, now); gain.gain.exponentialRampToValueAtTime(0.01, now+0.1); } osc.start(now); osc.stop(now+0.5); } catch(e){} }; // --- DATA BAB --- const CHAPTERS = [ { id: 'bab1', title: 'Bilangan Bulat', icon: Thermometer, color: 'bg-blue-600' }, { id: 'bab2', title: 'Bilangan Rasional', icon: PieChart, color: 'bg-pink-600' }, { id: 'bab3', title: 'Rasio & Proporsi', icon: Divide, color: 'bg-purple-600' }, { id: 'bab4', title: 'Bentuk Aljabar', icon: Box, color: 'bg-orange-600' }, { id: 'bab5', title: 'Kesebangunan', icon: Triangle, color: 'bg-emerald-600' }, { id: 'bab6', title: 'Data & Diagram', icon: BarChart2, color: 'bg-cyan-600' }, ]; // --- GENERATOR SOAL CERDAS (600 VARIASI) --- const generateQuestion = (chapterId, questionNumber) => { const r = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min; const names = ["Budi", "Siti", "Eko", "Ayu", "Dian"]; // Tentukan Tipe let type = 'pg'; if (questionNumber > 30) type = 'complex'; if (questionNumber > 50) type = 'input'; // Simplifikasi tipe untuk demo ini if (questionNumber > 80) type = 'pg'; let q = { id: questionNumber, type, text: "", ans: "", options: [], steps: [] }; // --- LOGIKA SOAL PER BAB --- if (chapterId === 'bab1') { // BILANGAN BULAT if (type === 'pg') { const a = r(-20,20), b = r(-20,20), c = r(-10,10); q.text = `Hasil dari ${a} - (${b}) + ${c} adalah...`; q.ans = a - b + c; q.options = [q.ans, q.ans+2, q.ans-2, -q.ans].sort(()=>Math.random()-.5); q.steps = [{instruction:`Langkah 1: Hitung ${a} - (${b}) = ...`, answer: a-b, type:'input'}, {instruction:`Langkah 2: Hasil tadi ditambah ${c} = ...`, answer:q.ans, type:'input'}]; } else if (type === 'input') { const t1 = r(20,35), t2 = r(5,15); q.text = `Suhu kamar ${t1}°C, suhu kulkas -${t2}°C. Selisihnya?`; q.ans = t1 - (-t2); q.steps = [{instruction:`Selisih = Besar - Kecil. ${t1} - (-${t2}) = ...`, answer: q.ans, type:'input'}]; } else { q.text = "Pernyataan yang BENAR tentang bilangan bulat? (Bisa >1)"; q.ans = ["-5 < 2"]; q.options = ["-5 < 2", "-10 > -2", "0 adalah bilangan positif", "-1 > 0"]; q.steps = ["Cek garis bilangan. Positif selalu lebih besar dari negatif."]; q.type = 'complex'; } } else if (chapterId === 'bab2') { // RASIONAL if (type === 'pg') { const n=1, d=r(2,5); q.text = `Bentuk persen dari ${n}/${d} adalah...`; q.ans = (n/d)*100 + "%"; q.options = [q.ans, ((n/d)*100+10)+"%", "50%", "25%"].sort(()=>Math.random()-.5); q.steps = [{instruction:`${n}/${d} x 100 = ...`, answer: (n/d)*100, type:'input'}]; } else { const a=0.5, b=0.25; q.text = `Hitung ${a} + ${b}`; q.ans = 0.75; q.type='input'; q.steps = [{instruction:`0.5 + 0.25 =`, answer: 0.75, type:'input'}]; } } else if (chapterId === 'bab3') { // RASIO if (type === 'pg') { const p = 5000, n = r(2,5); q.text = `Harga 1 buku Rp ${p}. Harga ${n} buku?`; q.ans = p*n; q.options = [p*n, p*n+2000, p*n-1000, 10000].sort(()=>Math.random()-.5); q.steps = [{instruction:`${p} x ${n} =`, answer:p*n, type:'input'}]; } else { q.text = "Sederhanakan 10:15 (Tulis a:b)"; q.ans = "2:3"; q.type='input'; q.steps = [{instruction:"Bagi kedua angka dengan 5.", answer:"2:3", type:'input'}]; } } else if (chapterId === 'bab4') { // ALJABAR const k = r(2,5); if (type === 'pg') { q.text = `Sederhanakan: ${k}x + 2x`; q.ans = `${k+2}x`; q.options = [`${k+2}x`, `${k}x`, `2x`, `${k*2}x`]; q.steps = [{instruction:`${k} + 2 = ...`, answer: k+2, type:'input'}]; } else { const val = r(2,5); q.text = `Jika x=${val}, nilai 2x+1 adalah...`; q.ans = 2*val+1; q.type='input'; q.steps = [{instruction:`2(${val}) + 1 =`, answer: 2*val+1, type:'input'}]; } } else if (chapterId === 'bab5') { // KESEBANGUNAN if (type === 'pg') { const s = r(2,4); q.text = `Segitiga A alas 5, Segitiga B alas ${5*s}. Jika tinggi A 4, tinggi B?`; q.ans = 4*s; q.options = [4*s, 4, 5*s, 10].sort(()=>Math.random()-.5); q.steps = [{instruction:`Faktor skala: ${5*s}/5 = ${s}. Tinggi = 4 x ${s}`, answer: 4*s, type:'input'}]; } else { q.text = "Syarat segitiga sebangun? (Pilih 2)"; q.type='complex'; q.ans = ["Sudut sama", "Sisi sebanding"]; q.options = ["Sudut sama", "Sisi sebanding", "Luas sama", "Keliling sama"]; q.steps = ["Ingat konsep dasar sebangun."]; } } else { // BAB 6 DATA const d = [r(2,9), r(2,9), r(2,9)]; const sum = d.reduce((a,b)=>a+b,0); q.text = `Rata-rata dari data: ${d.join(', ')}?`; q.ans = (sum/3).toFixed(1); q.type='input'; q.steps = [{instruction:`Jumlah: ${sum}. Bagi 3.`, answer: q.ans, type:'input'}]; } return q; }; // --- COMPONENTS --- const GuidedSolver = ({ question, steps, onComplete }) => { const [currentStep, setCurrentStep] = useState(0); const [inputVal, setInputVal] = useState(""); const [status, setStatus] = useState("idle"); const [history, setHistory] = useState([]); const scrollRef = useRef(null); const rawStep = steps[currentStep]; const step = typeof rawStep === 'string' ? { instruction: rawStep, type: 'info', answer: 'ok' } : rawStep; useEffect(() => { if(scrollRef.current) scrollRef.current.scrollTo({top: scrollRef.current.scrollHeight, behavior:'smooth'}); }, [currentStep, history]); const checkAnswer = (val) => { if (step.type === 'info') { playSound('click'); handleNext(step.instruction, 'Lanjut'); return; } // Improved Validation Logic const cleanVal = String(val).trim().toLowerCase().replace(/\s/g,'').replace(',', '.'); const correctVal = String(step.answer).trim().toLowerCase().replace(/\s/g,'').replace(',', '.'); if (cleanVal == correctVal) { playSound('step_success'); setStatus("correct"); handleNext(step.instruction, val); } else { playSound('wrong'); setStatus("wrong"); } }; const handleNext = (instruction, userAns) => { setHistory([...history, { instruction, userAnswer: userAns }]); setTimeout(() => { if (currentStep < steps.length - 1) { setCurrentStep(currentStep + 1); setInputVal(""); setStatus("idle"); } else { onComplete(); } }, step.type==='info'?300:1000); }; if (currentStep >= steps.length) return

Pembahasan Selesai!

Kamu telah menyelesaikan semua langkah.

; return (

Soal

{question}

{/* HISTORY ITEMS (NOW WITH USER ANSWER VISIBLE) */} {history.map((h, i) => (
{h.instruction}
Jawab: {h.userAnswer}
))} {/* CURRENT STEP CARD */}
{currentStep + 1}
Langkah {currentStep + 1}

{step.instruction}

{status==='wrong' &&
Coba lagi
} {status==='correct' &&
Benar!
}
{/* STICKY INPUT FOOTER */}
{step.type === 'info' ? ( ) : step.type === 'select' ? (
{step.options.map((opt, idx) => ())}
) : (
setInputVal(e.target.value)} placeholder="Ketik jawaban..." className="w-full p-3.5 bg-slate-50 border-2 border-slate-200 rounded-xl focus:border-indigo-500 focus:bg-white outline-none font-bold text-center text-lg text-slate-800 transition-all" onKeyDown={(e) => e.key==='Enter' && checkAnswer(inputVal)} autoFocus/>
)}
); }; const TeacherModal = ({ isOpen, onClose, question, steps }) => { const [pin, setPin] = useState(""); const [isUnlocked, setIsUnlocked] = useState(false); useEffect(() => { if(!isOpen) { setPin(""); setIsUnlocked(false); } }, [isOpen]); const handleUnlock = () => { if (pin === TEACHER_PIN) { setIsUnlocked(true); playSound('correct'); } else { playSound('wrong'); setPin(""); } }; if (!isOpen) return null; return (

{isUnlocked ? : } Pembahasan Guru

{!isUnlocked ? (

Masukkan PIN

Akses khusus guru/pembimbing

setPin(e.target.value)} maxLength={4} className="text-center text-4xl font-bold border-b-4 border-slate-200 w-32 focus:border-indigo-500 outline-none bg-transparent pb-2 tracking-widest" placeholder="••••"/>
) : ( {}} /> )}
); }; // --- QUIZ INTERFACE --- const BankSoalInterface = ({ chapter, goBack }) => { const [currentQNum, setCurrentQNum] = useState(1); const [qData, setQData] = useState(null); const [feedback, setFeedback] = useState(null); const [showSolution, setShowSolution] = useState(false); const [score, setScore] = useState(0); // Load question on mount or change useEffect(() => { const q = generateQuestion(chapter.id, currentQNum); setQData(q); setFeedback(null); setShowSolution(false); }, [chapter.id, currentQNum]); const handleAnswer = (val) => { let correct = false; if (qData.type === 'pg') correct = String(val) === String(qData.ans); else if (qData.type === 'complex') { const userSet = new Set(val); const ansSet = new Set(qData.ans); correct = [...ansSet].every(x => userSet.has(x)); } else { // Loose equality for input correct = String(val).trim().replace(/\s/g,'').toLowerCase() === String(qData.ans).trim().replace(/\s/g,'').toLowerCase(); } if (correct) { setFeedback('correct'); playSound('correct'); setScore(score + 10); } else { setFeedback('wrong'); playSound('wrong'); } }; // Complex Answer State Management const [complexSelected, setComplexSelected] = useState([]); const toggleComplex = (opt) => { if (complexSelected.includes(opt)) setComplexSelected(complexSelected.filter(x=>x!==opt)); else setComplexSelected([...complexSelected, opt]); }; if (!qData) return
Loading...
; return (
{/* HEADER */}
Bank Soal

{chapter.title}

Skor: {score}
{currentQNum}/{TOTAL_QUESTIONS_PER_CHAPTER}
{/* BODY */}
{/* Progress Bar */}
{/* Question Card */}
Tipe: {qData.type === 'pg' ? 'Pilihan Ganda' : qData.type === 'complex' ? 'PG Kompleks' : qData.type === 'input' ? 'Isian Singkat' : 'Uraian'} {feedback && (feedback==='correct' ? : )}

{qData.text}

{/* RENDER OPTIONS BASED ON TYPE */} {qData.type === 'pg' && (
{qData.options.map((opt, i) => ( ))}
)} {qData.type === 'complex' && (
{qData.options.map((opt, i) => ( ))}
)} {qData.type === 'input' && (
handleAnswer(e.target.value)}/>
)}
{/* FEEDBACK PANEL */} {feedback && (
{feedback==='correct'?'Hebat! Benar 🎉':'Kurang Tepat 🤔'}
Lanjutkan semangatmu!
)}
setShowSolution(false)} question={qData.text} steps={qData.steps}/>
); }; // --- MAIN APP --- const App = () => { const [activeChapter, setActiveChapter] = useState(null); return (
{!activeChapter ? ( <>
MindMath Pro
v3.0 Bank Soal

Bank Soal 600

Pilih Bab untuk mulai latihan intensif.

{CHAPTERS.map(chap => ( ))}
Created By Amiruddin, S.Pd.
) : ( setActiveChapter(null)} /> )}
); }; export default App;

Tidak ada komentar:

Posting Komentar

Matematika Kelas 7

Papan Belajar Matematika - Kelas 7 Papan B...