evaluacion / src /streamlit_app.py
andrespm's picture
Update src/streamlit_app.py
f5b9a51 verified
raw
history blame
7.59 kB
# streamlit_app.py
import json, random, streamlit as st
from pathlib import Path
DATA_FILE = Path(__file__).parent / "master_evaluacion_evaluado.json"
@st.cache_data
def load_data(path):
with open(path, encoding="utf-8") as f:
return json.load(f)
data = load_data(DATA_FILE)
# ───────── Helpers ─────────
def random_question():
return random.choice(data["preguntas"])
def random_case():
return random.choice(data["casos_clinicos"])
def build_exam():
preguntas = random.sample(data["preguntas"], 38)
casos = random.sample(data["casos_clinicos"], 1)
items = [{"grupo": "normal", "data": q} for q in preguntas]
for c in casos: # bloques de caso completos
for q in c["preguntas"]:
items.append({
"grupo": c["id"],
"data": {**q, "caso": c["titulo"], "context": c["contexto"]}
})
return items
# ───────── Estado inicial ─────────
if "mode" not in st.session_state:
st.session_state.mode = "preguntas"
st.session_state.question = random_question()
st.session_state.case_list = []
st.session_state.case_idx = 0
st.session_state.exam_items = []
st.session_state.exam_idx = 0
st.session_state.hits_norm = 0
st.session_state.hits_case = {}
st.session_state.total_case = {}
st.session_state.recorrido_idx = 0 # nuevo
# ───────── Barra lateral ─────────
st.sidebar.title("Evaluación")
if st.sidebar.button("Preguntas sueltas"):
st.session_state.mode = "preguntas"
st.session_state.question = random_question()
st.rerun()
if st.sidebar.button("Casos clínicos"):
st.session_state.mode = "caso"
caso = random_case()
st.session_state.case_list = [
{**q, "caso": caso["titulo"], "context": caso["contexto"]}
for q in caso["preguntas"]
]
st.session_state.case_idx = 0
st.session_state.question = st.session_state.case_list[0]
st.rerun()
if st.sidebar.button("Examen (38 + a caso)"):
st.session_state.mode = "examen"
st.session_state.exam_items = build_exam()
st.session_state.exam_idx = 0
st.session_state.hits_norm = 0
st.session_state.hits_case.clear()
st.session_state.total_case = {}
for it in st.session_state.exam_items:
if it["grupo"] != "normal":
st.session_state.total_case[it["grupo"]] = \
st.session_state.total_case.get(it["grupo"], 0) + 1
st.session_state.question = st.session_state.exam_items[0]["data"]
st.rerun()
if st.sidebar.button("Recorrido completo"):
st.session_state.mode = "recorrido"
st.session_state.recorrido_idx = 0
st.session_state.question = data["preguntas"][0]
st.rerun()
st.sidebar.markdown("---")
st.sidebar.markdown("Creado con ❤️ por Requetito")
# ───────── Encabezado: modo + progreso ─────────
mode_label = {
"preguntas": "Práctica – Preguntas sueltas",
"caso": "Práctica – Casos clínicos",
"examen": "Examen final",
"recorrido": "Recorrido completo – Todas las preguntas"
}
st.subheader(mode_label[st.session_state.mode])
progreso = ""
if st.session_state.mode == "examen":
progreso = f"{st.session_state.exam_idx + 1} / {len(st.session_state.exam_items)}"
elif st.session_state.mode == "caso":
progreso = f"{st.session_state.case_idx + 1} / {len(st.session_state.case_list)}"
elif st.session_state.mode == "recorrido":
total = len(data["preguntas"])
idx = st.session_state.recorrido_idx
progreso = f"{idx + 1} / {total}"
st.caption(progreso)
nuevo_idx = st.number_input("Ir a la pregunta n.º:", min_value=1, max_value=total, value=idx + 1, step=1)
if nuevo_idx - 1 != idx:
st.session_state.recorrido_idx = nuevo_idx - 1
st.session_state.question = data["preguntas"][nuevo_idx - 1]
st.rerun()
if progreso and st.session_state.mode != "recorrido":
st.caption(progreso)
# ───────── Pregunta ─────────
q = st.session_state.question
if "context" in q:
st.info(f"**CONTEXTO ({q['caso']})**\n\n{q['context']}")
st.markdown(f"### {q['pregunta']}")
selected = st.radio(
"Elige una respuesta:",
options=list(q["opciones"].keys()),
format_func=lambda k: f"{k}. {q['opciones'][k]}",
index=None,
key=f"radio_{q['id']}_{st.session_state.mode}"
)
col1, col2 = st.columns(2)
comprobar = col1.button("✅ Comprobar")
siguiente = col2.button("➡️ Siguiente")
# contenedores feedback
feedback_box = st.empty()
justif_box = st.empty()
# ───────── Comprobar ─────────
if comprobar and selected:
correcta = q["respuesta_correcta"]
ok = selected == correcta
if ok:
feedback_box.success("✅ ¡Correcto!")
else:
feedback_box.error(f"❌ Incorrecto. La respuesta correcta era **{correcta}**.")
justif_box.markdown(f"**Justificación:**\n{q['justificacion']}")
if st.session_state.mode == "examen":
grp = st.session_state.exam_items[st.session_state.exam_idx]["grupo"]
if grp == "normal" and ok:
st.session_state.hits_norm += 1
elif grp != "normal" and ok:
st.session_state.hits_case[grp] = \
st.session_state.hits_case.get(grp, 0) + 1
# ───────── Siguiente ─────────
if siguiente:
feedback_box.empty()
justif_box.empty()
if st.session_state.mode == "preguntas":
st.session_state.question = random_question()
elif st.session_state.mode == "caso":
st.session_state.case_idx += 1
if st.session_state.case_idx == len(st.session_state.case_list):
caso = random_case()
st.session_state.case_list = [
{**q, "caso": caso["titulo"], "context": caso["contexto"]}
for q in caso["preguntas"]
]
st.session_state.case_idx = 0
st.session_state.question = st.session_state.case_list[st.session_state.case_idx]
elif st.session_state.mode == "examen":
st.session_state.exam_idx += 1
if st.session_state.exam_idx == len(st.session_state.exam_items):
# Fin examen
pts_preg = st.session_state.hits_norm * (12.8 / 38)
pts_casos = 0
detalles = []
for cid, tot in st.session_state.total_case.items():
peso_por_preg = 3.2 / tot
aciertos = st.session_state.hits_case.get(cid, 0)
pts = aciertos * peso_por_preg
pts_casos += pts
detalles.append(f"{cid}: {pts:.2f} / 3.2")
total = pts_preg + pts_casos
aprobado = total >= 7.5
st.balloons()
st.markdown(
f"## 🏁 Examen finalizado\n\n"
f"**Preguntas (máx 12.8):** {pts_preg:.2f}\n\n"
+ "\n".join(detalles) +
f"\n\n**TOTAL:** {total:.2f} / 16 → "
+ ("✅ Aprobado" if aprobado else "❌ No aprobado")
)
st.stop()
st.session_state.question = \
st.session_state.exam_items[st.session_state.exam_idx]["data"]
elif st.session_state.mode == "recorrido":
st.session_state.recorrido_idx += 1
if st.session_state.recorrido_idx >= len(data["preguntas"]):
st.session_state.recorrido_idx = 0
st.session_state.question = data["preguntas"][st.session_state.recorrido_idx]
st.rerun()