import os import random import time import psycopg2 from flask import Flask, render_template, request, jsonify from difflib import SequenceMatcher app = Flask(__name__) # 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)