import sqlite3 from flask import Flask, render_template, request, jsonify, g DATABASE = "ranking.db" app = Flask(__name__) def get_db(): """ Abre una conexión a la base de datos SQLite y la asocia a 'g' para reutilizarla en cada petición. """ db = getattr(g, "_database", None) if db is None: db = g._database = sqlite3.connect(DATABASE) return db @app.teardown_appcontext def close_connection(exception): """ Al terminar el contexto de la petición, cierra la conexión si existe. """ db = getattr(g, "_database", None) if db is not None: db.close() def crear_tabla(): """ Crea la tabla ranking si no existe. """ conn = sqlite3.connect(DATABASE) c = conn.cursor() c.execute(""" CREATE TABLE IF NOT EXISTS ranking ( id INTEGER PRIMARY KEY AUTOINCREMENT, nombre TEXT NOT NULL, puntuacion INTEGER NOT NULL ) """) conn.commit() conn.close() def obtener_top10(): """ Devuelve una lista de tuplas [(nombre, puntuacion), ...] con el top 10 ordenado descendente. """ conn = get_db() c = conn.cursor() c.execute("SELECT nombre, puntuacion FROM ranking ORDER BY puntuacion DESC, id ASC LIMIT 10") resultados = c.fetchall() return resultados def puntuacion_entra_en_top(puntos): """ Comprueba si 'puntos' supera la última posición del top 10. Si hay menos de 10 filas, siempre devuelve True para guardar. """ top = obtener_top10() if len(top) < 10: return True # La décima posición es top[-1][1] (puntuacion más baja en top10) return puntos > top[-1][1] def guardar_puntuacion(nombre, puntos): """ Inserta la nueva puntuación en la tabla ranking. """ conn = get_db() c = conn.cursor() c.execute("INSERT INTO ranking (nombre, puntuacion) VALUES (?, ?)", (nombre, puntos)) conn.commit() @app.route("/") def index(): """ Página principal con instrucciones y botón para iniciar el juego. """ return render_template("index.html") @app.route("/juego") def juego(): """ Página donde se juega: se carga el HTML y el JS se encarga de todo lo demás. """ return render_template("game.html") @app.route("/ranking") def ranking(): """ Página que muestra el top 10. """ top10 = obtener_top10() return render_template("ranking.html", top10=top10) @app.route("/api/score", methods=["POST"]) def api_score(): """ Recibe JSON: { "puntuacion": } Comprueba si entra en top10 y devuelve JSON: { "entra_en_top": true/false, "top10": [...] } """ data = request.get_json() if not data or "puntuacion" not in data: return jsonify({"error": "No se recibió puntuación"}), 400 puntos = int(data["puntuacion"]) entra = puntuacion_entra_en_top(puntos) top10 = obtener_top10() # Devolvemos el top10 actual (ANTES de guardar la nueva puntuación) return jsonify({ "entra_en_top": entra, "top10": top10 }) @app.route("/api/score/save", methods=["POST"]) def api_score_save(): """ Recibe JSON: { "nombre": , "puntuacion": } Guarda en la BD y devuelve el ranking actualizado. """ data = request.get_json() if not data or "nombre" not in data or "puntuacion" not in data: return jsonify({"error": "Faltan parámetros"}), 400 nombre = data["nombre"].strip() puntos = int(data["puntuacion"]) # Sólo guardamos si efectivamente entra en top10 (por seguridad) if puntuacion_entra_en_top(puntos): guardar_puntuacion(nombre, puntos) top10 = obtener_top10() return jsonify({ "guardado": True, "top10": top10 }) if __name__ == "__main__": crear_tabla() app.run(debug=True)