Benutzer-Werkzeuge

Webseiten-Werkzeuge


tools:skalentrainer

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.

Link zu der Vergleichsansicht

Beide Seiten, vorherige ÜberarbeitungVorherige Überarbeitung
Nächste Überarbeitung
Vorherige Überarbeitung
tools:skalentrainer [15/05/2025 08:59] – gelöscht - Externe Bearbeitung (Unknown date) 127.0.0.1tools:skalentrainer [22/05/2025 16:31] (aktuell) Eric Weber
Zeile 1: Zeile 1:
 +<html>
 +<head>
 +    <meta charset="UTF-8">
 +    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 +    <title>Musikalische Skalen Trainer</title>
 +    <style>
 +        body {
 +            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
 +            line-height: 1.6;
 +            color: #333;
 +            max-width: 1000px;
 +            margin: 0 auto;
 +            padding: 20px;
 +            background-color: #f5f5f5;
 +        }
 +        h1, h2 {
 +            color: #2c3e50;
 +            text-align: center;
 +        }
 +        .container {
 +            background-color: white;
 +            border-radius: 8px;
 +            padding: 20px;
 +            box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
 +            margin-bottom: 20px;
 +        }
 +        .flex-row {
 +            display: flex;
 +            flex-wrap: wrap;
 +            gap: 10px;
 +            align-items: center;
 +            margin-bottom: 15px;
 +        }
 +        .scales-container {
 +            display: flex;
 +            flex-wrap: wrap;
 +            gap: 10px;
 +            margin-bottom: 15px;
 +        }
 +        .checkbox-container {
 +            display: flex;
 +            align-items: center;
 +            background-color: #ecf0f1;
 +            padding: 8px 12px;
 +            border-radius: 4px;
 +            cursor: pointer;
 +            transition: background-color 0.2s;
 +        }
 +        .checkbox-container:hover {
 +            background-color: #d5dbdb;
 +        }
 +        .checkbox-container input {
 +            margin-right: 8px;
 +        }
 +        label {
 +            margin-right: 10px;
 +            font-weight: 500;
 +        }
 +        button {
 +            background-color: #2c3e50;
 +            color: black;
 +            border: 2px solid #1a2530;
 +            padding: 10px 15px;
 +            border-radius: 4px;
 +            cursor: pointer;
 +            font-size: 16px;
 +            transition: all 0.2s;
 +            font-weight: 600;
 +            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
 +        }
 +        button:hover {
 +            background-color: #34495e;
 +            transform: translateY(-2px);
 +            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
 +        }
 +        button:active {
 +            transform: translateY(0);
 +            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
 +        }
 +        button:disabled {
 +            background-color: #95a5a6;
 +            border-color: #7f8c8d;
 +            cursor: not-allowed;
 +            box-shadow: none;
 +        }
 +        .select-all-btn {
 +            margin-left: auto;
 +        }
 +        .mode-selector {
 +            display: flex;
 +            justify-content: center;
 +            gap: 15px;
 +            margin-bottom: 20px;
 +        }
 +        .mode-btn {
 +            padding: 10px 20px;
 +            background-color: #ecf0f1;
 +            color: #2c3e50;
 +            border: 2px solid #bdc3c7;
 +            font-weight: 600;
 +        }
 +        .mode-btn.active {
 +            background-color: #2c3e50;
 +            color: black;
 +            border-color: #1a2530;
 +        }
 +        #practiceSection, #quizSection {
 +            margin-top: 30px;
 +        }
 +        #quizSection {
 +            display: none;
 +        }
 +        .practice-scales-container {
 +            display: grid;
 +            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
 +            gap: 15px;
 +            margin: 20px 0;
 +        }
 +        .practice-scale-btn {
 +            background-color: #ecf0f1;
 +            color: #2c3e50;
 +            border: 2px solid #bdc3c7;
 +            padding: 15px;
 +            border-radius: 8px;
 +            cursor: pointer;
 +            font-size: 16px;
 +            font-weight: 600;
 +            text-align: center;
 +            transition: all 0.2s;
 +        }
 +        .practice-scale-btn:hover {
 +            background-color: #d5dbdb;
 +            transform: translateY(-2px);
 +            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
 +        }
 +        .practice-scale-btn:active {
 +            transform: translateY(0);
 +            box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
 +        }
 +        .practice-scale-btn.playing {
 +            background-color: #3498db;
 +            color: black;
 +            border-color: #2980b9;
 +        }
 +        .quiz-options {
 +            display: grid;
 +            grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
 +            gap: 10px;
 +            margin: 20px 0;
 +        }
 +        .quiz-option {
 +            background-color: #ecf0f1;
 +            padding: 12px;
 +            border-radius: 4px;
 +            text-align: center;
 +            cursor: pointer;
 +            transition: all 0.2s;
 +        }
 +        .quiz-option:hover {
 +            background-color: #d5dbdb;
 +        }
 +        .correct {
 +            background-color: #27ae60 !important;
 +            color: black;
 +        }
 +        .incorrect {
 +            background-color: #c0392b !important;
 +            color: black;
 +        }
 +        .progress-container {
 +            margin-top: 30px;
 +            text-align: center;
 +        }
 +        .progress-bar {
 +            height: 10px;
 +            background-color: #ecf0f1;
 +            border-radius: 5px;
 +            margin-top: 10px;
 +            overflow: hidden;
 +        }
 +        .progress-fill {
 +            height: 100%;
 +            background-color: #3498db;
 +            width: 0%;
 +            transition: width 0.3s;
 +        }
 +        .progress-markers {
 +            display: flex;
 +            justify-content: space-between;
 +            margin-top: 5px;
 +        }
 +        .progress-marker {
 +            width: 20px;
 +            height: 20px;
 +            border-radius: 50%;
 +            background-color: #ecf0f1;
 +            display: flex;
 +            align-items: center;
 +            justify-content: center;
 +            font-size: 12px;
 +        }
 +        .progress-marker.completed {
 +            background-color: #3498db;
 +            color: black;
 +        }
 +        .progress-marker.correct {
 +            background-color: #27ae60;
 +            color: black;
 +        }
 +        .progress-marker.incorrect {
 +            background-color: #c0392b;
 +            color: black;
 +        }
 +        #keySelector {
 +            display: none;
 +            margin-top: 15px;
 +        }
 +        .separator {
 +            margin: 0 10px;
 +            color: #7f8c8d;
 +        }
 +        .control-section {
 +            display: flex;
 +            gap: 10px;
 +            margin: 20px 0;
 +        }
 +        #playAgainBtn, #showAnswerBtn, #nextQuestionBtn {
 +            display: none;
 +        }
 +        #results {
 +            font-weight: bold;
 +            font-size: 18px;
 +            margin-top: 20px;
 +            text-align: center;
 +        }
 +    </style>
 +</head>
 +<body>
 +    <h1>Skalen-Trainer</h1>
 +    
 +    <div class="container">
 +        <h2>Einstellungen</h2>
 +        
 +        <!-- Mode selection -->
 +        <div class="mode-selector">
 +            <button class="mode-btn active" data-mode="easy">Einfach<br>(Ohne Vorzeichen)</button>
 +            <button class="mode-btn" data-mode="intermediate">Fortgeschritten<br>(Bis 3 Vorzeichen)</button>
 +            <button class="mode-btn" data-mode="advanced">Profi<br>(Alle Vorzeichen)</button>
 +        </div>
 +        
 +        <!-- Scales selection -->
 +        <div class="flex-row">
 +            <label>Skalen:</label>
 +            <button id="toggleAllBtn" class="select-all-btn">Alle auswählen</button>
 +        </div>
 +        
 +        <div class="scales-container">
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-ionian">
 +                <label for="scale-ionian">Dur (Ionisch)</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-aeolian">
 +                <label for="scale-aeolian">Moll natürlich (Aeolisch)</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-harmonic-minor">
 +                <label for="scale-harmonic-minor">Moll harmonisch</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-melodic-minor">
 +                <label for="scale-melodic-minor">Moll melodisch</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-dorian">
 +                <label for="scale-dorian">Dorisch</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-lydian">
 +                <label for="scale-lydian">Lydisch</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-mixolydian">
 +                <label for="scale-mixolydian">Mixolydisch</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-phrygian">
 +                <label for="scale-phrygian">Phrygisch</label>
 +            </div>
 +            <div class="checkbox-container">
 +                <input type="checkbox" id="scale-locrian">
 +                <label for="scale-locrian">Lokrisch</label>
 +            </div>
 +        </div>
 +    </div>
  
 +    <div id="practiceSection" class="container">
 +        <h2>Übungsmodus</h2>
 +        <p>Klicke auf eine Skala, um sie abzuspielen:</p>
 +        
 +        <div class="practice-scales-container" id="practiceScalesContainer">
 +            <!-- Practice scale buttons will be generated here -->
 +        </div>
 +        
 +        <div class="flex-row" style="justify-content: center; margin-top: 20px;">
 +            <button id="startQuizBtn">Prüfung starten</button>
 +        </div>
 +    </div>
 +
 +    <div id="quizSection" class="container">
 +        <h2>Prüfungsmodus</h2>
 +        <p id="quizInstruction">Höre die Skala und wähle die richtige Antwort:</p>
 +        
 +        <button id="playScaleBtn">Skala abspielen</button>
 +        
 +        <div class="quiz-options" id="quizOptions">
 +            <!-- Options will be generated here -->
 +        </div>
 +        
 +        <div class="control-section">
 +            <button id="playAgainBtn">Noch einmal abspielen</button>
 +            <button id="showAnswerBtn">Lösung zeigen</button>
 +            <button id="nextQuestionBtn">Nächste Frage</button>
 +        </div>
 +        
 +        <div class="progress-container">
 +            <div id="progressText">Frage 0 von 10</div>
 +            <div class="progress-bar">
 +                <div class="progress-fill" id="progressFill"></div>
 +            </div>
 +            <div class="progress-markers" id="progressMarkers">
 +                <!-- Markers will be generated here -->
 +            </div>
 +            <div id="results"></div>
 +        </div>
 +    </div>
 +
 +    <script>
 +        // Audio context and main variables
 +        let audioContext;
 +        let currentMode = "easy";
 +        let allScalesSelected = false;
 +        let quizInProgress = false;
 +        let currentQuizQuestion = 0;
 +        let totalQuizQuestions = 10;
 +        let correctAnswers = 0;
 +        let quizScales = [];
 +        let currentScale;
 +        let questionAnswered = false;
 +        let currentlyPlayingScale = null;
 +
 +        // Function to stop all audio
 +        function stopAllAudio() {
 +            // If there's an active quiz or practice, stop it
 +            if (quizInProgress) {
 +                resetQuiz();
 +            }
 +            
 +            // Reset practice scale visual state
 +            resetPracticeScaleButtons();
 +            
 +            // If audio context exists, cancel all scheduled sounds
 +            if (audioContext) {
 +                // Create a new audio context to stop all sounds
 +                audioContext.close().then(() => {
 +                    audioContext = null;
 +                });
 +            }
 +        }
 +        
 +        // Reset quiz state
 +        function resetQuiz() {
 +            if (quizInProgress) {
 +                quizInProgress = false;
 +                document.getElementById("practiceSection").style.display = "block";
 +                document.getElementById("quizSection").style.display = "none";
 +                document.getElementById("playScaleBtn").style.display = "inline-block";
 +                document.getElementById("quizInstruction").style.display = "block";
 +                document.getElementById("results").textContent = "";
 +                document.getElementById("quizOptions").innerHTML = "";
 +                document.getElementById("playAgainBtn").style.display = "none";
 +                document.getElementById("showAnswerBtn").style.display = "none";
 +                document.getElementById("nextQuestionBtn").style.display = "none";
 +            }
 +        }
 +
 +        // Reset practice scale button visual states
 +        function resetPracticeScaleButtons() {
 +            document.querySelectorAll(".practice-scale-btn").forEach(btn => {
 +                btn.classList.remove("playing");
 +            });
 +            currentlyPlayingScale = null;
 +        }
 +
 +        // Initialize the application
 +        document.addEventListener("DOMContentLoaded", function() {
 +            // Set up event listeners
 +            document.getElementById("toggleAllBtn").addEventListener("click", toggleAllScales);
 +            document.getElementById("startQuizBtn").addEventListener("click", startQuiz);
 +            document.getElementById("playScaleBtn").addEventListener("click", () => playCurrentQuizScale());
 +            document.getElementById("playAgainBtn").addEventListener("click", () => playCurrentQuizScale());
 +            document.getElementById("showAnswerBtn").addEventListener("click", showCorrectAnswer);
 +            document.getElementById("nextQuestionBtn").addEventListener("click", nextQuestion);
 +
 +            // Mode buttons
 +            document.querySelectorAll(".mode-btn").forEach(btn => {
 +                btn.addEventListener("click", function() {
 +                    setMode(this.dataset.mode);
 +                    stopAllAudio();
 +                    updatePracticeScales();
 +                });
 +            });
 +
 +            // Add event listeners to stop audio when settings change
 +            document.querySelectorAll(".scales-container input[type='checkbox']").forEach(checkbox => {
 +                checkbox.addEventListener("change", function() {
 +                    stopAllAudio();
 +                    updatePracticeScales();
 +                });
 +            });
 +
 +            // Initialize progress markers and practice scales
 +            initializeProgressMarkers();
 +            updatePracticeScales();
 +        });
 +
 +        // Toggle all scales selection
 +        function toggleAllScales() {
 +            const scaleCheckboxes = document.querySelectorAll(".scales-container input[type='checkbox']");
 +            allScalesSelected = !allScalesSelected;
 +            
 +            scaleCheckboxes.forEach(checkbox => {
 +                checkbox.checked = allScalesSelected;
 +            });
 +            
 +            document.getElementById("toggleAllBtn").textContent = allScalesSelected ? "Alle abwählen" : "Alle auswählen";
 +            updatePracticeScales();
 +        }
 +
 +        // Set the difficulty mode
 +        function setMode(mode) {
 +            currentMode = mode;
 +            
 +            // Update UI
 +            document.querySelectorAll(".mode-btn").forEach(btn => {
 +                btn.classList.remove("active");
 +                if (btn.dataset.mode === mode) {
 +                    btn.classList.add("active");
 +                }
 +            });
 +        }
 +
 +        // Update practice scales display
 +        function updatePracticeScales() {
 +            const container = document.getElementById("practiceScalesContainer");
 +            container.innerHTML = "";
 +            
 +            const selectedScales = getSelectedScales();
 +            
 +            if (selectedScales.length === 0) {
 +                container.innerHTML = "<p style='text-align: center; color: #666; grid-column: 1 / -1;'>Bitte wähle mindestens eine Skala aus.</p>";
 +                return;
 +            }
 +            
 +            selectedScales.forEach(scale => {
 +                const button = document.createElement("button");
 +                button.className = "practice-scale-btn";
 +                button.textContent = getScaleName(scale);
 +                button.dataset.scale = scale;
 +                
 +                button.addEventListener("click", function() {
 +                    playPracticeScale(scale, this);
 +                });
 +                
 +                container.appendChild(button);
 +            });
 +        }
 +
 +        // Play a practice scale
 +        function playPracticeScale(scale, buttonElement) {
 +            // Reset all button states
 +            resetPracticeScaleButtons();
 +            
 +            // Set current button as playing
 +            buttonElement.classList.add("playing");
 +            currentlyPlayingScale = scale;
 +            
 +            const startNote = getScaleStartNote(scale);
 +            
 +            playScale(scale, startNote, () => {
 +                // Remove playing state after scale finishes
 +                if (currentlyPlayingScale === scale) {
 +                    buttonElement.classList.remove("playing");
 +                    currentlyPlayingScale = null;
 +                }
 +            });
 +        }
 +
 +        // Check if at least one scale is selected
 +        function isAnyScaleSelected() {
 +            const scaleCheckboxes = document.querySelectorAll(".scales-container input[type='checkbox']");
 +            return Array.from(scaleCheckboxes).some(checkbox => checkbox.checked);
 +        }
 +
 +        // Get selected scales
 +        function getSelectedScales() {
 +            const scales = [];
 +            
 +            if (document.getElementById("scale-ionian").checked) scales.push("ionian");
 +            if (document.getElementById("scale-aeolian").checked) scales.push("aeolian");
 +            if (document.getElementById("scale-harmonic-minor").checked) scales.push("harmonic-minor");
 +            if (document.getElementById("scale-melodic-minor").checked) scales.push("melodic-minor");
 +            if (document.getElementById("scale-dorian").checked) scales.push("dorian");
 +            if (document.getElementById("scale-lydian").checked) scales.push("lydian");
 +            if (document.getElementById("scale-mixolydian").checked) scales.push("mixolydian");
 +            if (document.getElementById("scale-phrygian").checked) scales.push("phrygian");
 +            if (document.getElementById("scale-locrian").checked) scales.push("locrian");
 +            
 +            return scales;
 +        }
 +
 +        // Initialize the audio context (must be triggered by user interaction)
 +        function initAudioContext() {
 +            if (!audioContext) {
 +                audioContext = new (window.AudioContext || window.webkitAudioContext)();
 +            }
 +            return audioContext;
 +        }
 +
 +        // Scale definitions (intervals in semitones)
 +        const scaleDefinitions = {
 +            "ionian": {
 +                ascending: [0, 2, 4, 5, 7, 9, 11, 12],
 +                descending: [12, 11, 9, 7, 5, 4, 2, 0]
 +            },
 +            "aeolian": {
 +                ascending: [0, 2, 3, 5, 7, 8, 10, 12],
 +                descending: [12, 10, 8, 7, 5, 3, 2, 0]
 +            },
 +            "harmonic-minor": {
 +                ascending: [0, 2, 3, 5, 7, 8, 11, 12],
 +                descending: [12, 11, 8, 7, 5, 3, 2, 0]
 +            },
 +            "melodic-minor": {
 +                ascending: [0, 2, 3, 5, 7, 9, 11, 12],
 +                // Melodic minor descending is the same as natural minor (aeolian)
 +                descending: [12, 10, 8, 7, 5, 3, 2, 0]
 +            },
 +            "dorian": {
 +                ascending: [0, 2, 3, 5, 7, 9, 10, 12],
 +                descending: [12, 10, 9, 7, 5, 3, 2, 0]
 +            },
 +            "lydian": {
 +                ascending: [0, 2, 4, 6, 7, 9, 11, 12],
 +                descending: [12, 11, 9, 7, 6, 4, 2, 0]
 +            },
 +            "mixolydian": {
 +                ascending: [0, 2, 4, 5, 7, 9, 10, 12],
 +                descending: [12, 10, 9, 7, 5, 4, 2, 0]
 +            },
 +            "phrygian": {
 +                ascending: [0, 1, 3, 5, 7, 8, 10, 12],
 +                descending: [12, 10, 8, 7, 5, 3, 1, 0]
 +            },
 +            "locrian": {
 +                ascending: [0, 1, 3, 5, 6, 8, 10, 12],
 +                descending: [12, 10, 8, 6, 5, 3, 1, 0]
 +            }
 +        };
 +
 +        // Scale starting notes for easy mode
 +        const easyModeStartNotes = {
 +            "ionian": 60, // C4
 +            "aeolian": 69, // A4
 +            "harmonic-minor": 69, // A4
 +            "melodic-minor": 69, // A4
 +            "dorian": 62, // D4
 +            "lydian": 64, // E4
 +            "mixolydian": 65, // F4
 +            "phrygian": 67, // G4
 +            "locrian": 71  // B4
 +        };
 +
 +        // Keys for intermediate mode (0-3 sharps/flats)
 +        const intermediateModeKeys = [
 +            { name: "C", midiBase: 60 },  // C (no sharps/flats)
 +            { name: "G", midiBase: 67 },  // G (1 sharp)
 +            { name: "D", midiBase: 62 },  // D (2 sharps)
 +            { name: "A", midiBase: 69 },  // A (3 sharps)
 +            { name: "F", midiBase: 65 },  // F (1 flat)
 +            { name: "Bb", midiBase: 70 }, // Bb (2 flats)
 +            { name: "Eb", midiBase: 63 }  // Eb (3 flats)
 +        ];
 +
 +        // Convert note name to MIDI number
 +        function noteToMidi(note, octave) {
 +            const noteValues = {
 +                "C": 0, "C#": 1, "D": 2, "D#": 3, 
 +                "E": 4, "F": 5, "F#": 6, "G": 7, 
 +                "G#": 8, "A": 9, "A#": 10, "B": 11
 +            };
 +            
 +            return 12 + (octave * 12) + noteValues[note];
 +        }
 +
 +        // Get random chromatic note between C3 and C5
 +        function getRandomChromatic() {
 +            // C3 is MIDI 48, C5 is MIDI 72
 +            return Math.floor(Math.random() * 25) + 48;
 +        }
 +
 +        // Get scale start note based on selected mode
 +        function getScaleStartNote(scale) {
 +            if (currentMode === "easy") {
 +                return easyModeStartNotes[scale];
 +            } else if (currentMode === "intermediate") {
 +                // Choose random key from intermediate keys
 +                const randomKey = intermediateModeKeys[Math.floor(Math.random() * intermediateModeKeys.length)];
 +                // Adjust to ensure it's between C3 and C5
 +                let midiNote = randomKey.midiBase;
 +                while (midiNote < 48) midiNote += 12;
 +                while (midiNote > 72) midiNote -= 12;
 +                return midiNote;
 +            } else { // advanced
 +                return getRandomChromatic();
 +            }
 +        }
 +
 +        // Play a note with Web Audio API
 +        function playNote(midiNote, time, duration) {
 +            const oscillator = audioContext.createOscillator();
 +            const gainNode = audioContext.createGain();
 +            
 +            oscillator.type = 'sine';
 +            oscillator.frequency.value = 440 * Math.pow(2, (midiNote - 69) / 12);
 +            
 +            // Apply a simple envelope
 +            gainNode.gain.setValueAtTime(0, time);
 +            gainNode.gain.linearRampToValueAtTime(0.5, time + 0.02);
 +            gainNode.gain.linearRampToValueAtTime(0.3, time + 0.1);
 +            gainNode.gain.linearRampToValueAtTime(0, time + duration);
 +            
 +            oscillator.connect(gainNode);
 +            gainNode.connect(audioContext.destination);
 +            
 +            oscillator.start(time);
 +            oscillator.stop(time + duration);
 +        }
 +
 +        // Play a scale
 +        function playScale(scale, startNoteMidi, callback) {
 +            initAudioContext();
 +            
 +            const scaleData = scaleDefinitions[scale];
 +            const noteDuration = 0.4;
 +            let time = audioContext.currentTime;
 +            
 +            // Play ascending
 +            for (let i = 0; i < scaleData.ascending.length; i++) {
 +                playNote(startNoteMidi + scaleData.ascending[i], time, noteDuration);
 +                time += noteDuration;
 +            }
 +            
 +            // Play descending
 +            for (let i = 0; i < scaleData.descending.length; i++) {
 +                if (i > 0) { // Skip first note as it's the same as last ascending note
 +                    playNote(startNoteMidi + scaleData.descending[i], time, noteDuration);
 +                    time += noteDuration;
 +                }
 +            }
 +            
 +            // Execute callback after scale has played
 +            if (callback) {
 +                setTimeout(callback, (scaleData.ascending.length + scaleData.descending.length - 1) * noteDuration * 1000);
 +            }
 +        }
 +
 +        // Initialize quiz
 +        function startQuiz() {
 +            if (!isAnyScaleSelected()) {
 +                alert("Bitte wähle mindestens eine Skala aus.");
 +                return;
 +            }
 +            
 +            // Set up quiz environment
 +            document.getElementById("practiceSection").style.display = "none";
 +            document.getElementById("quizSection").style.display = "block";
 +            
 +            // Reset quiz variables
 +            quizInProgress = true;
 +            currentQuizQuestion = 0;
 +            correctAnswers = 0;
 +            
 +            // Create quiz questions
 +            const selectedScales = getSelectedScales();
 +            quizScales = [];
 +            
 +            // Generate 10 random questions from selected scales
 +            for (let i = 0; i < totalQuizQuestions; i++) {
 +                const randomScaleIndex = Math.floor(Math.random() * selectedScales.length);
 +                const scale = selectedScales[randomScaleIndex];
 +                quizScales.push(scale);
 +            }
 +            
 +            // Reset progress markers
 +            resetProgressMarkers();
 +            
 +            // Start first question
 +            nextQuestion();
 +        }
 +
 +        // Play the current quiz scale
 +        function playCurrentQuizScale() {
 +            if (!quizInProgress || currentQuizQuestion >= quizScales.length) return;
 +            
 +            currentScale = quizScales[currentQuizQuestion];
 +            const startNote = getScaleStartNote(currentScale);
 +            
 +            playScale(currentScale, startNote);
 +            
 +            // Enable play again button
 +            document.getElementById("playAgainBtn").style.display = "inline-block";
 +        }
 +
 +        // Show quiz options
 +        function showQuizOptions() {
 +            const optionsContainer = document.getElementById("quizOptions");
 +            optionsContainer.innerHTML = "";
 +            
 +            // Get selected scales for options
 +            const scales = getSelectedScales();
 +            
 +            // Shuffle the options
 +            const shuffledScales = [...scales].sort(() => Math.random() - 0.5);
 +            
 +            // Create option buttons
 +            shuffledScales.forEach(scale => {
 +                const optionElement = document.createElement("div");
 +                optionElement.className = "quiz-option";
 +                optionElement.dataset.scale = scale;
 +                optionElement.textContent = getScaleName(scale);
 +                
 +                optionElement.addEventListener("click", function() {
 +                    if (questionAnswered) return;
 +                    
 +                    questionAnswered = true;
 +                    checkAnswer(scale);
 +                });
 +                
 +                optionsContainer.appendChild(optionElement);
 +            });
 +        }
 +
 +        // Get human-readable scale name
 +        function getScaleName(scale) {
 +            const scaleNames = {
 +                "ionian": "Dur (Ionisch)",
 +                "aeolian": "Moll natürlich (Aeolisch)",
 +                "harmonic-minor": "Moll harmonisch",
 +                "melodic-minor": "Moll melodisch",
 +                "dorian": "Dorisch",
 +                "lydian": "Lydisch",
 +                "mixolydian": "Mixolydisch",
 +                "phrygian": "Phrygisch",
 +                "locrian": "Lokrisch"
 +            };
 +            
 +            return scaleNames[scale] || scale;
 +        }
 +
 +        // Check the selected answer
 +        function checkAnswer(selectedScale) {
 +            const isCorrect = selectedScale === currentScale;
 +            
 +            // Update progress markers
 +            updateProgressMarker(currentQuizQuestion, isCorrect);
 +            
 +            // Update score
 +            if (isCorrect) {
 +                correctAnswers++;
 +            }
 +            
 +            // Show visual feedback
 +            const options = document.querySelectorAll(".quiz-option");
 +            options.forEach(option => {
 +                if (option.dataset.scale === selectedScale) {
 +                    option.classList.add(isCorrect ? "correct" : "incorrect");
 +                }
 +            });
 +            
 +            // Show control buttons
 +            document.getElementById("playAgainBtn").style.display = "inline-block";
 +            document.getElementById("showAnswerBtn").style.display = isCorrect ? "none" : "inline-block";
 +            document.getElementById("nextQuestionBtn").style.display = "inline-block";
 +        }
 +
 +        // Show the correct answer
 +        function showCorrectAnswer() {
 +            const options = document.querySelectorAll(".quiz-option");
 +            options.forEach(option => {
 +                if (option.dataset.scale === currentScale) {
 +                    option.classList.add("correct");
 +                }
 +            });
 +            
 +            // Hide show answer button
 +            document.getElementById("showAnswerBtn").style.display = "none";
 +        }
 +
 +        // Move to the next question
 +        function nextQuestion() {
 +            // Reset question state
 +            questionAnswered = false;
 +            
 +            // Increment question counter
 +            currentQuizQuestion++;
 +            
 +            // Update progress
 +            document.getElementById("progressText").textContent = `Frage ${currentQuizQuestion} von ${totalQuizQuestions}`;
 +            document.getElementById("progressFill").style.width = `${(currentQuizQuestion / totalQuizQuestions) * 100}%`;
 +            
 +            // Reset controls
 +            document.getElementById("playAgainBtn").style.display = "none";
 +            document.getElementById("showAnswerBtn").style.display = "none";
 +            document.getElementById("nextQuestionBtn").style.display = "none";
 +            
 +            // Check if quiz is complete
 +            if (currentQuizQuestion >= totalQuizQuestions) {
 +                finishQuiz();
 +                return;
 +            }
 +            
 +            // Show options for the next question
 +            showQuizOptions();
 +            
 +            // Play the scale automatically
 +            playCurrentQuizScale();
 +        }
 +
 +        // Finish the quiz and show results
 +        function finishQuiz() {
 +            quizInProgress = false;
 +            
 +            // Hide quiz controls
 +            document.getElementById("playScaleBtn").style.display = "none";
 +            document.getElementById("quizOptions").innerHTML = "";
 +            document.getElementById("quizInstruction").style.display = "none";
 +            
 +            // Show results
 +            const resultsElement = document.getElementById("results");
 +            const percentage = Math.round((correctAnswers / totalQuizQuestions) * 100);
 +            resultsElement.textContent = `Quiz beendet! Ergebnis: ${correctAnswers} von ${totalQuizQuestions} richtig (${percentage}%)`;
 +            
 +            // Show restart button
 +            const restartBtn = document.createElement("button");
 +            restartBtn.textContent = "Neues Quiz starten";
 +            restartBtn.addEventListener("click", function() {
 +                // Reset UI
 +                document.getElementById("practiceSection").style.display = "block";
 +                document.getElementById("quizSection").style.display = "none";
 +                document.getElementById("playScaleBtn").style.display = "inline-block";
 +                document.getElementById("quizInstruction").style.display = "block";
 +                document.getElementById("results").textContent = "";
 +                
 +                // Remove restart button
 +                this.remove();
 +            });
 +            
 +            resultsElement.appendChild(document.createElement("br"));
 +            resultsElement.appendChild(restartBtn);
 +        }
 +
 +        // Initialize progress markers
 +        function initializeProgressMarkers() {
 +            const container = document.getElementById("progressMarkers");
 +            container.innerHTML = "";
 +            
 +            for (let i = 0; i < totalQuizQuestions; i++) {
 +                const marker = document.createElement("div");
 +                marker.className = "progress-marker";
 +                marker.textContent = i + 1;
 +                container.appendChild(marker);
 +            }
 +        }
 +
 +        // Reset progress markers
 +        function resetProgressMarkers() {
 +            const markers = document.querySelectorAll(".progress-marker");
 +            markers.forEach(marker => {
 +                marker.className = "progress-marker";
 +            });
 +        }
 +
 +        // Update progress marker
 +        function updateProgressMarker(index, isCorrect) {
 +            const markers = document.querySelectorAll(".progress-marker");
 +            if (markers[index]) {
 +                markers[index].classList.add("completed");
 +                markers[index].classList.add(isCorrect ? "correct" : "incorrect");
 +            }
 +        }
 +    </script>
 +</body>
 +</html>