Skip to content

Commit ce9f66f

Browse files
committed
feat: add classroom abandonment metrics and refresh prioritized roadmap
1 parent 0dd6a64 commit ce9f66f

File tree

9 files changed

+43
-8
lines changed

9 files changed

+43
-8
lines changed

apps/backend/src/main/java/com/juegodefinitivo/autobook/api/dto/ClassroomDashboardResponse.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ public record ClassroomDashboardResponse(
88
String teacherName,
99
int students,
1010
int assignments,
11+
int activeAttempts,
12+
int completedAttempts,
13+
int abandonmentRatePercent,
1114
List<StudentProgressView> studentProgress
1215
) {
1316
}

apps/backend/src/main/java/com/juegodefinitivo/autobook/service/TeacherWorkspaceService.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ public ClassroomDashboardResponse getDashboard(String classroomId, LocalDate fro
124124
List<TeacherWorkspaceRepository.AttemptRow> attempts = loadAttempts(classroomId, from, to);
125125

126126
List<StudentProgressView> progressViews = new ArrayList<>();
127+
int totalAttempts = 0;
128+
int totalCompletedAttempts = 0;
127129
for (TeacherWorkspaceRepository.StudentRow student : students) {
128130
List<TeacherWorkspaceRepository.AttemptRow> studentAttempts = attempts.stream()
129131
.filter(attempt -> attempt.studentId().equals(student.id()))
@@ -139,6 +141,8 @@ public ClassroomDashboardResponse getDashboard(String classroomId, LocalDate fro
139141
int avgProgress = (int) states.stream().mapToInt(this::progressPercent).average().orElse(0);
140142
int completed = (int) states.stream().filter(GameStateResponse::completed).count();
141143
String difficulty = dominantDifficulty(states);
144+
totalAttempts += studentAttempts.size();
145+
totalCompletedAttempts += completed;
142146

143147
progressViews.add(new StudentProgressView(
144148
student.id(),
@@ -152,12 +156,20 @@ public ClassroomDashboardResponse getDashboard(String classroomId, LocalDate fro
152156
));
153157
}
154158

159+
int activeAttempts = Math.max(0, totalAttempts - totalCompletedAttempts);
160+
int abandonmentRatePercent = totalAttempts == 0
161+
? 0
162+
: (int) ((activeAttempts / (double) totalAttempts) * 100);
163+
155164
return new ClassroomDashboardResponse(
156165
classroom.id(),
157166
classroom.name(),
158167
classroom.teacherName(),
159168
students.size(),
160169
assignments.size(),
170+
activeAttempts,
171+
totalCompletedAttempts,
172+
abandonmentRatePercent,
161173
progressViews
162174
);
163175
}

apps/backend/src/test/java/com/juegodefinitivo/autobook/TeacherControllerTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ void shouldCreateTeacherWorkspaceAndProduceDashboard() throws Exception {
100100
mockMvc.perform(get("/api/teacher/classrooms/" + classroomId + "/dashboard"))
101101
.andExpect(status().isOk())
102102
.andExpect(jsonPath("$.classroomId").value(classroomId))
103+
.andExpect(jsonPath("$.activeAttempts").isNumber())
104+
.andExpect(jsonPath("$.completedAttempts").isNumber())
105+
.andExpect(jsonPath("$.abandonmentRatePercent").isNumber())
103106
.andExpect(jsonPath("$.studentProgress[0].studentId").value(studentId));
104107

105108
mockMvc.perform(get("/api/teacher/classrooms/" + classroomId + "/dashboard")

apps/frontend/e2e/guided-flow.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ test("guided flow supports start, manual action and autoplay with telemetry", as
9696
teacherName: "Docente",
9797
students: 0,
9898
assignments: 0,
99+
activeAttempts: 0,
100+
completedAttempts: 0,
101+
abandonmentRatePercent: 0,
99102
studentProgress: [],
100103
},
101104
});

apps/frontend/src/App.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ const EMPTY_DASHBOARD: ClassroomDashboard = {
9292
teacherName: "",
9393
students: 0,
9494
assignments: 0,
95+
activeAttempts: 0,
96+
completedAttempts: 0,
97+
abandonmentRatePercent: 0,
9598
studentProgress: [],
9699
};
97100

@@ -652,6 +655,12 @@ function App() {
652655
<p>
653656
Estudiantes: <strong>{dashboard.students}</strong> · Asignaciones: <strong>{dashboard.assignments}</strong>
654657
</p>
658+
<p>
659+
Intentos activos: <strong>{dashboard.activeAttempts}</strong> · Finalizados: <strong>{dashboard.completedAttempts}</strong>
660+
</p>
661+
<p>
662+
Abandono estimado: <strong>{dashboard.abandonmentRatePercent}%</strong>
663+
</p>
655664
<ul>
656665
{dashboard.studentProgress.slice(0, 8).map((row) => (
657666
<li key={row.studentId}>

apps/frontend/src/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ export type ClassroomDashboard = {
9292
teacherName: string;
9393
students: number;
9494
assignments: number;
95+
activeAttempts: number;
96+
completedAttempts: number;
97+
abandonmentRatePercent: number;
9598
studentProgress: StudentProgress[];
9699
};
97100

docs/NEXT_STEPS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- Auth API por roles con token (`student/teacher/admin`) para endpoints `/api/**`.
1919
- Rate limiting basico por IP para endpoints de escritura.
2020
- Filtros temporales (`from`, `to`) para dashboard y reporte docente.
21+
- Dashboard docente con intentos activos/finalizados y tasa estimada de abandono.
2122

2223
1. Persistencia productiva
2324
- Agregar estrategia de backup/restore y retencion.

docs/PRIORITY_REQUIREMENTS.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,21 @@ Definir que implementar primero para maximizar valor comunitario (estudiantes, d
99
- Regla de salida: no pasa a implementacion si no tiene criterio de aceptacion medible.
1010

1111
## Current Priority Order
12-
1. Seguridad institucional minima (`R5`):
12+
1. Seguridad institucional minima (`R5`) [P0]:
1313
- Autenticacion/roles (`teacher`, `student`, `admin`).
1414
- Seguridad de importacion de archivos (MIME/firma, limites, saneamiento).
1515
- Endurecimiento de errores y controles anti-abuso (rate limiting).
16-
2. Evidence Pack docente avanzado (`R2`):
16+
2. Evidence Pack docente avanzado (`R2`) [P1]:
1717
- Tiempo efectivo de lectura.
1818
- Abandono por actividad.
1919
- Segmentacion por cohorte y periodo.
20-
3. Calidad pedagogica (`R3`):
20+
3. Calidad pedagogica (`R3`) [P1]:
2121
- Mejorar banco de preguntas por nivel lector/habilidad.
2222
- Mantener benchmark de calidad en CI como gate obligatorio.
23-
4. Accesibilidad estudiantil (`R1` + `R3`):
23+
4. Accesibilidad estudiantil (`R1` + `R3`) [P1]:
2424
- Alto contraste y modo lectura amigable.
2525
- Narracion asistida (TTS) y ayudas de lectura.
26-
5. Operacion de plataforma (`R5`):
26+
5. Operacion de plataforma (`R5`) [P2]:
2727
- Observabilidad (logs estructurados y metricas).
2828
- Backup/restore y retencion.
2929
- Contratos OpenAPI para integracion segura.
@@ -34,9 +34,10 @@ Definir que implementar primero para maximizar valor comunitario (estudiantes, d
3434
3. E2E base `npm run test:e2e` en verde.
3535
4. Criterios de mercado trazados en `docs/MARKET_VALUE_REQUIREMENTS.md`.
3636

37-
## Active Delivery Slice (now)
37+
## Active Delivery Slice (status)
3838
1. Hardening de import de libros. (implementado base)
3939
2. Anti-duplicados y consistencia de evidencia docente. (implementado)
4040
3. UX infantil accesible (lectura amigable + alto contraste). (implementado)
4141
4. Auth por roles y rate limiting basico. (implementado base)
4242
5. Segmentacion temporal docente (`from`/`to`) en dashboard y CSV. (implementado base)
43+
6. Pendiente inmediato: metrica de tiempo efectivo y abandono por actividad real. (siguiente P1)

docs/ROADMAP.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
7. `v3.5` (parcial): panel docente y analitica por estudiante con export CSV.
1111

1212
## Next Milestones
13-
1. `v3.5`: cerrar analitica docente avanzada (tiempo, abandono, cohortes).
14-
2. `v3.6`: instalador firmado + observabilidad de produccion.
13+
1. `v3.5`: cerrar analitica docente avanzada (tiempo, abandono, cohortes) y consolidar filtros por periodo.
14+
2. `v3.6`: seguridad institucional (auth/roles productivo), observabilidad de produccion y backup/restore.
1515
3. `v3.7`: mejora profunda de lectura de libros (OCR, tablas, encabezados complejos, chunking semantico).

0 commit comments

Comments
 (0)