englisch6a/app/app.py
2025-12-27 11:17:27 +00:00

212 lines
6.1 KiB
Python

import os
import random
import time
import psycopg2
from flask import Flask, render_template, request, jsonify
from difflib import SequenceMatcher
app = Flask(__name__)
print("--- DEBUG START ---")
# Wo bin ich gerade?
cwd = os.getcwd()
print(f"Ich befinde mich im Ordner: {cwd}")
# Was sehe ich hier?
try:
print(f"Dateien in {cwd}: {os.listdir(cwd)}")
except Exception as e:
print(f"Konnte {cwd} nicht lesen: {e}")
# Existiert /app?
if os.path.exists('/app'):
print(f"Dateien in /app: {os.listdir('/app')}")
else:
print("Der Ordner /app existiert gar nicht!")
print("--- DEBUG ENDE ---")
# DB Verbindung mit Retry-Logik
def get_db_connection():
max_retries = 5
for i in range(max_retries):
try:
conn = psycopg2.connect(
host=os.environ.get('DB_HOST', 'postgres'),
database=os.environ.get('DB_NAME', 'englisch6a'),
user=os.environ.get('DB_USER', 'englisch6a'),
password=os.environ.get('DB_PASS', 'englisch')
)
return conn
except psycopg2.OperationalError:
if i < max_retries - 1:
time.sleep(2)
continue
else:
raise
def init_db_if_needed():
try:
conn = get_db_connection()
cur = conn.cursor()
# Prüfen ob Tabelle existiert
cur.execute("SELECT EXISTS (SELECT FROM information_schema.tables WHERE table_name = 'vocabulary');")
exists = cur.fetchone()[0]
if not exists:
print("Tabelle 'vocabulary' nicht gefunden. Initialisiere Datenbank aus init.sql...")
if os.path.exists('init.sql'):
with open('init.sql', 'r', encoding='utf-8') as f:
sql_commands = f.read()
cur.execute(sql_commands)
conn.commit()
print("Datenbank erfolgreich initialisiert!")
else:
print("Fehler: init.sql nicht gefunden!")
else:
# Optional: Prüfen ob leer
cur.execute("SELECT COUNT(*) FROM vocabulary")
count = cur.fetchone()[0]
if count == 0:
print("Tabelle leer. Fülle Daten...")
if os.path.exists('init.sql'):
with open('init.sql', 'r', encoding='utf-8') as f:
sql_commands = f.read()
cur.execute(sql_commands)
conn.commit()
cur.close()
conn.close()
except Exception as e:
print(f"Datenbank-Check Fehler: {e}")
@app.route('/')
def index():
return render_template('index.html')
@app.route('/api/pages')
def get_pages():
conn = get_db_connection()
cur = conn.cursor()
cur.execute('SELECT DISTINCT page FROM vocabulary ORDER BY page')
pages = [row[0] for row in cur.fetchall()]
cur.close()
conn.close()
return jsonify(pages)
@app.route('/api/start', methods=['POST'])
def start_quiz():
data = request.json
pages = data.get('pages', [])
mode = data.get('mode', 'random')
conn = get_db_connection()
cur = conn.cursor()
if not pages:
cur.execute('SELECT id, english, german FROM vocabulary')
else:
cur.execute('SELECT id, english, german FROM vocabulary WHERE page = ANY(%s)', (pages,))
rows = cur.fetchall()
cur.close()
conn.close()
vocab_list = []
for row in rows:
vid, eng, ger = row
direction = mode
if mode == 'random':
direction = random.choice(['de-en', 'en-de'])
question = ""
answer = ""
if direction == 'de-en':
question = ger
answer = eng
else:
question = eng
answer = ger
vocab_list.append({
'id': vid,
'question': question,
'answer': answer,
'direction': direction
})
random.shuffle(vocab_list)
return jsonify(vocab_list)
def expand_variants(text):
segments = [s.strip() for s in text.split(';')]
possibilities = []
for seg in segments:
if '/-' in seg:
parts = seg.split('/-')
base = parts[0].strip()
suffixes = parts[1:]
possibilities.append(base)
for suf in suffixes:
clean_suf = suf.strip()
if clean_suf:
possibilities.append(base + clean_suf)
elif '/' in seg:
choices = seg.split('/')
possibilities.extend([c.strip() for c in choices])
else:
possibilities.append(seg)
return possibilities
def clean_text_for_comparison(text):
text = text.lower().strip()
if text.startswith('to '):
text = text[3:].strip()
return text
@app.route('/api/check', methods=['POST'])
def check_answer():
data = request.json
user_input = data.get('input', '')
db_answer = data.get('correct', '')
clean_user = clean_text_for_comparison(user_input)
valid_answers_raw = expand_variants(db_answer)
valid_answers_clean = [clean_text_for_comparison(v) for v in valid_answers_raw]
if clean_user in valid_answers_clean:
return jsonify({'status': 'correct', 'msg': 'Richtig!'})
best_ratio = 0
best_match = ""
for correct_option in valid_answers_clean:
ratio = SequenceMatcher(None, clean_user, correct_option).ratio()
if ratio > best_ratio:
best_ratio = ratio
best_match = correct_option
threshold = 0.75
if len(best_match) <= 4:
threshold = 0.8
if best_ratio >= threshold:
return jsonify({
'status': 'typo',
'msg': f'Fast richtig! Meintest du: "{best_match}"? (Es war "{user_input}")'
})
return jsonify({
'status': 'wrong',
'msg': f'Leider falsch. Versuche es erneut.'
})
if __name__ == '__main__':
# Beim Start DB prüfen und ggf. befüllen
init_db_if_needed()
app.run(host='0.0.0.0', port=5000)