update tasks and sidebar
This commit is contained in:
@@ -5,6 +5,7 @@ const API_BASE = '';
|
|||||||
let totalPoints = 0;
|
let totalPoints = 0;
|
||||||
let tasks = [];
|
let tasks = [];
|
||||||
let chapters = [];
|
let chapters = [];
|
||||||
|
let chapterDescriptions = {}; // Map von chapter name zu description
|
||||||
let activeChapter = null;
|
let activeChapter = null;
|
||||||
|
|
||||||
// Initialisiere die App
|
// Initialisiere die App
|
||||||
@@ -12,7 +13,7 @@ async function init() {
|
|||||||
await loadTasks();
|
await loadTasks();
|
||||||
extractChapters();
|
extractChapters();
|
||||||
calculateTotalPoints();
|
calculateTotalPoints();
|
||||||
renderTabs();
|
renderSidebar();
|
||||||
renderTasks();
|
renderTasks();
|
||||||
updateProgress();
|
updateProgress();
|
||||||
}
|
}
|
||||||
@@ -40,9 +41,15 @@ async function loadTasks() {
|
|||||||
// Extrahiere alle Chapters aus den Tasks
|
// Extrahiere alle Chapters aus den Tasks
|
||||||
function extractChapters() {
|
function extractChapters() {
|
||||||
const chapterSet = new Set();
|
const chapterSet = new Set();
|
||||||
|
chapterDescriptions = {};
|
||||||
|
|
||||||
tasks.forEach(task => {
|
tasks.forEach(task => {
|
||||||
if (task.chapter) {
|
if (task.chapter) {
|
||||||
chapterSet.add(task.chapter);
|
chapterSet.add(task.chapter);
|
||||||
|
// Speichere die erste gefundene Beschreibung für jedes Kapitel
|
||||||
|
if (task.chapterDescription && !chapterDescriptions[task.chapter]) {
|
||||||
|
chapterDescriptions[task.chapter] = task.chapterDescription;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
chapters = Array.from(chapterSet).sort();
|
chapters = Array.from(chapterSet).sort();
|
||||||
@@ -56,32 +63,37 @@ function extractChapters() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rendere Tabs für alle Chapters
|
// Rendere Sidebar für alle Chapters
|
||||||
function renderTabs() {
|
function renderSidebar() {
|
||||||
const tabsContainer = document.getElementById('tabsContainer');
|
const sidebar = document.getElementById('sidebar');
|
||||||
tabsContainer.innerHTML = '';
|
sidebar.innerHTML = '';
|
||||||
|
|
||||||
// Zeige Tabs nur an, wenn es Chapters gibt
|
// Zeige Sidebar nur an, wenn es Chapters gibt
|
||||||
if (chapters.length === 0) {
|
if (chapters.length === 0) {
|
||||||
tabsContainer.style.display = 'none';
|
sidebar.style.display = 'none';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tabsContainer.style.display = 'flex';
|
sidebar.style.display = 'block';
|
||||||
|
|
||||||
chapters.forEach(chapter => {
|
chapters.forEach(chapter => {
|
||||||
const tabButton = document.createElement('button');
|
const sidebarItem = document.createElement('div');
|
||||||
tabButton.className = `tab-button ${activeChapter === chapter ? 'active' : ''}`;
|
sidebarItem.className = `sidebar-item ${activeChapter === chapter ? 'active' : ''}`;
|
||||||
tabButton.textContent = chapter;
|
sidebarItem.onclick = () => switchChapter(chapter);
|
||||||
tabButton.onclick = () => switchChapter(chapter);
|
|
||||||
tabsContainer.appendChild(tabButton);
|
const title = document.createElement('div');
|
||||||
|
title.className = 'sidebar-item-title';
|
||||||
|
title.textContent = chapter;
|
||||||
|
sidebarItem.appendChild(title);
|
||||||
|
|
||||||
|
sidebar.appendChild(sidebarItem);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wechsle zu einem anderen Chapter
|
// Wechsle zu einem anderen Chapter
|
||||||
function switchChapter(chapter) {
|
function switchChapter(chapter) {
|
||||||
activeChapter = chapter;
|
activeChapter = chapter;
|
||||||
renderTabs();
|
renderSidebar();
|
||||||
renderTasks();
|
renderTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +108,18 @@ function getTasksForActiveChapter() {
|
|||||||
// Rendere Aufgaben
|
// Rendere Aufgaben
|
||||||
function renderTasks() {
|
function renderTasks() {
|
||||||
const container = document.getElementById('taskContainer');
|
const container = document.getElementById('taskContainer');
|
||||||
|
const descriptionEl = document.getElementById('chapterDescription');
|
||||||
|
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
// Zeige Kapitel-Beschreibung an
|
||||||
|
if (activeChapter && chapterDescriptions[activeChapter]) {
|
||||||
|
descriptionEl.textContent = chapterDescriptions[activeChapter];
|
||||||
|
descriptionEl.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
descriptionEl.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
const tasksToShow = getTasksForActiveChapter();
|
const tasksToShow = getTasksForActiveChapter();
|
||||||
|
|
||||||
tasksToShow.forEach(task => {
|
tasksToShow.forEach(task => {
|
||||||
@@ -203,7 +225,7 @@ async function checkAnswer(taskId) {
|
|||||||
|
|
||||||
// Nach Animation die Aufgabe entfernen
|
// Nach Animation die Aufgabe entfernen
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
renderTabs();
|
renderSidebar();
|
||||||
renderTasks();
|
renderTasks();
|
||||||
updateProgress();
|
updateProgress();
|
||||||
}, 1500);
|
}, 1500);
|
||||||
@@ -214,9 +236,9 @@ async function checkAnswer(taskId) {
|
|||||||
input.focus();
|
input.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rendere Tabs und Tasks neu, um den aktuellen Status anzuzeigen (nur wenn nicht korrekt)
|
// Rendere Sidebar und Tasks neu, um den aktuellen Status anzuzeigen (nur wenn nicht korrekt)
|
||||||
if (!data.correct) {
|
if (!data.correct) {
|
||||||
renderTabs();
|
renderSidebar();
|
||||||
renderTasks();
|
renderTasks();
|
||||||
updateProgress();
|
updateProgress();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,34 +7,38 @@
|
|||||||
<link rel="stylesheet" href="style.css">
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="app-wrapper">
|
||||||
<header>
|
<aside class="sidebar" id="sidebar">
|
||||||
<h1>🌟 MathQuest 🌟</h1>
|
<!-- Sidebar wird hier dynamisch eingefügt -->
|
||||||
<div class="points-display">
|
</aside>
|
||||||
<div class="points-label">Quest-Punkte</div>
|
<div class="main-content">
|
||||||
<div class="points-value" id="totalPoints">0</div>
|
<div class="container">
|
||||||
</div>
|
<header>
|
||||||
</header>
|
<h1>🌟 MathQuest 🌟</h1>
|
||||||
|
<div class="points-display">
|
||||||
|
<div class="points-label">Quest-Punkte</div>
|
||||||
|
<div class="points-value" id="totalPoints">0</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="progress-section">
|
<div class="progress-section">
|
||||||
<div class="progress-label">Fortschritt</div>
|
<div class="progress-label">Fortschritt</div>
|
||||||
<div class="progress-bar-container">
|
<div class="progress-bar-container">
|
||||||
<div class="progress-bar" id="progressBar"></div>
|
<div class="progress-bar" id="progressBar"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="progress-text" id="progressText">0 / 100</div>
|
<div class="progress-text" id="progressText">0 / 100</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="task-section">
|
<div class="task-section">
|
||||||
<h2>Mathe-Aufgaben</h2>
|
<div id="chapterDescription" class="chapter-description"></div>
|
||||||
<div class="tabs-container" id="tabsContainer">
|
<div id="taskContainer" class="task-container">
|
||||||
<!-- Tabs werden hier dynamisch eingefügt -->
|
<!-- Aufgaben werden hier dynamisch eingefügt -->
|
||||||
</div>
|
</div>
|
||||||
<div id="taskContainer" class="task-container">
|
</div>
|
||||||
<!-- Aufgaben werden hier dynamisch eingefügt -->
|
|
||||||
|
<div class="message" id="message"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="message" id="message"></div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
|
|||||||
149
public/style.css
149
public/style.css
@@ -8,13 +8,66 @@ body {
|
|||||||
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', cursive, sans-serif;
|
font-family: 'Comic Sans MS', 'Chalkboard SE', 'Comic Neue', cursive, sans-serif;
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
padding: 20px;
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.app-wrapper {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
gap: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 280px;
|
||||||
|
background: white;
|
||||||
|
border-radius: 20px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
|
||||||
|
position: sticky;
|
||||||
|
top: 20px;
|
||||||
|
height: fit-content;
|
||||||
|
max-height: calc(100vh - 40px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item {
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
|
||||||
|
border: 2px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item:hover {
|
||||||
|
transform: translateX(5px);
|
||||||
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item.active {
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: white;
|
||||||
|
border-color: rgba(255, 255, 255, 0.3);
|
||||||
|
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item-title {
|
||||||
|
font-size: 1.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.container {
|
.container {
|
||||||
max-width: 800px;
|
max-width: 100%;
|
||||||
margin: 0 auto;
|
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
@@ -93,50 +146,16 @@ h1 {
|
|||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-section h2 {
|
.chapter-description {
|
||||||
color: #667eea;
|
background: linear-gradient(135deg, #e8f5e9 0%, #fff3e0 100%);
|
||||||
margin-bottom: 20px;
|
padding: 20px;
|
||||||
text-align: center;
|
border-radius: 15px;
|
||||||
font-size: 1.8em;
|
margin-bottom: 25px;
|
||||||
}
|
|
||||||
|
|
||||||
.tabs-container {
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button {
|
|
||||||
background: linear-gradient(135deg, #a8edea 0%, #fed6e3 100%);
|
|
||||||
color: #333;
|
|
||||||
border: none;
|
|
||||||
padding: 12px 20px;
|
|
||||||
font-size: 1.1em;
|
font-size: 1.1em;
|
||||||
border-radius: 10px;
|
line-height: 1.6;
|
||||||
cursor: pointer;
|
color: #555;
|
||||||
font-family: 'Comic Sans MS', cursive;
|
border-left: 4px solid #667eea;
|
||||||
font-weight: bold;
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
transition: all 0.3s ease;
|
|
||||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button.active {
|
|
||||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
||||||
color: white;
|
|
||||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-button.active:hover {
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.5);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-container {
|
.task-container {
|
||||||
@@ -228,6 +247,7 @@ h1 {
|
|||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
|
|
||||||
.task-input-group {
|
.task-input-group {
|
||||||
@@ -332,6 +352,30 @@ h1 {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 900px) {
|
||||||
|
.app-wrapper {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
top: 0;
|
||||||
|
max-height: none;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
overflow-x: auto;
|
||||||
|
overflow-y: hidden;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item {
|
||||||
|
min-width: 200px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.container {
|
.container {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
@@ -352,4 +396,17 @@ h1 {
|
|||||||
.task-button {
|
.task-button {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item {
|
||||||
|
min-width: 180px;
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-item-title {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
tasks.json
10
tasks.json
@@ -1,10 +1,11 @@
|
|||||||
[{
|
[ {
|
||||||
"id": "bode-museum-1",
|
"id": "bode-museum-1",
|
||||||
"question": "🕵️ AKTE: Bode-Museum Berlin, 27.03.2017\n\nGESTOHLEN: 1 Goldmünze (Big Maple Leaf)\nGEWICHT: 100 kg\nGOLDPREIS (Tatzeit): 37.500 €/kg\n\nBerechne den Versicherungsschaden in Euro.",
|
"question": "🕵️ AKTE: Bode-Museum Berlin, 27.03.2017\n\nGESTOHLEN: 1 Goldmünze (Big Maple Leaf)\nGEWICHT: 100 kg\nGOLDPREIS (Tatzeit): 37.500 €/kg\n\nBerechne den Versicherungsschaden in Euro.",
|
||||||
"answer": 3750000,
|
"answer": 3750000,
|
||||||
"points": 50,
|
"points": 50,
|
||||||
"type": "word-problem",
|
"type": "word-problem",
|
||||||
"chapter": "🔍 Bode-Museum: Der Big Maple Leaf Raub"
|
"chapter": "🔍 Bode-Museum: Der Big Maple Leaf Raub",
|
||||||
|
"chapterDescription": "Am 27. März 2017 wurde aus dem Bode-Museum in Berlin eine der größten Goldmünzen der Welt gestohlen: die 'Big Maple Leaf' mit einem Gewicht von 100 kg. Die Täter drangen nachts in das Museum ein und entwendeten die wertvolle Münze. Die Polizei startete eine großangelegte Fahndung nach den Tätern und der gestohlenen Münze."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "bode-museum-2",
|
"id": "bode-museum-2",
|
||||||
@@ -28,11 +29,12 @@
|
|||||||
"answer": 1234000,
|
"answer": 1234000,
|
||||||
"points": 45,
|
"points": 45,
|
||||||
"type": "word-problem",
|
"type": "word-problem",
|
||||||
"chapter": "🏦 Berlin-Steglitz: Der Bankeinbruch 2013"
|
"chapter": "🏦 Berlin-Steglitz: Der Bankeinbruch 2013",
|
||||||
|
"chapterDescription": "Im Januar 2013 gruben Täter einen unterirdischen Tunnel von einem leerstehenden Ladenlokal zur Sparkasse in Berlin-Steglitz. Über mehrere Tage arbeiteten sie sich durch den Boden, um unbemerkt in die Tresorräume der Bank zu gelangen. Der Einbruch wurde erst entdeckt, nachdem die Täter bereits mit der Beute geflohen waren."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "steglitz-2",
|
"id": "steglitz-2",
|
||||||
"question": "Die Täter gruben einen Tunnel von einem leerstehenden Ladenlokal zur Sparkasse in Berlin-Steglitz. Der Tunnel sollte 47 Meter lang werden.\n\nDrei Täter gruben gemeinsam: Jeder grub pro Tag 8 Meter.\nNach 2 Tagen kam ein vierter Täter dazu und grub an einem Tag weitere 15 Meter.\n\nWie viele Meter des Tunnels fehlten noch, bis sie die Bank erreichten?",
|
"question": "Die Täter gruben einen Tunnel von einem leerstehenden Ladenlokal zur Sparkasse in Berlin-Steglitz. Der Tunnel sollte 47 Meter lang werden.\n\nDrei Täter gruben gemeinsam und schafften zusammen 8 Meter pro Tag.\nNach 2 Tagen kam ein vierter Täter dazu. An diesem Tag gruben alle vier zusammen weitere 15 Meter.\n\nWie viele Meter des Tunnels fehlten noch, bis sie die Bank erreichten?",
|
||||||
"answer": 16,
|
"answer": 16,
|
||||||
"points": 50,
|
"points": 50,
|
||||||
"type": "word-problem",
|
"type": "word-problem",
|
||||||
|
|||||||
Reference in New Issue
Block a user