149 lines
3.8 KiB
Python
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)
|
|
|