diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a4d6d9c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.vs/ \ No newline at end of file diff --git a/MainPage/stas/WoerterLernen.html b/MainPage/stas/WoerterLernen.html index f4862b4..408ddb7 100644 --- a/MainPage/stas/WoerterLernen.html +++ b/MainPage/stas/WoerterLernen.html @@ -7,29 +7,71 @@ -

Flashcards Generator

+
+

Flashcards Generator

+
+
+
+
+ +
+
+
+                Bitte formatiere meine Wortliste exakt nach folgendem Schema.
+                Jeder Eintrag muss durch eine Leerzeile getrennt sein.
 
-    
+                Englisches Wort
+                [IPA-Transkription]
+                Beispielsatz auf Englisch
+                Deutsche Übersetzung des Wortes
+                Beispielsatz auf Deutsch
+                
+ +
+
+
+ + +
+
+
+
+ +
+ -
-
-    Bitte formatiere meine Wortliste exakt nach folgendem Schema.
-    Jeder Eintrag muss durch eine Leerzeile getrennt sein.
+        
+
+
+ +
+
- Englisches Wort - [IPA-Transkription] - Beispielsatz auf Englisch - Deutsche Übersetzung des Wortes - Beispielsatz auf Deutsch +
-
- +
+

Wählt einen Schwierigkeitsgrad:

+ + + +
+ +
+
+
+ +
+ + + +
+ +
- -
- - -
- \ No newline at end of file diff --git a/MainPage/stas/drucker.jfif b/MainPage/stas/drucker.jfif new file mode 100644 index 0000000..2b0d101 Binary files /dev/null and b/MainPage/stas/drucker.jfif differ diff --git a/MainPage/stas/eigenerCode.js b/MainPage/stas/eigenerCode.js index cb37ed4..9073ce2 100644 --- a/MainPage/stas/eigenerCode.js +++ b/MainPage/stas/eigenerCode.js @@ -1,4 +1,6 @@ -document.getElementById('copyButton').addEventListener('click', () => { +let parsedArray = []; + +document.getElementById('copyButton').addEventListener('click', () => { const text = document.getElementById('formatText').innerText; navigator.clipboard.writeText(text).then(() => { @@ -8,8 +10,6 @@ }); }); -const inputText = document.getElementById("inputText").value; -const cards = parseWordText(inputText); function parseWordText(inputText) { const wortBlocks = inputText.trim().split("\n\n"); const wortListe = []; @@ -31,35 +31,279 @@ function parseWordText(inputText) { }; wortListe.push(wortObj); - console.log(wortObj); } return wortListe; } +function createPagePair() { + const frontPage = document.createElement("div"); + frontPage.className = "page page-front"; + + const backPage = document.createElement("div"); + backPage.className = "page page-back"; + + return { frontPage, backPage }; +} + const button = document.getElementById("kartenErstellen"); -const container = document.getElementById("kartenContainer"); +const onlineContainer = document.getElementById("kartenContainer"); +const frontPage = document.querySelector(".page_front"); +const backPage = document.querySelector(".page_back"); button.addEventListener("click", () => { - container.innerHTML = ""; - parsedArray.forEach((karte, index) => { - const karteDiv = document.createElement("div"); - karteDiv.classList.add("karte"); + const inputText = document.getElementById("inputText").value; + parsedArray = parseWordText(inputText); - karteDiv.innerHTML = ` -
-
-

${karte.englisch}

-

${karte.ipa}

-

Beispiel: ${karte.beispielEN}

-
-
-

${karte.deutsch}

-

Beispiel: ${karte.beispielDE}

-
-
- `; - container.appendChild(karteDiv); + if(parsedArray.length === 0) { + alert("Kein gültiges Format erkannt. Bitte überprüfe deine Eingabe."); + return; + } + alert("Karten erfolgreich erstellt!"); + + showView("modusAuswahlSeite"); + + document.getElementById("title").style.display = "none"; + button.style.display = "none"; + + document.getElementById("modusAuswahlSeite").style.display = "block"; +}); + +document.querySelectorAll(".modus-btn").forEach(button => { + button.addEventListener("click", () => { + const modus = button.dataset.modus; + + if (modus === "druck") { + createPDFPages(parsedArray); + } else { + console.log("Gewählter Modus:", modus); + } }); }); + +function createPDFPages(wordArray) { + const kartenContainer = document.getElementById("kartenContainer"); + + kartenContainer.innerHTML = ""; + kartenContainer.style.display = "flex"; + kartenContainer.style.flexDirection = "column"; + + for (let i = 0; i < parsedArray.length; i += 8) { + + const { frontPage, backPage } = createPagePair(); + + parsedArray.slice(i, i + 8).forEach((karte) => { + + const frontCard = document.createElement("div"); + frontCard.className = "card card-en"; + frontCard.innerHTML = ` +

${karte.englisch}

+
${karte.ipa}
+
${karte.beispielEN}
+ `; + frontPage.appendChild(frontCard); + + const backCard = document.createElement("div"); + backCard.className = "card card-de"; + backCard.innerHTML = ` +

${karte.deutsch}

+
${karte.beispielDE}
+ `; + backPage.appendChild(backCard); + }); + + kartenContainer.appendChild(frontPage); + kartenContainer.appendChild(backPage); + document.getElementById("druckenBtn").style.display = "block"; + } + alert("PDF-Seiten wurden erstellt! Du kannst sie jetzt drucken."); +} + +document.getElementById("druckenBtn").addEventListener("click", () => { + window.print(); +}); + +const modusBtns = document.querySelectorAll('.modus-btn'); +const trainingLevels = document.getElementById('trainingLevels'); + +modusBtns.forEach(btn => { + btn.addEventListener('click', () => { + const modus = btn.dataset.modus; + + if (modus === 'druck') { + showView('pdfPages'); + } + + else if (modus === 'training_einfach') { + showView('trainingLevels'); + } + + else if (modus === 'statistik') { + console.log("Statistik anzeigen..."); + } + }); +}); + +let trainingsZustand = { + modus: "leicht", + quelleKarten: [], + aktiveKarten: [], + gelernt: [], + nichtGelernt: [], +}; + +function startLeichtTraining() { + console.log("🔥 startLeichtTraining вызвана"); + + if (!parsedArray || parsedArray.length === 0) { + alert("Нет карточек для тренировки"); + return; + } + + trainingsZustand.quelleKarten = [...parsedArray]; + trainingsZustand.aktiveKarten = []; + trainingsZustand.gelernt = []; + trainingsZustand.nichtGelernt = []; + + for (let i = 0; i < 3; i++) { + if (trainingsZustand.quelleKarten.length > 0) { + const karte = trainingsZustand.quelleKarten.shift(); + karte.versuche = 0; + trainingsZustand.aktiveKarten.push(karte); + } + } + + zeigeNaechsteKarte(); +} + +function zeigeNaechsteKarte() { + if ( + trainingsZustand.aktiveKarten.length === 0 && + trainingsZustand.quelleKarten.length === 0 + ) { + alert(`Training beendet! + Gelernt: ${trainingsZustand.gelernt.length} + Nicht gelernt: ${trainingsZustand.nichtGelernt.length}`); + return; + } + + const index = Math.floor( + Math.random() * trainingsZustand.aktiveKarten.length + ); + + trainingsZustand.aktuelleKarte = + trainingsZustand.aktiveKarten[index]; + + renderLeichtKarte(trainingsZustand.aktuelleKarte); +} + +function renderLeichtKarte(karte) { + const container = document.getElementById("trainingLeicht"); + container.innerHTML = ""; + + const cardEl = document.createElement("div"); + cardEl.className = "training-card"; + cardEl.innerHTML = ` +
+
+

${karte.englisch}

+
${karte.ipa}
+
${karte.beispielEN}
+
+
+

${karte.deutsch}

+
${karte.beispielDE}
+
+
+ `; + + cardEl.onclick = () => cardEl.classList.toggle("flip"); + + const actions = document.createElement("div"); + actions.className = "training-actions"; + actions.innerHTML = ` + + + `; + + actions.querySelector("#knowBtn").onclick = () => antworteAufKarte(true); + actions.querySelector("#dontKnowBtn").onclick = () => antworteAufKarte(false); + + container.appendChild(cardEl); + container.appendChild(actions); +} + +function antworteAufKarte(weißIch) { + const karte = trainingsZustand.aktuelleKarte; + + if (weißIch) { + trainingsZustand.gelernt.push(karte); + trainingsZustand.aktiveKarten = trainingsZustand.aktiveKarten.filter(k => k !== karte); + } else { + karte.versuche++; + if (karte.versuche >= 5) { + trainingsZustand.nichtGelernt.push(karte); + trainingsZustand.aktiveKarten = trainingsZustand.aktiveKarten.filter(k => k !== karte); + } else { + trainingsZustand.aktiveKarten.push(trainingsZustand.aktiveKarten.splice(trainingsZustand.aktiveKarten.indexOf(karte), 1)[0]); + } + } + + if (trainingsZustand.aktiveKarten.length < 3 && trainingsZustand.quelleKarten.length > 0) { + let neueKarte = trainingsZustand.quelleKarten.shift(); + neueKarte.versuche = 0; + trainingsZustand.aktiveKarten.push(neueKarte); + } + + zeigeNaechsteKarte(); +} + +function showView(id) { + document.querySelectorAll(".modus-view").forEach(view => { + view.style.display = "none"; + }); + + const active = document.getElementById(id); + if (active) { + active.style.display = "block"; + } +} + +function showTrainingLevel(id) { + document.querySelectorAll(".training-view").forEach(view => { + view.style.display = "none"; + }); + + const active = document.getElementById(id); + if (active) { + active.style.display = "block"; + } +} + +document.querySelectorAll(".level-btn").forEach(btn => { + btn.addEventListener("click", () => { + const level = btn.dataset.level; + + if (level === "leicht") { + showTrainingLevel("trainingLeicht"); + startLeichtTraining(); + } + + if (level === "mittel") { + showTrainingLevel("trainingMittel"); + startMittelTraining(); + } + + if (level === "schwer") { + showTrainingLevel("trainingSchwer"); + startSchwerTraining(); + } + }); +}); + +document + .querySelector(".modus-btn[data-modus='training_einfach']") + .addEventListener("click", () => { + showView("onlineTraining"); +}); diff --git a/MainPage/stas/flashcards.webp b/MainPage/stas/flashcards.webp new file mode 100644 index 0000000..0baf4c7 Binary files /dev/null and b/MainPage/stas/flashcards.webp differ diff --git a/MainPage/stas/style.css b/MainPage/stas/style.css index a8138c5..dfe3695 100644 --- a/MainPage/stas/style.css +++ b/MainPage/stas/style.css @@ -1,31 +1,366 @@ -#aufgabe_fuer_gpt { - position: relative; - border: 1px solid #ccc; - padding: 10px; - border-radius: 5px; - width: 500px; - background: #f9f9f9; +body { + margin: 0; + padding: 0; + font-family: "Arial", sans-serif; + background-color: #f4f6fb; + color: #333; +} + +h1 { + text-align: center; + margin-top: 30px; + margin-bottom: 20px; +} + +.main-header { + position: relative; + top: 0; + width: 100%; + background-color: #880b75; + color: white; + padding: 18px 0; + text-align: center; + z-index: 1000; +} + +.main-header h1 { + margin: 0; + font-size: 46px; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif; + line-height: 1.5; +} + +.main-wrapper { + max-width: 900px; + margin: 0 auto; + margin-top: 10px; + padding: 20px; + background-color: #d9cfe0; + border-radius: 12px; + box-shadow: 0 10px 30px rgba(0,0,0,0.08); +} + +.input-section { + margin-bottom: 30px; +} + +.input-section h2 { + margin-bottom: 10px; +} + +.hint-text { + font-size: 14px; + color: #666; + margin-bottom: 10px; +} + +#aufgabe_fuer_gpt { + position: relative; + background-color: #f0f3ff; + border: 1px dashed #9aa5ff; + border-radius: 8px; + padding: 12px; + margin: 20px; + margin-top: 0; +} + +#aufgabe_fuer_gpt pre { + margin: 0; + font-size: 13px; + white-space: pre-wrap; +} + +#copyButton { + position: absolute; + top: 8px; + right: 8px; + background: white; + border: 1px solid #ccc; + border-radius: 6px; + cursor: pointer; + padding: 4px 6px; +} + +.content { + max-width: 900px; + margin: 0 auto; + padding: 30px 20px; +} + +.section-title { + display: block; + font-size: 18px; + font-weight: 600; + margin-bottom: 10px; +} + +#inputText { + width: 100%; + min-height: 220px; + padding: 14px; + font-size: 16px; + line-height: 1.5; + border-radius: 6px; + border: 1px solid #ccc; + resize: vertical; + box-sizing: border-box; } #kartenContainer { + margin-top: 30px; + display: none; + flex-direction: column; + gap: 40px; + align-items: center; +} + +.page { + width: 190mm; + height: 277mm; + padding: 0; + box-sizing: border-box; + background: white; + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(4, 1fr); + page-break-after: always; +} + +.page-back { + display: grid; + grid-template-columns: repeat(2, 1fr); + grid-template-rows: repeat(4, 1fr); + + direction: rtl; +} + +.page-back .card { + direction: ltr; +} + + +.card { + position: relative; + overflow: hidden; + border: 1px dashed #333; + border-radius: 0; + padding: 25px; + box-sizing: border-box; + + display: flex; + flex-direction: column; + justify-content: center; + + font-family: Arial, sans-serif; +} + +.card::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 10mm; +} + +.card-en::before { + background-color: #f4c430; +} + +.card-de::before { + background-color: #ccc; +} + +.card h2 { + margin: 0; + margin-bottom: 6px; + font-size: 22px; +} + +.card .ipa { + font-size: 14px; + color: #666; +} + +.card .example { + margin-top: 80px; + font-size: 14px; + color: #333; +} + +.button-wrapper { + max-width: 900px; + margin: 20px auto; + padding: 10px 20px; display: flex; - gap: 15px; - flex-wrap: wrap; justify-content: center; } -.karte { - width: 120px; +#kartenErstellen { + width: 100%; + height: 100px; + font-size: 46px; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif; + color: #dc6743; + border: none; + border-radius: 8px; + cursor: pointer; + box-sizing: border-box; + background: linear-gradient(rgba(255,255,255,0.7), rgba(255,255,255,0.9)), url("flashcards.webp"); + background-size: cover; + background-position: center; +} + +#druckenBtn { + width: 500px; + height: 100px; + font-size: 46px; + font-weight: 600; + font-family: -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", Arial, sans-serif; + color: #dc6743; + border: none; + border-radius: 8px; + cursor: pointer; + box-sizing: border-box; + background: linear-gradient(rgba(255,255,255,0.7), rgba(255,255,255,0.9)), url("drucker.jfif"); + background-repeat: repeat; + background-size: 80px; +} + +.erfolgsmeldung, +.modus-auswahl { + display: none; + max-width: 600px; + margin: 20px auto; + text-align: center; +} + +.erfolgsmeldung { + background-color: #e6f4f1; + color: #005b5b; + padding: 12px; + border-radius: 6px; + font-weight: 600; +} + +.modus-auswahl p { + margin-bottom: 12px; + font-weight: 500; +} + +.modus-btn { + margin: 6px; + padding: 10px 16px; + border: none; + border-radius: 6px; + background-color: #005b5b; + color: white; + cursor: pointer; +} + +.modus-btn:hover { + background-color: #007070; +} + +@media print { + body * { + visibility: hidden; + } + #kartenContainer, #kartenContainer * { + visibility: visible; + } + #kartenContainer { + position: absolute; + left: 0; + top: 0; + width: 100%; + margin: 0; + padding: 0; + } +} + +.training-card { + width: 300px; height: 180px; + margin: 10px auto; + perspective: 1000px; + cursor: pointer; +} + +.training-card-inner { + width: 100%; + height: 100%; + position: relative; + transition: transform 0.6s; + transform-style: preserve-3d; +} + +.training-card.flip .training-card-inner { + transform: rotateY(180deg); +} + +.training-front, +.training-back { + position: absolute; + width: 100%; + height: 100%; + backface-visibility: hidden; border: 2px solid #333; border-radius: 10px; - background-color: white; - box-shadow: 2px 2px 8px rgba(0,0,0,0.1); + padding: 15px; + box-sizing: border-box; display: flex; - align-items: center; + flex-direction: column; justify-content: center; - font-size: 24px; - cursor: pointer; - user-select: none; - transition: transform 0.2s; + gap: 10px; +} + +.training-back { + transform: rotateY(180deg); + background: #f3f3f3; +} + +.training-actions { + text-align: center; + margin-top: 15px; +} + +.training-actions button { + margin: 0 10px; + padding: 8px 16px; + font-size: 16px; + cursor: pointer; +} + +.training-front h2 { + margin-bottom: 4px; + margin-top: -25px; +} + +.training-front .ipa { + font-size: 16px; + color: #555; + margin-bottom: 34px; + margin-top: -12px; +} + +.training-front .example { + font-size: 15px; + line-height: 1.4; +} + +.training-back h2 { + margin-bottom: 54px; + margin-top: -28px; +} + +.modus-view { + display: none; +} + +.training-view { + display: none; + margin-top: 25px; } diff --git a/MainPage/younes/Streichholzreatsel.css b/MainPage/younes/Streichholzreatsel.css index e69de29..15a9bcc 100644 --- a/MainPage/younes/Streichholzreatsel.css +++ b/MainPage/younes/Streichholzreatsel.css @@ -0,0 +1,266 @@ + :root{ + --bg:#0b1020; + --panel:#0f1733; + --text:#e9eeff; + --muted:#9fb0ff; + --shadow: 0 10px 30px rgba(0,0,0,.35); + --gap: 14px; + --matchW: 14px; + --matchL: 68px; + --matchT: 14px; + --radius: 12px; + } + *{box-sizing:border-box} + body{ + margin:0; + min-height:100vh; + background: radial-gradient(1200px 600px at 20% 20%, #1a2a7a 0%, transparent 60%), + radial-gradient(900px 500px at 85% 30%, #2b1a7a 0%, transparent 60%), + var(--bg); + color:var(--text); + font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, sans-serif; + display:flex; + align-items:center; + justify-content:center; + padding:24px; + } + .app{ + width:min(1100px, 100%); + display:grid; + grid-template-columns: 1.3fr .9fr; + gap:18px; + } + @media (max-width: 980px){ + .app{grid-template-columns:1fr} + } + + .card{ + background: linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,.03)); + border: 1px solid rgba(255,255,255,.10); + border-radius: 18px; + box-shadow: var(--shadow); + overflow:hidden; + } + .card-header{ + padding:16px 18px; + border-bottom: 1px solid rgba(255,255,255,.10); + display:flex; + align-items:center; + justify-content:space-between; + gap:12px; + } + .title{ + display:flex; + flex-direction:column; + gap:4px; + } + .title h1{ + font-size:18px; + margin:0; + letter-spacing:.2px; + } + .title .sub{ + font-size:12px; + color:var(--muted); + } + .controls{ + display:flex; + gap:10px; + flex-wrap:wrap; + justify-content:flex-end; + } + button{ + border:none; + padding:10px 12px; + border-radius: 12px; + background: rgba(255,255,255,.12); + color:var(--text); + cursor:pointer; + font-weight:600; + letter-spacing:.2px; + transition: transform .05s ease, background .2s ease; + user-select:none; + } + button:hover{ background: rgba(255,255,255,.18); } + button:active{ transform: translateY(1px); } + button.primary{ + background: linear-gradient(180deg, rgba(102,168,255,.7), rgba(102,168,255,.35)); + } + button.primary:hover{ + background: linear-gradient(180deg, rgba(102,168,255,.85), rgba(102,168,255,.45)); + } + + .play{ + padding:18px; + display:flex; + flex-direction:column; + gap:14px; + } + + .statusRow{ + display:flex; + flex-wrap:wrap; + gap:10px; + align-items:center; + justify-content:space-between; + background: rgba(0,0,0,.18); + border: 1px solid rgba(255,255,255,.08); + border-radius: 14px; + padding:12px 14px; + } + .pill{ + display:inline-flex; + align-items:center; + gap:8px; + padding:8px 10px; + border-radius: 999px; + background: rgba(255,255,255,.08); + font-size:12px; + color:var(--text); + border:1px solid rgba(255,255,255,.08); + white-space:nowrap; + } + .dot{ + width:10px;height:10px;border-radius:50%; + background:#ff5c5c; + box-shadow: 0 0 0 3px rgba(255,92,92,.15); + } + .dot.ok{ + background:#29e07a; + box-shadow: 0 0 0 3px rgba(41,224,122,.15); + } + + /* Equation layout */ + .equationWrap{ + background: rgba(0,0,0,.18); + border: 1px solid rgba(255,255,255,.08); + border-radius: 16px; + padding:16px; + overflow:auto; + } + .equation{ + display:flex; + align-items:center; + gap: var(--gap); + padding:8px; + min-width: 740px; + } + .group{ + display:flex; + align-items:center; + gap: var(--gap); + } + .symbol{ + font-size: 34px; + font-weight: 900; + color: rgba(255,255,255,.85); + padding: 6px 10px; + border-radius: 14px; + background: rgba(255,255,255,.06); + border: 1px solid rgba(255,255,255,.08); + user-select:none; + } + + .digit{ + position:relative; + width: 110px; + height: 170px; + border-radius: 16px; + background: rgba(255,255,255,.04); + border: 1px solid rgba(255,255,255,.07); + box-shadow: inset 0 0 0 1px rgba(0,0,0,.35); + flex:0 0 auto; + } + + .seg{ + position:absolute; + width: var(--matchL); + height: var(--matchW); + border-radius: 999px; + cursor:pointer; + transition: filter .12s ease, transform .05s ease; + box-shadow: 0 10px 18px rgba(0,0,0,.25); + } + .seg:hover{ filter: brightness(1.1); } + .seg:active{ transform: translateY(1px); } + + .seg.removed{ + background: rgba(255,255,255,0) !important; + box-shadow:none; + cursor:not-allowed; + pointer-events:none; + } + + + .seg.a{ top: 16px; left: 21px; } + .seg.b{ top: 32px; left: 73px; width: var(--matchW); height: var(--matchL); } + .seg.c{ top: 92px; left: 73px; width: var(--matchW); height: var(--matchL); } + .seg.d{ top: 146px; left: 21px; } + .seg.e{ top: 92px; left: 23px; width: var(--matchW); height: var(--matchL); } + .seg.f{ top: 32px; left: 23px; width: var(--matchW); height: var(--matchL); } + .seg.g{ top: 81px; left: 21px; } + + .side{ + padding:18px; + display:flex; + flex-direction:column; + gap:14px; + } + .hint{ + background: rgba(0,0,0,.18); + border: 1px solid rgba(255,255,255,.08); + border-radius: 16px; + padding:14px; + color: rgba(255,255,255,.9); + font-size:13px; + line-height:1.4; + } + .hint b{ color:#fff; } + + .removedBox{ + background: rgba(0,0,0,.18); + border: 1px solid rgba(255,255,255,.08); + border-radius: 16px; + padding:14px; + min-height: 160px; + display:flex; + flex-direction:column; + gap:10px; + } + .removedHeader{ + display:flex; + align-items:center; + justify-content:space-between; + gap:10px; + } + .removedHeader .label{ + font-weight:800; + font-size:13px; + color: rgba(255,255,255,.92); + } + .removedHeader .count{ + font-size:12px; + color: var(--muted); + white-space:nowrap; + } + .removedGrid{ + display:flex; + flex-wrap:wrap; + gap:10px; + align-items:center; + } + .removedSeg{ + width: 44px; + height: 16px; + border-radius: 999px; + box-shadow: 0 8px 16px rgba(0,0,0,.25); + border: 1px solid rgba(255,255,255,.12); + } + .footerNote{ + font-size:12px; + color: rgba(255,255,255,.7); + line-height:1.35; + } + .mono{ + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono","Courier New", monospace; + } \ No newline at end of file diff --git a/MainPage/younes/Streichholzreatsel.html b/MainPage/younes/Streichholzreatsel.html index 4de0e9b..52ac2fa 100644 --- a/MainPage/younes/Streichholzreatsel.html +++ b/MainPage/younes/Streichholzreatsel.html @@ -1,14 +1,76 @@ - + - - - Streichholzrätsel + + + + Allumettes (Matchstick) Equation Infinite Levels + -

Streichholzrätsel Game

- +
+
+
+
+

Allumettes Equation Infinite Levels

+
Klicke auf die Streichhölzer, um sie zu entfernen (sie werden weiß bzw. unsichtbar). + Mache die Gleichung wahr, indem du genau die vorgegebene Anzahl entfernst.
+
+
+ + +
+
- +
+
+
Level: 1
+
lösch target: 2
+
gelöscht 0
+
+ + Equation ist falsch +
+
+ +
+
+
+ +
+ Goal: lösch N sodass die Gleichung WAHR wird. + Es ist nur das Entfernen erlaubt (kein Hinzufügen). Die Ziffern bestehen aus 7 Segmenten. +Der Generator garantiert, dass jedes Level lösbar ist (unendlich viele Level). +
+
+
+ +
+
+
+

gelöschte matches

+
jede click clont den match hier.
+
+
+ +
+
+ +
+
+
gelöschte pile
+
0 sticks
+
+
+
+ +
+ Tip: Du kannst Streichhölzer von jeder Ziffer in der Gleichung entfernen. +Eine Ziffer ändert sich nur dann in eine andere Ziffer, wenn die verbleibenden Segmente einem gültigen Muster von 0 bis 9 entsprechen. +
+
+
+
+ - \ No newline at end of file + diff --git a/MainPage/younes/Streichholzreatsel.js b/MainPage/younes/Streichholzreatsel.js index e69de29..ec669a7 100644 --- a/MainPage/younes/Streichholzreatsel.js +++ b/MainPage/younes/Streichholzreatsel.js @@ -0,0 +1,370 @@ + + + +// Die Namen der 7 Segmente (a bis g) +const SEGMENT_NAMEN = ["a", "b", "c", "d", "e", "f", "g"]; + +// Ein Mapping: Welches Segment hat welchen "Bit Wert"? +// a=1, b=2, c=4, d=8 ... das sind Zweierpotenzen. +const SEGMENT_INDEX = { a:0, b:1, c:2, d:3, e:4, f:5, g:6 }; + +// Diese Funktion rechnet eine Liste von Segmenten (z.B. "a", "b") in eine Zahl um. +function erstelleMuster(listeVonSegmenten) { + let muster = 0; + for (const segmentBuchstabe of listeVonSegmenten) { + // 1 << X bedeutet: Schiebe die 1 um X Stellen nach links + // Das | (ODER) fügt das Bit hinzu. + muster = muster | (1 << SEGMENT_INDEX[segmentBuchstabe]); + } + return muster; +} + +// Hier speichern wir das Muster für jede Ziffer von 0 bis 9 +// bitmasking: Jede Ziffer ist eine Kombination von Segmenten die an sind +const ZIFFERN_MUSTER = [ + erstelleMuster(["a","b","c","d","e","f"]), // 0 + erstelleMuster(["b","c"]), // 1 + erstelleMuster(["a","b","d","e","g"]), // 2 + erstelleMuster(["a","b","c","d","g"]), // 3 + erstelleMuster(["b","c","f","g"]), // 4 + erstelleMuster(["a","c","d","f","g"]), // 5 + erstelleMuster(["a","c","d","e","f","g"]), // 6 + erstelleMuster(["a","b","c"]), // 7 + erstelleMuster(["a","b","c","d","e","f","g"]), // 8 + erstelleMuster(["a","b","c","d","f","g"]) // 9 +]; + +// Eine Rückwärts Suche: Welches Muster gehört zu welcher Zahl? +// Wir bauen eine Map (Liste), um das schnell zu finden. +const MUSTER_ZU_ZAHL = new Map(); +ZIFFERN_MUSTER.forEach((muster, zahl) => { + MUSTER_ZU_ZAHL.set(muster, zahl); +}); + + + + +// Zählt, wie viele Bits in einer Zahl auf 1 stehen. +// (Also: Wie viele Streichhölzer sind an?) +function zaehleStreichhoelzer(zahl) { + let anzahl = 0; + // Solange die Zahl nicht 0 ist + while (zahl > 0) { + // Ein kleiner Trick um das letzte Bit zu löschen und zu zählen + zahl = zahl & (zahl - 1); + anzahl++; + } + return anzahl; +} + +// Gibt eine zufällige Zahl zwischen min und max zurück +function zufallsZahl(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min; +} + +// Wählt ein zufälliges Element aus einer Liste +function wähleZufällig(liste) { + return liste[zufallsZahl(0, liste.length - 1)]; +} + +// Findet alle Zahlen, aus denen man 'basisZahl' machen kann, indem man Hölzer entfernt. +// Beispiel: Aus einer 8 kann man eine 0 machen (Mitte wegnehmen). +// Aber aus einer 1 kann man keine 8 machen (man müsste hinzufügen). +function findeMoeglicheUrsprungsZiffern(basisZahl) { + const basisMuster = ZIFFERN_MUSTER[basisZahl]; + const moegliche = []; + + for (let z = 0; z <= 9; z++) { + const vergleichsMuster = ZIFFERN_MUSTER[z]; + + // Wenn das vergleichsMuster ALLE Striche vom basisMuster hat: + if ((vergleichsMuster & basisMuster) === basisMuster) { + moegliche.push(z); + } + } + return moegliche; +} + + + + +let aktuellesLevel = 1; +let zielAnzahlLoeschen = 2; // Wie viele muss man löschen? +let anzahlGeloescht = 0; // Wie viele hat der Spieler schon gelöscht? + +// Hier speichern wir die aktuellen Zahlen auf dem Bildschirm +let aktuelleGleichung = { A: 0, B: 0, C: 0 }; + +// Hier merken wir uns, welche Striche der Spieler angeklickt hat. +// Format: "Index-Segment", z.B. "0-a" (Erste Ziffer, Segment a) +let geloeschteStreichhoelzer = new Set(); + + + +const elGleichung = document.getElementById("equation"); +const elGeloeschtGrid = document.getElementById("removedGrid"); +const elZaehlerGeloescht = document.getElementById("removedCount"); +const elStapelZaehler = document.getElementById("pileCount"); +const elLevelAnzeige = document.getElementById("lvl"); +const elZielAnzeige = document.getElementById("target"); +const elZielText = document.getElementById("goalN"); +const elWahrheitPunkt = document.getElementById("truthDot"); +const elWahrheitText = document.getElementById("truthText"); +const elHinweis = document.getElementById("hint"); + +// Buttons aktivieren +document.getElementById("btnNew").addEventListener("click", () => { + aktuellesLevel++; + starteNeuesLevel(); +}); + +document.getElementById("btnReset").addEventListener("click", () => { + // Level neu starten (aber gleiches Level) + setzeSpielZurueck(); + zeichneGleichung(); + pruefeObWahr(); +}); + + + +function setzeSpielZurueck() { + geloeschteStreichhoelzer.clear(); // Liste leeren + anzahlGeloescht = 0; + elGeloeschtGrid.innerHTML = ""; // Anzeige leeren + updateZaehlerAnzeige(); +} + +function updateZaehlerAnzeige() { + elZaehlerGeloescht.textContent = anzahlGeloescht; + elStapelZaehler.textContent = anzahlGeloescht; +} + +// Berechnet, welche Zahl gerade angezeigt wird (basierend auf dem was gelöscht wurde) +function berechneAngezeigteZahl(originalZahl, positionIndex) { + let maske = ZIFFERN_MUSTER[originalZahl]; + + // Wir gehen alle 7 Segmente durch + for (const seg of SEGMENT_NAMEN) { + const schluessel = positionIndex + "-" + seg; + + // Wenn dieses Segment gelöscht wurde... + if (geloeschteStreichhoelzer.has(schluessel)) { + // ... dann schalten wir das Bit in der Maske aus (mit & ~) + maske = maske & ~(1 << SEGMENT_INDEX[seg]); + } + } + + // Schauen, ob das resultierende Muster eine gültige Zahl ist + if (MUSTER_ZU_ZAHL.has(maske)) { + return MUSTER_ZU_ZAHL.get(maske); + } else { + return null; // Keine gültige Zahl (Kaputt) + } +} + +// Prüft: Ist A + B = C ? +function istGleichungWahr() { + const a = berechneAngezeigteZahl(aktuelleGleichung.A, 0); + const b = berechneAngezeigteZahl(aktuelleGleichung.B, 1); + const c = berechneAngezeigteZahl(aktuelleGleichung.C, 2); + + // Wenn irgendeine Zahl ungültig ist, ist die Gleichung falsch + if (a === null || b === null || c === null) return false; + + return (a + b) === c; +} + +function pruefeObWahr() { + const istWahr = istGleichungWahr(); + + if (istWahr) { + elWahrheitPunkt.classList.add("ok"); + elWahrheitText.textContent = "Gleichung ist WAHR"; + } else { + elWahrheitPunkt.classList.remove("ok"); + elWahrheitText.textContent = "Gleichung ist FALSCH"; + } +} + + +// Erstellt das HTML für EINE Ziffer +function erstelleZifferHTML(zahlenWert, positionIndex, farbe) { + const zifferContainer = document.createElement("div"); + zifferContainer.className = "digit"; + + // Welche Segmente hat die Zahl ursprünglich? + const maske = ZIFFERN_MUSTER[zahlenWert]; + + for (let i = 0; i < 7; i++) { + const segName = SEGMENT_NAMEN[i]; + + // Prüfen: Hat die Zahl dieses Segment? (Bit Test) + const hatSegment = (maske & (1 << i)) !== 0; + + if (hatSegment) { + const segElement = document.createElement("div"); + segElement.className = "seg " + segName; + segElement.style.background = farbe; + + // Eindeutige ID für dieses Segment (z.B. "0-a") + const id = positionIndex + "-" + segName; + + // Wenn schon gelöscht, Klasse hinzufügen + if (geloeschteStreichhoelzer.has(id)) { + segElement.classList.add("removed"); + } + + // Klick Event (Hier passiert die Action!) + segElement.addEventListener("click", () => { + // Abbruch wenn schon weg oder Limit erreicht + if (geloeschteStreichhoelzer.has(id)) return; + if (anzahlGeloescht >= zielAnzahlLoeschen) return; + + // Löschen durchführen + geloeschteStreichhoelzer.add(id); + anzahlGeloescht++; + segElement.classList.add("removed"); + + // Kleines Streichholz in den Mülleimer animieren + const clone = document.createElement("div"); + clone.className = "removedSeg"; + clone.style.background = farbe; + elGeloeschtGrid.appendChild(clone); + + updateZaehlerAnzeige(); + pruefeObWahr(); + + // Gewinn Prüfung + if (anzahlGeloescht === zielAnzahlLoeschen) { + if (istGleichungWahr()) { + elHinweis.innerHTML = "Gelöst! Super gemacht. Klicke auf Neu level."; + } else { + elHinweis.innerHTML = "Nicht gelöst. Alle Züge verbraucht, aber Gleichung falsch. Reset?"; + } + } + }); + + zifferContainer.appendChild(segElement); + } + } + return zifferContainer; +} + +function zeichneGleichung() { + elGleichung.innerHTML = ""; // Alles löschen + + const farben = [ + "linear-gradient(180deg,#ff6b6b,#d64545)", // Rot für A + "linear-gradient(180deg,#6bcBff,#3a7bd5)", // Blau für B + "linear-gradient(180deg,#6bffb3,#1fae63)" // Grün für C + ]; + + // Gruppe A bauen + const g1 = document.createElement("div"); + g1.className = "group"; + g1.appendChild(erstelleZifferHTML(aktuelleGleichung.A, 0, farben[0])); + + // Plus Zeichen + const plus = document.createElement("div"); + plus.className = "symbol"; + plus.textContent = "+"; + + // Gruppe B bauen + const g2 = document.createElement("div"); + g2.className = "group"; + g2.appendChild(erstelleZifferHTML(aktuelleGleichung.B, 1, farben[1])); + + // Ist Gleich Zeichen + const eq = document.createElement("div"); + eq.className = "symbol"; + eq.textContent = "="; + + // Gruppe C bauen + const g3 = document.createElement("div"); + g3.className = "group"; + g3.appendChild(erstelleZifferHTML(aktuelleGleichung.C, 2, farben[2])); + + // Alles zusammenfügen + elGleichung.appendChild(g1); + elGleichung.appendChild(plus); + elGleichung.appendChild(g2); + elGleichung.appendChild(eq); + elGleichung.appendChild(g3); + + pruefeObWahr(); +} + + + + // 7. LEVEL GENERATOR (Das Gehirn) + // Hier wird ein Level gebaut, das garantiert lösbar ist. + + +function starteNeuesLevel() { + setzeSpielZurueck(); + + // Ziel berechnen: Level 1-2 -> 2 löschen, danach evtl mehr. Max 6. + zielAnzahlLoeschen = Math.min(2 + Math.floor(Math.log2(aktuellesLevel + 1)), 6); + + let versuche = 0; + + // Endlosschleife, bis wir ein passendes Level finden + while (true) { + versuche++; + // Sicherheitsnetz: Wenn es zu lange dauert, Ziel senken + if (versuche > 5000) { + zielAnzahlLoeschen = Math.max(2, zielAnzahlLoeschen - 1); + versuche = 0; + } + + // 1. Wir denken uns eine KORREKTE Lösung aus (z.B. 3 + 5 = 8) + const lsgA = zufallsZahl(0, 9); + const lsgB = zufallsZahl(0, 9); + const lsgC = lsgA + lsgB; + + if (lsgC > 9) continue; // Ergebnis darf nur 1 stellig sein (0-9) + + // 2. Wir suchen Zahlen, die mehr Striche haben als unsere Lösung + // (Aus denen man die Lösung "schnitzen" kann) + const moeglicheA = findeMoeglicheUrsprungsZiffern(lsgA); + const moeglicheB = findeMoeglicheUrsprungsZiffern(lsgB); + const moeglicheC = findeMoeglicheUrsprungsZiffern(lsgC); + + // Eine zufällige Auswahl treffen + const startA = wähleZufällig(moeglicheA); + const startB = wähleZufällig(moeglicheB); + const startC = wähleZufällig(moeglicheC); + + // 3. Berechnen: Wie viele Striche müssen weg, um zur Lösung zu kommen? + // XOR (^) zeigt den Unterschied an. + const diffA = zaehleStreichhoelzer(ZIFFERN_MUSTER[startA] ^ ZIFFERN_MUSTER[lsgA]); + const diffB = zaehleStreichhoelzer(ZIFFERN_MUSTER[startB] ^ ZIFFERN_MUSTER[lsgB]); + const diffC = zaehleStreichhoelzer(ZIFFERN_MUSTER[startC] ^ ZIFFERN_MUSTER[lsgC]); + + const gesamtWeg = diffA + diffB + diffC; + + // Passt das zu unserem Ziel? + if (gesamtWeg !== zielAnzahlLoeschen) continue; + + // 4. Wichtig: Die angezeigte Start Gleichung muss FALSCH sein. + // Sonst gibt es ja nichts zu rätseln. + if ((startA + startB) === startC) continue; + + // Gefunden! Speichern. + aktuelleGleichung = { A: startA, B: startB, C: startC }; + break; // Schleife beenden + } + + // UI Updates + elLevelAnzeige.textContent = aktuellesLevel; + elZielAnzeige.textContent = zielAnzahlLoeschen; + elZielText.textContent = zielAnzahlLoeschen; + + elHinweis.innerHTML = + `Level ${aktuellesLevel}: Mache die Gleichung wahr, indem du ${zielAnzahlLoeschen} Streichhölzer entfernst.`; + + zeichneGleichung(); +} + +// Spiel starten! +starteNeuesLevel(); \ No newline at end of file