initial import
This commit is contained in:
151
static/script.js
Normal file
151
static/script.js
Normal file
@ -0,0 +1,151 @@
|
||||
const canvas = document.getElementById('drawingCanvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
const textElement = document.getElementById('text');
|
||||
const wordDisplay = document.getElementById('wordDisplay');
|
||||
const textInput = document.getElementById('textInput');
|
||||
const submitAnswer = document.getElementById('submitAnswer');
|
||||
const toggleInput = document.getElementById('toggleInput');
|
||||
const clearCanvas = document.getElementById('clearCanvas');
|
||||
const previewDrawing = document.getElementById('previewDrawing');
|
||||
const recognizedText = document.getElementById('recognizedText');
|
||||
|
||||
let currentWord = null;
|
||||
let currentInputMode = 'text'; // 'text' or 'drawing'
|
||||
let isDrawing = false;
|
||||
|
||||
// Initialize input mode
|
||||
function initializeInputMode() {
|
||||
textInput.style.display = 'block';
|
||||
canvas.style.display = 'none';
|
||||
clearCanvas.style.display = 'none';
|
||||
previewDrawing.style.display = 'none';
|
||||
toggleInput.textContent = 'Zu Zeichnen wechseln';
|
||||
recognizedText.textContent = '';
|
||||
}
|
||||
|
||||
// Load a new word
|
||||
function loadWord() {
|
||||
fetch('/get_random_vocab')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.error) {
|
||||
wordDisplay.textContent = 'Keine Vokabeln gefunden.';
|
||||
} else {
|
||||
currentWord = data;
|
||||
const isEnglish = Math.random() < 0.5;
|
||||
wordDisplay.textContent = isEnglish ? `English: ${currentWord.english}` : `Deutsch: ${currentWord.german}`;
|
||||
textElement.textContent = '';
|
||||
textInput.value = '';
|
||||
recognizedText.textContent = '';
|
||||
if (currentInputMode === 'drawing') {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Fehler beim Laden der Vokabel:', error));
|
||||
}
|
||||
|
||||
// Switch between input modes
|
||||
toggleInput.addEventListener('click', () => {
|
||||
if (currentInputMode === 'text') {
|
||||
textInput.style.display = 'none';
|
||||
canvas.style.display = 'block';
|
||||
clearCanvas.style.display = 'inline-block';
|
||||
previewDrawing.style.display = 'inline-block';
|
||||
toggleInput.textContent = 'Zu Texteingabe wechseln';
|
||||
currentInputMode = 'drawing';
|
||||
} else {
|
||||
textInput.style.display = 'block';
|
||||
canvas.style.display = 'none';
|
||||
clearCanvas.style.display = 'none';
|
||||
previewDrawing.style.display = 'none';
|
||||
toggleInput.textContent = 'Zu Zeichnen wechseln';
|
||||
currentInputMode = 'text';
|
||||
}
|
||||
});
|
||||
|
||||
// Clear the canvas
|
||||
clearCanvas.addEventListener('click', () => {
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
recognizedText.textContent = ''; // Clear the recognized text as well
|
||||
});
|
||||
|
||||
// Drawing functionality
|
||||
canvas.addEventListener('mousedown', () => {
|
||||
isDrawing = true;
|
||||
});
|
||||
|
||||
canvas.addEventListener('mouseup', () => {
|
||||
isDrawing = false;
|
||||
ctx.beginPath();
|
||||
});
|
||||
|
||||
canvas.addEventListener('mousemove', draw);
|
||||
|
||||
function draw(event) {
|
||||
if (!isDrawing) return;
|
||||
ctx.lineWidth = 5;
|
||||
ctx.lineCap = 'round';
|
||||
ctx.strokeStyle = 'black';
|
||||
|
||||
ctx.lineTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop);
|
||||
ctx.stroke();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(event.clientX - canvas.offsetLeft, event.clientY - canvas.offsetTop);
|
||||
}
|
||||
|
||||
// Preview the drawing recognition
|
||||
previewDrawing.addEventListener('click', () => {
|
||||
const dataURL = canvas.toDataURL('image/png');
|
||||
|
||||
fetch(dataURL)
|
||||
.then(res => res.blob())
|
||||
.then(blob => {
|
||||
Tesseract.recognize(
|
||||
blob,
|
||||
'eng',
|
||||
{ logger: info => console.log(info) }
|
||||
).then(({ data: { text } }) => {
|
||||
recognizedText.textContent = `Erkannter Text: ${text.trim()}`;
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Fehler beim Erkennen des Textes:', error);
|
||||
});
|
||||
});
|
||||
|
||||
// Submit answer
|
||||
submitAnswer.addEventListener('click', () => {
|
||||
let answer = '';
|
||||
|
||||
if (currentInputMode === 'text') {
|
||||
answer = textInput.value.trim();
|
||||
} else {
|
||||
answer = recognizedText.textContent.replace('Erkannter Text:', '').trim();
|
||||
}
|
||||
|
||||
checkAnswer(answer);
|
||||
});
|
||||
|
||||
// Check if the answer is correct
|
||||
function checkAnswer(answer) {
|
||||
const correctAnswer = (wordDisplay.textContent.startsWith('English:') ? currentWord.german : currentWord.english).trim().toLowerCase();
|
||||
if (answer.toLowerCase() === correctAnswer) {
|
||||
textElement.textContent = 'Richtig!';
|
||||
textElement.style.color = 'green';
|
||||
// Update the vocabulary level
|
||||
fetch(`/update_vocab_level/${currentWord.id}`, { method: 'POST' })
|
||||
.then(() => {
|
||||
setTimeout(loadWord, 2000); // Show the result for 2 seconds before loading the next word
|
||||
});
|
||||
} else {
|
||||
textElement.textContent = `Falsch! Die richtige Antwort ist: ${correctAnswer}`;
|
||||
textElement.style.color = 'red';
|
||||
setTimeout(loadWord, 3000); // Show the result for 3 seconds before loading the next word
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize the input mode and load the first word
|
||||
initializeInputMode();
|
||||
loadWord();
|
||||
|
33
static/styles.css
Normal file
33
static/styles.css
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
canvas {
|
||||
border: 1px solid #000;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 10px;
|
||||
padding: 10px 20px;
|
||||
background-color: #007bff;
|
||||
color: #fff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
160
static/vocab.js
Normal file
160
static/vocab.js
Normal file
@ -0,0 +1,160 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
loadVocab();
|
||||
|
||||
document.getElementById('addVocab').addEventListener('click', () => {
|
||||
const englishInput = document.getElementById('englishInput').value;
|
||||
const germanInput = document.getElementById('germanInput').value;
|
||||
|
||||
if (englishInput && germanInput) {
|
||||
fetch('/add_vocab', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
body: new URLSearchParams({
|
||||
english: englishInput,
|
||||
german: germanInput,
|
||||
level: 1 // Automatisch Level 1 setzen
|
||||
})
|
||||
}).then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
loadVocab();
|
||||
|
||||
document.getElementById('englishInput').value = '';
|
||||
document.getElementById('germanInput').value = '';
|
||||
} else {
|
||||
alert(data.error);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Fehler beim Hinzufügen der Vokabel:', error);
|
||||
});
|
||||
} else {
|
||||
alert('Bitte alle Felder ausfüllen.');
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById('backToHome').addEventListener('click', () => {
|
||||
window.location.href = '/'; // Pfad zur Startseite anpassen
|
||||
});
|
||||
});
|
||||
|
||||
function loadVocab() {
|
||||
fetch('/get_vocab')
|
||||
.then(response => response.json())
|
||||
.then(vocabList => {
|
||||
const tables = [1, 2, 3, 4, 5].map(level => document.getElementById(`vocab-list-${level}`));
|
||||
tables.forEach(table => table.querySelector('tbody').innerHTML = '');
|
||||
|
||||
vocabList.forEach(vocab => {
|
||||
const row = document.createElement('tr');
|
||||
row.dataset.id = vocab.id;
|
||||
row.dataset.level = vocab.level; // Level in dataset speichern
|
||||
row.innerHTML = `
|
||||
<td class="editable">${vocab.english}</td>
|
||||
<td class="editable">${vocab.german}</td>
|
||||
<td>
|
||||
<button class="edit-btn">Bearbeiten</button>
|
||||
<button class="delete-btn" data-id="${vocab.id}">Löschen</button>
|
||||
</td>
|
||||
`;
|
||||
|
||||
const targetTable = document.getElementById(`vocab-list-${vocab.level}`);
|
||||
targetTable.querySelector('tbody').appendChild(row);
|
||||
});
|
||||
|
||||
// Event-Listener für den „Löschen“-Button
|
||||
document.querySelectorAll('.delete-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (event) => {
|
||||
const vocabId = event.target.getAttribute('data-id');
|
||||
fetch(`/delete_vocab/${vocabId}`, {
|
||||
method: 'DELETE'
|
||||
}).then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
loadVocab();
|
||||
} else {
|
||||
alert(data.error);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Fehler beim Löschen der Vokabel:', error);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Event-Listener für den „Bearbeiten“-Button
|
||||
document.querySelectorAll('.edit-btn').forEach(btn => {
|
||||
btn.addEventListener('click', (event) => {
|
||||
const row = event.target.closest('tr');
|
||||
const id = row.dataset.id;
|
||||
const english = row.children[0].textContent;
|
||||
const german = row.children[1].textContent;
|
||||
const level = row.dataset.level || 1; // Level aus dem dataset lesen, Fallback auf 1
|
||||
|
||||
// Setze die Zeile in den Bearbeitungsmodus
|
||||
row.innerHTML = `
|
||||
<td><input type="text" class="editable-input" value="${english}"></td>
|
||||
<td><input type="text" class="editable-input" value="${german}"></td>
|
||||
<td class="edit-controls">
|
||||
<div class="level-input-container">
|
||||
<label for="levelInput">Level:</label>
|
||||
<input type="number" id="levelInput" class="level-input" min="1" max="5" value="${level}">
|
||||
</div>
|
||||
<button class="save-btn">Speichern</button>
|
||||
<button class="cancel-btn">Abbrechen</button>
|
||||
</td>
|
||||
`;
|
||||
|
||||
row.querySelector('.save-btn').addEventListener('click', () => {
|
||||
const englishInput = row.querySelector('.editable-input').value;
|
||||
const germanInput = row.querySelectorAll('.editable-input')[1].value;
|
||||
const levelInput = row.querySelector('#levelInput').value;
|
||||
|
||||
fetch(`/update_vocab/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
english: englishInput,
|
||||
german: germanInput,
|
||||
level: parseInt(levelInput, 10)
|
||||
})
|
||||
}).then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
loadVocab();
|
||||
} else {
|
||||
alert(data.error);
|
||||
}
|
||||
}).catch(error => {
|
||||
console.error('Fehler beim Aktualisieren der Vokabel:', error);
|
||||
});
|
||||
});
|
||||
|
||||
row.querySelector('.cancel-btn').addEventListener('click', () => {
|
||||
loadVocab();
|
||||
});
|
||||
});
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error('Fehler beim Laden der Vokabeln:', error);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//sqlite3 anstatt cokkies
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user