Minggu, 02 Agustus 2026

5w1h

 <!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>English Game: Asking & Giving Information</title>
   
    <!-- Tailwind CSS for Styling -->
    <script src="https://cdn.tailwindcss.com"></script>
   
    <!-- React & Babel for Game Logic -->
    <script src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
   
    <!-- Animate.css for Animations -->
    <link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" rel="stylesheet">
   
    <!-- Custom Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Fredoka+One&family=Nunito:wght@400;700;900&display=swap" rel="stylesheet">

    <style>
        body {
            font-family: 'Nunito', sans-serif;
            background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
            min-height: 100vh;
            overflow-x: hidden;
            margin: 0;
            padding: 0;
        }
        .title-font {
            font-family: 'Fredoka One', cursive;
        }
        .word-btn {
            transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
            box-shadow: 0 6px 0 rgba(0,0,0,0.15);
        }
        .word-btn:active {
            transform: translateY(6px);
            box-shadow: 0 0 0 rgba(0,0,0,0.15);
        }
        .drop-zone {
            min-height: 90px;
            border: 3px dashed rgba(255, 255, 255, 0.8);
            background: rgba(255, 255, 255, 0.3);
            border-radius: 1.5rem;
        }
        .glass-panel {
            background: rgba(255, 255, 255, 0.85);
            backdrop-filter: blur(10px);
            border: 1px solid rgba(255, 255, 255, 0.5);
            border-radius: 2rem;
        }
    </style>
</head>
<body>
    <div id="root"></div>

    <script type="text/babel">
        const { useState, useEffect, useRef } = React;

        // Data berdasarkan materi yang Anda berikan
        const GAME_DATA = [
            { id: 1, sentence: "What is your favorite subject", translation: "Apa mata pelajaran favoritmu?" },
            { id: 2, sentence: "Where do you study", translation: "Di mana kamu belajar?" },
            { id: 3, sentence: "When is your birthday", translation: "Kapan ulang tahunmu?" },
            { id: 4, sentence: "Who is your English teacher", translation: "Siapa guru bahasa Inggrismu?" },
            { id: 5, sentence: "Why do you like English", translation: "Mengapa kamu suka bahasa Inggris?" },
            { id: 6, sentence: "How do you go to school", translation: "Bagaimana kamu pergi ke sekolah?" },
            { id: 7, sentence: "Which book is yours", translation: "Buku yang mana milikmu?" },
            { id: 8, sentence: "Whose bag is this", translation: "Tas milik siapa ini?" },
            { id: 9, sentence: "What is your address", translation: "Di mana alamatmu?" },
            { id: 10, sentence: "What is your name", translation: "Siapa namamu?" },
            { id: 11, sentence: "What is your age", translation: "Berapa usiamu?" },
            { id: 12, sentence: "Where is your school", translation: "Di mana sekolahmu?" },
            { id: 13, sentence: "Who is your teacher", translation: "Siapa gurumu?" },
            { id: 14, sentence: "What is your favorite color", translation: "Apa warna favoritmu?" },
            { id: 15, sentence: "Write the answer in your book", translation: "Tulis jawaban di bukumu." },
            { id: 16, sentence: "Listen to the question", translation: "Dengarkan pertanyaan itu." },
            { id: 17, sentence: "I want to ask you a question", translation: "Saya ingin bertanya kepadamu." },
            { id: 18, sentence: "Give me some information about you", translation: "Beri saya informasi tentangmu." },
            { id: 19, sentence: "Math is my favorite subject", translation: "Matematika adalah pelajaran favoritku." },
            { id: 20, sentence: "My birthday is in May", translation: "Ulang tahunku di bulan Mei." }
        ];

        const App = () => {
            const [gameState, setGameState] = useState('LOGIN'); // LOGIN, PLAYING, RESULT
            const [playerName, setPlayerName] = useState('');
            const [currentLevel, setCurrentLevel] = useState(0);
            const [score, setScore] = useState(0);
           
            // Gameplay states
            const [timer, setTimer] = useState(30);
            const [scrambledWords, setScrambledWords] = useState([]);
            const [userAnswer, setUserAnswer] = useState([]);
            const [feedback, setFeedback] = useState(null);

            useEffect(() => {
                let interval;
                if (gameState === 'PLAYING' && timer > 0 && !feedback) {
                    interval = setInterval(() => {
                        setTimer(prev => prev - 1);
                    }, 1000);
                } else if (timer === 0 && gameState === 'PLAYING' && !feedback) {
                    handleTimeOut();
                }
                return () => clearInterval(interval);
            }, [gameState, timer, feedback]);

            const startGame = () => {
                if (playerName.trim().length > 0) {
                    setGameState('PLAYING');
                    setScore(0);
                    setCurrentLevel(0);
                    setupLevel(0);
                }
            };

            const setupLevel = (levelIndex) => {
                let words = GAME_DATA[levelIndex].sentence.split(' ');
                if (levelIndex < 14) words.push('?');
                else words.push('.');
               
                const shuffled = [...words].sort(() => Math.random() - 0.5);
               
                setScrambledWords(shuffled);
                setUserAnswer([]);
                setTimer(30);
                setFeedback(null);
            };

            const handleWordClick = (word, index, isFromScrambled) => {
                if (feedback) return;

                if (isFromScrambled) {
                    setUserAnswer([...userAnswer, word]);
                    setScrambledWords(scrambledWords.filter((_, i) => i !== index));
                } else {
                    setScrambledWords([...scrambledWords, word]);
                    setUserAnswer(userAnswer.filter((_, i) => i !== index));
                }
            };

            const checkAnswer = () => {
                let expectedSentence = GAME_DATA[currentLevel].sentence;
                let userSentence = userAnswer.join(' ');
                let punctuation = currentLevel < 14 ? ' ?' : ' .';
               
                if (userSentence === expectedSentence + punctuation) {
                    setFeedback('correct');
                    const pointsEarned = 100 + (timer * 10); // Bonus skor berdasarkan sisa waktu
                    setScore(prev => prev + pointsEarned);
                    setTimeout(() => nextLevel(), 1500);
                } else {
                    setFeedback('wrong');
                    setTimeout(() => {
                        const allWords = [...scrambledWords, ...userAnswer].sort(() => Math.random() - 0.5);
                        setScrambledWords(allWords);
                        setUserAnswer([]);
                        setFeedback(null);
                    }, 1500);
                }
            };

            const handleTimeOut = () => {
                setFeedback('timeout');
                setTimeout(() => nextLevel(), 2000);
            };

            const nextLevel = () => {
                if (currentLevel + 1 < GAME_DATA.length) {
                    setCurrentLevel(prev => prev + 1);
                    setupLevel(currentLevel + 1);
                } else {
                    setGameState('RESULT');
                }
            };

            if (gameState === 'LOGIN') {
                return (
                    <div className="flex flex-col items-center justify-center min-h-screen p-4 sm:p-6">
                        <div className="glass-panel p-8 sm:p-12 shadow-2xl w-full max-w-md animate__animated animate__zoomIn text-center relative overflow-hidden">
                           
                            <div className="absolute top-[-50px] right-[-50px] w-32 h-32 bg-yellow-300 rounded-full opacity-50 z-0"></div>
                           
                            <div className="relative z-10">
                                <div className="mb-6">
                                    <span className="text-6xl drop-shadow-md">🧩</span>
                                </div>
                                <h1 className="title-font text-4xl sm:text-5xl text-indigo-600 mb-2 drop-shadow-sm">Word Scramble</h1>
                                <p className="text-gray-700 font-bold mb-8 bg-indigo-100 inline-block px-4 py-1 rounded-full text-sm sm:text-base">Unit 1: WH-Questions</p>
                               
                                <div className="space-y-6 text-left">
                                    <div>
                                        <label className="block text-gray-700 font-bold mb-3 text-lg ml-2">Siapa namamu?</label>
                                        <input
                                            type="text"
                                            maxLength="15"
                                            className="w-full border-4 border-indigo-200 rounded-2xl px-5 py-4 text-xl focus:border-indigo-500 outline-none transition font-bold text-gray-700 bg-white"
                                            placeholder="Ketik namamu di sini..."
                                            value={playerName}
                                            onChange={(e) => setPlayerName(e.target.value)}
                                            onKeyDown={(e) => e.key === 'Enter' && startGame()}
                                        />
                                    </div>
                                    <button
                                        onClick={startGame}
                                        className="w-full bg-gradient-to-r from-yellow-400 to-orange-400 hover:from-yellow-500 hover:to-orange-500 text-white title-font text-2xl py-4 rounded-2xl transition transform hover:scale-105 shadow-[0_6px_0_#d97706] active:shadow-[0_0px_0_#d97706] active:translate-y-[6px]"
                                    >
                                        MULAI BERMAIN!
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                );
            }

            if (gameState === 'RESULT') {
                return (
                    <div className="flex flex-col items-center justify-center min-h-screen p-4 sm:p-6">
                        <div className="glass-panel p-10 shadow-2xl w-full max-w-md text-center animate__animated animate__tada">
                            <h2 className="title-font text-4xl text-indigo-600 mb-2">Kerja Bagus!</h2>
                            <p className="text-xl text-gray-700 font-bold mb-6">{playerName}, kamu berhasil menyelesaikan Unit 1!</p>
                           
                            <div className="bg-gradient-to-br from-indigo-500 to-purple-600 rounded-3xl p-8 mb-8 text-white shadow-inner relative overflow-hidden">
                                <div className="absolute top-0 right-0 text-6xl opacity-20 transform rotate-12 mt-2 mr-2">🌟</div>
                                <p className="text-indigo-200 text-lg font-bold uppercase tracking-wider mb-1">Total Skor Kamu</p>
                                <p className="title-font text-6xl drop-shadow-md">{score}</p>
                            </div>

                            <button
                                onClick={() => window.location.reload()}
                                className="w-full bg-green-400 hover:bg-green-500 text-white title-font text-2xl py-4 rounded-2xl transition transform hover:scale-105 shadow-[0_6px_0_#16a34a] active:shadow-none active:translate-y-[6px]"
                            >
                                MAIN LAGI
                            </button>
                        </div>
                    </div>
                );
            }

            const progressColor = timer > 15 ? 'bg-green-400' : timer > 5 ? 'bg-yellow-400' : 'bg-red-500';
            const progressWidth = `${(timer / 30) * 100}%`;

            return (
                <div className="max-w-4xl mx-auto p-4 sm:p-6 min-h-screen flex flex-col justify-center">
                   
                    {/* Header Game */}
                    <div className="flex justify-between items-center glass-panel p-4 mb-6 shadow-md">
                        <div className="flex flex-col sm:flex-row items-start sm:items-center gap-2 sm:gap-4">
                            <div className="bg-indigo-600 text-white px-4 py-1.5 rounded-full font-bold text-sm">
                                LEVEL {currentLevel + 1} / {GAME_DATA.length}
                            </div>
                            <span className="font-bold text-gray-700 flex items-center gap-2">
                                👤 {playerName}
                            </span>
                        </div>
                        <div className="text-right flex flex-col items-end">
                            <span className="text-xs font-bold text-gray-500 tracking-wider">SKOR</span>
                            <span className="title-font text-2xl sm:text-3xl text-indigo-600">{score}</span>
                        </div>
                    </div>

                    {/* Bar Waktu (Timer) */}
                    <div className="w-full bg-white/50 rounded-full h-5 mb-8 shadow-inner overflow-hidden border-2 border-white/60 backdrop-blur-sm">
                        <div
                            className={`h-full transition-all duration-1000 ease-linear ${progressColor} flex justify-end pr-2 items-center`}
                            style={{ width: progressWidth }}
                        >
                            <span className="text-xs font-bold text-white drop-shadow-md">{timer}s</span>
                        </div>
                    </div>

                    {/* Area Permainan Utama */}
                    <div className="flex-grow flex flex-col items-center w-full">
                       
                        {/* Petunjuk Bahasa Indonesia */}
                        <div className="text-center mb-8 w-full">
                            <div className="bg-white/70 inline-block px-6 py-2 rounded-2xl mb-3 shadow-sm">
                                <span className="text-gray-600 font-bold text-sm uppercase tracking-wide">Susun kata-kata untuk:</span>
                            </div>
                            <h3 className="text-2xl sm:text-3xl font-black text-gray-800 drop-shadow-sm px-4">
                                "{GAME_DATA[currentLevel].translation}"
                            </h3>
                        </div>

                        {/* Kotak Jawaban (Drop Zone) */}
                        <div className={`w-full p-6 drop-zone flex flex-wrap justify-center items-center gap-3 mb-8 transition-colors duration-300 relative
                            ${feedback === 'correct' ? 'bg-green-400/50 border-green-500' :
                              feedback === 'wrong' ? 'bg-red-400/50 border-red-500 animate__animated animate__shakeX' :
                              feedback === 'timeout' ? 'bg-gray-400/50 border-gray-500' : ''}`}
                        >
                            {userAnswer.length === 0 && (
                                <span className="absolute inset-0 flex items-center justify-center text-gray-600/60 font-bold text-lg sm:text-xl select-none text-center px-4">
                                    Tekan kata di bawah untuk menyusun kalimat
                                </span>
                            )}
                           
                            {userAnswer.map((word, i) => (
                                <button
                                    key={`ans-${i}`}
                                    onClick={() => handleWordClick(word, i, false)}
                                    className="word-btn bg-white text-indigo-700 border-2 border-indigo-200 px-5 py-3 rounded-2xl font-black text-xl sm:text-2xl z-10 animate__animated animate__bounceIn"
                                >
                                    {word}
                                </button>
                            ))}

                            {feedback === 'correct' && <div className="absolute -top-6 -right-2 text-6xl animate__animated animate__bounceIn">🎯</div>}
                            {feedback === 'wrong' && <div className="absolute -top-6 -right-2 text-6xl animate__animated animate__bounceIn">❌</div>}
                            {feedback === 'timeout' && <div className="absolute -top-6 -right-2 text-6xl animate__animated animate__bounceIn">⏰</div>}
                        </div>

                        {/* Bank Kata Acak */}
                        <div className="flex flex-wrap justify-center gap-3 sm:gap-4 w-full p-6 glass-panel min-h-[140px] shadow-lg">
                            {scrambledWords.map((word, i) => (
                                <button
                                    key={`scram-${i}`}
                                    onClick={() => handleWordClick(word, i, true)}
                                    className="word-btn bg-indigo-500 text-white px-5 py-3 rounded-2xl font-black text-xl sm:text-2xl animate__animated animate__fadeInUp"
                                >
                                    {word}
                                </button>
                            ))}
                        </div>

                        {/* Tombol Periksa Jawaban */}
                        <div className="mt-8 mb-4 w-full sm:w-2/3 md:w-1/2">
                            <button
                                onClick={checkAnswer}
                                disabled={userAnswer.length === 0 || feedback !== null}
                                className={`w-full title-font text-2xl py-4 rounded-2xl transition transform shadow-[0_6px_0_rgba(0,0,0,0.2)]
                                    ${userAnswer.length > 0 && !feedback
                                        ? 'bg-blue-500 hover:bg-blue-400 text-white active:translate-y-[6px] active:shadow-none cursor-pointer'
                                        : 'bg-white/50 text-gray-400 opacity-80 cursor-not-allowed border-2 border-transparent'}`}
                            >
                                PERIKSA JAWABAN
                            </button>
                        </div>

                    </div>
                </div>
            );
        };

        const root = ReactDOM.createRoot(document.getElementById('root'));
        root.render(<App />);
    </script>
</body>
</html>

Senin, 01 Juni 2026

KELAS 5

Fill in the Blanks - Sentence Completion

📚 English Vocabulary Learning

Master English with pronunciation guides and comprehensive lessons!

✅ Correct: 0 ❌ Wrong: 0 📊 Progress: 0/15

MATCHING

Vocabulary Matching Quiz

🎯 Vocabulary Matching Quiz

Match the English word with its correct Indonesian translation!

✅ Correct: 0 ❌ Wrong: 0 📊 Total: 0/40

Minggu, 31 Mei 2026

matching

Vocabulary Matching Quiz

🎯 Vocabulary Matching Quiz

Match the English word with its correct Indonesian translation!

✅ Correct: 0 ❌ Wrong: 0 📊 Total: 0/40