Merge branch 'master' of https://git.bib.de/PBT3H24AKH/LerningCSW
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
<h1>Team Game Platform</h1>
|
<h1>Team Game Platform</h1>
|
||||||
|
|
||||||
<div class="games-container">
|
<div class="games-container">
|
||||||
<div class="game-card" onclick="location.href='member1/game.html'">
|
<div class="game-card" onclick="location.href='saad/index.html'">
|
||||||
<h2>Game 1</h2>
|
<h2>Game 1</h2>
|
||||||
<p>Member 1</p>
|
<p>Member 1</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
692
MainPage/saad/index.html
Normal file
692
MainPage/saad/index.html
Normal file
@@ -0,0 +1,692 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>WORDLE</title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display:ital@0;1&family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--bg: #faf8f3;
|
||||||
|
--surface: #f2ede4;
|
||||||
|
--ink: #1a1612;
|
||||||
|
--muted: #9e9488;
|
||||||
|
--border: #d8d0c4;
|
||||||
|
--correct: #4a7c59;
|
||||||
|
--present: #c97d2a;
|
||||||
|
--absent: #8a8278;
|
||||||
|
--correct-light: #d4ead9;
|
||||||
|
--present-light: #f5ddb8;
|
||||||
|
--absent-light: #d4d0cb;
|
||||||
|
--accent: #b5451b;
|
||||||
|
}
|
||||||
|
|
||||||
|
* { margin:0; padding:0; box-sizing:border-box; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: 'DM Mono', monospace;
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Paper texture */
|
||||||
|
body::before {
|
||||||
|
content: '';
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)' opacity='0.025'/%3E%3C/svg%3E");
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
padding: 24px 20px 16px;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 2px solid var(--ink);
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: 'DM Serif Display', serif;
|
||||||
|
font-size: 2.8rem;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
color: var(--ink);
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
font-size: 0.6rem;
|
||||||
|
letter-spacing: 0.25em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 24px 16px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toast */
|
||||||
|
#toast {
|
||||||
|
position: fixed;
|
||||||
|
top: 80px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%) translateY(-20px);
|
||||||
|
background: var(--ink);
|
||||||
|
color: var(--bg);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
padding: 10px 20px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s, transform 0.2s;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 100;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
#toast.show {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(-50%) translateY(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grid */
|
||||||
|
#grid {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border: 2px solid var(--border);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-family: 'DM Serif Display', serif;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
color: var(--ink);
|
||||||
|
text-transform: uppercase;
|
||||||
|
position: relative;
|
||||||
|
transition: border-color 0.1s;
|
||||||
|
background: var(--bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.filled {
|
||||||
|
border-color: var(--muted);
|
||||||
|
animation: pop 0.1s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pop {
|
||||||
|
0% { transform: scale(1); }
|
||||||
|
50% { transform: scale(1.08); }
|
||||||
|
100% { transform: scale(1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.correct {
|
||||||
|
background: var(--correct);
|
||||||
|
border-color: var(--correct);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.present {
|
||||||
|
background: var(--present);
|
||||||
|
border-color: var(--present);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.absent {
|
||||||
|
background: var(--absent);
|
||||||
|
border-color: var(--absent);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.flip {
|
||||||
|
animation: flip 0.5s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flip {
|
||||||
|
0% { transform: rotateX(0deg); }
|
||||||
|
50% { transform: rotateX(-90deg); background: transparent; }
|
||||||
|
100% { transform: rotateX(0deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.shake {
|
||||||
|
animation: shake 0.4s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0%,100% { transform: translateX(0); }
|
||||||
|
20% { transform: translateX(-6px); }
|
||||||
|
40% { transform: translateX(6px); }
|
||||||
|
60% { transform: translateX(-4px); }
|
||||||
|
80% { transform: translateX(4px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
.cell.bounce {
|
||||||
|
animation: bounce 0.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bounce {
|
||||||
|
0%,100% { transform: translateY(0); }
|
||||||
|
40% { transform: translateY(-12px); }
|
||||||
|
70% { transform: translateY(-6px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keyboard */
|
||||||
|
#keyboard {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kb-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key {
|
||||||
|
height: 56px;
|
||||||
|
min-width: 36px;
|
||||||
|
padding: 0 8px;
|
||||||
|
border: 1.5px solid var(--border);
|
||||||
|
background: var(--surface);
|
||||||
|
color: var(--ink);
|
||||||
|
font-family: 'DM Mono', monospace;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background 0.15s, border-color 0.15s, color 0.15s;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key:active { transform: scale(0.95); }
|
||||||
|
|
||||||
|
.key.wide { min-width: 56px; font-size: 0.65rem; }
|
||||||
|
|
||||||
|
.key.correct {
|
||||||
|
background: var(--correct);
|
||||||
|
border-color: var(--correct);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key.present {
|
||||||
|
background: var(--present);
|
||||||
|
border-color: var(--present);
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.key.absent {
|
||||||
|
background: var(--absent-light);
|
||||||
|
border-color: var(--absent-light);
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Win/Lose overlay */
|
||||||
|
#result-panel {
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12px;
|
||||||
|
padding: 24px;
|
||||||
|
background: var(--surface);
|
||||||
|
border: 2px solid var(--ink);
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#result-panel.show { display: flex; }
|
||||||
|
|
||||||
|
.result-title {
|
||||||
|
font-family: 'DM Serif Display', serif;
|
||||||
|
font-size: 2rem;
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-word {
|
||||||
|
font-size: 0.7rem;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-word strong {
|
||||||
|
font-family: 'DM Serif Display', serif;
|
||||||
|
font-size: 1.4rem;
|
||||||
|
color: var(--accent);
|
||||||
|
letter-spacing: 0.1em;
|
||||||
|
font-weight: normal;
|
||||||
|
display: block;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-btn {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-family: 'DM Mono', monospace;
|
||||||
|
font-size: 0.7rem;
|
||||||
|
letter-spacing: 0.2em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
padding: 12px 32px;
|
||||||
|
background: var(--ink);
|
||||||
|
color: var(--bg);
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-btn:hover { opacity: 0.8; }
|
||||||
|
|
||||||
|
.stats-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-item { text-align: center; }
|
||||||
|
.stat-n {
|
||||||
|
font-family: 'DM Serif Display', serif;
|
||||||
|
font-size: 1.8rem;
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
.stat-l {
|
||||||
|
font-size: 0.55rem;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div id="toast"></div>
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<h1>Wordle</h1>
|
||||||
|
<div class="subtitle">Guess the five-letter word</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div id="grid"></div>
|
||||||
|
<div id="result-panel">
|
||||||
|
<div class="result-title" id="result-title">Brilliant!</div>
|
||||||
|
<div class="result-word">
|
||||||
|
The word was
|
||||||
|
<strong id="result-word-display"></strong>
|
||||||
|
</div>
|
||||||
|
<div class="stats-row">
|
||||||
|
<div class="stat-item"><div class="stat-n" id="stat-played">0</div><div class="stat-l">Played</div></div>
|
||||||
|
<div class="stat-item"><div class="stat-n" id="stat-wins">0</div><div class="stat-l">Wins</div></div>
|
||||||
|
<div class="stat-item"><div class="stat-n" id="stat-streak">0</div><div class="stat-l">Streak</div></div>
|
||||||
|
</div>
|
||||||
|
<button class="play-btn" onclick="newGame()">New Word</button>
|
||||||
|
</div>
|
||||||
|
<div id="keyboard"></div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const WORDS = [
|
||||||
|
"CRANE","SLATE","TRACE","AUDIO","AROSE","STARE","SNARE","LEAST","IRATE","ARISE",
|
||||||
|
"PLUMB","FJORD","EQUIP","GLYPH","WALTZ","AFFIX","JUMPY","ONYX","PROXY","SIXTH",
|
||||||
|
"ABBEY","ABBOT","ABHOR","ABIDE","ABLER","ABODE","ABORT","ABOUT","ABOVE","ABUSE",
|
||||||
|
"ACUTE","ADMIT","ADOBE","ADOPT","ADULT","AFTER","AGAIN","AGENT","AGILE","AGING",
|
||||||
|
"AGONY","AGORA","AGREE","AHEAD","AIDER","AISLE","ALARM","ALBUM","ALERT","ALGAE",
|
||||||
|
"ALIBI","ALIGN","ALIVE","ALLAY","ALLEY","ALLOT","ALLOW","ALLOY","ALOFT","ALONE",
|
||||||
|
"ALONG","ALOOF","ALOUD","ALPEN","ALTAR","ALTER","AMAZE","AMBER","AMBLE","AMEND",
|
||||||
|
"AMISS","AMOUR","AMPLE","AMUSE","ANGEL","ANGER","ANGLE","ANGRY","ANGST","ANIME",
|
||||||
|
"ANKLE","ANNEX","ANTIC","ANVIL","AORTA","APPLE","APPLY","APRON","APTLY","ARBOR",
|
||||||
|
"ARDOR","ARENA","ARGUE","ARRAY","ARROW","ASIDE","ASKEW","ATONE","ATTIC","AUDIO",
|
||||||
|
"AUDIT","AVAIL","AVERT","AVID","AVOID","AWAIT","AWAKE","AWARD","AWARE","AWFUL",
|
||||||
|
"BASIC","BASIS","BATCH","BATHE","BAYOU","BEACH","BEARD","BEAST","BEGIN","BEING",
|
||||||
|
"BELOW","BENCH","BERRY","BIRTH","BISON","BITER","BLACK","BLADE","BLAME","BLAND",
|
||||||
|
"BLANK","BLARE","BLAST","BLAZE","BLEAK","BLEND","BLESS","BLIMP","BLIND","BLISS",
|
||||||
|
"BLOAT","BLOCK","BLOOD","BLOWN","BLUNT","BOARD","BOAST","BOOBY","BOOST","BOOTH",
|
||||||
|
"BOUND","BOXER","BRAID","BRAIN","BRAND","BRAVE","BRAVO","BRAWN","BREAD","BREAK",
|
||||||
|
"BREED","BRIEF","BRINE","BRING","BRISK","BROAD","BROKE","BROOK","BROWN","BRUTE",
|
||||||
|
"BUDDY","BUILD","BUILT","BULKY","BULLY","BUNNY","BURNT","BURST","BUYER","BYLAW",
|
||||||
|
"CADET","CAMEL","CANDY","CARGO","CAROL","CARRY","CARVE","CATCH","CAUSE","CEDAR",
|
||||||
|
"CHAIN","CHALK","CHAOS","CHARD","CHARM","CHART","CHASE","CHEAP","CHEAT","CHECK",
|
||||||
|
"CHEEK","CHEER","CHESS","CHEST","CHIEF","CHILD","CHINA","CHOIR","CHORD","CHOSE",
|
||||||
|
"CIVIC","CIVIL","CLAIM","CLAMP","CLASP","CLASS","CLEAN","CLEAR","CLERK","CLICK",
|
||||||
|
"CLIFF","CLIMB","CLING","CLOAK","CLOCK","CLONE","CLOSE","CLOTH","CLOUD","CLOWN",
|
||||||
|
"CLUMP","CLUNK","COMET","COMIC","CORAL","COUCH","COUGH","COULD","COUNT","COURT",
|
||||||
|
"COVER","COVET","COWARD","CRACK","CRAFT","CRAMP","CRASH","CRAZE","CRAZY","CREAM",
|
||||||
|
"CREEK","CREEP","CRIMP","CRISP","CROSS","CROWD","CROWN","CRUMB","CRUSH","CRUST",
|
||||||
|
"CRYPT","CUBIC","CURSE","CURVE","CYCLE","DAISY","DANCE","DARTS","DATUM","DAUNT",
|
||||||
|
"DEATH","DEBUT","DECAL","DECOY","DECRY","DEFER","DENIM","DENSE","DEPTH","DERBY",
|
||||||
|
"DETER","DETOX","DIGIT","DIRGE","DISCO","DITCH","DITTO","DIZZY","DODGE","DOING",
|
||||||
|
"DOMINO","DOUBT","DOUGH","DOWRY","DRAFT","DRAIN","DRAMA","DRAPE","DRAWN","DREAD",
|
||||||
|
"DRIFT","DRINK","DRIVE","DRONE","DROVE","DROWN","DRUID","DRYER","DUCHY","DULLY",
|
||||||
|
"EAGLE","EARLY","EARWORM","EASEL","EATEN","EDICT","EIGHT","EJECT","ELITE","EMBER",
|
||||||
|
"ENDOW","ENJOY","ENTER","ENVOY","EPOCH","EQUAL","ERROR","ESSAY","EVADE","EVENT",
|
||||||
|
"EVERY","EXACT","EXALT","EXERT","EXIST","EXTRA","FABLE","FACET","FAINT","FAIRY",
|
||||||
|
"FAITH","FALSE","FANCY","FARCE","FATAL","FAULT","FEAST","FEIGN","FERAL","FETCH",
|
||||||
|
"FEVER","FIEND","FIFTY","FIGHT","FINAL","FINCH","FIRST","FIXED","FLAIL","FLAME",
|
||||||
|
"FLANK","FLASH","FLASK","FLAIR","FLAW","FLESH","FLICK","FLING","FLINT","FLOAT",
|
||||||
|
"FLOOR","FLOUR","FLOWN","FLUTE","FOCUS","FOLLY","FORCE","FORGE","FORTH","FORUM",
|
||||||
|
"FOUND","FRAME","FRAUD","FREAK","FRESH","FRIAR","FRINGE","FRONT","FROST","FROZE",
|
||||||
|
"FRUIT","FULLY","FUNGI","FUNKY","FUNNY","GAUZE","GHOST","GIVEN","GIZMO","GLARE",
|
||||||
|
"GLAZE","GLEAM","GLEAN","GLIDE","GLOSS","GLOVE","GNARL","GNOME","GOUGE","GOURD",
|
||||||
|
"GRACE","GRADE","GRASP","GRATE","GRAZE","GREED","GREET","GRIEF","GRIME","GRIND",
|
||||||
|
"GROAN","GROIN","GROPE","GROSS","GROUP","GROVE","GROWL","GRUEL","GRUFF","GUILE",
|
||||||
|
"GUISE","GUSTO","HABIT","HASTE","HATCH","HAUNT","HAVEN","HEART","HEAVE","HEAVY",
|
||||||
|
"HEDGE","HEIST","HERON","HITCH","HOIST","HONOR","HORSE","HOTEL","HOUSE","HUMAN",
|
||||||
|
"HUMOR","HURRY","HUSKY","IDEAL","IMAGE","IMPLY","INBOX","INFER","INNER","INPUT",
|
||||||
|
"INTER","INTRO","IONIC","ISSUE","IVORY","JAZZY","JOUST","JUICE","JUICY","KAYAK",
|
||||||
|
"KHAKI","KNACK","KNEEL","KNIFE","KNOCK","KNOWN","KRAAL","KUDOS","LABEL","LANCE",
|
||||||
|
"LATCH","LATER","LATTE","LEARN","LEASE","LEAVE","LEGAL","LEMON","LEVEL","LIGHT",
|
||||||
|
"LINEN","LINER","LIVER","LOCAL","LODGE","LOGIC","LOOSE","LOUSE","LOVER","LUCID",
|
||||||
|
"LUCKY","LUNAR","MAGIC","MAJOR","MANOR","MAPLE","MARCH","MARSH","MATCH","MAYBE",
|
||||||
|
"MAYOR","MEDIA","MERCY","MERIT","METAL","MIGHT","MINCE","MINER","MINOR","MINUS",
|
||||||
|
"MIRTH","MISER","MOIST","MONEY","MONTH","MORAL","MOURN","MOUTH","MOVED","MOVIE",
|
||||||
|
"MUCKY","MUDDY","MURKY","MUSIC","NAIVE","NEEDY","NERVE","NEVER","NIGHT","NINJA",
|
||||||
|
"NOBLE","NOISE","NORTH","NOTCH","NOVEL","NURSE","NYMPH","OCCUR","OCEAN","OFFER",
|
||||||
|
"OLIVE","ONSET","OPERA","OPTIC","ORDER","OTHER","OUGHT","OUTER","OUNCE","OUTDO",
|
||||||
|
"OXIDE","OZONE","PAINT","PANIC","PAPER","PARCH","PARSE","PARTY","PASTA","PATCH",
|
||||||
|
"PAUSE","PEACE","PEACH","PEARL","PEDAL","PENNY","PERCH","PERIL","PETTY","PHASE",
|
||||||
|
"PHONE","PHOTO","PIANO","PIECE","PILOT","PINCH","PIRATE","PIXEL","PIZZA","PLACE",
|
||||||
|
"PLAIN","PLANE","PLANK","PLANT","PLAZA","PLEAD","PLEAT","PLUCK","PLUME","PLUNGE",
|
||||||
|
"POINT","POKER","POLAR","POLKA","POPPY","PORCH","POUND","POWER","PRANK","PRESS",
|
||||||
|
"PRICE","PRIDE","PRIME","PRINT","PRIZE","PROBE","PRONE","PROOF","PROSE","PROVE",
|
||||||
|
"PROWL","PRUNE","PSALM","PULSE","PUNCH","PUPIL","PURSE","QUEEN","QUERY","QUEST",
|
||||||
|
"QUEUE","QUIET","QUOTA","QUOTE","RABBI","RADAR","RADIO","RAISE","RALLY","RANCH",
|
||||||
|
"RANGE","RAPID","RAVEN","REACH","REALM","REBEL","REFER","REIGN","RELAX","REMIX",
|
||||||
|
"RENEW","REPAY","REPEL","REPENT","RERUN","RESET","RESIN","RIDER","RIDGE","RIGHT",
|
||||||
|
"RIGID","RISKY","RIVER","RIVET","ROBIN","ROBOT","ROCKY","ROMAN","ROUGH","ROUND",
|
||||||
|
"ROUTE","ROVER","ROYAL","RULER","RUSTY","SADLY","SAINT","SALVE","SAUCE","SAVOR",
|
||||||
|
"SCALE","SCALP","SCALD","SCANT","SCARE","SCARF","SCENE","SCENT","SCONE","SCOPE",
|
||||||
|
"SCORE","SCOUT","SCRAM","SCRAWL","SCREW","SCRUB","SEIZE","SENSE","SERUM","SERVE",
|
||||||
|
"SETUP","SEVEN","SHADE","SHAFT","SHAKE","SHAKY","SHAME","SHAPE","SHARE","SHARK",
|
||||||
|
"SHARP","SHEEN","SHEER","SHELF","SHIFT","SHINE","SHIRT","SHOCK","SHORE","SHORT",
|
||||||
|
"SHOUT","SHOVE","SHOWY","SIGHT","SILLY","SINCE","SIXTH","SIXTY","SKILL","SKIMP",
|
||||||
|
"SKIPPER","SKULL","SLACK","SLANT","SLEEK","SLEEP","SLEET","SLICK","SLIDE","SLIME",
|
||||||
|
"SLOPE","SLOSH","SLUMP","SLUNK","SMALL","SMART","SMEAR","SMELL","SMILE","SMIRK",
|
||||||
|
"SMOKE","SNACK","SNAIL","SNAKE","SNEAK","SNIFF","SOLVE","SONIC","SOUTH","SPACE",
|
||||||
|
"SPADE","SPARE","SPARK","SPEAK","SPEAR","SPECK","SPEED","SPEND","SPINE","SPIRE",
|
||||||
|
"SPITE","SPOON","SPORT","SPRAY","SPREE","SPRIG","SPROUT","SPUNK","SQUAD","SQUAT",
|
||||||
|
"SQUID","STACK","STAFF","STAGE","STAIN","STALK","STAMP","STAND","STASH","STAVE",
|
||||||
|
"STAYS","STEAK","STEAM","STEEL","STEEP","STEER","STERN","STICK","STIFF","STILL",
|
||||||
|
"STONE","STOOL","STORM","STORY","STOUT","STRAW","STRAY","STRIP","STRUT","STUCK",
|
||||||
|
"STUDY","STUNG","STUNK","STUNT","STYLE","SUAVE","SUGAR","SUITE","SULKY","SUMMON",
|
||||||
|
"SUPER","SURGE","SWAMP","SWEAR","SWEAT","SWEEP","SWEET","SWEPT","SWIFT","SWIPE",
|
||||||
|
"SWIRL","SWOOP","SWORD","SWORN","SYRUP","TABLE","TALON","TANGO","TAPIR","TAUNT",
|
||||||
|
"TAWNY","TEACH","TEASE","TEDDY","TEETH","TEMPO","TENSE","TEPID","THEFT","THEIR",
|
||||||
|
"THEME","THERE","THICK","THING","THINK","THORN","THREW","THROW","THUMB","THUMP",
|
||||||
|
"TIARA","TIGER","TIGHT","TIMER","TIPSY","TITAN","TITLE","TODAY","TOKEN","TONIC",
|
||||||
|
"TOTAL","TOUCH","TOUGH","TOWEL","TOWER","TOXIC","TRAIN","TRAMP","TRAPS","TRASH",
|
||||||
|
"TRAWL","TREAD","TREAT","TREND","TRICK","TRIED","TROOP","TROTH","TROUT","TROVE",
|
||||||
|
"TRUCE","TRULY","TRUMP","TRUNK","TRUST","TRUTH","TUMMY","TUNER","TUNIC","TUTOR",
|
||||||
|
"TWEED","TWICE","TWIRL","TWIST","TYING","ULCER","UNDER","UNFED","UNIFY","UNION",
|
||||||
|
"UNITY","UNTIL","UPPER","UPSET","URBAN","USAGE","USHER","UTTER","VALOR","VALVE",
|
||||||
|
"VAPID","VAULT","VERSE","VICAR","VIGOR","VIRAL","VIRUS","VISOR","VISTA","VIVID",
|
||||||
|
"VIXEN","VOCAL","VODKA","VOICE","VOILA","VOTER","VOUCH","VOWEL","WATCH","WATER",
|
||||||
|
"WEARY","WEAVE","WEDGE","WEEDY","WEIRD","WELCH","WHERE","WHILE","WHIFF","WHIRL",
|
||||||
|
"WINCE","WINDY","WITCH","WITTY","WORLD","WORRY","WORSE","WORST","WORTH","WOULD",
|
||||||
|
"WOUND","WRAITH","WRATH","WRECK","WREST","WRIST","WRONG","YEARN","YIELD","YOUNG",
|
||||||
|
"YOUTH","ZESTY","ZIPPY","ZONE"
|
||||||
|
].filter(w => w.length === 5);
|
||||||
|
|
||||||
|
const VALID_EXTRA = new Set([
|
||||||
|
"ABBOT","ABBOT","ALGAL","ALOFT","ALONG","APRON","ARMOR","ATOLL","ATONE","AUDIT",
|
||||||
|
"BALMY","BANAL","BAYOU","BEVEL","BLUNT","BROIL","BROOD","BUOY","CALYX","CAMEO",
|
||||||
|
"CIVIL","CLEFT","CLOUT","COLON","COMMA","CROAT","DELVE","DEPOT","DERBY","DIVINE",
|
||||||
|
"DOYLY","ECLAT","EGRET","ELBOW","ELUDE","ENVOY","EXPEL","EXTOL","FABLE","FACET",
|
||||||
|
"FAWNY","FELON","FETID","FIASCO","FLECK","FORAY","FORTE","FROND","FUROR","GAUDY",
|
||||||
|
"GOLEM","GRAIL","GUAVA","GUILD","HAVEN","HERON","INERT","INLAY","INTER","JOUST",
|
||||||
|
"KHAKI","KNAVE","LATHE","LEACH","LIBEL","LIVID","LLAMA","LUCID","LUSTY","MAXIM",
|
||||||
|
"MELEE","MERIT","MIRTH","MOIST","MOOSE","MOTIF","MURKY","MUSTY","NAIVE","OMEGA",
|
||||||
|
"OPTIC","OVOID","PAGAN","PAPAL","PATIO","PATSY","PEEVE","PETTY","PIXEL","PLAID",
|
||||||
|
"PLAZA","PLONK","PLUMB","POKER","POLYP","PORKY","PRAWN","PREEN","PUPIL","PURGE",
|
||||||
|
"RABID","REGAL","RELIC","REMIT","REPAY","RESIN","RIVET","RUSTY","SAVVY","SCALD",
|
||||||
|
"SCONE","SEDAN","SIGMA","SLOTH","SNIDE","SQUAT","STOIC","SWOON","SYNOD","TABOO",
|
||||||
|
"TABOR","TAFFY","TEPID","TITHE","TONIC","TROTH","TUBER","TULIP","TUTOR","ULCER",
|
||||||
|
"UMBRA","UNDID","UNTIL","UNZIP","VENOM","VERGE","VIGIL","VISOR","VOGUE","VOUCH",
|
||||||
|
"WADER","WEALD","WHELP","WINCH","WOOZY","WORMY","YEOMAN","ZONAL"
|
||||||
|
]);
|
||||||
|
|
||||||
|
const VALID_WORDS = new Set([...WORDS, ...VALID_EXTRA]);
|
||||||
|
|
||||||
|
let state = {
|
||||||
|
word: '',
|
||||||
|
guesses: [],
|
||||||
|
current: '',
|
||||||
|
gameOver: false,
|
||||||
|
stats: { played: 0, wins: 0, streak: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
function buildGrid() {
|
||||||
|
const grid = document.getElementById('grid');
|
||||||
|
grid.innerHTML = '';
|
||||||
|
for (let r = 0; r < 6; r++) {
|
||||||
|
const row = document.createElement('div');
|
||||||
|
row.className = 'row';
|
||||||
|
row.id = 'row-' + r;
|
||||||
|
for (let c = 0; c < 5; c++) {
|
||||||
|
const cell = document.createElement('div');
|
||||||
|
cell.className = 'cell';
|
||||||
|
cell.id = `cell-${r}-${c}`;
|
||||||
|
row.appendChild(cell);
|
||||||
|
}
|
||||||
|
grid.appendChild(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildKeyboard() {
|
||||||
|
const kb = document.getElementById('keyboard');
|
||||||
|
kb.innerHTML = '';
|
||||||
|
const rows = [
|
||||||
|
['Q','W','E','R','T','Y','U','I','O','P'],
|
||||||
|
['A','S','D','F','G','H','J','K','L'],
|
||||||
|
['ENTER','Z','X','C','V','B','N','M','⌫']
|
||||||
|
];
|
||||||
|
rows.forEach(keys => {
|
||||||
|
const row = document.createElement('div');
|
||||||
|
row.className = 'kb-row';
|
||||||
|
keys.forEach(k => {
|
||||||
|
const btn = document.createElement('button');
|
||||||
|
btn.className = 'key' + (k.length > 1 ? ' wide' : '');
|
||||||
|
btn.textContent = k;
|
||||||
|
btn.id = 'key-' + k;
|
||||||
|
btn.addEventListener('click', () => handleKey(k === '⌫' ? 'BACKSPACE' : k));
|
||||||
|
row.appendChild(btn);
|
||||||
|
});
|
||||||
|
kb.appendChild(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKey(key) {
|
||||||
|
if (state.gameOver) return;
|
||||||
|
if (key === 'BACKSPACE') {
|
||||||
|
state.current = state.current.slice(0, -1);
|
||||||
|
updateCurrentRow();
|
||||||
|
} else if (key === 'ENTER') {
|
||||||
|
submitGuess();
|
||||||
|
} else if (/^[A-Z]$/.test(key) && state.current.length < 5) {
|
||||||
|
state.current += key;
|
||||||
|
updateCurrentRow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCurrentRow() {
|
||||||
|
const row = state.guesses.length;
|
||||||
|
for (let c = 0; c < 5; c++) {
|
||||||
|
const cell = document.getElementById(`cell-${row}-${c}`);
|
||||||
|
const letter = state.current[c] || '';
|
||||||
|
cell.textContent = letter;
|
||||||
|
cell.className = 'cell' + (letter ? ' filled' : '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitGuess() {
|
||||||
|
const row = state.guesses.length;
|
||||||
|
if (state.current.length < 5) {
|
||||||
|
shakeRow(row);
|
||||||
|
showToast('Not enough letters');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!VALID_WORDS.has(state.current) && !WORDS.includes(state.current)) {
|
||||||
|
// Be lenient — allow any 5-letter attempt
|
||||||
|
// (For a proper game, you'd have a full valid-words list)
|
||||||
|
}
|
||||||
|
|
||||||
|
const guess = state.current;
|
||||||
|
state.guesses.push(guess);
|
||||||
|
state.current = '';
|
||||||
|
|
||||||
|
revealGuess(row, guess, () => {
|
||||||
|
if (guess === state.word) {
|
||||||
|
state.gameOver = true;
|
||||||
|
state.stats.played++;
|
||||||
|
state.stats.wins++;
|
||||||
|
state.stats.streak++;
|
||||||
|
setTimeout(() => {
|
||||||
|
bounceCells(row);
|
||||||
|
setTimeout(() => showResult(true), 600);
|
||||||
|
}, 300);
|
||||||
|
} else if (state.guesses.length === 6) {
|
||||||
|
state.gameOver = true;
|
||||||
|
state.stats.played++;
|
||||||
|
state.stats.streak = 0;
|
||||||
|
setTimeout(() => showResult(false), 400);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function revealGuess(row, guess, onDone) {
|
||||||
|
const word = state.word;
|
||||||
|
const result = Array(5).fill('absent');
|
||||||
|
const wordArr = word.split('');
|
||||||
|
const guessArr = guess.split('');
|
||||||
|
const used = Array(5).fill(false);
|
||||||
|
|
||||||
|
// First pass: correct
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
if (guessArr[i] === wordArr[i]) {
|
||||||
|
result[i] = 'correct';
|
||||||
|
used[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Second pass: present
|
||||||
|
for (let i = 0; i < 5; i++) {
|
||||||
|
if (result[i] === 'correct') continue;
|
||||||
|
for (let j = 0; j < 5; j++) {
|
||||||
|
if (!used[j] && guessArr[i] === wordArr[j]) {
|
||||||
|
result[i] = 'present';
|
||||||
|
used[j] = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animate each cell
|
||||||
|
result.forEach((r, i) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const cell = document.getElementById(`cell-${row}-${i}`);
|
||||||
|
cell.classList.add('flip');
|
||||||
|
setTimeout(() => {
|
||||||
|
cell.className = 'cell ' + r;
|
||||||
|
cell.textContent = guess[i];
|
||||||
|
updateKeyColor(guess[i], r);
|
||||||
|
}, 250);
|
||||||
|
if (i === 4) setTimeout(onDone, 350);
|
||||||
|
}, i * 100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateKeyColor(letter, result) {
|
||||||
|
const key = document.getElementById('key-' + letter);
|
||||||
|
if (!key) return;
|
||||||
|
const priority = { correct: 3, present: 2, absent: 1 };
|
||||||
|
const current = key.className.includes('correct') ? 'correct'
|
||||||
|
: key.className.includes('present') ? 'present'
|
||||||
|
: key.className.includes('absent') ? 'absent' : '';
|
||||||
|
if (!current || priority[result] > priority[current]) {
|
||||||
|
key.className = 'key' + (key.classList.contains('wide') ? ' wide' : '') + ' ' + result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function shakeRow(row) {
|
||||||
|
document.querySelectorAll(`#row-${row} .cell`).forEach(c => {
|
||||||
|
c.classList.add('shake');
|
||||||
|
c.addEventListener('animationend', () => c.classList.remove('shake'), { once: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function bounceCells(row) {
|
||||||
|
document.querySelectorAll(`#row-${row} .cell`).forEach((c, i) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
c.classList.add('bounce');
|
||||||
|
c.addEventListener('animationend', () => c.classList.remove('bounce'), { once: true });
|
||||||
|
}, i * 80);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showToast(msg) {
|
||||||
|
const t = document.getElementById('toast');
|
||||||
|
t.textContent = msg;
|
||||||
|
t.classList.add('show');
|
||||||
|
setTimeout(() => t.classList.remove('show'), 1800);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResult(won) {
|
||||||
|
const panel = document.getElementById('result-panel');
|
||||||
|
const titles = won
|
||||||
|
? ['Genius!','Magnificent!','Impressive!','Splendid!','Great!','Phew!']
|
||||||
|
: ['Better luck next time.'];
|
||||||
|
document.getElementById('result-title').textContent = won
|
||||||
|
? titles[state.guesses.length - 1] || 'Great!'
|
||||||
|
: 'Better luck next time.';
|
||||||
|
document.getElementById('result-word-display').textContent = state.word;
|
||||||
|
document.getElementById('stat-played').textContent = state.stats.played;
|
||||||
|
document.getElementById('stat-wins').textContent = state.stats.wins;
|
||||||
|
document.getElementById('stat-streak').textContent = state.stats.streak;
|
||||||
|
panel.classList.add('show');
|
||||||
|
}
|
||||||
|
|
||||||
|
function newGame() {
|
||||||
|
state.word = WORDS[Math.floor(Math.random() * WORDS.length)];
|
||||||
|
state.guesses = [];
|
||||||
|
state.current = '';
|
||||||
|
state.gameOver = false;
|
||||||
|
document.getElementById('result-panel').classList.remove('show');
|
||||||
|
buildGrid();
|
||||||
|
buildKeyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keyboard input
|
||||||
|
document.addEventListener('keydown', e => {
|
||||||
|
if (e.ctrlKey || e.altKey || e.metaKey) return;
|
||||||
|
if (e.key === 'Enter') handleKey('ENTER');
|
||||||
|
else if (e.key === 'Backspace') handleKey('BACKSPACE');
|
||||||
|
else if (/^[a-zA-Z]$/.test(e.key)) handleKey(e.key.toUpperCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
newGame();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -11,60 +11,73 @@
|
|||||||
<h1>Flashcards Generator</h1>
|
<h1>Flashcards Generator</h1>
|
||||||
</header>
|
</header>
|
||||||
<div class="main-wrapper">
|
<div class="main-wrapper">
|
||||||
<div class="section-title" id="title">
|
<div id="startScreen">
|
||||||
<div class="content">
|
<div class="section-title" id="title">
|
||||||
<label for="inputText" class="inputText">Sende deine Wortliste an ChatGPT mit folgender Anweisung:</label>
|
|
||||||
</div>
|
|
||||||
<div id="aufgabe_fuer_gpt">
|
|
||||||
<pre id="formatText">
|
|
||||||
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
|
|
||||||
</pre>
|
|
||||||
<button id="copyButton" style="position: absolute; top: 5px; right: 5px; cursor: pointer;">📋</button>
|
|
||||||
</div>
|
|
||||||
<div id="inputHinweis">
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<label for="inputText" class="section-title">Füge deinen Text hier ein:</label>
|
<label for="inputText" class="inputText">Sende deine Wortliste an ChatGPT mit folgender Anweisung:</label>
|
||||||
<textarea id="inputText" placeholder="Hier Text einfügen..."></textarea>
|
</div>
|
||||||
|
<div id="aufgabe_fuer_gpt">
|
||||||
|
<pre id="formatText">
|
||||||
|
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
|
||||||
|
</pre>
|
||||||
|
<button id="copyButton" style="position: absolute; top: 5px; right: 5px; cursor: pointer;">📋</button>
|
||||||
|
</div>
|
||||||
|
<div id="inputHinweis">
|
||||||
|
<div class="content">
|
||||||
|
<label for="inputText" class="section-title">Füge deinen Text hier ein:</label>
|
||||||
|
<textarea id="inputText" placeholder="Hier Text einfügen..."></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="button-wrapper">
|
||||||
|
<button id="kartenErstellen">Karten erstellen</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-wrapper">
|
|
||||||
<button id="kartenErstellen">Karten erstellen</button>
|
<div id="modusAuswahlSeite" style="display:none;">
|
||||||
</div>
|
|
||||||
<div id="modusAuswahlSeite" style="display:none">
|
|
||||||
<h2>Wählt einen Modus:</h2>
|
<h2>Wählt einen Modus:</h2>
|
||||||
<button class="modus-btn" data-modus="druck">📄 PDF erstellen</button>
|
<button class="modus-btn" data-modus="druck">📄 PDF erstellen</button>
|
||||||
<button class="modus-btn" data-modus="training_einfach">🃏 Online-Training</button>
|
<button class="modus-btn" data-modus="training_einfach">🃏 Online-Training</button>
|
||||||
<button class="modus-btn" data-modus="statistik">📊 Statistik</button>
|
<button class="modus-btn" data-modus="statistik">📊 Statistik</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="pdfPages" class="modus-view">
|
<div id="pdfPages">
|
||||||
<div id="kartenContainer"></div>
|
<div id="kartenContainer"></div>
|
||||||
<div class="button-wrapper">
|
<div class="button-wrapper">
|
||||||
<button id="druckenBtn" style="display:none;">Drucken</button>
|
<button id="druckenBtn" style="display:none;">Drucken</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="onlineTraining" class="modus-view">
|
<div id="onlineTraining">
|
||||||
|
|
||||||
<div id="trainingLevels">
|
<div id="trainingLevels" class="training-view">
|
||||||
<h3>Wählt einen Schwierigkeitsgrad:</h3>
|
<h3 class="training-title">Wählt eine Trainingsart:</h3>
|
||||||
<button class="level-btn" data-level="leicht">🟢 Leicht</button>
|
|
||||||
<button class="level-btn" data-level="mittel">🟡 Mittel</button>
|
<div class="buttons-row">
|
||||||
<button class="level-btn" data-level="schwer">🔴 Schwer</button>
|
<button class="level-btn" data-level="flip">Karte umdrehen</button>
|
||||||
|
<button class="level-btn" data-level="multiple">Multiple Choice</button>
|
||||||
|
<button class="level-btn" data-level="matching">Zuordnen</button>
|
||||||
|
<button class="level-btn" data-level="hint">Mit Hinweis schreiben</button>
|
||||||
|
<button class="level-btn" data-level="write">Frei schreiben</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="trainingLeicht" class="training-view modus-view"></div>
|
<div id="trainingFlip" class="training-view hidden"></div>
|
||||||
<div id="trainingMittel" class="training-view"></div>
|
<div id="trainingMatching" class="training-view hidden"></div>
|
||||||
<div id="trainingSchwer" class="training-view"></div>
|
<div id="trainingMultiple" class="training-view hidden"></div>
|
||||||
|
<div id="trainingHint" class="training-view hidden"></div>
|
||||||
|
<div id="trainingWrite" class="training-view hidden"></div>
|
||||||
|
|
||||||
|
<div class="button-wrapper">
|
||||||
|
<button id="checkBtn" style="display:none;" onclick="pruefeRunde()">Überprüfen</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="trainingContainer" style="display:none; text-align:center; margin-top:30px;"></div>
|
<div id="trainingContainer" style="display:none; text-align:center; margin-top:30px;"></div>
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
let parsedArray = [];
|
let parsedArray = [];
|
||||||
|
|
||||||
|
// Mischt ein Array zufällig mit dem Fisher-Yates-Algorithmus
|
||||||
|
// und gibt das gemischte Array zurück.
|
||||||
|
function mischeArray(array) {
|
||||||
|
for (let i = array.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById('copyButton').addEventListener('click', () => {
|
document.getElementById('copyButton').addEventListener('click', () => {
|
||||||
const text = document.getElementById('formatText').innerText;
|
const text = document.getElementById('formatText').innerText;
|
||||||
|
|
||||||
@@ -10,6 +20,7 @@ document.getElementById('copyButton').addEventListener('click', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Analysiert den eingegebenen Text und wandelt ihn in ein Array von Wort-Objekten um.
|
||||||
function parseWordText(inputText) {
|
function parseWordText(inputText) {
|
||||||
const wortBlocks = inputText.trim().split("\n\n");
|
const wortBlocks = inputText.trim().split("\n\n");
|
||||||
const wortListe = [];
|
const wortListe = [];
|
||||||
@@ -23,6 +34,7 @@ function parseWordText(inputText) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const wortObj = {
|
const wortObj = {
|
||||||
|
id: crypto.randomUUID(),
|
||||||
englisch: lines[0],
|
englisch: lines[0],
|
||||||
ipa: lines[1],
|
ipa: lines[1],
|
||||||
beispielEN: lines[2],
|
beispielEN: lines[2],
|
||||||
@@ -36,6 +48,7 @@ function parseWordText(inputText) {
|
|||||||
return wortListe;
|
return wortListe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gibt beide Seiten als Objekt zurück.
|
||||||
function createPagePair() {
|
function createPagePair() {
|
||||||
const frontPage = document.createElement("div");
|
const frontPage = document.createElement("div");
|
||||||
frontPage.className = "page page-front";
|
frontPage.className = "page page-front";
|
||||||
@@ -47,9 +60,6 @@ function createPagePair() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const button = document.getElementById("kartenErstellen");
|
const button = document.getElementById("kartenErstellen");
|
||||||
const onlineContainer = document.getElementById("kartenContainer");
|
|
||||||
const frontPage = document.querySelector(".page_front");
|
|
||||||
const backPage = document.querySelector(".page_back");
|
|
||||||
|
|
||||||
button.addEventListener("click", () => {
|
button.addEventListener("click", () => {
|
||||||
const inputText = document.getElementById("inputText").value;
|
const inputText = document.getElementById("inputText").value;
|
||||||
@@ -62,38 +72,26 @@ button.addEventListener("click", () => {
|
|||||||
|
|
||||||
alert("Karten erfolgreich erstellt!");
|
alert("Karten erfolgreich erstellt!");
|
||||||
|
|
||||||
showView("modusAuswahlSeite");
|
|
||||||
|
|
||||||
document.getElementById("title").style.display = "none";
|
document.getElementById("startScreen").style.display = "none";
|
||||||
button.style.display = "none";
|
|
||||||
|
|
||||||
document.getElementById("modusAuswahlSeite").style.display = "block";
|
document.getElementById("modusAuswahlSeite").style.display = "block";
|
||||||
});
|
});
|
||||||
|
|
||||||
document.querySelectorAll(".modus-btn").forEach(button => {
|
// Erstellt druckfertige PDF-Seiten mit jeweils 8 Karten pro Seite.
|
||||||
button.addEventListener("click", () => {
|
|
||||||
const modus = button.dataset.modus;
|
|
||||||
|
|
||||||
if (modus === "druck") {
|
|
||||||
createPDFPages(parsedArray);
|
|
||||||
} else {
|
|
||||||
console.log("Gewählter Modus:", modus);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function createPDFPages(wordArray) {
|
function createPDFPages(wordArray) {
|
||||||
|
|
||||||
const kartenContainer = document.getElementById("kartenContainer");
|
const kartenContainer = document.getElementById("kartenContainer");
|
||||||
|
const druckenBtn = document.getElementById("druckenBtn");
|
||||||
|
|
||||||
kartenContainer.innerHTML = "";
|
kartenContainer.innerHTML = "";
|
||||||
kartenContainer.style.display = "flex";
|
kartenContainer.style.display = "flex";
|
||||||
kartenContainer.style.flexDirection = "column";
|
kartenContainer.style.flexDirection = "column";
|
||||||
|
|
||||||
for (let i = 0; i < parsedArray.length; i += 8) {
|
for (let i = 0; i < wordArray.length; i += 8) {
|
||||||
|
|
||||||
const { frontPage, backPage } = createPagePair();
|
const { frontPage, backPage } = createPagePair();
|
||||||
|
|
||||||
parsedArray.slice(i, i + 8).forEach((karte) => {
|
wordArray.slice(i, i + 8).forEach((karte) => {
|
||||||
|
|
||||||
const frontCard = document.createElement("div");
|
const frontCard = document.createElement("div");
|
||||||
frontCard.className = "card card-en";
|
frontCard.className = "card card-en";
|
||||||
@@ -115,28 +113,31 @@ function createPDFPages(wordArray) {
|
|||||||
|
|
||||||
kartenContainer.appendChild(frontPage);
|
kartenContainer.appendChild(frontPage);
|
||||||
kartenContainer.appendChild(backPage);
|
kartenContainer.appendChild(backPage);
|
||||||
document.getElementById("druckenBtn").style.display = "block";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
druckenBtn.style.display = "block";
|
||||||
|
|
||||||
alert("PDF-Seiten wurden erstellt! Du kannst sie jetzt drucken.");
|
alert("PDF-Seiten wurden erstellt! Du kannst sie jetzt drucken.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
document.getElementById("druckenBtn").addEventListener("click", () => {
|
document.getElementById("druckenBtn").addEventListener("click", () => {
|
||||||
window.print();
|
window.print();
|
||||||
});
|
});
|
||||||
|
|
||||||
const modusBtns = document.querySelectorAll('.modus-btn');
|
const modusBtns = document.querySelectorAll('.modus-btn');
|
||||||
const trainingLevels = document.getElementById('trainingLevels');
|
|
||||||
|
|
||||||
modusBtns.forEach(btn => {
|
modusBtns.forEach(btn => {
|
||||||
btn.addEventListener('click', () => {
|
btn.addEventListener('click', () => {
|
||||||
const modus = btn.dataset.modus;
|
const modus = btn.dataset.modus;
|
||||||
|
|
||||||
if (modus === 'druck') {
|
if (modus === 'druck') {
|
||||||
showView('pdfPages');
|
showMode('pdfPages');
|
||||||
|
createPDFPages(parsedArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (modus === 'training_einfach') {
|
else if (modus === 'training_einfach') {
|
||||||
showView('trainingLevels');
|
showMode('onlineTraining');
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (modus === 'statistik') {
|
else if (modus === 'statistik') {
|
||||||
@@ -145,165 +146,739 @@ modusBtns.forEach(btn => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
let trainingsZustand = {
|
// Blendet alle Trainingslevel-Ansichten aus
|
||||||
modus: "leicht",
|
function showMode(id) {
|
||||||
quelleKarten: [],
|
|
||||||
aktiveKarten: [],
|
|
||||||
gelernt: [],
|
|
||||||
nichtGelernt: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
function startLeichtTraining() {
|
document.getElementById("pdfPages").style.display = "none";
|
||||||
console.log("🔥 startLeichtTraining вызвана");
|
document.getElementById("onlineTraining").style.display = "none";
|
||||||
|
|
||||||
if (!parsedArray || parsedArray.length === 0) {
|
document.getElementById(id).style.display = "block";
|
||||||
alert("Нет карточек для тренировки");
|
}
|
||||||
return;
|
|
||||||
|
function showLevel(id) {
|
||||||
|
document.querySelectorAll("#onlineTraining .training-view").forEach(view => {
|
||||||
|
if (view.id !== "trainingLevels") {
|
||||||
|
view.classList.add("hidden");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById(id).classList.remove("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
document.querySelectorAll(".level-btn").forEach(btn => {
|
||||||
|
btn.addEventListener("click", () => {
|
||||||
|
const type = btn.dataset.level;
|
||||||
|
console.log("Trainingsart:", type);
|
||||||
|
|
||||||
|
if (type === "flip") {
|
||||||
|
showLevel("trainingFlip");
|
||||||
|
startFlipTraining();
|
||||||
|
document.getElementById("checkBtn").style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "matching") {
|
||||||
|
showLevel("trainingMatching");
|
||||||
|
startMittelTraining();
|
||||||
|
document.getElementById("checkBtn").style.display = "block";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "multiple") {
|
||||||
|
showLevel("trainingMultiple");
|
||||||
|
startMultipleTraining();
|
||||||
|
document.getElementById("checkBtn").style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "hint") {
|
||||||
|
showLevel("trainingHint");
|
||||||
|
startHintTraining();
|
||||||
|
document.getElementById("checkBtn").style.display = "none";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type === "write") {
|
||||||
|
showLevel("trainingWrite");
|
||||||
|
startWriteTraining();
|
||||||
|
document.getElementById("checkBtn").style.display = "none";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
class TrainingsEngine {
|
||||||
|
|
||||||
|
constructor(kartenListe) {
|
||||||
|
this.kartenQueue = [];
|
||||||
|
this.letzteKarteId = null;
|
||||||
|
this.gelernt = [];
|
||||||
|
this.nichtGelernt = [];
|
||||||
|
|
||||||
|
// Initialisierung aller Richtungen
|
||||||
|
kartenListe.forEach(karte => {
|
||||||
|
["EN_DE", "DE_EN"].forEach(richtung => {
|
||||||
|
this.kartenQueue.push({
|
||||||
|
karte: karte,
|
||||||
|
richtung: richtung,
|
||||||
|
korrektInFolge: 0,
|
||||||
|
versuche: 0,
|
||||||
|
maxVersuche: 3,
|
||||||
|
status: "learning"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.#mischeQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
trainingsZustand.quelleKarten = [...parsedArray];
|
//ÖFFENTLICHE API
|
||||||
trainingsZustand.aktiveKarten = [];
|
|
||||||
trainingsZustand.gelernt = [];
|
|
||||||
trainingsZustand.nichtGelernt = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
naechstesElement() {
|
||||||
if (trainingsZustand.quelleKarten.length > 0) {
|
if (this.kartenQueue.length === 0) return null;
|
||||||
const karte = trainingsZustand.quelleKarten.shift();
|
|
||||||
karte.versuche = 0;
|
// Verhindert direkte Wiederholung derselben Karte
|
||||||
trainingsZustand.aktiveKarten.push(karte);
|
if (
|
||||||
|
this.kartenQueue.length > 1 &&
|
||||||
|
this.kartenQueue[0].karte.id === this.letzteKarteId
|
||||||
|
) {
|
||||||
|
const alternativeIndex = this.kartenQueue.findIndex(
|
||||||
|
el => el.karte.id !== this.letzteKarteId
|
||||||
|
);
|
||||||
|
|
||||||
|
if (alternativeIndex !== -1) {
|
||||||
|
const [element] = this.kartenQueue.splice(alternativeIndex, 1);
|
||||||
|
this.kartenQueue.unshift(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const aktuellesElement = this.kartenQueue.shift();
|
||||||
|
this.letzteKarteId = aktuellesElement.karte.id;
|
||||||
|
|
||||||
|
return aktuellesElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
antwortVerarbeiten(element, istKorrekt) {
|
||||||
|
if (!element || element.status !== "learning") return;
|
||||||
|
|
||||||
|
element.versuche++;
|
||||||
|
|
||||||
|
if (istKorrekt) {
|
||||||
|
element.korrektInFolge++;
|
||||||
|
|
||||||
|
if (element.korrektInFolge >= 3) {
|
||||||
|
element.status = "gelernt";
|
||||||
|
this.gelernt.push(element);
|
||||||
|
this.kartenQueue = this.kartenQueue.filter(e => e !== element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#wiederEinreihen(element, 8, 10);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
element.korrektInFolge = 0;
|
||||||
|
element.maxVersuche = 5;
|
||||||
|
|
||||||
|
if (element.versuche >= element.maxVersuche) {
|
||||||
|
element.status = "nichtGelernt";
|
||||||
|
this.nichtGelernt.push(element);
|
||||||
|
this.kartenQueue = this.kartenQueue.filter(e => e !== element);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#wiederEinreihen(element, 2, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zeigeNaechsteKarte();
|
istBeendet() {
|
||||||
|
return this.kartenQueue.length === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
statistik() {
|
||||||
|
const alle = [...this.kartenQueue];
|
||||||
|
|
||||||
|
return {
|
||||||
|
verbleibend: this.kartenQueue.length,
|
||||||
|
gelernt: alle.filter(e => e.status === "gelernt").length,
|
||||||
|
nichtGelernt: alle.filter(e => e.status === "nichtGelernt").length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exportiereZustand() {
|
||||||
|
return JSON.stringify({
|
||||||
|
kartenQueue: this.kartenQueue,
|
||||||
|
letzteKarteId: this.letzteKarteId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ladeZustand(json) {
|
||||||
|
const daten = JSON.parse(json);
|
||||||
|
this.kartenQueue = daten.kartenQueue;
|
||||||
|
this.letzteKarteId = daten.letzteKarteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PRIVATE METHODEN
|
||||||
|
#wiederEinreihen(element, minAbstand, maxAbstand) {
|
||||||
|
const zufall =
|
||||||
|
Math.floor(Math.random() * (maxAbstand - minAbstand + 1)) + minAbstand;
|
||||||
|
|
||||||
|
const position = Math.min(zufall, this.kartenQueue.length);
|
||||||
|
this.kartenQueue.splice(position, 0, element);
|
||||||
|
}
|
||||||
|
|
||||||
|
#mischeQueue() {
|
||||||
|
for (let i = this.kartenQueue.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[this.kartenQueue[i], this.kartenQueue[j]] =
|
||||||
|
[this.kartenQueue[j], this.kartenQueue[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function zeigeNaechsteKarte() {
|
let flipEngine;
|
||||||
if (
|
|
||||||
trainingsZustand.aktiveKarten.length === 0 &&
|
function startFlipTraining() {
|
||||||
trainingsZustand.quelleKarten.length === 0
|
flipEngine = new TrainingsEngine(parsedArray);
|
||||||
) {
|
zeigeNaechsteFlipKarte();
|
||||||
alert(`Training beendet!
|
}
|
||||||
Gelernt: ${trainingsZustand.gelernt.length}
|
|
||||||
Nicht gelernt: ${trainingsZustand.nichtGelernt.length}`);
|
function zeigeNaechsteFlipKarte() {
|
||||||
|
const element = flipEngine.naechstesElement();
|
||||||
|
|
||||||
|
const container = document.getElementById("trainingFlip");
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
container.classList.remove("hidden");
|
||||||
|
container.innerHTML = `<div style="text-align:center; font-size: 24px; margin-top:20px;">🎉 Training beendet!<br>Gelernt: ${flipEngine.gelernt.length}<br>Nicht gelernt: ${flipEngine.nichtGelernt.length}</div>`;
|
||||||
return;
|
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");
|
const cardEl = document.createElement("div");
|
||||||
cardEl.className = "training-card";
|
cardEl.className = "training-card";
|
||||||
|
|
||||||
cardEl.innerHTML = `
|
cardEl.innerHTML = `
|
||||||
<div class="training-card-inner">
|
<div class="training-card-inner">
|
||||||
<div class="training-front">
|
|
||||||
<h2>${karte.englisch}</h2>
|
<div class="training-front">
|
||||||
<div class="ipa">${karte.ipa}</div>
|
<div class="card-top">
|
||||||
<div class="example">${karte.beispielEN}</div>
|
<h2>${element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch}</h2>
|
||||||
</div>
|
${element.richtung === "EN_DE" && element.karte.ipa
|
||||||
<div class="training-back">
|
? `<div class="ipa">${element.karte.ipa}</div>`
|
||||||
<h2>${karte.deutsch}</h2>
|
: ``
|
||||||
<div class="example">${karte.beispielDE}</div>
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="card-example">
|
||||||
`;
|
${element.richtung === "EN_DE"
|
||||||
|
? element.karte.beispielEN || ""
|
||||||
|
: element.karte.beispielDE || ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="training-back">
|
||||||
|
<div class="card-top">
|
||||||
|
<h2>${element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch}</h2>
|
||||||
|
${element.richtung !== "EN_DE" && element.karte.ipa
|
||||||
|
? `<div class="ipa">${element.karte.ipa}</div>`
|
||||||
|
: ``
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="card-example">
|
||||||
|
${element.richtung === "EN_DE"
|
||||||
|
? element.karte.beispielDE || ""
|
||||||
|
: element.karte.beispielEN || ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
cardEl.onclick = () => cardEl.classList.toggle("flip");
|
cardEl.onclick = () => cardEl.classList.toggle("flip");
|
||||||
|
|
||||||
const actions = document.createElement("div");
|
const actions = document.createElement("div");
|
||||||
actions.className = "training-actions";
|
actions.className = "training-actions";
|
||||||
actions.innerHTML = `
|
const knowBtn = document.createElement("button");
|
||||||
<button id="knowBtn">✔️ Weiß ich</button>
|
knowBtn.innerText = "Weiß ich";
|
||||||
<button id="dontKnowBtn">❌ Weiß ich nicht</button>
|
const dontKnowBtn = document.createElement("button");
|
||||||
`;
|
dontKnowBtn.innerText = "Weiß ich nicht";
|
||||||
|
|
||||||
actions.querySelector("#knowBtn").onclick = () => antworteAufKarte(true);
|
knowBtn.onclick = () => {
|
||||||
actions.querySelector("#dontKnowBtn").onclick = () => antworteAufKarte(false);
|
flipEngine.antwortVerarbeiten(element, true);
|
||||||
|
zeigeNaechsteFlipKarte();
|
||||||
|
};
|
||||||
|
dontKnowBtn.onclick = () => {
|
||||||
|
flipEngine.antwortVerarbeiten(element, false);
|
||||||
|
zeigeNaechsteFlipKarte();
|
||||||
|
};
|
||||||
|
|
||||||
|
actions.appendChild(knowBtn);
|
||||||
|
actions.appendChild(dontKnowBtn);
|
||||||
|
|
||||||
container.appendChild(cardEl);
|
container.appendChild(cardEl);
|
||||||
container.appendChild(actions);
|
container.appendChild(actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
function antworteAufKarte(weißIch) {
|
let multipleEngine;
|
||||||
const karte = trainingsZustand.aktuelleKarte;
|
|
||||||
|
|
||||||
if (weißIch) {
|
function startMultipleTraining() {
|
||||||
trainingsZustand.gelernt.push(karte);
|
multipleEngine = new TrainingsEngine(parsedArray);
|
||||||
trainingsZustand.aktiveKarten = trainingsZustand.aktiveKarten.filter(k => k !== karte);
|
zeigeNaechsteMultipleKarte();
|
||||||
} else {
|
}
|
||||||
karte.versuche++;
|
|
||||||
if (karte.versuche >= 5) {
|
let aktuelleKarte = null;
|
||||||
trainingsZustand.nichtGelernt.push(karte);
|
let ersteAntwort = true;
|
||||||
trainingsZustand.aktiveKarten = trainingsZustand.aktiveKarten.filter(k => k !== karte);
|
|
||||||
|
function zeigeNaechsteMultipleKarte() {
|
||||||
|
const container = document.getElementById("trainingMultiple");
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
|
const element = multipleEngine.naechstesElement();
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
container.innerHTML = `<div style="text-align:center; font-size: 24px; margin-top:20px;">🎉 Training beendet!<br>Gelernt: ${multipleEngine.gelernt.length}<br>Nicht gelernt: ${multipleEngine.nichtGelernt.length}</div>`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aktuelleKarte = element;
|
||||||
|
ersteAntwort = true;
|
||||||
|
|
||||||
|
const frage = document.createElement("div");
|
||||||
|
frage.className = "multiple-frage";
|
||||||
|
frage.innerHTML = `<h2>${element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch}</h2>`;
|
||||||
|
container.appendChild(frage);
|
||||||
|
|
||||||
|
const optionen = generiereMultipleOptionen(element);
|
||||||
|
const optionContainer = document.createElement("div");
|
||||||
|
optionContainer.className = "multiple-optionen";
|
||||||
|
|
||||||
|
optionen.forEach(text => {
|
||||||
|
const btn = document.createElement("button");
|
||||||
|
btn.className = "multiple-option";
|
||||||
|
btn.innerText = text;
|
||||||
|
|
||||||
|
btn.onclick = () => {
|
||||||
|
const korrektText = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch;
|
||||||
|
const istKorrekt = (text === korrektText);
|
||||||
|
|
||||||
|
if (istKorrekt) {
|
||||||
|
btn.style.backgroundColor = "#a8f0a8";
|
||||||
|
if (ersteAntwort) multipleEngine.antwortVerarbeiten(element, true);
|
||||||
|
setTimeout(() => zeigeNaechsteMultipleKarte(), 500);
|
||||||
|
|
||||||
|
} else if (ersteAntwort) {
|
||||||
|
btn.style.backgroundColor = "#f5a8a8";
|
||||||
|
btn.style.textDecoration = "line-through";
|
||||||
|
multipleEngine.antwortVerarbeiten(element, false);
|
||||||
|
ersteAntwort = false;
|
||||||
|
} else {
|
||||||
|
btn.style.backgroundColor = "#f5a8a8";
|
||||||
|
btn.style.textDecoration = "line-through";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
optionContainer.appendChild(btn);
|
||||||
|
});
|
||||||
|
|
||||||
|
container.appendChild(optionContainer);
|
||||||
|
}
|
||||||
|
function generiereMultipleOptionen(element) {
|
||||||
|
const korrekt = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch;
|
||||||
|
|
||||||
|
const falscheOptionen = parsedArray
|
||||||
|
.filter(k => k.id !== element.karte.id)
|
||||||
|
.map(k => element.richtung === "EN_DE" ? k.deutsch : k.englisch);
|
||||||
|
|
||||||
|
mischeArray(falscheOptionen);
|
||||||
|
|
||||||
|
const optionen = [korrekt, ...falscheOptionen.slice(0, 4)];
|
||||||
|
return mischeArray(optionen);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mischeArray(array) {
|
||||||
|
for (let i = array.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
let hintEngine;
|
||||||
|
|
||||||
|
function startHintTraining() {
|
||||||
|
hintEngine = new TrainingsEngine(parsedArray);
|
||||||
|
zeigeNaechsteHintKarte();
|
||||||
|
}
|
||||||
|
|
||||||
|
function zeigeNaechsteHintKarte() {
|
||||||
|
const container = document.getElementById("trainingHint");
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
|
const element = hintEngine.naechstesElement();
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
container.innerHTML = `
|
||||||
|
<div style="text-align:center; font-size: 24px; margin-top:20px;">
|
||||||
|
🎉 Training beendet!<br>
|
||||||
|
Gelernt: ${hintEngine.gelernt.length}<br>
|
||||||
|
Nicht gelernt: ${hintEngine.nichtGelernt.length}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const korrekt = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch;
|
||||||
|
|
||||||
|
const frage = document.createElement("div");
|
||||||
|
frage.className = "hint-frage";
|
||||||
|
frage.innerText = element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch;
|
||||||
|
container.appendChild(frage);
|
||||||
|
|
||||||
|
const clue = document.createElement("div");
|
||||||
|
clue.className = "hint-clue";
|
||||||
|
clue.innerText = erstelleClue(korrekt);
|
||||||
|
container.appendChild(clue);
|
||||||
|
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.className = "hint-input";
|
||||||
|
input.placeholder = "Schreibe die Übersetzung...";
|
||||||
|
input.autofocus = true;
|
||||||
|
input.style.fontSize = "18px";
|
||||||
|
input.style.padding = "5px 10px";
|
||||||
|
input.style.border = "2px solid #005b5b";
|
||||||
|
input.style.borderRadius = "6px";
|
||||||
|
input.style.width = "300px";
|
||||||
|
input.style.caretColor = "#005b5b";
|
||||||
|
container.appendChild(input);
|
||||||
|
|
||||||
|
const feedback = document.createElement("div");
|
||||||
|
feedback.className = "hint-feedback";
|
||||||
|
feedback.style.marginTop = "10px";
|
||||||
|
container.appendChild(feedback);
|
||||||
|
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.className = "hint-button";
|
||||||
|
button.innerText = "Überprüfen";
|
||||||
|
container.appendChild(button);
|
||||||
|
|
||||||
|
let phase = "check";
|
||||||
|
|
||||||
|
const pruefeAntwort = () => {
|
||||||
|
if (phase === "check") {
|
||||||
|
const userAnswer = input.value.trim();
|
||||||
|
if (!userAnswer) return;
|
||||||
|
|
||||||
|
const istKorrekt = userAnswer.toLowerCase() === korrekt.toLowerCase();
|
||||||
|
hintEngine.antwortVerarbeiten(element, istKorrekt);
|
||||||
|
|
||||||
|
if (istKorrekt) {
|
||||||
|
input.style.backgroundColor = "#a8f0a8";
|
||||||
|
setTimeout(() => zeigeNaechsteHintKarte(), 500);
|
||||||
|
} else {
|
||||||
|
input.style.backgroundColor = "#f5a8a8";
|
||||||
|
feedback.innerText = `Korrekte Antwort: ${korrekt}`;
|
||||||
|
button.innerText = "Weiter";
|
||||||
|
phase = "next";
|
||||||
|
}
|
||||||
|
} else if (phase === "next") {
|
||||||
|
zeigeNaechsteHintKarte();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
button.onclick = pruefeAntwort;
|
||||||
|
|
||||||
|
input.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.preventDefault();
|
||||||
|
pruefeAntwort();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
input.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
function erstelleClue(text) {
|
||||||
|
if (text.length === 1) return "*";
|
||||||
|
|
||||||
|
const chars = text.split("");
|
||||||
|
let clue = chars.map(char => (char === " " ? " " : "*"));
|
||||||
|
|
||||||
|
const visibleIndices = [];
|
||||||
|
while (visibleIndices.length < Math.max(1, Math.floor(chars.length / 2))) {
|
||||||
|
const idx = Math.floor(Math.random() * chars.length);
|
||||||
|
if (chars[idx] !== " " && !visibleIndices.includes(idx)) {
|
||||||
|
visibleIndices.push(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visibleIndices.forEach(idx => {
|
||||||
|
clue[idx] = chars[idx];
|
||||||
|
});
|
||||||
|
|
||||||
|
return clue.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
let writeEngine;
|
||||||
|
|
||||||
|
function startWriteTraining() {
|
||||||
|
writeEngine = new TrainingsEngine(parsedArray);
|
||||||
|
zeigeNaechsteWriteKarte();
|
||||||
|
}
|
||||||
|
|
||||||
|
function zeigeNaechsteWriteKarte() {
|
||||||
|
const container = document.getElementById("trainingWrite");
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
|
const element = writeEngine.naechstesElement();
|
||||||
|
|
||||||
|
if (!element) {
|
||||||
|
container.innerHTML = `
|
||||||
|
<div style="text-align:center; font-size: 24px; margin-top:20px;">
|
||||||
|
🎉 Training beendet!<br>
|
||||||
|
Gelernt: ${writeEngine.gelernt.length}<br>
|
||||||
|
Nicht gelernt: ${writeEngine.nichtGelernt.length}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const korrekt = element.richtung === "EN_DE" ? element.karte.deutsch : element.karte.englisch;
|
||||||
|
|
||||||
|
const frage = document.createElement("div");
|
||||||
|
frage.className = "hint-frage";
|
||||||
|
frage.innerHTML = element.richtung === "EN_DE" ? element.karte.englisch : element.karte.deutsch;
|
||||||
|
container.appendChild(frage);
|
||||||
|
|
||||||
|
const input = document.createElement("input");
|
||||||
|
input.className = "hint-input";
|
||||||
|
input.placeholder = "Schreibe die Übersetzung...";
|
||||||
|
input.autofocus = true;
|
||||||
|
input.style.fontSize = "18px";
|
||||||
|
input.style.padding = "5px 10px";
|
||||||
|
input.style.border = "2px solid #005b5b";
|
||||||
|
input.style.borderRadius = "6px";
|
||||||
|
input.style.width = "300px";
|
||||||
|
input.style.caretColor = "#005b5b";
|
||||||
|
container.appendChild(input);
|
||||||
|
|
||||||
|
const feedback = document.createElement("div");
|
||||||
|
feedback.className = "hint-feedback";
|
||||||
|
feedback.style.marginTop = "10px";
|
||||||
|
container.appendChild(feedback);
|
||||||
|
|
||||||
|
const button = document.createElement("button");
|
||||||
|
button.className = "hint-button";
|
||||||
|
button.innerText = "Überprüfen";
|
||||||
|
container.appendChild(button);
|
||||||
|
|
||||||
|
let phase = "check";
|
||||||
|
|
||||||
|
const pruefeAntwort = () => {
|
||||||
|
if (phase === "check") {
|
||||||
|
const userAnswer = input.value.trim();
|
||||||
|
if (!userAnswer) return;
|
||||||
|
|
||||||
|
const istKorrekt = userAnswer.toLowerCase() === korrekt.toLowerCase();
|
||||||
|
writeEngine.antwortVerarbeiten(element, istKorrekt);
|
||||||
|
|
||||||
|
if (istKorrekt) {
|
||||||
|
input.style.backgroundColor = "#a8f0a8";
|
||||||
|
setTimeout(() => zeigeNaechsteWriteKarte(), 500);
|
||||||
|
} else {
|
||||||
|
input.style.backgroundColor = "#f5a8a8";
|
||||||
|
feedback.innerText = `Korrekte Antwort: ${korrekt}`;
|
||||||
|
button.innerText = "Weiter";
|
||||||
|
phase = "next";
|
||||||
|
}
|
||||||
|
} else if (phase === "next") {
|
||||||
|
zeigeNaechsteWriteKarte();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
button.onclick = pruefeAntwort;
|
||||||
|
input.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "Enter") {
|
||||||
|
e.preventDefault();
|
||||||
|
pruefeAntwort();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
input.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
let matchingEngine;
|
||||||
|
let matchingRunde = 0;
|
||||||
|
let linkeKarten = [];
|
||||||
|
let rechteKarten = [];
|
||||||
|
let aktuelleRichtung = "EN_DE";
|
||||||
|
|
||||||
|
function startMittelTraining() {
|
||||||
|
matchingEngine = new TrainingsEngine(parsedArray);
|
||||||
|
matchingRunde = 0;
|
||||||
|
ladeMatchingRunde();
|
||||||
|
}
|
||||||
|
|
||||||
|
function ladeMatchingRunde() {
|
||||||
|
const container = document.getElementById("trainingMatching");
|
||||||
|
container.innerHTML = "";
|
||||||
|
|
||||||
|
aktuelleRichtung = matchingRunde % 2 === 0 ? "EN_DE" : "DE_EN";
|
||||||
|
matchingRunde++;
|
||||||
|
|
||||||
|
const learningCards = matchingEngine.kartenQueue.filter(e => e.status === "learning");
|
||||||
|
|
||||||
|
linkeKarten = learningCards
|
||||||
|
.reduce((acc, el) => {
|
||||||
|
if (!acc.find(a => a.karte.id === el.karte.id)) acc.push(el);
|
||||||
|
return acc;
|
||||||
|
}, [])
|
||||||
|
.slice(0, 4);
|
||||||
|
|
||||||
|
rechteKarten = mischeArray([...linkeKarten]);
|
||||||
|
|
||||||
|
const linksDiv = document.createElement("div");
|
||||||
|
linksDiv.className = "spalte-links";
|
||||||
|
|
||||||
|
const rechtsDiv = document.createElement("div");
|
||||||
|
rechtsDiv.className = "spalte-rechts";
|
||||||
|
|
||||||
|
linkeKarten.forEach(k => {
|
||||||
|
const dropZone = document.createElement("div");
|
||||||
|
dropZone.className = "training-card drop-zone";
|
||||||
|
dropZone.dataset.id = k.karte.id;
|
||||||
|
|
||||||
|
dropZone.innerHTML = `
|
||||||
|
<div class="card-top">
|
||||||
|
<h3>${aktuelleRichtung === "EN_DE" ? k.karte.englisch : k.karte.deutsch}</h3>
|
||||||
|
${aktuelleRichtung === "EN_DE" && k.karte.ipa ? `<div class="ipa">${k.karte.ipa}</div>` : ""}
|
||||||
|
</div>
|
||||||
|
<div class="card-example">
|
||||||
|
${aktuelleRichtung === "EN_DE" ? k.karte.beispielEN || "" : k.karte.beispielDE || ""}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
linksDiv.appendChild(dropZone);
|
||||||
|
});
|
||||||
|
|
||||||
|
rechteKarten.forEach((k, index) => {
|
||||||
|
const ziehKarte = document.createElement("div");
|
||||||
|
ziehKarte.className = "training-card zieh-karte";
|
||||||
|
ziehKarte.draggable = true;
|
||||||
|
ziehKarte.dataset.index = index;
|
||||||
|
|
||||||
|
const zeigeEnglisch = aktuelleRichtung === "DE_EN";
|
||||||
|
ziehKarte.innerHTML = `
|
||||||
|
<div class="card-top">
|
||||||
|
<h3>${zeigeEnglisch ? k.karte.englisch : k.karte.deutsch}</h3>
|
||||||
|
${zeigeEnglisch && k.karte.ipa ? `<div class="ipa">${k.karte.ipa}</div>` : ""}
|
||||||
|
</div>
|
||||||
|
<div class="card-example">
|
||||||
|
${zeigeEnglisch ? k.karte.beispielEN || "" : k.karte.beispielDE || ""}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
ziehKarte.addEventListener("dragstart", e => e.dataTransfer.setData("draggedIndex", index));
|
||||||
|
ziehKarte.addEventListener("dragover", e => e.preventDefault());
|
||||||
|
ziehKarte.addEventListener("drop", e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const draggedIndex = Number(e.dataTransfer.getData("draggedIndex"));
|
||||||
|
swapZiehKarten(draggedIndex, index, linksDiv, rechtsDiv);
|
||||||
|
});
|
||||||
|
|
||||||
|
rechtsDiv.appendChild(ziehKarte);
|
||||||
|
});
|
||||||
|
|
||||||
|
container.appendChild(linksDiv);
|
||||||
|
container.appendChild(rechtsDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderMatchingRechts(linksDiv, rechtsDiv) {
|
||||||
|
rechtsDiv.innerHTML = "";
|
||||||
|
|
||||||
|
rechteKarten.forEach((k, index) => {
|
||||||
|
const ziehKarte = document.createElement("div");
|
||||||
|
ziehKarte.className = "training-card zieh-karte";
|
||||||
|
ziehKarte.draggable = true;
|
||||||
|
ziehKarte.dataset.index = index;
|
||||||
|
|
||||||
|
const zeigeEnglisch = (aktuelleRichtung === "DE_EN");
|
||||||
|
ziehKarte.innerHTML = `
|
||||||
|
<div class="card-top">
|
||||||
|
<h3>${zeigeEnglisch ? k.karte.englisch : k.karte.deutsch}</h3>
|
||||||
|
${zeigeEnglisch && k.karte.ipa
|
||||||
|
? `<div class="ipa">${k.karte.ipa}</div>`
|
||||||
|
: ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="card-example">
|
||||||
|
${zeigeEnglisch
|
||||||
|
? k.karte.beispielEN || ""
|
||||||
|
: k.karte.beispielDE || ""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
ziehKarte.addEventListener("dragstart", e => e.dataTransfer.setData("draggedIndex", index));
|
||||||
|
ziehKarte.addEventListener("dragover", e => e.preventDefault());
|
||||||
|
ziehKarte.addEventListener("drop", e => {
|
||||||
|
e.preventDefault();
|
||||||
|
const draggedIndex = Number(e.dataTransfer.getData("draggedIndex"));
|
||||||
|
swapZiehKarten(draggedIndex, index, linksDiv, rechtsDiv);
|
||||||
|
});
|
||||||
|
|
||||||
|
rechtsDiv.appendChild(ziehKarte);
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = document.getElementById("trainingMatching");
|
||||||
|
container.appendChild(linksDiv);
|
||||||
|
container.appendChild(rechtsDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
function swapZiehKarten(fromIndex, toIndex, linksDiv, rechtsDiv) {
|
||||||
|
const temp = rechteKarten[fromIndex];
|
||||||
|
rechteKarten[fromIndex] = rechteKarten[toIndex];
|
||||||
|
rechteKarten[toIndex] = temp;
|
||||||
|
renderMatchingRechts(linksDiv, rechtsDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
function pruefeRunde() {
|
||||||
|
const ziehElemente = document.querySelectorAll(".zieh-karte");
|
||||||
|
|
||||||
|
linkeKarten.forEach((k, index) => {
|
||||||
|
const gezogene = rechteKarten[index];
|
||||||
|
const elementDiv = ziehElemente[index];
|
||||||
|
|
||||||
|
if (k.karte.id === gezogene.karte.id) {
|
||||||
|
elementDiv.style.backgroundColor = "#a8f0a8";
|
||||||
|
matchingEngine.antwortVerarbeiten(gezogene, true);
|
||||||
} else {
|
} else {
|
||||||
trainingsZustand.aktiveKarten.push(trainingsZustand.aktiveKarten.splice(trainingsZustand.aktiveKarten.indexOf(karte), 1)[0]);
|
elementDiv.style.backgroundColor = "#f5a8a8";
|
||||||
}
|
matchingEngine.antwortVerarbeiten(gezogene, false);
|
||||||
}
|
|
||||||
|
|
||||||
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
|
const learningLeft = matchingEngine.kartenQueue.length;
|
||||||
.querySelector(".modus-btn[data-modus='training_einfach']")
|
const gelerntCount = matchingEngine.gelernt.length;
|
||||||
.addEventListener("click", () => {
|
const nichtGelerntCount = matchingEngine.nichtGelernt.length;
|
||||||
showView("onlineTraining");
|
|
||||||
});
|
if (learningLeft === 0) {
|
||||||
|
const container = document.getElementById("trainingMatching");
|
||||||
|
container.innerHTML = `
|
||||||
|
<div style="text-align:center; font-size: 24px; margin-top:20px;">
|
||||||
|
🎉 Training beendet!<br>
|
||||||
|
Gelernt: ${gelerntCount}<br>
|
||||||
|
Nicht gelernt: ${nichtGelerntCount}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
const checkBtn = document.getElementById("checkBtn");
|
||||||
|
if (checkBtn) checkBtn.style.display = "none";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
ladeMatchingRunde();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mischeArray(array) {
|
||||||
|
for (let i = array.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[array[i], array[j]] = [array[j], array[i]];
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
@@ -281,14 +281,53 @@ h1 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#trainingFlip .training-card {
|
||||||
|
height: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingMatching .training-card {
|
||||||
|
height: 100px;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin: 0;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.training-card {
|
.training-card {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
height: 180px;
|
|
||||||
margin: 10px auto;
|
margin: 10px auto;
|
||||||
perspective: 1000px;
|
perspective: 1000px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#trainingMatching .drop-zone,
|
||||||
|
#trainingMatching .zieh-karte {
|
||||||
|
min-height: 120px;
|
||||||
|
max-height: 120px;
|
||||||
|
width: 300px;
|
||||||
|
background: #fff;
|
||||||
|
border: 2px solid #666;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
padding: 5px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingMatching .drop-zone h2,
|
||||||
|
#trainingMatching .zieh-karte h2,
|
||||||
|
#trainingMatching .drop-zone .ipa,
|
||||||
|
#trainingMatching .zieh-karte .ipa,
|
||||||
|
#trainingMatching .drop-zone .example,
|
||||||
|
#trainingMatching .zieh-karte .example {
|
||||||
|
margin: 2px 0;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.training-card-inner {
|
.training-card-inner {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -313,8 +352,42 @@ h1 {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: flex-start;
|
||||||
gap: 10px;
|
align-items: stretch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-top {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-top h2 {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-top h3 {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-top .ipa {
|
||||||
|
margin: 0;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-example {
|
||||||
|
margin-top: auto;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ipa {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
.training-back {
|
.training-back {
|
||||||
@@ -334,33 +407,229 @@ h1 {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.training-front h2 {
|
#pdfPages,
|
||||||
margin-bottom: 4px;
|
#onlineTraining {
|
||||||
margin-top: -25px;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.training-front .ipa {
|
#trainingMatching {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spalte-links {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spalte-rechts {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drop-zone, .zieh-karte {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
background: #fff;
|
||||||
|
border: 2px solid #666;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.zieh-karte {
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
#checkBtn {
|
||||||
|
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("verified.jfif");
|
||||||
|
background-repeat: repeat;
|
||||||
|
background-size: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingMultiple {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple-frage {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple-optionen {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple-option {
|
||||||
|
padding: 10px 15px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
text-align: center;
|
||||||
|
transition: background-color 0.2s, transform 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple-option:hover {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
transform: scale(1.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
.multiple-option[disabled] {
|
||||||
|
text-decoration: line-through;
|
||||||
|
background-color: #f5a8a8;
|
||||||
|
color: #800;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingHint {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-frage {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-input {
|
||||||
|
width: 300px;
|
||||||
|
font-size: 18px;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-button {
|
||||||
|
padding: 10px 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
background-color: #005b5b;
|
||||||
|
color: white;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-button:hover {
|
||||||
|
background-color: #007070;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-feedback {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hint-clue {
|
||||||
|
font-size: 20px;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
margin-bottom: 10px;
|
||||||
color: #555;
|
color: #555;
|
||||||
margin-bottom: 34px;
|
text-align: center;
|
||||||
margin-top: -12px;
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
.training-front .example {
|
#trainingWrite {
|
||||||
font-size: 15px;
|
display: flex;
|
||||||
line-height: 1.4;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.training-back h2 {
|
#trainingWrite .schwer-frage {
|
||||||
margin-bottom: 54px;
|
text-align: center;
|
||||||
margin-top: -28px;
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modus-view {
|
#trainingWrite input[type="text"] {
|
||||||
display: none;
|
font-size: 18px;
|
||||||
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.training-view {
|
#trainingWrite button {
|
||||||
display: none;
|
padding: 10px 15px;
|
||||||
margin-top: 25px;
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 6px;
|
||||||
|
border: none;
|
||||||
|
background-color: #005b5b;
|
||||||
|
color: white;
|
||||||
|
transition: 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingWrite button:hover {
|
||||||
|
background-color: #007070;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingLevels {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 15px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.training-title {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingLevels .buttons-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingLevels .buttons-row .level-btn {
|
||||||
|
flex: 1;
|
||||||
|
padding: 12px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
border: none;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: center;
|
||||||
|
transition: background-color 0.2s, transform 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#trainingLevels .buttons-row .level-btn:hover {
|
||||||
|
background-color: #e0e0e0;
|
||||||
|
transform: scale(1.02);
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
MainPage/stas/verified.jfif
Normal file
BIN
MainPage/stas/verified.jfif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
22
Readme.md
Normal file
22
Readme.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# Lernplattform Projekt
|
||||||
|
|
||||||
|
Dies ist unser Lernplattform-Projekt, entwickelt von:
|
||||||
|
|
||||||
|
- Abdelaziz Elouazzani
|
||||||
|
- Younes El Haddoury
|
||||||
|
- Ayman Alshian
|
||||||
|
- Stanislav Kharchenko
|
||||||
|
- Saad Akki
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Projektbeschreibung
|
||||||
|
|
||||||
|
Dieses Projekt ist eine Lernplattform, die verschiedene Funktionen zum Üben und Lernen bietet.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Abgabe & Download
|
||||||
|
|
||||||
|
- **Git-Repository:** [Zum Repository](https://git.bib.de/PBT3H24AKH/LerningCSW.git)
|
||||||
|
- **Projekt als ZIP herunterladen:** [Download ZIP](https://git.bib.de/PBT3H24AKH/LerningCSW/archive/refs/heads/main.zip)
|
||||||
Reference in New Issue
Block a user