multi-game/app.py
2025-07-16 17:57:35 +02:00

149 lines
3.8 KiB
Python

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": <int> }
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": <string>, "puntuacion": <int> }
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)