User request — especificación para desarrollo ← Todos los gadgets Ver la maqueta
Gadget 01 · User request

Generador de evaluaciones

wc-laravel Laravel 5.7 / PHP 7.1 Profesor · UTP Borrador para revisión 2026-09-11

Un editor de pruebas donde lo que se ve en pantalla es la hoja impresa, las preguntas y alternativas se reordenan arrastrándolas, cada pregunta queda categorizada por objetivo de aprendizaje e indicador, y hay herramientas de IA que consumen una bolsa de tokens del establecimiento.

1El problema

Crear una prueba en WebClass hoy pasa por el módulo que vive en el repo vanilla (sistema/webclass/home/preguntas, home/pruebas, home/evaluacionesbanco, home/importarpreguntas). Tiene lo esencial y lleva años funcionando, pero arrastra cuatro problemas concretos:

Lo que esto NO es

No es un módulo nuevo desde cero: es llevar a Laravel el editor que hoy está en vanilla, sobre las mismas tablas. Si se crean tablas paralelas, el banco de preguntas del establecimiento queda partido en dos y la corrección de respuestas de alumnos —que sigue en vanilla— deja de encontrar sus preguntas.

La excepción, y es una sola: la rúbrica por pregunta (§6.4) no existe hoy —es la funcionalidad nueva que este documento propone— y es lo único que pide tocar el modelo de datos fuera de las tablas de tokens. Va marcada funcionalidad nueva donde aparece.

Lo demás marcado como nuevo —el banco de items, la categorización múltiple, el plan del generador con IA— es pantalla: se apoya en tablas que ya existen y con la forma que ya tienen.

2Quién lo usa

RolQué hace con estoQué le importa
Profesor de asignatura Arma la prueba, la imprime, la aplica. Que salga bien impresa y que se demore poco.
Jefe de UTP Revisa que la prueba cubra los objetivos acordados antes de autorizarla. La tabla de especificaciones y la cobertura por OA.
Coordinador de departamento Valida preguntas para que entren al banco del establecimiento. Que las preguntas lleguen categorizadas y con su retroalimentación escrita.

3Lo que ya existe en la base — reusar, no recrear

Relevado el 2026-09-11 leyendo los DAO del repo vanilla y los modelos Eloquent de wc-laravel/app/. La estructura para casi todo lo que pide este gadget ya está.

TablaPara quéModelo Eloquent que ya existe
pruebaCabecera: título, instrucciones, sector, colegio, profesor, tipo, estado, visible, revisada, validadoApp\Prueba
preguntaEl ítem: texto, tipo, dificultad, penalización, y tres campos de retroalimentación (retrocorrecta, retroparcial, retroincorrecta)App\Pregunta
prueba_preguntasQué preguntas tiene una prueba, y en qué ordenApp\PruebaPregunta (sin $table declarado)
respuesta_alternativaAlternativas de selección múltiple—
respuesta_vofVerdadero / falso—
respuesta_cortaRespuesta corta—
respuesta_enpareja_orden
respuesta_enpareja_vinculo
Emparejamiento (dos columnas)—
pregunta_atributo
(pregunta, eje, tipo, atributo)
Objetivos, habilidades y contenidos por pregunta. Es la categorización que pide el gadget. N:M: admite varios por pregunta (§6.5.b).
Columnas verificadas en el código; tipo dice a qué catálogo apunta atributo: 1 contenidos · 2 aprendizaje · 3 objetivos · 4 habilidades · 7 actitudes — cada uno su propia tabla, con id, nombre, nomenclatura y eje. No guarda el nivel (§11)
—
pregunta_indicador → indicadoresIndicador de evaluación por pregunta, con columna objetivo que lo amarra al OA. También N:MApp\EvaluationIndicators
pregunta_ambito / prueba_ambitoÁmbito y nivelApp\AmbitoPregunta
prueba_atributoAtributos a nivel de prueba—
respuesta_*_alumnoRespuestas rendidas. No se toca en este gadget, pero manda dos veces: si cambia el id de una pregunta ya rendida se pierde la corrección, y de acá sale el logro por objetivo de §5.3varios
cursoLos cursos del establecimiento. Los lee el quinto camino de creación (§5.3); sólo lectura—
Consecuencia de diseño

4Dónde vive en wc-laravel

El producto no tiene un layout común: cada módulo trae el suyo. Este gadget necesita ser un módulo propio.

resources/views/evaluaciones/
├── layouts/header.blade.php      layout propio del modulo
├── crear.blade.php               pantalla 1
└── editor.blade.php              pantalla 2

resources/js/evaluaciones/evaluaciones.js    entrada Vue 2
resources/sass/evaluaciones.scss

app/Http/Controllers/Evaluaciones/
├── EvaluacionController.php      CRUD de la prueba
├── PreguntaController.php        alta/edicion/orden de preguntas
├── CategorizacionController.php  OA, indicador, atributos
└── AsistenteIaController.php     herramientas de IA + tokens

Una línea más en webpack.mix.js

.js('resources/js/evaluaciones/evaluaciones.js', 'public/js')

Rutas (routes/web.php)

Route::group(['prefix' => 'evaluaciones', 'namespace' => 'Evaluaciones'], function () {
    Route::get('/crear',            'EvaluacionController@crear');
    Route::post('/',                'EvaluacionController@store');
    Route::get('/{prueba}/editor',  'EvaluacionController@editor');
    Route::post('/{prueba}/orden',  'PreguntaController@reordenar');
    Route::post('/{prueba}/guardar', 'EvaluacionController@guardar');
    Route::post('/ia/{herramienta}','AsistenteIaController@ejecutar');
});
Restricciones del stack — no son negociables
Lo que habilita MySQL 8.4 en las migraciones de este gadget

Un detalle de operación, no de este gadget: en 8.4 el mysql_native_password ya no viene activo. Si el sistema conecta hoy es porque el asunto está resuelto; sólo hay que tenerlo presente si se crea un usuario o una conexión nueva para esta funcionalidad.

5Pantalla 1 — Crear el recurso

Arriba, el título de la herramienta —«Generador de evaluaciones»— y debajo el nombre del recurso con su etiqueta «Nombre:». Los dos juntos y en ese orden: sin el título no se sabe en qué herramienta se está, y sin la etiqueta el nombre del recurso se lee como el título de la pantalla y nadie descubre que es editable.

Después, tres selectores y cuatro caminos de creación. Nivel y asignatura son obligatorios: definen qué catálogo de objetivos de aprendizaje se ofrece después, así que no se puede entrar al editor sin ellos.

Los caminos van en filas agrupadas, no en tarjetas de colores

La primera versión eran cuatro tarjetas en una fila, cada una con su icono y su fondo de color. Gerencia las rechazó por la diagramación, y tenían además un problema de fondo: presentaban como equivalentes cosas que no lo son, y el color de cada tarjeta no significaba nada —era decoración—.

Los cuatro caminos se parten en dos grupos, que es la diferencia que de verdad existe:

Cada camino es una fila a lo ancho: título, una bajada de una línea y «Comenzar →» a la derecha. Sin iconos y sin fondo de color; el único color es el azul de acción del producto, y aparece al pasar por encima. Ocupa la mitad del alto, se lee de arriba abajo como el resto del formulario, y admite un quinto camino sin rediseñar nada.

El «Comenzar →» no es decoración: una fila con un título y una bajada se lee como un párrafo, y sin algo que diga que es pulsable nadie le hace clic.

La fila es la acción: no hay botón «Crear»

Elegir el camino crea el recurso. El paso intermedio no aportaba nada: marcar «desde cero» y después confirmar «Crear» eran dos clics para una sola decisión, y el botón deshabilitado obligaba a adivinar qué faltaba.

«Desde el banco de items» salió de la creación. El banco se usa desde el botón + del editor, para traer items sueltos a una prueba que ya existe. Empezar una prueba entera desde el banco era la misma pantalla de búsqueda abierta dos veces.

CaminoQué haceNota
Desde ceroEditor con la hoja vacía.El más simple; sirve de base para los otros.
Digitalizar desde un archivoSube la prueba en PDF o en Word y separa preguntas y alternativas.El resultado siempre queda en revisión: el reconocimiento de fórmulas e imágenes falla seguido.
A partir de tabla de especificaciones funcionalidad nuevaLa tabla del currículo: qué objetivos y qué habilidades entran, cuántas preguntas de cada uno, de qué tipos, y si salen del banco o de la IA. Ver §5.2.Reúne lo que antes eran dos tarjetas. El Excel de UTP se importa acá y llena esta misma tabla. Consume tokens sólo por lo generado, y el costo se ve antes.
A partir de situación curso/alumno funcionalidad nuevaLa misma pantalla, con el logro de cada objetivo y de cada habilidad según todo lo que el curso —o los alumnos que se elijan dentro de él— ya rindieron. Ver §5.3.El único camino que parte de datos y no de la memoria del profesor.

Se puede entregar por etapas. «Desde cero» y «desde el banco» son el mínimo para reemplazar lo que hay hoy. El PDF y la tabla de especificaciones pueden ir en una segunda entrega sin bloquear nada.

5.1 Importar la tabla de especificaciones

La tabla ya existe en el colegio, en una planilla de UTP. Obligar a reescribirla campo por campo dentro de WebClass es la forma más segura de que nadie use esta función. Se aceptan dos entradas:

Después de leerla se muestra una vista previa con las columnas identificadas — objetivo, indicador, nº de preguntas, puntaje, habilidad, dificultad, eje — y el docente corrige la que esté mal antes de continuar. Con eso se crean las preguntas vacías, cada una ya asignada a su OA e indicador, repartiendo el puntaje de la fila entre sus preguntas.

Cinco cosas que decide este diseño
  1. No se adivina el formato: se propone y se confirma. Cada colegio titula sus columnas distinto. Se detecta el rol por el título (/objetivo|oa/, /indicador/, /nº|cantidad|preguntas/…) y se deja un select por columna para corregirlo.
  2. El separador se detecta. Excel y Sheets ponen TAB en el portapapeles; un .csv exportado en Chile suele venir con punto y coma, no con coma.
  3. Hay que respetar las comillas. Un indicador como "Resuelve problemas de área, perímetro y volumen" lleva coma adentro: partir por coma a secas lo corta en dos columnas y descuadra la fila entera. También hay que tratar "" como comilla literal.
  4. Si no hay fila de títulos, igual se puede. Se detecta mirando si la primera fila trae números; si no los hay, se asume que son títulos.
  5. Los OA importados pueden no estar en el catálogo. Hay que agregarlos igual al desplegable de categorización — si no, al abrir la pregunta el select aparece en «sin asignar» y se pierde en silencio lo que traía la especificación. Lo mismo con el indicador.
El Excel no necesita librería nueva

composer.json de wc-laravel ya trae cuatro: maatwebsite/excel 3.1, phpoffice/phpspreadsheet, box/spout y cyber-duck/laravel-excel. La primera se usa en todo app/Exports/, así que el equipo ya la conoce — y sirve tanto para exportar como para importar.

El .xlsx se lee en el servidor, no en el navegador. El pegado y el .csv sí se pueden procesar en el cliente, que da respuesta instantánea; el .xlsx es un ZIP con XML adentro y no vale la pena resolverlo en JavaScript teniendo la librería en PHP.

Precedente útil: el módulo home/importarpreguntas del repo vanilla ya importa preguntas desde Excel, con plantillas por tipo (corta.xls, desarollo.xls, emparejamiento.xls, fyv.xls). Conviene mirar esas plantillas antes de inventar un formato.

5.2 La tabla: qué se mide y cuántas preguntas de cada cosa funcionalidad nueva

Dos de los cuatro caminos —«a partir de tabla de especificaciones» y «a partir de la situación del curso»— abren la misma pantalla, en pantalla propia. Es una tabla con una fila por objetivo (o por habilidad) del nivel, y en cada fila se decide cuántas preguntas y de dónde salen. La diferencia entre los dos caminos son dos columnas: el de curso trae el logro, el otro no.

Por qué eran dos tarjetas y ahora es una

«Desde la tabla de especificaciones» y «con ayuda de la IA» preguntaban lo mismo —qué objetivos y cuántas preguntas de cada uno— y se diferenciaban sólo en de dónde salía cada pregunta: una estructura vacía para llenar a mano en un caso, una propuesta de la IA en el otro.

Eso no es un camino distinto: es una columna más, y se decide fila por fila, porque la respuesta cambia por objetivo. Del banco cuando hay material —que es lo barato y lo ya validado—, con IA cuando no lo hay. Obligar a elegir una sola fuente para toda la prueba era la pregunta equivocada.

El Excel de UTP no desapareció. Sigue estando, pero ahora llena esta tabla en vez de saltarse la pantalla: lo importado se revisa en el mismo lugar donde se decide todo lo demás. Lo que no calce con el catálogo del nivel se dice —cuántas filas y cuáles— en vez de descartarse en silencio.

Objetivos o habilidades — dos pestañas sobre la misma tabla

El currículo se mira de dos maneras y las dos están en la base, en pregunta_atributo: qué contenido mide una pregunta y qué habilidad exige. Hay departamentos que arman la prueba por objetivo y otros que la arman por habilidad —«necesito tres de analizar»—, y las dos formas son legítimas.

La clave de cada fila lleva su nivel, no sólo el código

Consecuencia directa de lo anterior, y no es un detalle de implementación: «Aplicar» de 1° Medio y «Aplicar» de 2° Medio son la misma cadena. Con la habilidad sola como identificador se pisan entre sí, y al cambiar de nivel se pierde lo pedido en el anterior. Lo pedido se guarda contra tipo + nivel + asignatura + código.

Lo mismo vale al importar el Excel de UTP: el código de cada objetivo se busca en todos los niveles de esa asignatura, no sólo en el que está a la vista. Una tabla de UTP para un recuperativo trae objetivos de dos años, y descartar los del otro nivel sería perder justo lo que distingue a esa prueba.

Arriba de todo, una fila comodín: «Cualquiera del nivel» funcionalidad nueva

No todo profesor arma la prueba objetivo por objetivo. Hay quien quiere diez preguntas de 2° Medio · Matemática y revisarlas después, y sin esta fila ese camino obligaba a repartir a mano entre catorce objetivos para pedir algo que da lo mismo de cuál salga. Era el atajo que tenía la tarjeta del plan de IA antes de fusionarla con esta pantalla, y se repone acá.

Abajo, los objetivos propios del colegio funcionalidad nueva

Un colegio mide cosas que el catálogo del Mineduc no trae: un sello del proyecto educativo, una habilidad que el departamento decidió seguir. WebClass ya lo permite —es pregunta_atributo_adicional, ver §6.5.c— y el producto calcula su logro igual que el de un objetivo del catálogo. Si la tabla no los mostrara, armar la prueba desde acá sería un retroceso frente a lo que el profesor ya puede hacer.

De paso se arregló «Proponer»

Borraba todo lo pedido en la pestaña, incluido lo pedido a mano en el comodín, aunque este documento decía que no lo tocaba. Ahora rehace sólo las filas del currículo; el comodín y los propios quedan como el profesor los dejó.

De dónde sale cada pregunta: banco o IA, por fila

De qué tipos

5.3 Lo que agrega el camino curso/alumno: el logro funcionalidad nueva

Los otros caminos parten de lo que el profesor quiere evaluar. Este parte de lo que el curso necesita que le evalúen, que no es lo mismo y casi nunca se mira. Y no se mira por una razón concreta: el dato ya existe en WebClass —lo calcula el informe de aprendizaje—, pero vive en otra sección, a cuatro clics del lugar donde se arma la prueba. Un dato que hay que ir a buscar a otra pantalla es un dato que no se usa.

Se elige un curso y la tabla gana tres columnas: ya evaluado, logro y estado, calculados sobre todas las evaluaciones ya rendidas. Vale para las dos pestañas: un curso puede tener los objetivos al día y estar al debe en «analizar», y eso es lo que la prueba siguiente tendría que ejercitar.

Sólo se ofrecen los cursos del nivel elegido arriba. Mostrar los de otros niveles contradecía el paso anterior —el profesor ya dijo qué nivel iba a evaluar— y cambiaba el catálogo entero por accidente.

Y también por alumno: el promedio del curso esconde a quien hay que evaluar

Bajo el curso hay un campo de alumnos. Se puede elegir uno o varios, y entonces el logro que muestra la tabla es el de ellos: lo que salga descendido es lo suyo, y la prueba se arma para eso.

Va como el «Para:» de un correo, no como una fila de botones: un curso tiene 34 alumnos y puede tener 45. En botones ocupaban cinco renglones y no se encontraba a nadie. Se escribe para filtrar —sin importar tildes—, lo elegido queda como ficha dentro del campo, Enter agrega el primero que calza y Retroceso con el campo vacío quita la última. Vacío significa todo el curso, y el marcador dice eso mismo.

El motivo es que un promedio de curso esconde justamente al que hay que evaluar distinto. Si la mitad va en 80% y la otra en 40%, el objetivo aparece «en proceso» y nadie se entera. En la maqueta se ve directo: el curso 2° Medio A tiene 2 objetivos bajos y 2 logrados; eligiendo a un alumno descendido pasa a 4 bajos y ninguno logrado —la misma tabla, otra prueba—.

Es la misma consulta del cuadro de arriba con un filtro por alumno: no hay cálculo nuevo ni tabla nueva. Y sirve para lo que hoy no tiene herramienta: la prueba diferenciada de dos o tres alumnos, y el recuperativo de los que quedaron abajo.

El título de la pantalla y las migas dicen de quién es la situación que se está mirando, y la evaluación queda registrada con el curso y los alumnos de los que salió (§6.10).

«Sin evaluar» y «logro bajo» son dos cosas distintas

Un objetivo que el curso nunca rindió no es un 0%: es que no se sabe. Mostrarlo como cero sería afirmar algo falso sobre el curso, y dejarlo fuera de la tabla —que es lo que pasa si se parte de lo evaluado— escondería justamente lo que hay que mirar.

Los dos estados piden cosas distintas: el sin evaluar pide averiguar, el logro bajo pide reforzar. Por eso van con etiquetas separadas, y en este camino el orden de la tabla es la recomendación: primero lo nunca medido, después lo más bajo. Sin curso no hay nada que recomendar y se deja el orden del currículo, que es el que el profesor conoce.

El botón «Proponer según el logro» llena las cantidades solo: 3 a lo nunca evaluado y a lo bajo, 2 a lo que va en proceso y ninguna a lo logrado. Es una propuesta editable, para no partir de una tabla en blanco, que es donde la mayoría abandona.

Los alumnos del PIE se avisan acá, no después de imprimir funcionalidad nueva

Elegido el curso, la pantalla dice cuántos de sus alumnos tienen necesidades educativas especiales, separando permanentes de transitorias, y qué adecuación pide cada diagnóstico. En el campo de alumnos, los del PIE van marcados —tanto en el listado de búsqueda como en la ficha, una vez elegidos— con su tipo a la vista.

Va en esta pantalla y no en otra porque acá es donde se decide la prueba. Si el curso tiene un alumno con discapacidad visual, el tamaño de letra deja de ser una preferencia; si tiene dos con déficit atencional, treinta preguntas apretadas en una hoja es una decisión y no un descuido. Enterarse después de imprimir no sirve de nada.

De dónde sale el dato, y qué hay que confirmar

WebClass ya tiene el formulario PIE —su layout es, de hecho, el que layouts/app.blade.php sirve en el repo—, así que el dato existe: quién está en el programa y con qué diagnóstico. Esta pantalla sólo lo lee. No se crea ninguna tabla.

Lo que hay que confirmar antes de programar, y va en el §11: en qué tabla vive la nómina PIE y con qué campo se relaciona con curso; si el diagnóstico está codificado o es texto libre; y quién puede verlo, que es lo más delicado.

Los nombres se muestran. Decidido por WebClass el 23-09: hoy en el colegio esa información ya está a la vista de todos, y a esta funcionalidad sólo entran docentes. Así que el aviso dice quiénes son, no sólo cuántos — que es lo que el profesor necesita para armar la prueba.

Dos límites que igual hay que respetar al programarlo, y que no dependen de esa decisión:

Lo que la maqueta inventa, y hay que reemplazar

Los alumnos PIE de la maqueta están puestos a mano, respetando los topes del decreto 170: hasta 2 permanentes y 5 transitorias por curso. Se respetaron a propósito —un curso con veinte alumnos PIE no existe, y una maqueta que lo muestre hace discutir un caso que no se da—. El curso 2° Medio B se dejó sin ninguno, para poder ver también esa pantalla.

Las adecuaciones sugeridas por diagnóstico las escribió la maqueta y WebClass las revisó y aprobó el 23-09, de forma provisoria: quedan como están hasta que avisen lo contrario.

Lo que sí conviene dejar resuelto al programarlo: que ese texto se pueda cambiar sin tocar el código. Es contenido pedagógico, lo va a corregir el equipo PIE tarde o temprano, y una frase incrustada en un if convierte una corrección de redacción en un despliegue.

ColumnaQué muestraDe dónde sale
Objetivo / HabilidadCódigo, nombre y eje, o el nombre de la habilidadCatálogo Mineduc del nivel
Ya evaluado (sólo con curso)Cuántas preguntas, en cuántas evaluaciones, y la fecha de la últimarespuesta_*_alumno → prueba_preguntas → pregunta_atributo
Logro (sólo con curso)Barra y porcentaje: puntaje obtenido sobre posible, del curso completoLa misma consulta
Estado (sólo con curso)Sin evaluar / Bajo / En proceso / LogradoLos umbrales del informe de aprendizaje, no una escala nueva
PreguntasCuántas se quieren de esa filaLo decide el profesor
De dóndeBanco o IA, por fila, con la cuenta de lo que el banco tienepregunta_atributo / pregunta_indicador
Qué hay que confirmar de este cálculo

El logro por objetivo y por habilidad es una consulta sobre datos que ya están, pero hay tres decisiones que no se pueden tomar desde acá:

Por qué va en pantalla propia y no en el panel de abajo

Los otros caminos abren un panel bajo las filas porque preguntan dos o tres cosas. Este muestra una tabla de seis columnas con una fila por objetivo del nivel y ahí abajo no se lee. Además es la única pantalla del gadget que se mira antes de decidir, no mientras se trabaja.

Se lee en pasos numerados y el pie queda fijo abajo: con quince objetivos, el total y el botón de crear no pueden quedar al final del scroll.

Tres decisiones de control que no son cosméticas, porque se repiten una vez por fila: el curso va en tarjetas y no en un desplegable —se elige una vez y tiene que quedar a la vista mientras se lee la tabla—; la cantidad va con botones −/+, porque las flechitas nativas de un campo numérico miden ocho píxeles; y banco o IA son dos botones a la vista, porque la cuenta del banco es el dato con el que se elige y dentro de un <select> hay que abrirlo para verla.

6Pantalla 2 — El editor

6.1 El editor está paginado: cada hoja de la pantalla es una página del PDF

El centro de la pantalla no es un lienzo continuo con una línea de corte dibujada encima: son hojas de verdad, separadas, cada una a escala real con su número de página al pie. Cuando el contenido pasa del alto útil, la pregunta siguiente se va a la hoja siguiente, igual que al imprimir. Es lo que resuelve el problema principal del §1.

Dos cosas que se aprendieron construyendo la maqueta

6.2 Los enunciados y las alternativas se escriben en un editor WYSIWYG con LaTeX

Tanto el enunciado como cada alternativa son campos con formato: negrita, cursiva, subrayado, superíndice, subíndice, tipografía, tamaño de letra, imágenes y fórmulas.

Alineación por fila

La barra trae los cuatro botones habituales —izquierda, centro, derecha y justificado— y se aplican a la fila donde está el cursor, o a lo que esté seleccionado. El botón queda hundido mostrando cómo está alineado eso: sin esa seña, los cuatro se ven iguales y no hay forma de saberlo.

Dos trampas de execCommand que hay que esquivar
  1. El texto tiene que estar dentro de bloques. Los enunciados vienen como texto suelto separado por <br>. Sobre eso, justifyCenter no encuentra un párrafo al que aplicarse y Chrome termina alineando el campo entero: se pide centrar una línea y se centra todo. La maqueta envuelve cada fila en un <div> al abrir el editor, una vez, y ahí la alineación queda por fila.
  2. Con una imagen seleccionada no se usa execCommand. Habría que dejarle la selección sobre la imagen, y entonces Chrome toma los límites del rango en el elemento padre: alineaba también el párrafo vecino y dejaba <div> vacíos de regalo. Se escribe el text-align directo en el bloque que envuelve la imagen.

También hay que leer el estado de la alineación del text-align calculado, no de queryCommandState: justo después de aplicarla, queryCommandState devuelve el valor anterior y el botón queda hundido con un paso de atraso.

Dos formas de poner una imagen: subirla o generarla

La barra trae dos botones distintos, no uno: 🖼️ Subir una imagen y 🎨 Generar una imagen con IA (§7.b). Son dos caminos separados y el segundo cuesta tokens; mezclarlos en un solo botón obligaría a entrar a un formulario de IA al profesor que sólo quiere poner la figura que ya tiene escaneada.

En el producto, el archivo no puede quedar en el HTML

La maqueta mete la imagen como data: dentro del enunciado, porque no tiene servidor. En el producto hay que subirla y guardar una URL: un enunciado con una foto embebida en base64 son cientos de kilobytes en la columna de texto de pregunta, se replica en cada copia de la prueba y rompe cualquier búsqueda sobre ese campo.

Hay que definir dónde viven (el gadget no tiene tabla de archivos propia) y quién las puede ver: una imagen de una prueba no rendida no puede quedar en una URL pública adivinable.

El tamaño de una imagen se cambia tirando de una esquina

Las imágenes del enunciado —la generada por IA y la recortada de un PDF— entran con un tamaño de oficio que casi nunca es el que el profesor quiere. Un clic la selecciona y aparecen cuatro tiradores, uno por esquina; se arrastra cualquiera de ellos.

El marco de los tiradores va fuera del campo editable

Si el marco y sus cuatro tiradores vivieran dentro del contenteditable, entrarían en el HTML que se guarda en el enunciado y terminarían impresos en la prueba. Van en un elemento aparte, posicionado encima —lo que obliga a reubicarlo cuando el campo se desplaza o la ventana cambia de tamaño—.

Por lo mismo, la clase que marca la imagen elegida se saca antes de leer el HTML al aplicar. Es el tipo de basura que no se nota hasta que aparece en un PDF.

Las imágenes van en línea (inline-block) dentro de un bloque con text-align, no sueltas: con display:block y margin:auto quedaban siempre centradas y los botones de alineación no las movían.

Y se recorta: mostrar sólo una parte funcionalidad nueva

Una figura escaneada, generada por IA o traída de un Word casi nunca viene encuadrada: arrastra el enunciado de al lado, media tabla, el borde de la hoja, el número de página del libro. Hasta ahora la única salida era recortarla en otro programa y volver a subirla — un viaje de ida y vuelta por algo que se resuelve con un rectángulo.

El original no se destruye, y eso decide cómo se guarda

Un recorte es una forma de mirar la imagen, no una manera de destruirla. Si se guarda sólo el resultado, equivocarse de encuadre cuesta volver a conseguir el archivo — que puede ser un escaneo que ya no está. Por eso hay «Quitar el recorte», que devuelve la imagen entera.

En el producto eso se guarda como un rectángulo, no como una imagen nueva. La imagen sube una vez y el recorte viaja como cuatro números —x, y, ancho, alto en fracción del original— junto a su URL. Así el recorte se puede cambiar después, dos preguntas pueden usar dos recortes de la misma imagen sin subirla dos veces, y el PDF se arma en el servidor recortando al vuelo. Guardar la imagen recortada como archivo nuevo duplica el almacenamiento y pierde justamente lo que hace falta para corregirla.

La maqueta guarda el original en data-original y reemplaza el src, porque no tiene servidor donde poner el archivo; el comportamiento visible —recortar y poder volver atrás— es el mismo.

Tipografía y tamaño, en dos niveles

La fórmula se inserta escribiendo LaTeX con vista previa en vivo y una fila de atajos para lo más usado (fracción, raíz, ±, ≤, π, Δ, ∑). Una vez puesta se comporta como un objeto: se selecciona entera y al hacer clic se vuelve a abrir el editor de LaTeX. No se puede escribir por dentro, que es lo que la rompería.

Cómo se guarda — esta era la duda abierta y queda resuelta

El enunciado se guarda como HTML (es lo que el editor WYSIWYG necesita) y cada fórmula viaja dentro como un <span> que conserva el LaTeX original en un atributo:

<span class="formula" data-latex="k = \frac{25}{16}">…render…</span>

Así se puede volver a editar la fórmula sin re-interpretar el HTML, y el día que se cambie de renderizador basta recorrer los data-latex y volver a pintar. Guardar sólo el HTML renderizado dejaría las fórmulas inmodificables.

Qué librerías usar — y el problema del PDF

6.2.b Tablas dentro de una pregunta

El botón de tabla abre un selector de tamaño por rejilla — se pasa el mouse y se elige 3 × 4, como en Word o Docs — con la opción de usar la primera fila como encabezado. Después se escribe directo en las celdas.

Sirve para lo que en matemática y ciencias aparece todo el tiempo: tablas de frecuencia, de valores x/y, de datos experimentales. Las tablas van dentro del enunciado, no como un objeto aparte: son parte de la pregunta y tienen que viajar con ella al banco de items.

Lo que falta y hay que definir: agregar y borrar filas o columnas después de creada, combinar celdas, y alineación por columna. La maqueta inserta la tabla y deja escribir, nada más. Si se usa CKEditor, esto viene resuelto.

6.2.c Gráficos interactivos: JSXGraph

Un bloque de gráfico dentro del enunciado, con dos formas de describirlo en el mismo campo:

No hay que elegir el modo: se reconoce solo. La marca es la misma en todos los ejemplos de la librería —JXG.JSXGraph.initBoard, o un board.create(— y ninguna de esas cadenas puede aparecer en la forma corta, que no lleva llamadas ni puntos. BOARDID es el hueco que la propia documentación deja para el id del contenedor, así que el ejemplo se pega sin tocar una letra.

Lo que pasaba antes, y por qué era peor que un error

Pegar un ejemplo de la documentación no fallaba: cada línea de código se descartaba en silencio por no calzar con ninguna de las tres formas cortas, el tablero salía vacío con sus ejes —que parece un gráfico legítimo— y las sesenta líneas de código quedaban impresas en la cabecera del bloque, encima del dibujo.

Dos arreglos, y el segundo vale para cualquier motor: el código se ejecuta, y cuando no se entiende nada se dice con todas sus letras en vez de dibujar una cuadrícula vacía. Un gráfico en blanco que parece correcto llega impreso a la sala; un mensaje de error, no. La cabecera, además, ahora es una referencia —«27 líneas»—, no el contenido.

El código del autor no puede correr en la página del alumno

Aceptar código significa que el enunciado de una pregunta guarda JavaScript del profesor y que alguien lo ejecuta. En la maqueta da igual: es código propio en el navegador propio. En el producto no, y hay que decidirlo antes de programarlo — una pregunta del banco la escribe un profesor y la rinde el alumno de otro colegio.

Las dos salidas razonables, y las dos sirven:

Mientras eso no se defina, lo prudente es que el modo código quede restringido a quien crea preguntas y no viaje al alumno.

El problema: GeoGebra no es gratis para nosotros

GeoGebra es gratis sólo para uso no comercial, y su licencia dice explícitamente que eso «depende del uso, no del usuario»: que el colegio sea educativo no basta, porque el uso que hace WebClass es incorporarlo a un producto que se vende. Su propio texto pide, para uso comercial, un License and Collaboration Agreement escribiendo a office@geogebra.org; y la cláusula de embedding exige además que el licenciatario garantice que los usuarios finales le den un uso no comercial.

Desmos tiene el mismo problema, aunque menos visible: su modelo son «paid partnerships with publishers, assessment companies, educational institutions and other commercial partners», y para usar su API remiten a partnerships@desmos.com. No hay un precio público: es acuerdo caso a caso.

La alternativa: JSXGraph

JSXGraph (Universidad de Bayreuth) está doblemente licenciado bajo LGPL y MIT. Se puede usar dentro de un producto que se vende, sin pedir permiso, sin pagar y sin cláusulas sobre qué hace el usuario final.

LicenciaUso en un producto que se vendeSalida
JSXGraphLGPL + MITLibreSVG o canvas
CindyJSApache 2.0Librecanvas
GeoGebraPropietariaRequiere acuerdocanvas (PNG por API)
DesmosPropietariaRequiere partnershipcanvas

Técnicamente JSXGraph también calza mejor: es una librería suelta sin dependencias (no un applet de terceros), corre entera en el navegador sin servidor, cubre geometría euclidiana, gráficos de funciones, estadística y 3D, y —lo que más importa acá— dibuja en SVG. Un SVG entra directo al PDF sin pasar por una captura de pantalla; un applet en canvas no.

Decidido con el negocio: JSXGraph, y GeoGebra queda fuera. La maqueta tenía un selector de motor con las dos opciones, por si algún día se conseguía el acuerdo; se quitó. Un desplegable que ofrece algo que no se puede usar invita a elegirlo, y después hay que explicar por qué no. Con un solo motor tampoco hay selector: la pantalla dice cuál es y bajo qué licencia, y punto.

Con GeoGebra se fue también el selector de tipo de applet (gráficos, geometría, 3D, probabilidad), que era suyo, y la carga de deployggb.js desde geogebra.org.

JSXGraph está probado con seis casos: parábola, recta, raíz, trigonométrica, función con asíntota y función con punto marcado. Más uno en modo código: la superficie 3D con deslizador y plano tangente del propio sitio de la librería, pegada sin editar, sobre la versión 1.13.3 —que trae view3d y functiongraph3d, comprobado, no supuesto—.

Tres cosas que igual hay que resolver, con cualquier motor
  1. En papel no existe un gráfico interactivo. La misma pregunta tiene que dar interactivo en línea y una imagen estática en el PDF. Con JSXGraph la imagen es el propio SVG, que se puede guardar junto al bloque; hay que guardarlo al crear la pregunta, no generarlo al imprimir, porque el PDF se arma en el servidor y ahí no hay navegador dibujando.
  2. Encuadrar bien una función cualquiera es un problema de verdad. Ajustar al mínimo y máximo muestreados deja una parábola aplastada contra el eje; se probó recortar las colas por percentiles y tampoco sirve, porque la distribución de valores está muy sesgada. Por eso hay ventana=(x₀,x₁,y₀,y₁): el autor la fija cuando le importa. Desmos y GeoGebra lo resuelven con heurísticas propias; no hay que intentar reinventarlas.
  3. No sirve para evaluar, sólo para ilustrar — al menos en esta etapa. Que el estudiante responda manipulando el gráfico es otro producto: exige capturar su construcción y corregirla.

En la maqueta el bloque muestra una vista previa estática y un botón «Ver el gráfico real» que recién ahí carga la librería. Se hizo así a propósito: la maqueta tiene que abrir sin internet, que es como se muestra en una reunión.

6.3 Agregar preguntas — botón flotante, como en Google Forms

Un botón fijo a la ventana, abajo a la derecha, siempre visible. Al pulsarlo se despliega hacia arriba una paleta con los tipos de pregunta y los dos orígenes alternativos:

La pregunta se agrega al final, la vista baja hasta ella y el cursor queda en el enunciado, listo para escribir.

6.3.a Los tipos de pregunta: los que WebClass ya guarda

No se inventó ninguno. La lista sale de leer el módulo home/preguntas/CreaPreguntas del vanilla: el if($tipo==N) de controlador/controladorPregunta.php y las clases Objetos/Respuesta_*.php. pregunta.tipo es un entero y estos son sus valores:

tipoQué esDónde vive la respuestaEn la maqueta
1Verdadero / Falsorespuesta_vofsí
1V/F con justificaciónrespuesta_vof_justificacion — tiene justificacion y puntajeObtenido propiossí, nuevo
2Términos pareadosrespuesta_enpareja_orden (texto, columna, orden) + respuesta_enpareja_vinculo (vinculo_a, vinculo_v, puntaje)sí, nuevo
3Desarrollo (ensayo)respuesta_desarrollosí
4Selección múltiple, una correctarespuesta_alternativa (texto, puntaje, orden, retroalimentacion)sí
4Selección múltiple, varias correctasLa misma tabla, usando puntaje como porcentaje en vez de banderasí, nuevo
5Respuesta cortarespuesta_corta (texto, puntaje, retroalimentacion)sí, nuevo

Los iconos del producto (truefalse.gif, match.gif, essay.gif, multichoice.gif, shortAnswer.gif) son los de Moodle, y existe un módulo giftEvaluation: la numeración viene de ahí. Conviene tenerlo presente si alguna vez se quiere importar o exportar en formato GIFT.

El hallazgo: el puntaje por alternativa ya existe

respuesta_alternativa tiene una columna puntaje por alternativa. Lo que se ve en algunas partes del código es que se la lee como bandera —if($res->getPuntaje()>0) → «Opción correcta»—, pero el producto ya la escribe como porcentaje. Eso cambia la conclusión y vale la pena verlo entero.

El porcentaje por alternativa ya existe, y se guarda como fracción de 0 a 1

En el formulario de creación de preguntas, cada alternativa tiene su propio campo de calificación —id_fraction_0…id_fraction_7, o sea hasta ocho alternativas— que viaja como calificacionRespuestaN y termina en respuesta_alternativa.puntaje. Los nombres delatan el origen: es el modelo de Moodle, y en el repo está además el importador de GIFT.

La regla la impone el propio producto, en editarPreguntas.php:

var sumfrac = frac0 + frac1 + … + frac7;
if (sumfrac != 1) { alert('La calificación sugerida no es el 100%'); return; }

O sea: las fracciones tienen que sumar 1. Es exactamente lo que hace la maqueta —repartir 100% entre las correctas y no dejar guardar si no cuadra—, con una sola diferencia que hay que respetar al implementar: la base guarda 0,5, no 50. La maqueta muestra porcentajes porque es lo que el profesor entiende; al escribir hay que dividir por 100.

Lo mismo vale para respuesta_corta.puntaje —aceptar «7» al 100% y «2 y 5» al 50%— y para respuesta_enpareja_vinculo.puntaje, que habilita puntaje parcial por par acertado. Ninguna tabla nueva.

Pero el corrector de hoy ignora el porcentaje, y eso es un riesgo real

Se guarda una fracción, sí. Pero al corregir, el producto la lee como bandera. En DatosTestDao, para una pregunta de alternativas:

$puntaje = respuesta_alternativa.puntaje;      // la fraccion
if ($puntaje > 0) { $puntaje = $puntajePregunta; }   // ← el puntaje COMPLETO
else               { $puntaje = 0; }

O sea: cualquier fracción mayor que cero da el puntaje entero de la pregunta. Una pregunta autorizada 50/50 le daría 100% al alumno que marcó sólo una. Y recibe una alternativa, no varias: hoy es selección única.

Consecuencia para el alcance. Este gadget crea preguntas y la aplicación sigue el camino actual de WebClass —decidido así—, pero entonces hay que decirlo sin rodeos: si se publica la autoría de varias correctas sin tocar el corrector, las notas salen mal y nadie se entera. Es peor que no tener la funcionalidad. Las dos salidas honestas son ajustar el corrector junto con esto, o no habilitar el tipo hasta que se ajuste.

Y la validación del 100% no bloquea de verdad

valida_porcentaje() muestra la alerta y hace return, pero retorna de sí misma, no del que la llama: quien la invoca (validar_retroalimentacion) no mira lo que devuelve y el formulario se envía igual.

Consecuencia práctica para este gadget: en producción puede haber preguntas cuyas fracciones no sumen 1. El generador no puede asumir que el dato viene limpio — al traer una pregunta del banco hay que mirar la suma y avisar, no confiar. Es el mismo criterio que ya se aplica a las alternativas repetidas (§8.a): lo que ya está mal no se corrige solo, se muestra.

Selección múltiple con varias correctas

Términos pareados

El señuelo sin pareja «+ distractor»

La columna B puede llevar opciones que no calzan con ningún término de la A. Sin ellas, el último par sale gratis: quien ya emparejó el resto acierta por descarte. Con un señuelo, cada fila hay que resolverla.

Modelo de datos: ya existe, no hay que inventarlo. Un señuelo es una fila de respuesta_enpareja_orden con columna = B y su orden, cuyo vínculo en respuesta_enpareja_vinculo queda con vinculo_a = -2. Es exactamente lo que el producto llama «distractor» en editarPreguntas.php y controladorPregunta.php. El control está comentado en varios archivos: la tarea es descomentarlo y completarlo —y verificar que el corrector no intente emparejar un -2—, no escribirlo de cero. Ver la caja sobre la palabra «distractor», porque en la otra acepción sí se descartó.

Respuesta corta

Desarrollo, con rúbrica para el profesor funcionalidad nueva

Esto no existe hoy en WebClass — es una propuesta

WebClass tiene rúbricas, pero son un recurso aparte: se arman en Evaluación › Rúbricas de aprendizaje y se aplican a trabajos o actividades. Lo que no existe es una rúbrica pegada a una pregunta de una prueba, que viaje con ella y salga en su pauta de corrección.

Eso es lo que este documento propone, y es el único punto del gadget donde hay que agregar algo al modelo de datos fuera de las tablas de tokens. Todo lo demás —la forma de la rúbrica, sus criterios, sus niveles de logro— se toma tal cual del producto, para no abrir un formato paralelo que después haya que reconciliar.

Decisión de negocio antes de programar: si esto se aprueba, hay que definir también si la rúbrica de una pregunta puede guardarse en el banco de Rúbricas de aprendizaje para reutilizarla, o si vive sólo dentro de la evaluación. Ver §11.

En el papel la pregunta es un bloque de líneas. Lo que se agrega es que nace acompañada de una rúbrica: es el único tipo que no se corrige solo, y sin pauta «6 puntos de desarrollo» los reparte cada profesor a ojo —con dos cursos paralelos, eso es una diferencia de nota que nadie puede explicar después.

La forma de la rúbrica sí se reusa tal cual

El módulo Rúbricas de aprendizaje ya guarda rúbricas, y este gadget usa ese mismo modelo:

En la maquetaTabla del productoCampo
La rúbricarubricaid_nivel, id_sector, autor
Un criterio (fila)rubrica_criteriotitulo, orden, tipo
Un nivel de logro (columna)concepto_valoresdescripcion, conversion, color, simbolo
La celda (descriptor)rubrica_criterio_detalletitulo, id_rubrica_criterio, id_concepto_valores
Lo que se marca al corregirrubrica_alumno_criterio / rubrica_alumno_evaid_rub_crit_det

El conversion de concepto_valores es el «%» que se ve en la cabecera de cada columna: el porcentaje del puntaje del criterio que se paga en ese nivel. No hubo que inventarlo.

Lo único que hay que agregar: el amarre pregunta → rúbrica

Hoy rubrica cuelga de una evaluación (id_concepto_evaluacion), de un nivel y de una asignatura. No tiene forma de apuntar a una pregunta. Ese es el amarre que falta, y es todo lo que falta.

Propuesta: una columna anulable en la tabla que ya existe.

ALTER TABLE rubrica ADD COLUMN id_pregunta INT NULL DEFAULT NULL;
-- NULL  = rúbrica del banco, como hoy: se arma y se aplica aparte
-- id    = rúbrica de esa pregunta, viaja con ella y sale en su pauta

Se prefiere la columna por sobre una tabla puente porque la relación es uno a uno —una pregunta, una rúbrica— y porque así las rúbricas de preguntas y las del banco siguen siendo la misma entidad: el día que se quiera guardar una en el banco, basta con poner la columna en NULL. Con una tabla puente habría que migrar filas.

Vive en el carril lateral, no sobre la hoja

La rúbrica no se dibuja dentro de la hoja. La hoja es lo que se imprime, y meterle una tabla de corrección adentro rompe la única promesa del editor: lo que ves es lo que sale. Además empujaba las preguntas a la página siguiente y hacía que la vista dejara de mostrar la paginación real.

En cambio es una opción más del carril lateral de la pregunta, junto a Categorización y Retroalimentación, y sólo aparece en las preguntas de desarrollo. Al hacerle clic se abre un modal ancho con la tabla: en el cajón lateral no cabría, porque es una matriz de criterios por niveles.

Dónde se imprime: en la pauta, nunca en la hoja del alumno

Como la rúbrica no vive en la hoja, para la pauta hay que bajarla al papel a propósito. Al Descargar:

Detalle de implementación que importa: no alcanza con la bandera de «mostrar correctas». En el editor esa bandera está puesta casi siempre —para que el profesor vea la clave mientras arma—, así que colgarse de ella haría reaparecer la rúbrica sobre la hoja, que es justo lo que se sacó. Hace falta una bandera aparte, activa sólo mientras se genera la pauta.

Las decisiones que esta funcionalidad deja abiertas están juntas en §11, encabezando la lista.

V/F con justificación

Es el tipo 1 más un bloque de líneas rotulado «Justifica tu respuesta». La justificación se corrige a mano y tiene su propio puntaje: la tabla respuesta_vof_justificacion ya trae justificacion y puntajeObtenido por separado.

Tres detalles que no son cosméticos

6.3.b Recortar de un PDF o imagen — una pregunta por recorte

El profesor sube el PDF o la foto de una prueba anterior, ve el documento en pantalla y arrastra un rectángulo sobre cada pregunta. Cada recorte entra como una pregunta, en texto editable: el enunciado queda escrito, las alternativas se separan solas y las tablas se rehacen como tabla.

Un PDF digital no necesita OCR

Esto antes entraba como imagen, y la razón era el OCR: se midió con Tesseract.js y las alternativas salían 3mx8m, mxgm, smx8m — se comía el signo × y confundía dígitos con letras. Una alternativa mal transcrita es peor que ninguna: se imprime con el error y nadie lo nota hasta que el curso la está respondiendo.

Pero un PDF nacido digital no se lee con OCR. Trae la capa de texto con coordenadas, y recortar es filtrar por rectángulo: lo que sale es exacto, no adivinado. Es la misma técnica del §6.3.c, acotada a lo que el profesor encuadró.

Si el recorte no tiene texto por debajo —un escaneo, una foto—, la pantalla lo dice en la lista, y ofrece reconocerlo. Ver más abajo.

Recortar de una imagen: reconocer el texto

Este era el caso que quedaba afuera, y es el más común en un colegio: la prueba del año pasado está fotocopiada, o el profesor le saca una foto con el celular. Sin capa de texto, el recorte entero entraba como imagen, con las alternativas en blanco para llenar a mano — es decir, no se ahorraba nada.

El OCR no consume tokens, y no es un detalle de precio

Los tokens existen por una razón concreta: las herramientas de IA llaman a un proveedor externo que cobra por uso, y la bolsa es lo que le pone techo a esa cuenta. El OCR no es eso. El reconocimiento de texto se hace con Tesseract, que es open source, y corre en dos lugares posibles, ninguno de los cuales cobra por página:

Cobrarlo con tokens habría sido cobrar dos veces por algo que no cuesta, y peor: habría puesto un peaje justo en el camino del profesor que llega con la prueba fotocopiada, que es el que más ayuda necesita.

Lo que hay que saber antes de prometerlo

En la maqueta el reconocimiento está simulado. No se puede hacer de verdad ahí: haría falta una librería de varios MB por CDN —que las convenciones de estas maquetas no permiten— o un servicio en el servidor, que es como va en el producto. Lo que sí es real, y es lo que hay que discutir, es el flujo: el costo por recorte, la espera, y que todo lo reconocido entra marcado para revisar.

Y la advertencia de siempre, que sigue en pie: se midió con Tesseract.js y las alternativas salían 3mx8m, mxgm, smx8m. Con fórmulas el OCR es malo, y una alternativa mal transcrita que nadie revisa es peor que ninguna. Por eso el borrador obligatorio y el recorte original guardado al lado: el OCR no reemplaza al profesor, le ahorra el tecleo.

Falta definir: si se sirve en el navegador o en el servidor. En el navegador el colegio no paga nada y las imágenes no salen del computador; en el servidor la calidad se puede mejorar con preprocesado, a cambio de CPU. Ninguna de las dos usa tokens.

Dos fallas de la importación que se veían juntas

Una tabla llegaba aplanada como párrafo, con las celdas de las tres columnas intercaladas en orden de lectura («Menú 1 Menú 2 Menú 3 • Fideos con carne y • Ensalada de…»), y encima aparecían recuadros vacíos montados sobre el texto. Eran dos problemas distintos que se manifestaban en el mismo lugar:

  1. La detección exigía que todas las líneas tuvieran el mismo número de celdas. Una tabla real no cumple eso: cuando el texto de una celda no cabe en una línea, la de abajo trae una o dos celdas, no tres. Con la primera línea corta se cortaba el bloque, no llegaba al mínimo de tres filas, y la tabla entera caía al camino de «texto suelto».
    Ahora las columnas se fijan con la primera línea y cada línea se reparte en ellas; una con menos celdas deja columnas vacías en vez de romper la tabla. Y una línea cuyo texto arranca indentado respecto del inicio de su columna se une a la celda de arriba: es la seña que da el propio PDF, no una suposición sobre viñetas.
  2. Las rayas de la tabla se importaban como una figura. El detector de figuras busca bandas con tinta y sin texto, y las líneas horizontales de una tabla son exactamente eso. Entraban como imagen: un recuadro vacío con los bordes, encima del texto.
    Ahora las tablas se detectan primero y sus franjas se excluyen del barrido de figuras.

Para el desarrollador: el orden importa. Detectar tablas antes que figuras no es una preferencia de estilo; sin eso, toda tabla con bordes aporta una figura fantasma.

Las fórmulas se traen como LaTeX, y se pueden editar

Un PDF nacido digital no guarda «√12»: guarda un √ y un 12 con sus coordenadas, y la raya de la raíz es un trazo vectorial aparte. Lo mismo con un exponente —el 7 de 2⁷ es un trozo más chico y más arriba— y con una fracción, que son dos trozos apilados. Aplanar eso a texto daba 2 7 3 y la pregunta quedaba sin sentido.

Ahora esas señas —alto del trozo, desplazamiento respecto de la línea base, apilamiento— se leen y se reconstruye el LaTeX. La fórmula entra como el mismo <span class="formula" data-latex="…"> que produce el editor, así que se abre y se corrige como cualquier otra.

En el PDFEntra como
√12\sqrt{12}
6√56\sqrt{5}
∛2⁷ — raíz con índice\sqrt[3]{2^{7}}, con el exponente dentro
2⁷2^{7}
2 elevado a 7/3 (fracción apilada)2^{\frac{7}{3}}
x₁x_{1}
Una fracción apilada — 3 sobre 8\frac{3}{8}
≤ ≥ ≠ ± × ÷ π Δ ∞…Su comando LaTeX
Tres decisiones que hacen que esto funcione
  1. Sólo se convierte lo que tiene una seña matemática. La prosa queda como prosa: una frase no se vuelve fórmula por tener un número. «Un rectángulo mide 3 metros más que su altura» entra como texto.
  2. El cuerpo de la línea es el trozo MÁS ALTO, no la mediana ni el más ancho. Un exponente es siempre más chico que el cuerpo, nunca más grande, así que el máximo no se confunde. Con la mediana o con el peso por ancho, una línea corta como 2^{7/3} —un trozo de cuerpo y dos chicos— elegía el tamaño del exponente como «lo normal», y entonces no se detectaba ninguna seña.
  3. Ser chico no basta para ser exponente: hay que estar desplazado de la línea base. El texto del cuerpo nunca lo está.

El texto viaja con un marcador en lugar de la fórmula hasta el último paso, para que todo lo que ya existía —partir alternativas, detectar tablas, buscar el número de la pregunta— siga trabajando sobre texto plano. El marcador se cambia por el HTML recién al escapar.

Límites, y hay que decirlos: la capa de texto no trae la raya de la raíz ni la de la fracción —son trazos vectoriales—, así que el alcance del radicando se deduce de que lo que va debajo de la raya va sin separación. Funciona para lo que aparece en una prueba de colegio; una integral, una matriz o una fracción de varios niveles no van a salir bien. El profesor las corrige en el editor de fórmulas, que es donde ya están.

La fracción no es un trozo: son dos, y barajaban la línea entera

Una fracción escrita como numerador sobre denominador son dos trozos de texto con una raya vectorial al medio que la capa de texto no trae. Como los dos caen dentro de la tolerancia con que se arman las líneas, terminaban ambos en la misma línea; y al ordenarlos por x se intercalaban con los de las fracciones vecinas. De ahí salía 3 6 8 3 … 8 16 3 11: los numeradores y denominadores de cuatro fracciones, barajados, y la pregunta ilegíble.

Las fracciones se unen ANTES de armar las líneas, en un solo trozo que ya trae su LaTeX. De ahí en adelante el importador ve una fracción donde hay una fracción.

Lo que distingue una fracción de dos líneas de un párrafo es que están centradas una sobre otra. Dos líneas de texto comparten el margen izquierdo pero no el centro; el numerador y el denominador sí. Sin esa condición, cualquier párrafo de dos líneas cortas se convertiría en una fracción.

Un PDF puede traer texto y aun así no servir

Hay un tercer caso, distinto del PDF digital y del escaneo: el documento trae capa de texto pero no dice qué letra es cada símbolo. Pasa cuando la fuente matemática viene incrustada sin su tabla ToUnicode, que es lo habitual en pruebas exportadas desde un editor de ecuaciones. Lo que se extrae son caracteres del área de uso privado, que en pantalla se ven como cuadraditos: □3 6 □ 8 3.

Es traicionero porque el importador no lo distingue de un PDF sano: hay texto, así que lo transcribe. Ahora se mide la proporción de caracteres sin significado y, si pasa del 12%, se declara la capa ilegible y se ofrece reconocer el texto —que no cuesta tokens— o dejarlo como imagen. Transcribir cuadraditos en silencio es peor que no transcribir.

Para el producto: el umbral es una decisión que conviene revisar con PDFs reales del colegio. No es cero para tolerar una viñeta o un símbolo suelto que el visor no supo mapear.

El recortador ocupa el 90% de la pantalla, con zoom

El documento es el trabajo, no un detalle del formulario. En un notebook de 13″ la página entraba tan chica que el texto no se leía, y encuadrar «la pregunta completa» a ojo era imposible.

Un recorte, una pregunta

Antes todos los recortes se sumaban a una sola pregunta, para el caso de una pregunta partida entre dos columnas. Estaba mal calibrado: lo habitual es encuadrar varias preguntas seguidas, y recibirlas todas pegadas obliga a deshacer a mano lo que el sistema juntó. Ahora cada recorte es una pregunta; una partida en dos se arregla con un recorte que abarque las dos partes, o pegando el texto después —que ahora se puede, porque es texto—.

Qué se reconoce dentro del recorte

En el documentoEntra como
El número de la pregunta — 1., 2), o dentro de un círculo, o solo en su líneaSe descarta: la numeración la pone la hoja.
El enunciadoTexto editable.
A) B) C)… — una por línea, varias en la misma línea, o en dos columnasAlternativas separadas, en orden A–D, sin clave marcada. Ver abajo.
Verdadero / FalsoLa pregunta nace de tipo V/F.
Sin alternativasLa pregunta nace de tipo desarrollo.
Una tabla, aunque sus celdas ocupen varias líneasTabla editable (<table>), no una foto. Ver abajo.
Una figura (banda con tinta y sin texto)Imagen, en su lugar dentro del enunciado — antes, entre o después de las líneas.
Un dibujo con rótulos adentro: un plano, una cuadrícula de coordenadas, un diagrama con etiquetasUna sola imagen, con sus rótulos dentro. Ver abajo.
Las rayas de una tablaNada: se saltan. Son tinta sin texto, pero no son una figura.
Una fórmula: raíces, exponentes, subíndices, fraccionesLaTeX reeditable (<span class="formula" data-latex="…">), no texto aplanado. Ver abajo.
Una línea puede traer varias alternativas

Leer «una alternativa por línea» parece lo natural y está mal. Cuando las opciones son cortas —y en matemática casi siempre lo son— las pruebas las aprietan:

Con la lectura por línea, los cuatro casos daban lo mismo: una sola alternativa con las cuatro opciones adentro. La pregunta quedaba inservible y había que escribirla de nuevo, que es exactamente lo que el importador venía a evitar.

Dos reglas evitan inventar alternativas donde hay prosa: la línea tiene que empezar con una marca, y la primera alternativa de la pregunta tiene que ser la A. Así, «El vértice A. Se ubica…» o «según la figura, a) y b) son paralelas» siguen siendo enunciado. Y una letra ya usada no abre alternativa nueva: es continuación de la anterior.

El reordenado por letra sólo se aplica si están todas, de la A hasta la última sin saltos. Si falta una, se deja como venía: ordenar a medias escondería el error en vez de mostrarlo.

Esto vale igual para el recorte y para el PDF completo. Conviene que sea una sola función usada por los dos caminos: estuvo duplicada y las dos copias tenían el mismo defecto.

Las tablas se reconocen por alineación, no por los bordes dibujados: hay tablas sin bordes y hay rayas que no son tablas. Se acepta como tabla una seguidilla de tres o más líneas que se parten en el mismo número de celdas y en las mismas posiciones; con dos filas podría ser cualquier cosa.

Un dibujo puede tener texto adentro, y ahí el texto no es texto

Un plano con «Museo», «Biblioteca» y «Plaza» en sus celdas; una cuadrícula de coordenadas con sus letras y números en los bordes; un diagrama rotulado. Son el mismo caso: el dibujo lleva palabras adentro, y esas palabras sin el dibujo no dicen nada. «Museo / Biblioteca / Plaza / Escuela», una por línea, no es una pregunta.

El barrido de figuras de arriba sólo mira las bandas que el texto no ocupa, así que un dibujo cuyas filas llevan rótulos le resulta invisible: las rayas se pierden y los rótulos salen sueltos, como si fueran prosa. La pregunta queda inservible, que es exactamente lo que el importador venía a evitar.

La seña es la tinta que el texto no explica. Se rasteriza el recorte, se tapan los rectángulos de cada item de la capa de texto, y se mira lo que sobra: las rayas, los ejes, los bordes de las celdas. Donde eso se acumula a lo largo de varias franjas seguidas hay un dibujo, y las líneas que caen ahí adentro son sus rótulos: entran dentro de la imagen, no como texto aparte.

Tres reglas evitan convertir en foto lo que sí es texto:

Y aun así: el que recortó puede mandar

Ninguna heurística sobre un PDF rasterizado va a acertar siempre. Un plano rotulado, un gráfico con sus ejes y una tabla con bordes se parecen mucho entre sí mirando píxeles.

Por eso cada recorte trae, en el panel de revisión, un par de botones: «Como texto» o «Como imagen». El que dibujó el recuadro ya sabe qué encerró; lo único que faltaba era dónde decirlo. Y va en el panel de revisión, no en un menú aparte, porque la decisión se toma mirando el recorte y tiene que poder cambiarse antes de importar, no después de tener quince preguntas rotas en la hoja.

Marcado como imagen, el recorte entra como una sola figura con las alternativas en blanco para marcar la clave, igual que un escaneo sin capa de texto. Y la oferta de OCR no aparece para ese recorte: el profesor no pidió reconocer nada, pidió una imagen.

Las figuras se buscan por bandas: se toman las franjas horizontales del recorte que ninguna línea de texto ocupa y se mira si tienen tinta. Hay que mirar las tres clases de banda —antes de la primera línea, entre dos líneas y después de la última—: el caso más común es la figura bajo el enunciado, y mirar sólo los huecos intermedios lo dejaba fuera.

La imagen se recorta al ancho del recorte, no al del texto —una figura suele ser más ancha que las líneas— y después se le quita el aire blanco ajustando al contorno de la tinta. Sin eso la figura entra rodeada de página en blanco y se ve como un error.

Una banda que no llega al 0,4% de tinta se descarta: es espacio entre párrafos, no un dibujo. Y un recorte que trae sólo una figura, sin texto, entra igual — como pregunta de desarrollo con la imagen dentro.

El panel de la derecha muestra, por cada recorte, qué se reconoció —tipo, cuántas alternativas, si trae tabla o figura— antes de importar nada. Es la única forma de darse cuenta de que algo salió mal antes de tener quince preguntas rotas en la hoja.

La clave se marca a mano, igual que antes

El documento trae la prueba, no la pauta: ninguna pregunta importada llega con la respuesta correcta marcada, y Guardar se bloquea hasta que estén todas (§8.b).

Lo que hay que resolver al programarlo
  1. El PDF hay que rasterizarlo para poder recortar encima, y además hay que leer su capa de texto. Las dos cosas las hace pdf.js (Mozilla, Apache 2.0 — sin problema de licencia), que es lo que usa la maqueta: el archivo no sale del computador hasta que el profesor decide crear las preguntas. Son ~320 KB de librería más 1 MB de worker, que conviene cargar sólo al abrir este cargador y no en cada pantalla. En el servidor están Imagick y Ghostscript —los que generan los PDF hoy— para el escaneo pesado.
  2. Hay que guardar las coordenadas, no sólo el resultado. Por cada recorte: archivo de origen, número de página y el rectángulo. Así se puede volver a interpretar el mismo recorte cuando el reconocimiento mejore, sin pedirle al profesor que recorte de nuevo.
  3. La deteccion de tablas necesita datos reales. El umbral de la maqueta —tres filas, columnas alineadas dentro de 40 pt— se calibró con un PDF de ejemplo. Antes de soltarlo hay que pasarle pruebas de verdad del colegio y ajustar; una tabla mal reconocida es peor que ninguna.
  4. Los recortes cruzan páginas. Se navega por el PDF y se sigue recortando. En pantalla, cada marco se dibuja sólo sobre su página; la lista lateral los muestra todos, numerados y con su página.
  5. No cuesta tokens. Leer la capa de texto es aritmética, no IA: no hay llamada a ningún proveedor y no hay nada que cobrar. Sólo costaría si alguna vez se agrega el modelo de visión para los escaneos (§7).

Fuera de alcance por ahora: detectar solo dónde empieza y termina cada pregunta, enderezar un escaneo torcido, y separar columnas automáticamente. Si el escaneo viene muy inclinado, conviene avisarlo antes de que el profesor pierda el tiempo recortando.

6.3.c Digitalizar desde un archivo completo — sin recortar nada a mano

La diferencia con §6.3.b no es de grado: allá el profesor encuadra cada pregunta y lo encuadrado entra como imagen. Acá se lee el archivo entero y se separan solas las preguntas y sus alternativas. Acepta PDF y Word, y en el PDF aprovecha que un PDF nacido digital trae capa de texto con coordenadas. No es OCR y no adivina: pdf.js entrega cada trozo con su x, su y y su tamaño, y eso es información exacta.

Se lee en dos fases, y la primera mira el documento entero

Hay dos decisiones que no se pueden tomar página por página, y tomarlas mal arruina todo lo demás:

Recién en la segunda fase se rasterizan las páginas para recortar las figuras, que es la parte cara.

Qué es una pregunta y qué no

Una prueba trae otras listas numeradas. Las instrucciones de la portada —«1. Lee atentamente cada pregunta», «2. Marca solo una alternativa»— son cinco líneas que empiezan con número, y el importador las tomaba por las cinco primeras preguntas.

El daño no era una pregunta de más: la serie quedaba enganchada en el 5, y las preguntas 1 a 5 de verdad, que empiezan de nuevo en la página siguiente, ya no calzaban con la secuencia y se perdían.

Se eligen las aperturas que forman la mejor cadena creciente del documento completo, y lo que rompe el empate es tener alternativas debajo: una lista de instrucciones no las tiene, una pregunta sí. Así la cadena de las instrucciones —cinco, sin alternativas— pierde contra la de las cuarenta preguntas.

Lo apilado no es una fracción sólo por estar apilado

Una fracción no es un trozo: son dos, uno sobre otro, con una raya vectorial al medio que la capa de texto no trae. Unirlos es necesario —si no, los numeradores y denominadores salen barajados— pero unir de más es peor: dos celdas de una tabla y dos alternativas consecutivas también están una sobre otra y perfectamente centradas.

La separación vertical no los distingue. Medido sobre una prueba real:

CasoSeparación / alto de letra
Fracción de verdad1,25
Alternativas A) y B)1,33
Dos filas de una tabla1,48

Con cualquier umbral que deje pasar la primera pasan las otras dos. Lo que sí distingue es que una fracción vive DENTRO de una línea de texto: su raya queda a la altura de la base del renglón, así que hay otro trozo —«A)», «Camila comió», «<»— cuya y cae justo entre el numerador y el denominador. Entre dos filas de una tabla, o entre dos alternativas, no hay nada: hay papel.

Sin esto, una tabla de «Entrada / Salida» entraba como 12⁄18, 9⁄15, y las cuatro alternativas como dos fracciones. En la prueba de ejemplo, el reconocimiento pasó de 12 preguntas rotas a 40 correctas.

Dos cosas más que la fórmula no debe llevarse
Preguntas pegadas como imagen: el caso más común de todos

Hay pruebas —muchas— donde cada ejercicio se pegó en Word como captura de pantalla. De esas preguntas el PDF trae, en su capa de texto, exactamente un item: el número. El enunciado, la figura y las alternativas son un dibujo.

Medido sobre una prueba real de IV° Medio: de 32 preguntas, 5 tienen texto y 27 son imágenes. Ningún lector puede extraer texto que no fue escrito como texto — copiar y pegar desde Acrobat da exactamente lo mismo. No es un defecto del importador: es el archivo.

Lo que sí era un defecto es cómo se comportaba. Las daba por reconocidas y entraban vacías, sin enunciado y sin alternativas: el profesor importaba 27 cáscaras y lo descubría después. Ahora:

Un cuidado que esto obligó a tomar: el detector de pies repetidos (arriba) no puede tocar una apertura de pregunta. La firma de «6)» es #) —los dígitos se ignoran a propósito— igual que la de todas las demás, así que sin esa salvedad se comía los números de pregunta que caen cerca del borde inferior, y esas preguntas desaparecían del resultado. En la prueba de ejemplo eran 7 de 32.

También desde Word funcionalidad nueva

La mitad de las pruebas de un colegio están en .docx, no en PDF: el PDF es lo que se imprime, el Word es el original que el profesor guarda. Pedirle que exporte a PDF para poder importarlo es pedirle un paso que no entiende para qué sirve.

Lo que cambia es sólo el lector. El reconocimiento —qué línea abre una pregunta, cuál es una alternativa, cuál es el pie que se repite, cuál de las listas numeradas es la de preguntas— es el mismo código para los dos formatos. El lector de Word produce las mismas líneas que produce pdf.js y de ahí en adelante el camino es idéntico, incluida la pantalla de revisión.

Un .docx se lee sin librería

Un .docx es un ZIP con XML adentro, y el navegador ya sabe hacer las dos cosas que hacen falta: DecompressionStream('deflate-raw') infla y DOMParser parsea. Lo único que hay que escribir es la lectura del directorio central del ZIP, que son cuatro desplazamientos fijos. En la maqueta se hizo así por su regla —abre sin internet—, y en el producto también conviene: una dependencia menos que mantener en el webpack.mix.js de un Laravel 5.7.

La trampa que cuesta encontrar: el largo del nombre y del extra del encabezado local de cada archivo no coinciden con los del central —Word escribe cosas distintas en cada uno—, así que el comienzo de los datos hay que calcularlo con los del local. Leerlo del central da bytes corridos y un XML que no parsea.

La prueba word.js corre contra un .docx escrito por Word de verdad, no contra un ZIP armado a mano: con texto, tabla e imagen. Un archivo sintético no habría mostrado esa trampa.

Cuando las alternativas son dibujos

«¿Cuál de los cuerpos geométricos tiene 6 caras cuadradas?», con cuatro figuras rotuladas A) B) C) D) debajo. Entraban como desarrollo con una sola imagen: el alumno ve las cuatro opciones en el papel, pero el sistema no sabe que son cuatro y no hay dónde marcar la clave, así que la pregunta no se podía corregir. En el ensayo de ejemplo son 2 de 40; en pruebas de Geometría de básica son bastantes más.

Las letras no sirven de guía: se midió la capa de texto de esa página y los rótulos A) B) C) D) no están ahí —son parte del dibujo—. Lo único que trae el PDF es el enunciado y la línea «Marca la letra de la imagen elegida». Lo que sí se puede leer es la imagen: las figuras están separadas por blancos verticales, que es como se dibujaron.

El importador recorre la banda de la figura columna por columna, marca cuáles tienen tinta y corta donde hay un blanco ancho. Si salen entre 3 y 6 grupos, son las alternativas: cada uno se recorta en su propia imagen, se les asignan las letras en orden y la pregunta entra como selección múltiple, con su clave por marcar como cualquier otra. Se avisa en la lista previa: «sus alternativas son dibujos: entran como imágenes».

Las dos reglas que deciden, y por qué no son otras

Con esto el ensayo de ejemplo entra completo: 40 de 40 preguntas con sus 4 alternativas, dos de ellas como imágenes.

En el producto, cada recorte es un archivo más: son cuatro por pregunta y van en respuesta_alternativa como URL, con la misma regla que las imágenes del enunciado —§6.2, «Dos formas de poner una imagen»—. En la maqueta van como data: porque no hay servidor.

6.4 Arrastrar y soltar

Dos detalles que se ven al programarlo

6.4.b Un recurso compartido por varias preguntas funcionalidad nueva

«Lee el siguiente texto y responde las preguntas 11 a 14». El texto —o la imagen, o la tabla de datos, o el gráfico— se escribe una sola vez y vale para todas ellas. Es la forma de casi todo ensayo SIMCE y PAES, y de cualquier prueba de comprensión lectora.

Hoy la única manera es copiar el texto dentro de cada enunciado. Eso falla de tres formas, y la tercera es la grave:

  1. Ocupa la hoja cuatro veces. Un texto de media página repetido en cuatro preguntas es una prueba de tres hojas que debería ser de una.
  2. Se corrige en un lugar y queda mal en los otros tres. Una errata detectada el día antes de imprimir hay que arreglarla cuatro veces, y basta olvidar una.
  3. Se rompe al barajar. Al asignar la prueba a un curso, WebClass puede repartir las preguntas en orden distinto para cada alumno. Si el texto vive dentro del enunciado de la pregunta 11, al alumno que la recibe de última le llega el texto al final y las preguntas 12, 13 y 14 antes, apuntando a un texto que todavía no leyó. La prueba deja de tener sentido y nadie se entera hasta que la rinde.
La solución no es prohibir barajar: es declarar un bloque

Estas preguntas pasan a ser una unidad. El bloque entero se puede mover a cualquier posición de la prueba, y las preguntas se pueden revolver dentro de él, pero ninguna sale del bloque y el recurso va siempre delante. Barajar sigue funcionando; lo que cambia es la unidad que se baraja.

Eso es una restricción que viaja con la prueba, no una decisión de esta pantalla: la respeta quien la aplique. Acá el gadget hace dos cosas —dejar armar el bloque y garantizar que las preguntas de un recurso queden siempre contiguas y detrás de él—; el que baraja tiene que leer esa marca. Si no la lee, el problema vuelve.

Cómo se usa

Dos cosas que se ven al programarlo
En la base: el mecanismo existe, pero hoy sólo guarda un archivo

El vínculo ya existe y se llama pregunta.idrecurso —sin guion bajo—. Verificado en el código del producto: apunta a la tabla archivo, y lo que se lee de ahí es la URL y la extensión del archivo.

// EvaluationsController
->leftJoin('archivo as a', 'p.idrecurso', '=', 'a.id')
->select( … 'a.url as url_archivo', 'a.archivo_extension', … )

archivo es la biblioteca de Recursos del colegio: tiene nombre, autor, niveles, etiqueta, material, colegio, visible. Es un catálogo de archivos, no un lugar donde escribir texto.

Consecuencia directa: el recurso compartido de hoy sirve para una imagen. Para un texto —que es el caso de comprensión lectora, el más común de todos— falta dónde guardarlo. La versión anterior de este documento decía que esta funcionalidad «no agrega nada a la base»; era falso y está corregido acá.

Dónde guardar el texto: hay que decidirlo

Lo que NO hay que hacer es guardar el texto como un archivo en archivo —un .html o una imagen del texto—. Tres motivos, y el tercero es el que manda:

  1. archivo es una biblioteca que el colegio ve y ordena. Llenarla de fragmentos sueltos de pruebas la vuelve inservible para lo que es.
  2. Un texto dentro de un archivo no se busca con SQL ni se edita en la pantalla: hay que bajarlo, abrirlo y volver a subirlo.
  3. Un texto como imagen no se puede agrandar, no lo lee un lector de pantalla y no se reflowea. Choca de frente con lo que este mismo documento pide en §5.3 para un alumno con discapacidad visual: cuerpo 14 o mayor. Sería resolver una cosa rompiendo otra.

Decidido por WebClass el 23-09: la tabla propia. Se describe primero; la otra queda anotada sólo para dejar dicho por qué se descartó.

Queda por definir un detalle menor de la tabla elegida: si el estímulo es del colegio —y entonces reutilizable entre profesores, como el banco— o del profesor que lo escribió. La columna colegio de arriba asume lo primero, que es lo coherente con el banco de items.

El clon del producto no trae las migraciones, así que las columnas de archivo salen de las consultas y de los modelos, no del esquema. Confirmarlo contra producción antes de escribir la migración.

Lo que sí se aprovecha tal cual: el vínculo va en la pregunta

Que el vínculo viva en pregunta y no en prueba_preguntas es lo que hace útil al banco, y eso no cambia sea texto o imagen: el recurso viaja con la pregunta. Una pregunta que dice «en el fragmento leído» no significa nada sin el fragmento; atado a la pregunta, se la trae a cualquier prueba y el texto llega con ella. Si el vínculo viviera en la prueba, esa misma pregunta entraría huérfana y habría que pegarle el texto a mano cada vez.

En la maqueta se ve: el banco tiene tres preguntas de Lengua que comparten un fragmento —van marcadas «📄 con su texto»—. Al traerlas, entra un texto y no tres copias, y quedan agrupadas solas.

El barajado de hoy rompe el bloque, y ya se sabe dónde

La pregunta abierta de «quién baraja» tiene respuesta. Está en test.barajar y test.barajar_resp, y el reparto por alumno es literalmente esto:

$preguntas = $barajarPreguntas == 1 ? $preguntas->shuffle() : $preguntas;

Un shuffle() plano sobre todas las preguntas del test. No sabe que existe idrecurso, así que con el barajado encendido un estímulo compartido queda separado de sus preguntas — que es exactamente el problema que esta funcionalidad viene a resolver.

Ahí hay que barajar por bloques: agrupar las preguntas por su recurso, revolver los grupos entre sí y las preguntas dentro de cada grupo, y volver a aplanar. Son pocas líneas en el mismo lugar, pero sin eso la funcionalidad no sirve, y el archivo está identificado: MobileApp/Evaluations/EvaluationsController — hay que revisar si el render web tiene su propia copia de esa lógica.

Lo que el generador agrega sobre ese mecanismo

Si el motor ya muestra el recurso una vez al llegar a la primera pregunta que lo usa, ¿para qué forzar que estén contiguas? Porque «una vez, en la primera» y «justo antes de todas» sólo coinciden si no hay otra pregunta en medio. Con las preguntas 11, 14 y 19 apuntando al mismo texto, el alumno lee el texto en la 11 y tiene que volver dos páginas atrás en la 19.

El gadget garantiza la contigüidad —mete la pregunta junto al bloque— para que lo que se imprime sea lo que el motor asume. No es una restricción nueva sobre la base: es no producir pruebas que el mecanismo soporta pero que se leen mal.

6.5 Categorización — el carril de la derecha

Cada pregunta tiene, a su derecha y alineada con ella, una tarjeta con tres estados: Categorización y Retroalimentación. Cada uno se marca solo cuando está completo, así se ve de un vistazo qué falta. Hay además una banderita para marcar una pregunta y volver a ella.

Al hacer clic se abre un cajón lateral. Los campos de categorización:

El orden sigue el del currículo: primero dónde se busca —nivel, asignatura, eje— y después qué se eligió ahí dentro —objetivo, indicador—. Con el eje debajo del objetivo, el filtro aparecía después de lo filtrado y no servía de nada.

CampoOrigenObligatorio
NivelPor defecto el de la evaluación, editable (ver abajo)Sí
AsignaturaPor defecto la de la evaluación, editableSí
Eje temáticoSale del propio catálogo de ese nivel + asignatura, no de una lista aparte. Filtra los objetivosNo
Objetivo de aprendizajeCatálogo Mineduc filtrado por nivel + asignatura + eje → pregunta_atributoSí
Indicador de evaluaciónindicadores, filtrado por el OA elegido → pregunta_indicadorSí
HabilidadConocer / Comprender / Aplicar / Analizar / Evaluar / CrearNo
Dificultad estimadaBaja / Media / Alta → pregunta.dificultadNo
PuntajeNumérico, por preguntaSí

Las seis primeras filas —de nivel a habilidad— se repiten una vez por objetivo: una pregunta puede declarar varios. Ver §6.5.b. La dificultad y el puntaje, en cambio, van una sola vez por pregunta.

No hay campo de etiquetas libres. Estuvo y se quitó: para filtrar el banco de items ya están el objetivo, el indicador, la habilidad, el eje, la dificultad y el nivel —todos de catálogo y todos comparables entre colegios—. Un texto libre al lado se llena distinto en cada sala («u3», «Unidad 3», «unidad III») y termina siendo ruido en el buscador en vez de un filtro.

Nivel y asignatura son de la PREGUNTA, no sólo de la prueba

Vienen puestos con los de la evaluación, pero se pueden cambiar. No es un lujo: un recuperativo casi siempre arrastra contenido del nivel anterior, y un control de síntesis mezcla ejes de varias unidades. Obligar a que el objetivo sea del mismo nivel que la prueba sería mentir sobre lo que la pregunta mide, y la cobertura curricular quedaría mal calculada.

En consecuencia, pregunta_atributo tiene que guardar el objetivo con su nivel, no deducirlo de la prueba. Y hoy no lo guarda, verificado en el código del producto: el INSERT es (pregunta, eje, tipo, atributo) y el nivel sale de prueba.sector → sector.nivel. Así que esto es un cambio de modelo, no sólo de pantalla, y es el único de todo el documento: está encabezando el §11.

Cuando la pregunta se aparta del nivel o la asignatura de la evaluación, la pantalla lo dice en naranjo: es una decisión válida, pero no debe pasar por accidente.

Cambiar el nivel o la asignatura limpia eje, objetivo e indicador, y se avisa: apuntan a un catálogo que ya no es el vigente, y dejarlos produciría combinaciones que no existen en ningún currículo. Por lo mismo, al cambiar el OA se limpia el indicador.

Al revés, elegir un objetivo completa el eje solo: el eje es un dato del objetivo, no una etiqueta que el profesor tenga que recordar.

6.5.b Una pregunta puede medir varios objetivos funcionalidad nueva

Hoy la pantalla deja declarar un objetivo por pregunta, y eso no alcanza. Un problema de área que se resuelve con una ecuación cuadrática mide geometría y álgebra; una pregunta de un recuperativo mide un objetivo del año anterior junto con el del año en curso. Con un solo casillero, el profesor tiene que elegir cuál declarar, y la tabla de especificaciones queda contando de menos justamente en las preguntas más ricas.

El cajón pasa a tener una tarjeta por objetivo, cada una con su nivel, asignatura, eje, objetivo, indicador y habilidad completos, más un botón «+ otro objetivo» y una × por tarjeta. Todas las reglas de §6.5 —el eje filtra, cambiar el nivel limpia lo de abajo, elegir el objetivo completa el eje, lo ajeno se marca en naranjo— siguen valiendo dentro de cada tarjeta, por separado.

El puntaje se reparte entre los objetivos; no se cuenta dos veces

Una pregunta de 3 puntos que mide dos objetivos aporta 1,5 a cada uno en la tabla de especificaciones. Sumarla entera en los dos haría que la columna de puntos diera más que el total de la prueba y que los porcentajes pasaran de 100: la tabla dejaría de servir para ver el equilibrio, que es para lo único que existe.

En la planilla exportada eso se ve como una fila por objetivo, con el puntaje de la pregunta y el que le toca a ese objetivo en columnas distintas. La segunda es la que suma el total.

En la base de datos esto ya calza: no hay migración

pregunta_atributo y pregunta_indicador son tablas de relación N:M —llave compuesta, una fila por pregunta y atributo—. Siempre admitieron varios atributos por pregunta. El límite de uno solo estaba en la interfaz, no en el modelo.

Lo que hay que cambiar, entonces, no es el esquema sino el guardado: hoy se escribe una fila y se reemplaza; tiene que escribirse el conjunto de filas de la pregunta y borrarse las que ya no están. La única pregunta abierta es la de §6.5: si el nivel del atributo se guarda o se deduce de prueba —con varios objetivos de niveles distintos, deducirlo deja de ser posible—.

6.5.c El objetivo propio, fuera del catálogo

No es nuevo en WebClass: hoy el profesor le puede poner a una pregunta un objetivo que no está en el catálogo, y queda en pregunta_atributo_adicional (id, pregunta_id, tipo, caracteristica) con caracteristica en texto libre. Verificado en el vanilla: los informes lo leen (test_informe, informepme), el logro lo cuenta —EvaluacionDao tiene la misma consulta con esta tabla en vez de pregunta_atributo— y se copia al duplicar la pregunta. Lo que faltaba era que el generador lo ofreciera.

En el cajón, junto a «+ Otro objetivo», va «+ Objetivo propio». La tarjeta que agrega pide dos cosas y nada más:

Sin nivel, sin eje, sin indicador: la tabla no tiene esas columnas y pedirlos sería inventarlas. Por lo mismo un objetivo propio nunca se marca como ajeno: su nivel es el de la prueba.

El informe agrupa por el texto exacto: la pantalla tiene que evitar que se escriba dos veces

atributosDao::mostrarAtributosAdicionalesDeLasPreguntasDeLaEvaluacion hace GROUP BY paa.caracteristica. «Comunica su procedimiento» y «comunica su procedimiento.» son, para el informe, dos objetivos con la mitad de las preguntas cada uno, y el logro de los dos es mentira. Con texto libre eso no es un caso raro: es lo que pasa por defecto.

Por eso la tarjeta ofrece los que el colegio ya usa —los de la prueba primero, después los de otras preguntas del mismo nivel y asignatura— para elegirlos con un clic, y si se escribe uno que sólo difiere en mayúsculas, tildes, espacios o el punto final, se adopta el existente y se avisa. La comparación es ésa y no más: «modela funciones» y «modela con funciones» siguen siendo dos, porque decidir que son el mismo ya es corregirle el objetivo al profesor.

Para el desarrollo

El guardado es el mismo cambio que pide §6.5.b para pregunta_atributo: escribir el conjunto de filas de la pregunta y borrar las que ya no están. La lista de «ya usados» sale de un SELECT DISTINCT tipo, caracteristica sobre las preguntas del colegio en ese nivel y asignatura —el nivel se deduce de la prueba, porque la tabla no lo guarda—. Conviene normalizar al guardar (espacios repetidos y en los extremos): es gratis y ya evita la mitad de los duplicados.

6.6 Retroalimentación

La pestaña se llamaba «Explicación» y ofrecía un campo de texto. Al revisar el producto resultó que WebClass ya guarda siete textos de retroalimentación por pregunta, y que el nombre correcto es el suyo. Relevado en App\Pregunta, Api/ScormController y los Objetos/Respuesta_*.php del vanilla:

ColumnaCuándo se muestra
pregunta.retroalimentacionSiempre, gane o pierda. Es el «por qué» de la pregunta y lo que va en la pauta del docente.
pregunta.retrocorrectaSi responde correcto.
pregunta.retroparcialSi responde parcialmente correcto.
pregunta.retroincorrectaSi responde incorrecto.
respuesta_vof.retroalimentacionV
respuesta_vof.retroalimentacionF
Según marque Verdadero o Falso. Dos textos distintos, no uno.
respuesta_alternativa.retroalimentacionPor cada alternativa, incluida la correcta.
respuesta_corta.retroalimentacionPor cada respuesta aceptada.
«Distractores»: la palabra significa dos cosas y sólo una existe

La maqueta tenía una pestaña Distractores para anotar, por cada alternativa incorrecta, qué error comete quien la elige. Se quitó: se buscó la palabra en todo el producto y no hay ninguna funcionalidad con ese nombre.

Peor: donde sí aparece, significa una cosa distinta. En el editor de términos pareados (editarPreguntas.php, controladorPregunta.php) un «distractor» es un concepto de la columna B que no tiene pareja — una opción señuelo en un emparejamiento, que se guarda con vinculo_a = -2. Nada que ver con analizar el error de una alternativa. Y en varios archivos el control está comentado, así que ni siquiera se usa completo.

Lo que sí se conserva es la retroalimentación por alternativa, porque respuesta_alternativa.retroalimentacion es una columna real. Vive ahora dentro de esta misma pestaña, como un grupo más: es el mismo dato, llamado como lo llama el producto. También se fue la herramienta de IA «Proponer distractores».

El distractor de verdad —el señuelo sin pareja— sí entra al gadget. Es el único de los dos sentidos que existe en el producto, hace más exigente el ejercicio, y el control ya está a medias en editarPreguntas.php: hay que descomentarlo y terminarlo, no inventarlo. Ver Términos pareados para el comportamiento y el modelo de datos.

Dos hallazgos que cambian el alcance

1. La retroalimentación ya es condicional en la base, pero no en la pantalla. Tener retrocorrecta, retroparcial y retroincorrecta significa que el producto ya contempla que el alumno lea algo distinto según lo que respondió, que es lo que convierte a la retroalimentación en algo formativo y no en una pauta escondida. Ofrecer un solo campo dejaba tres columnas sin usar.

2. retroparcial confirma el puntaje parcial. Que la columna exista es evidencia de que la corrección parcial está contemplada — lo que sostiene el tipo de varias correctas con porcentaje (§6.3.a). En la maqueta ese campo sólo aparece en los tipos que reparten puntaje: varias correctas, pareados y respuesta corta. Mostrarlo en una de una sola correcta sería pedir un texto que nunca se va a mostrar.

En pregunta hay además tres columnas que parecían gobernar el puntaje. Se fueron a mirar al código y ninguna lo hace:

Lo último deja un hueco chico en este gadget: correccion es un campo por pregunta que el producto ya tiene y que el editor no ofrece. Para las de desarrollo lo cubre la rúbrica (§6.4), que es mejor; para los demás tipos, hay que decidir si se rescata o se da por reemplazado. No se inventó nada para llenarlo: escribir ahí sin saber quién lo lee sería peor.

6.7 Dos pestañas

PestañaContenido
ContenidoEl editor. Es la pestaña por defecto y donde se pasa el 95% del tiempo.
EspecificacionesSe arma sola con lo categorizado: OA → indicador → nº de preguntas, puntos y % del total. Las preguntas sin categorizar salen destacadas en una fila propia, no escondidas.
Por qué no hay pestaña «General»

Tenía título, nivel, asignatura, tipo, exigencia e instrucciones. Al revisarla campo por campo, casi nada correspondía estar ahí:

6.9.b El banco de items funcionalidad nueva

Es lo que justifica económicamente el gadget. Un profesor escribe unas 40 preguntas al año y al año siguiente las vuelve a escribir. Reusar gana lejos sobre generar, y hoy el camino más rápido para armar una prueba es digitalizar el PDF del año pasado —teniendo esas preguntas en la base de datos—.

El dato que un banco tiene y una pregunta nueva no puede tener

Cada item muestra cuántas veces se aplicó y su % de logro. Eso es lo que permite armar una prueba equilibrada en vez de una donde todo resultó difícil, y es información que ya existe: sale de las respuestas de alumnos que el producto guarda en respuesta_*_alumno. Un banco sin esa columna es sólo una carpeta de preguntas viejas.

Se busca por atributo, no por palabra del enunciado

El campo de búsqueda por texto se sacó. Nadie recuerda con qué palabras redactó una pregunta hace un año —y si las recordara, no necesitaría buscarla—. Lo que el profesor sí tiene claro es qué quiere medir, y eso es justamente lo que el banco guarda en pregunta_atributo y pregunta_indicador.

Los filtros encadenan igual que la categorización: el eje acota los objetivos, el objetivo acota los indicadores, y cambiar uno de arriba suelta los de abajo. Un profesor que ya sabe categorizar no tiene que aprender otra mecánica.

Cada opción dice cuántos items tiene detrás —«MA2M OA 03 — Ecuaciones cuadráticas (5)»— y las que tendrían cero no se ofrecen. Un selector con los 30 objetivos del año, de los cuales 26 no tienen ni una pregunta, obliga a ir probándolos uno por uno; con la cuenta al lado, el profesor ve de una dónde hay material y dónde va a tener que escribir.

Consecuencia para el desarrollo: la consulta del banco necesita un conteo agrupado por cada atributo, no sólo la lista filtrada. Son dos consultas, no una.

6.10 Cambiar el nivel, la asignatura o el tipo después de crear

Los tres se eligen al crear la evaluación y quedan en ⚙ Opciones › La evaluación, arriba de todo. Equivocarse de nivel y tener que rehacer la prueba entera es el problema más caro de los que hay en juego acá, más caro que cualquiera de los que trae el cambio.

Qué pasa con las preguntas ya categorizadas: nada se borra

Esta era una pregunta abierta y ahora tiene respuesta. Las tres salidas posibles eran descategorizar, bloquear el cambio u ofrecer un mapeo. La que se toma es una cuarta, que el gadget ya habilitó sin querer: conservar y avisar.

Desde que la categorización de cada pregunta admite atributos de otros niveles y asignaturas (§6.5), una pregunta con un OA de 2° Medio dentro de una prueba de 1° Medio no es un error: es un caso que ya se soporta y se muestra marcado como ajeno. Cambiar el contexto, entonces, no rompe nada.

Detalle de implementación, y no es menor. Una pregunta guarda su nivel y asignatura sólo cuando son distintos de los de la prueba; si no, los hereda. Al cambiar el contexto hay que fijárselos antes, con el valor viejo. Sin eso, todas las preguntas pasan a «pertenecer» al nivel nuevo en silencio —aunque su OA siga siendo del anterior— y el descalce que se quiere avisar desaparece justo en el momento en que aparece. Es un fallo que no da ningún síntoma: se ve todo bien y la tabla de especificaciones queda mintiendo.

Por qué no hay pestaña «Formas»

Generaba formas equivalentes barajando el orden de preguntas y alternativas, con su pauta. Se sacó del alcance de este gadget.

No es que sobre: es que es otra funcionalidad. Barajar tiene sentido cuando la prueba se aplica, y la aplicación —asignar a un curso, fijar fecha y hora, corregir— vive en otra parte de WebClass. Mezclarla con la autoría hacía que este gadget tuviera dos dueños y dos momentos de uso distintos.

También desapareció la herramienta de IA «Generar una forma equivalente», que apuntaba a esa pestaña.

6.8 La barra del editor: una sola línea

Al centro, en la misma línea, las cuatro pestañas y después de un separador los dos botones que abren cajón: ⚙ Opciones y ✨ Herramientas de IA. A la derecha, Descargar y Guardar — son lo que se hace al terminar y la relación entre ellas importa (§6.9).

No hay una segunda fila de menú. Es alto robado a la hoja, que es lo único que el profesor necesita mirar. El separador marca la diferencia entre las dos mitades: a la izquierda se cambia de vista, a la derecha se abre un cajón. Cuando la ventana es angosta, pestañas y botones bajan juntos a una segunda fila: separarlos reinventaría el menú que se acaba de eliminar.

EntradaQué tiene
⚙ Opciones Encabezado de la primera hoja: insignia del establecimiento y casillas de la ficha del alumno — nombre y apellido, curso y fecha (§6.8.b).
Vista del editor: ver saltos de página.
Texto: tipografía y tamaño base.
La hoja: tipo de hoja (A4, Carta, Oficio), márgenes (1,5 / 2 / 2,5 cm) y columnas para las alternativas.
✨ Herramientas de IA§7.
Cinco decisiones sobre esta barra

«Ver saltos de página» apagado muestra una tira continua, cómoda para escribir seguido. La pantalla lo advierte: con los saltos apagados el editor deja de coincidir con la impresión.

6.8.b El encabezado de la hoja

Qué llevaDónde
Insignia del establecimientoArriba a la izquierda.
Título de la evaluaciónCentrado, y nada debajo.
Ficha del alumnoConfigurable: qué casillas hay, cómo se llaman y en qué orden. Ver §6.8.c.
InstruccionesEn su recuadro, editables sobre la hoja.
Lo que se sacó del encabezado, y por qué

6.8.c Las casillas que llena el alumno son configurables funcionalidad nueva

Eran tres interruptores fijos —nombre, curso, fecha— y cada colegio pide alguno más: RUT, sala, número de lista, firma del apoderado, puntaje obtenido. Con una lista cerrada, el que necesita otra casilla la dibuja a mano sobre la fotocopia.

Ahora es una lista: se ocultan las que no se usan, se agregan otras del catálogo de WebClass, se crean propias con el nombre que se quiera, se reordenan arrastrando y cada una elige su ancho.

Se abre desde la propia ficha, no desde Opciones

Un clic sobre las casillas de la hoja abre el modal. Es el lugar donde el profesor está mirando justo cuando se da cuenta de que le falta el RUT; un interruptor guardado en otro cajón no se encuentra. En Opciones queda sólo un atajo, para quien lo busque ahí.

De fábrica o propio: la diferencia no es cosmética

Los campos de fábrica —Nombre, Apellido, Curso, Fecha, Puntaje, Nota, Profesor, N° de lista— llevan un id estable y se marcan en el modal como «de WebClass». Los que crea el profesor son texto libre y no lo llevan.

Importa porque el día que WebClass imprima una copia por alumno con el nombre y el curso ya puestos, sólo va a poder rellenar los que reconoce. Un campo propio siempre va a quedar en blanco: es una casilla dibujada. Eso se dice en el modal, no se deja para que lo descubran.

Con más de tres casillas la ficha pasa a dos filas y el rótulo se corre al costado izquierdo, que es como se llena una ficha en papel: en una sola fila, cuatro campos quedan tan angostos que el alumno escribe encima del de al lado.

Dónde se guarda: una columna JSON en prueba, no una tabla
ALTER TABLE prueba ADD COLUMN encabezado TEXT NULL DEFAULT NULL;
// App\Prueba
protected $casts = ['encabezado' => 'array'];

Esto no son datos de la evaluación: es cómo se imprime el documento. Nadie va a consultar nunca «dame todas las pruebas que tienen campo RUT», ni cruzarlo con nada. Normalizarlo en prueba_campo_encabezado(id, id_prueba, etiqueta, orden, ancho, visible) cuesta una tabla, un modelo, un join en cada lectura y un borrado en cascada, y no compra ninguna consulta que se vaya a escribir. Es la clase de tabla que se crea por prolijidad y después nadie usa.

NULL significa «los de siempre», así que la gran mayoría de las filas queda vacía y no ocupa nada.

{"logo":true,
 "datos":false,            <-- la linea bajo el titulo
 "campos":[
  {"id":"nombre","visible":true,"ancho":"ancho"},
  {"id":"curso","visible":false},
  {"id":"c1","etiqueta":"RUT","ancho":"corto"}
]}

Los dos interruptores del encabezado —la insignia y la línea de datos bajo el título— van en el mismo JSON y por la misma razón: describen cómo se ve esta hoja y no se consultan nunca. Nadie va a preguntar «cuántas pruebas llevan la insignia».

Dos decisiones que van con eso

El nombre y las instrucciones se editan en la hoja

El nombre de la evaluación tenía un campo en la barra superior y se quitó. Era el mismo dato en dos lugares, y el de arriba ni siquiera lo mostraba con la tipografía con que se va a imprimir: se escribía a ciegas. Ahora se edita sobre el título de la hoja, que es donde el profesor lo va a leer. La miga de pan lo sigue mientras se escribe.

Ese campo no abre el editor de texto: se escribe directo sobre la hoja. Un nombre es un rótulo, no un párrafo —ofrecerle negrita, tipografía, fórmulas, tablas y gráficos es ruido— y abrir un modal para teclear cuatro palabras sería peor que el problema que resuelve. Lo mismo vale para los términos pareados y las respuestas aceptadas. Ver §6.2.

Es el texto que más se retoca —cambia con cada prueba— y mandarlo a un formulario aparte era un rodeo para tres palabras. Ahora se escriben sobre la hoja, igual que el enunciado de una pregunta, y ese es el único lugar donde se editan.

Cuando quedan vacías, en el editor se ve un texto guía en gris —si no, no habría dónde hacer clic para volver a escribirlas— pero al imprimir el recuadro desaparece.

6.9 Guardar y Descargar

El botón principal dice Guardar, no «Publicar»: en WebClass una evaluación no se publica — se guarda, y después se asigna a un curso, que es otra acción y de otro módulo. Al lado va Descargar.

Al guardar hay dos niveles, y la diferencia importa:

Qué faltaQué pasa
Alguna pregunta sin la clave completa (§8.b) No deja guardar. No hay «guardar igual».
No hay ninguna pregunta No deja guardar.
Preguntas sin objetivo de aprendizaje o indicador Avisa y guarda igual; la prueba queda marcada como incompleta y no entra al banco de items.
Preguntas generadas por IA sin revisar Igual que la anterior.
Sin clave no se guarda — y es a propósito

Una evaluación sin respuestas correctas no se puede corregir, y una evaluación que no se puede corregir no sirve de nada guardada: no tiene pauta y no se puede aplicar en línea. Es la única regla del gadget que no admite «guardar igual».

Para que no sea una pared ciega, el aviso es accionable:

8.b Qué es «clave completa» en cada tipo

Cada tipo tiene su propia idea de estar listo, así que la regla vive en el catálogo de tipos y no repartida en condiciones sueltas por el código. Agregar un tipo nuevo es agregar una fila acá, no buscar todos los if que hablaban de «desarrollo».

TipoEstá listo cuando…
Selección múltiple · V/F · V/F con justificación · recorte Hay una alternativa marcada correcta.
Selección múltiple con varias correctas Hay al menos una correcta y los porcentajes suman 100%.
Términos pareados Hay al menos dos pares, ninguno tiene una columna vacía y ningún distractor quedó sin texto.
Respuesta corta Hay al menos una respuesta aceptada con texto.
Desarrollo sin rúbrica Siempre. Se corrige a mano; no hay clave que exigir.
Desarrollo con rúbrica Los criterios suman el puntaje de la pregunta, ninguno está sin nombre y ninguna celda sin descriptor.
No se puede descargar sin guardar

La descarga se genera desde la versión guardada, no desde lo que hay en pantalla. Con cambios sin guardar, el PDF no coincidiría con lo que el profesor está viendo — y ese PDF es el que se imprime y se le pasa al curso.

La clave se decide al descargar, no antes

Al pulsar Descargar hay que elegir entre dos archivos:

Antes esto era un interruptor de Opciones («marcar respuesta correcta») que apagaba las marcas en pantalla. Era el control equivocado en el lugar equivocado: mientras arma la prueba el docente siempre quiere ver cuál es la correcta —es lo que está decidiendo— y lo que en realidad necesita elegir es qué sale en el papel.

Y tenía un modo de fallo caro: dejarlo encendido y olvidarlo significaba imprimirle al curso la prueba con las respuestas. Un interruptor persistente que hay que acordarse de apagar antes de cada impresión es una trampa; una pregunta en el momento de generar el archivo, no.

En el editor la clave se ve siempre. Durante la generación se cambia la vista, se genera y se deja como estaba: si el editor quedara sin las marcas, el docente creería que se le borraron.

6.11 Qué le pareció la pregunta al profesor funcionalidad nueva

Cada pregunta que propuso la plataforma —traída del banco o generada por IA— muestra en su carril dos pulgares: 👍 la volvería a usar y 👎 no me gusta, cámbiala.

Es el dato que WebClass no tiene y más vale

Hoy el banco crece sin que nadie sepa qué parte de él sirve: una pregunta mal redactada o con dos respuestas correctas sigue ofreciéndose a todos los profesores del país hasta que alguien la reporta por otro canal. Y la IA vuelve a proponer lo mismo que ya rechazaron, porque nadie le dijo que lo rechazaron.

Con el pulgar, esa señal queda: qué preguntas se reusan y cuáles se descartan, quién lo dijo y para qué objetivo.

Lo elegido queda a la vista, no sólo hundido

Dos pulgares grises uno al lado del otro no dicen cuál se apretó: hay que acordarse. Con veinte preguntas en la prueba, eso es justo lo que no se puede pedir. Así que lo elegido se pinta: amarillo el pulgar arriba, rojo el pulgar abajo, el otro se apaga para que en el carril haya una sola respuesta a la vista, y el rótulo dice en palabras lo mismo que dice el color —«La volverías a usar» / «No te gustó»—, porque el color solo no basta para quien no lo distingue.

Sólo se pregunta por lo que la plataforma propuso

Una pregunta que el profesor escribió él, o que importó de su propio PDF, no pide valoración. Pedirle que califique lo suyo es pedirle que se califique solo: no dice nada de la plataforma y ensucia el dato justo donde se lo quiere limpio.

El pulgar abajo no es sólo una queja: viene con el reemplazo

Lo que se cambia no se borra del banco. Que a un profesor no le sirva no es motivo para retirarla; que se lo digan varios, sí — y esa decisión no es de una prueba, es del establecimiento o de WebClass.

Dónde se guarda: acá sí corresponde una tabla
CREATE TABLE pregunta_valoracion (
  id          INT AUTO_INCREMENT PRIMARY KEY,
  id_pregunta INT      NOT NULL,
  id_usuario  INT      NOT NULL,
  id_prueba   INT      NULL,        -- en qué prueba se opinó
  valor       TINYINT  NOT NULL,    -- 1 la volvería a usar · -1 no me gusta
  creado      DATETIME NOT NULL,
  UNIQUE KEY uq_opinion (id_pregunta, id_usuario)
);

Contraste deliberado con §6.8.c, donde las casillas del encabezado van en una columna JSON: aquello es cómo se imprime un documento y nadie lo consulta; esto se consulta y se agrega —«las 20 preguntas más descartadas de Matemática 2° Medio»—. Un dato que se agrupa gana su tabla; uno que sólo se lee junto con su fila, no.

La clave única (id_pregunta, id_usuario) es lo que hace utilizable el dato. Sin ella, un profesor que reusa la misma pregunta en cinco pruebas cuenta cinco veces, y el ranking termina midiendo quién reusa más, no qué pregunta es mejor. Volver a opinar actualiza su opinión.

id_prueba queda como contexto —sirve para saber si la descartaron en un recuperativo o en una prueba de unidad—, pero la opinión es de la pregunta, no de la prueba: por eso no cuelga de ella.

La pregunta de IA que se descarta se guarda igual — decidido

Una pregunta generada todavía no existe en la base: no tiene id_pregunta hasta que la prueba se guarda. Y la que el profesor descarta nunca llegaría a guardarse — justo la que más interesa registrar, porque es el único rastro de qué produjo la IA y fue rechazado. Sin ella, la señal más valiosa se pierde en el momento exacto en que se produce.

Se guarda igual, marcada como descartada y sin quedar colgada de la prueba: no es una pregunta de esa evaluación, es un registro de lo que la plataforma propuso. Con eso tiene id, la valoración apunta a algo inspeccionable, y se puede responder la pregunta que importa: qué está generando la IA que los profesores no aceptan.

pregunta.visible = 0 sí sirve para esconderla, verificado: la consulta que arma la prueba del alumno filtra por p.visible = 1 (AlumnoTestDao::getPreguntasPorIdTest), así que una descartada no llega a nadie. Lo que falta confirmar es si una pregunta sin fila en prueba_preguntas rompe algo del módulo viejo —el listado del banco, los informes—. Si rompiera, la salida es una tabla aparte para descartes, con el texto y los atributos con que se pidió, sin tocar pregunta.

La marca de «descartada» no se muestra en pantalla: es un dato para la plataforma. Una pregunta que el profesor no sólo no volvería a usar sino que sacó de la prueba pesa más que un pulgar abajo, y esa diferencia sólo la puede usar quien revise el banco.

7Herramientas de IA y tokens

Todas las acciones de IA descuentan de una bolsa de tokens del establecimiento, que el WebClass manager del colegio reparte entre sus profesores (más abajo). Lo que el profesor ve en el cajón lateral, en todo momento, es su cupo.

HerramientaQué haceCosto de referencia
Generar preguntas desde un OA o una habilidadPropone preguntas con sus alternativas, desde el cajón o desde la tabla (§5.2)40 por pregunta
Categorizar automáticamenteAsigna OA e indicador a las que no tienen25 por pregunta
Redactar la retroalimentaciónEscribe la general y las de correcto e incorrecto, en un paso35
Mejorar la redacciónAjusta el enunciado al nivel lector del curso20
Generar una imagen
sólo desde la barra del editor de texto
Crea la figura, el esquema o la ilustración descrita y la inserta donde está el cursor150

7.a El generador de preguntas pregunta sobre qué

Antes tomaba «algún OA del nivel de la prueba» sin preguntar. Eso servía para una demo y para nada más: lo primero que hace un profesor es decidir sobre qué quiere las preguntas. El formulario pide nivel y asignatura —con los de la evaluación puestos por defecto—, después el objetivo, y opcionalmente el indicador, además de cuántas, de qué tipo y con qué dificultad.

La clave de lo generado se reparte entre las letras

Un generador que deja la respuesta en la primera alternativa produce pruebas con la clave AAAA…, y eso el alumno lo descubre antes que el profesor. Las alternativas se revuelven después de armarlas: el texto de cada una dice qué error representa, así que el orden da lo mismo salvo por esto.

En V/F no se revuelve —«Verdadero» va primero, siempre— pero sí se alterna cuál es la correcta: si no, todas las generadas se responden «verdadero», que es el mismo vicio con otra forma.

El reparto es determinista, no al azar: sale del número de pregunta, para que dos miradas a la misma prueba den lo mismo. Y no basta con que «varíe»: alternar B, D, B, D también varía y sigue siendo un patrón. Con cuatro alternativas, la correcta tiene que recorrer las cuatro letras.

Este es el generador del cajón, para agregar preguntas a una prueba que ya existe: pide un objetivo y agrega unas pocas. La tabla de §5.2 es el mismo motor pero al crear, con varias filas, su reparto por tipo y la posibilidad de traer del banco. Conviene que compartan el endpoint y el registro de consumo, y que se diferencien sólo en el formulario. El endpoint tiene que aceptar además el caso sin objetivo —la fila comodín de §5.2—, donde el objetivo lo elige y devuelve el servidor: la pregunta vuelve categorizada, no en blanco.

7.b El generador de imágenes

No se lista en el cajón de Herramientas de IA. Vive sólo en el botón 🎨 de la barra del editor de texto, al lado del de subir una imagen. El motivo es concreto: una imagen se inserta donde está el cursor, y desde un cajón lateral no hay cursor al que apuntar —terminaba cayendo al final del enunciado—. Igual sigue en el catálogo de herramientas por dentro, porque el precio y el registro de consumo tienen que salir de un solo lugar.

El formulario pide qué se tiene que ver, un estilo (esquema o diagrama, ilustración, línea de tiempo, gráfico de datos) y una proporción. Genera, muestra la vista previa, y recién ahí se inserta.

«Siempre en los márgenes de lo educacional» — dónde va ese límite de verdad

El límite se declara antes de generar, en el propio formulario: no produce armas ni explosivos, violencia explícita, contenido sexual, drogas, autolesiones ni marcas comerciales, y no reproduce personas reales identificables. Declararlo antes evita que el profesor gaste 150 tokens en algo que no va a salir.

El filtro del navegador no es el filtro. En la maqueta la revisión corre en el cliente porque no hay servidor, pero cualquiera abre la consola y la saltea. En el producto el control va en tres capas, y las tres son necesarias:

  1. En el cliente, sólo como aviso temprano y ahorro de tokens.
  2. En el servidor, antes de llamar al proveedor. Es la que manda. La petición rechazada no se cobra y queda registrada en ia_consumo con exito = 0.
  3. La política del proveedor, que rechaza por su cuenta. Hay que traducir su error a un mensaje que diga qué corregir, no un «solicitud rechazada» que deja al profesor adivinando.

Las personas reales son un caso aparte y se trata como aviso, no como veto: «un retrato de O’Higgins» es material de aula perfectamente válido y sale como ilustración, no como retrato fiel; una persona viva identificable no se genera. Meterlo en la lista de veto habría bloqueado medio programa de Historia.

Falta definir con el negocio: quién responde si igual pasa algo inapropiado —¿se revisa antes de imprimir, se puede reportar una imagen, queda un registro que UTP pueda mirar?—. Y si el establecimiento puede apagar el generador de imágenes dejando el resto de la IA encendida.

Reglas del sistema de tokens
  1. El costo se muestra antes de gastar, y si no alcanza se dice cuánto falta en vez de fallar con un error genérico.
  2. Todo lo generado por IA nace marcado como borrador y la prueba no queda completa mientras haya borradores sin revisar. Una prueba mal generada que llega al curso es un problema del colegio, no del proveedor.
  3. El consumo se guarda por usuario, prueba y herramienta. Sin eso no se puede responder «¿en qué se nos fueron los tokens este mes?».
  4. El descuento y la llamada al proveedor van en la misma transacción: si la llamada falla, no se cobra.
  5. La clave del proveedor no llega nunca al navegador. El front llama a /evaluaciones/ia/{herramienta} y el servidor habla con el proveedor.

La bolsa es del colegio, y el WebClass manager la reparte

Decidido: una bolsa por establecimiento. El WebClass manager del colegio la divide entre sus profesores —es él quien sabe quién está armando pruebas este mes y quién no—, y cada profesor gasta contra su cupo, no contra el total. Así un profesor no se lleva la bolsa entera en marzo.

Tablas nuevas (las únicas del gadget)

ia_bolsa_tokens
    id, colegio, tokens_asignados, tokens_consumidos,
    periodo_inicio, periodo_fin, activo

ia_cupo_profesor                    <-- el reparto que hace el manager
    id, bolsa, usuario, tokens_asignados, tokens_consumidos
    UNIQUE (bolsa, usuario)

ia_consumo
    id, colegio, usuario, prueba, pregunta (nullable),
    herramienta, tokens, exito, mensaje_error, created_at

ia_cupo_profesor es tabla y no una columna en usuario porque el reparto cambia cada período y hay que poder mirar el anterior: un cupo guardado encima del usuario no tiene historia. La suma de tokens_asignados de los cupos no puede pasar el de la bolsa, y esa validación es del servidor.

Falta definir con el negocio

7.cDeshacer y borrador automático

Deshacer (Ctrl+Z) — lo más barato de construir y lo que más falta

El editor está lleno de acciones destructivas de un solo clic: quitar una pregunta, quitar un par, quitar la rúbrica, y sobre todo «Revolver B», que cambia la clave de un pareado que quizá ya se imprimió. Sin deshacer, cada una es un camino de ida.

Borrador automático — la red debajo de Guardar

Cuarenta minutos escribiendo y un cierre del navegador se llevaba todo. El borrador no reemplaza a Guardar: cubre lo escrito entre dos guardados. Al volver, se ofrece; no se aplica solo, porque recuperar en silencio un borrador de ayer encima de lo que el profesor viene a hacer hoy es peor que perderlo.

Una trampa que costó encontrar, porque no da síntoma. Entrar al editor dispara un repintado, y ese repintado guardaba el estado recién abierto encima del borrador, antes de alcanzar a ofrecerlo: el modal aparecía igual, pero recuperaba lo que acababa de pisar. El borrador hay que leerlo antes de tocar nada, y no escribir ninguno mientras haya uno esperando respuesta. Y la lectura va en el embudo por el que pasan todos los caminos de entrada: uno solo que se lo saltee deja el borrador perdido sin que se note.

8Reglas y validaciones

8.a Opciones repetidas funcionalidad nueva

Dos alternativas iguales no son un descuido de forma: cambian lo que la pregunta mide. Si la repetida es la correcta, la pregunta tiene dos correctas y se corrige mal —el alumno que marcó la otra pierde puntaje por una respuesta que era cierta—. Si es incorrecta, el alumno las descarta las dos de una sola vez y la pregunta mide menos de lo que dice medir.

Y no es un caso raro: pasa solo, copiando una alternativa para editarla y olvidándose de cambiarla. Nadie relee las cuatro opciones de las treinta preguntas antes de imprimir.

Qué cuenta como «igual», y dónde se mira

Se compara el texto visible: sin etiquetas HTML, sin distinguir mayúsculas, con los espacios colapsados y sin el punto final. «Verdadero» y «verdadero.» son la misma opción para quien responde, y comparar el HTML crudo dejaría pasar justo el caso que importa —la alternativa copiada y reformateada—. Las vacías se ignoran: de esas ya reclama la clave.

Se mira en los tres lugares donde el alumno elige entre opciones, no sólo en las alternativas:

9Fuera de alcance

10Criterios de aceptación

  1. No se puede llegar al editor sin nivel y asignatura elegidos.
  2. Arrastrar una pregunta a otra posición renumera la prueba y el orden sobrevive a recargar la página.
  3. Una pregunta se puede arrastrar de una hoja a otra, y la prueba se repagina sola.
  4. Arrastrar una alternativa reasigna las letras y la respuesta correcta sigue siendo la misma alternativa, no la misma letra.
  5. El número de hojas del editor es igual al número de páginas del PDF, y el corte cae entre las mismas preguntas.
  6. Ninguna pregunta queda partida entre dos páginas.
  7. Cambiar el tipo de hoja o los márgenes vuelve a paginar en el momento, y el PDF sale en ese tamaño.
  8. Una fórmula insertada se puede volver a editar: al abrir el campo y hacerle clic dentro del editor reaparece su LaTeX original, no el HTML renderizado.
  9. Escribir en un enunciado no rompe una fórmula vecina: se selecciona y se borra entera.
  10. Las fórmulas salen bien en el PDF, no sólo en pantalla.
  11. El botón flotante de agregar está siempre visible sin scrollear, responde al clic en toda su superficie, agrega la pregunta, baja la vista hasta ella y abre el editor de texto en su enunciado.
  12. Cambiar la tipografía o el tamaño base repagina la prueba, y el PDF sale con esa letra.
  13. Una tabla insertada en un enunciado se imprime con sus bordes y no se parte entre dos páginas.
  14. Pegar una tabla de especificaciones copiada de Excel identifica sola las columnas, y un indicador con coma adentro no descuadra la fila.
  15. Las preguntas creadas desde la especificación llegan con su OA e indicador puestos, y esos valores siguen ahí al abrir la categorización aunque no estén en el catálogo.
  16. Un bloque de gráfico aparece en el PDF como imagen, no como un hueco en blanco.
  17. Un PDF de varias páginas se muestra y se puede navegar; dos recortes de páginas distintas se acumulan en una pregunta.
  18. Cada recorte de un PDF con texto entra como una pregunta distinta, en texto editable, con sus alternativas separadas y sus tablas como <table>.
  19. Una pregunta numerada sin separador —el número dentro de un círculo, que en la capa de texto es un 4 suelto— se reconoce igual, y también cuando el número va solo en su línea. Un 3 metros más que su altura no se confunde con una numeración.
  20. Los recortes sin capa de texto se cuentan aparte y ofrecen reconocer el texto; lo reconocido entra como texto editable, marcado como borrador, y conserva el recorte original al lado.
  21. Reconocer el texto no descuenta tokens ni aparece en el consumo: no es una llamada a un proveedor de IA.
  22. Una tabla cuyas celdas ocupan varias líneas entra como <table> con sus columnas correctas y cada celda entera —no aplanada como párrafo, ni con las tres columnas intercaladas—.
  23. Una raíz, un exponente, un subíndice o una fracción apilada del PDF entran como fórmula reeditable: al hacerle clic dentro del editor reaparece su LaTeX.
  24. En ∛2⁷ el exponente queda dentro de la raíz, y en 2^{7/3} la fracción queda dentro del exponente.
  25. Una frase con números no se convierte en fórmula.
  26. Una línea con varias fracciones apiladas entra con cada fracción entera y en su lugar —no con los numeradores y denominadores barajados—, y un párrafo de dos líneas no se convierte en fracción.
  27. Un PDF con la capa de texto ilegible se detecta, se dice por qué, y se ofrece reconocer el texto en vez de importar cuadraditos.
  28. Las rayas de una tabla no se importan como si fueran una figura: no aparecen recuadros vacíos montados sobre el texto.
  29. El recortador ocupa el 90% de la pantalla y trae un selector de zoom; recortar sigue cayendo donde corresponde en cualquier zoom.
  30. Un recorte con texto e imagen trae las dos cosas, y la imagen queda en el mismo lugar que ocupaba respecto del texto.
  31. La imagen importada llega sin el blanco sobrante alrededor.
  32. Un recorte sin capa de texto entra como imagen, y la pantalla lo dice antes y después de importar.
  33. El número de la pregunta del documento original no queda dentro del enunciado.
  34. Esa pregunta nace sin clave, muestra la etiqueta «sin clave», y Guardar se bloquea sin ofrecer «guardar igual».
  35. Marcada la clave, la etiqueta desaparece y Guardar deja de bloquearse por ese motivo.
  36. Cambiar el número de alternativas (2 a 6) conserva la clave si sigue existiendo esa letra.
  37. Al insertar una fórmula, tabla o gráfico, el contenido entra donde estaba el cursor: abrir el diálogo no puede perder el punto de inserción.
  38. Después de insertar un gráfico se puede seguir escribiendo debajo.
  39. Un ejemplo de jsxgraph.org pegado tal cual se reconoce como código y se dibuja, deslizadores y 3D incluidos; el bloque lo dice y la cabecera muestra cuántas líneas, no el código entero encima del dibujo.
  40. Un texto que no se entiende en el campo del gráfico avisa por qué y deja el motivo escrito en el bloque: no dibuja una cuadrícula vacía que parece correcta.
  41. En el modal del gráfico, la ayuda no se monta sobre el campo, ni siquiera después de estirarlo.
  42. El diálogo se llama «Digitalizar desde un archivo» y acepta PDF y .docx; el reconocimiento de preguntas y alternativas es el mismo para los dos.
  43. Un .docx se lee sin internet y sin librería, con sus imágenes puestas en la pregunta que las contiene.
  44. Las tablas de Word entran como una línea por fila sin perder datos, y el resumen avisa que hay que rehacerlas.
  45. Un .doc antiguo dice qué hacer —guardarlo como .docx—, no «formato no soportado».
  46. Un Word sin texto manda a recortar a mano, no ofrece OCR: el OCR es para escaneos.
  47. Una imagen del enunciado se puede recortar desde su propio marco: se arrastra un rectángulo, lo de afuera se oscurece y se dice qué porcentaje se va a ver.
  48. Lo que queda es exactamente la parte marcada, en el tamaño del recorte y no en el de la imagen entera.
  49. El original se conserva y «Quitar el recorte» lo devuelve entero; recortar dos veces seguidas no pierde el archivo de partida.
  50. Descargar con cambios sin guardar no descarga: explica por qué y ofrece guardar y descargar en un paso.
  51. La tabla de especificaciones cuadra: la suma de puntos por indicador es el puntaje total, y las sin categorizar aparecen en su propia fila.
  52. Al cambiar el OA de una pregunta, el indicador queda vacío y sólo ofrece los del OA nuevo.
  53. El eje aparece sobre el objetivo y lo filtra; elegir un objetivo completa el eje solo.
  54. Una pregunta puede categorizarse con un objetivo de otro nivel o asignatura, y la pantalla lo advierte.
  55. Cambiar el nivel o la asignatura de la pregunta limpia eje, objetivo e indicador y lo avisa.
  56. Una pregunta admite varios objetivos, cada uno con su propio nivel y asignatura, y el carril los muestra todos.
  57. Un objetivo agregado sobre otro nivel ofrece el catálogo de ese nivel y se marca como ajeno.
  58. La dificultad y el puntaje aparecen una sola vez, fuera de las tarjetas de objetivo.
  59. El puntaje de una pregunta con dos objetivos se reparte entre ellos: la tabla de especificaciones sigue sumando 100 %.
  60. Una pregunta con un objetivo completo y otro a medias sigue contando como categorizada.
  61. Si los tipos no suman las preguntas que va a generar la IA, se dice cuántas faltan o sobran y Crear queda deshabilitado; «Repartir automáticamente» lo resuelve.
  62. Cada fila entrega la cantidad pedida de preguntas, con su objetivo o su habilidad puesta.
  63. Marcar crear imágenes suma su costo al total antes de generar, y las preguntas generadas llegan con imagen.
  64. En una prueba generada, la respuesta correcta recorre las cuatro letras: ni todas en la A, ni alternando entre dos.
  65. Las de V/F generadas no se responden todas «Verdadero».
  66. Cada pregunta del banco o generada muestra los dos pulgares en su carril; una escrita a mano no los muestra.
  67. Volver a apretar el mismo pulgar retira la opinión.
  68. El pulgar abajo ofrece el reemplazo del mismo origen: del banco si vino del banco, generada si la generó la IA — y siempre deja dejarla como está.
  69. El reemplazo conserva puntaje y posición, y no cambia cuántas preguntas tiene la prueba.
  70. La del banco que se ofrece no está ya en la prueba.
  71. Una pregunta generada que se descarta se guarda igual, marcada como tal: la opinión sobre ella no se pierde al reemplazarla.
  72. Al guardar no se cuentan las opiniones ni se pide nada por ellas: el profesor ya vio el pulgar que apretó.
  73. Una línea con las cuatro alternativas juntas (A) 2 B) 4 C) 6 D) 8) entra como cuatro alternativas, no como una.
  74. Alternativas en dos columnas —A y C arriba, B y D abajo— entran en orden A–D.
  75. A.2, sin espacio tras el punto, entra como alternativa; «El vértice A. Se ubica…» y «a) y b) son paralelas» no.
  76. Si a las alternativas les falta una letra, se dejan en el orden del documento en vez de reordenarse a medias.
  77. El pie que se repite en todas las páginas no queda pegado al final de ninguna alternativa.
  78. Las instrucciones numeradas de la portada no entran como preguntas, y las preguntas 1 a 5 de verdad sí.
  79. Dos celdas de una tabla, o dos alternativas consecutivas, no se unen en una fracción; una fracción de verdad sí se reconoce.
  80. Una alternativa con signos matemáticos —A) 56 ÷ 0 = 56— sigue siendo una alternativa, no parte del enunciado.
  81. La prosa que sigue a una fórmula no queda dentro de ella.
  82. Una prueba con los ejercicios pegados como imagen entrega todas sus preguntas, cada una con su imagen y la clave para marcar.
  83. El resumen distingue las que traen su texto de las pegadas como imagen, y explica por qué.
  84. Se ofrece OCR también en el camino del PDF completo; lo reconocido entra como borrador y conserva la imagen original.
  85. El detector de pies repetidos no elimina números de pregunta aunque caigan en la banda del borde.
  86. Un recorte de un plano o cuadrícula con rótulos adentro entra como una sola imagen con sus rótulos dentro, no como palabras sueltas.
  87. Un párrafo enmarcado y una tabla reconocida no se convierten en imagen: siguen siendo editables.
  88. Un subrayado o la raya para responder no disparan la detección de dibujo.
  89. Cada recorte ofrece «Como texto» / «Como imagen» en el panel de revisión, y lo elegido manda sobre lo detectado.
  90. Un recorte marcado como imagen deja de aparecer en la oferta de OCR.
  91. Hay cuatro caminos de creación: no existe ya uno para «con ayuda de la IA» aparte de la tabla de especificaciones.
  92. Los caminos van en filas agrupadas en dos bloques —«empezar a escribir» y «partir del currículo»—, sin iconos y sin fondo de color; los dos que consumen tokens lo dicen.
  93. «A partir de tabla de especificaciones» y «a partir de la situación del curso» abren una pantalla propia —no un panel bajo las filas, y no el editor—, con su miga de pan y un Volver.
  94. La tabla tiene dos pestañas, Objetivos y Habilidades; cambiar de una a otra no borra lo pedido en la otra, y cada rótulo lleva la cuenta de lo pedido ahí.
  95. La fila «Cualquiera del nivel» va primera en Objetivos y no aparece en Habilidades; ofrece el banco del nivel entero, no entra en las cuentas del currículo y «Proponer» no la llena.
  96. Lo pedido en esa fila llega con un objetivo distinto por pregunta, tomado del catálogo del nivel: ninguna entra sin categorizar, y el enunciado dice que el objetivo lo eligió la plataforma.
  97. «Proponer» no borra lo pedido a mano en el comodín ni en los objetivos propios.
  98. Los objetivos propios del colegio aparecen después del currículo, con su logro en el camino del curso, sin entrar en las cuentas del nivel. Agregar uno casi igual a uno existente usa el existente y lo avisa.
  99. En el cajón, «+ Objetivo propio» agrega una tarjeta de tipo y texto, sin nivel, eje ni indicador, que ofrece los que el colegio ya usa. Un texto que sólo difiere en mayúsculas, tildes, espacios o punto final queda escrito como el existente.
  100. Una pregunta con sólo un objetivo propio de tipo objetivo cuenta como categorizada; en la tabla de especificaciones es una fila que se lleva su parte del puntaje, y los puntos siguen sumando el total. Las habilidades y actitudes propias van aparte, sin puntaje.
  101. La valoración elegida se ve de lejos: amarillo el pulgar arriba, rojo el pulgar abajo, el otro apagado, y el rótulo dice en palabras lo mismo que el color.
  102. Un texto compartido se imprime una sola vez, antes de sus preguntas, con el rótulo «responde las preguntas N a M» armado solo.
  103. Las preguntas de un recurso quedan siempre contiguas y detrás de él: meter una la mueve a ella junto al bloque, no mueve el bloque hacia ella.
  104. El rótulo del rango se actualiza al agregar, sacar o reordenar preguntas.
  105. Al paginar, el recurso no queda separado de su primera pregunta por un salto de hoja.
  106. Separar el recurso deja las preguntas y borra el texto, avisando antes; borrar la última pregunta de un recurso avisa que el texto se va con ella.
  107. La prueba guardada deja el bloque declarado, para que quien la baraje al asignarla baraje bloques y nunca deje una pregunta antes de su recurso.
  108. Elegido un curso, se avisa cuántos de sus alumnos están en el PIE, separando permanentes de transitorias, y cada diagnóstico trae su adecuación.
  109. Los alumnos del PIE van marcados en el listado de búsqueda y en su ficha una vez elegidos.
  110. Con alumnos elegidos el aviso habla de ellos; si ninguno es del PIE lo dice, sin dejar de recordar que el curso sí tiene.
  111. Un curso sin alumnos PIE también lo dice: el silencio se lee como «no se comprobó».
  112. Proponer rehace sólo la pestaña que se está mirando.
  113. Hay un reparto por tipo de pregunta; la cuenta que tiene que calzar es la de las generadas por IA, no el total, y se rehace sola al cambiar las cantidades.
  114. Las preguntas creadas respetan el reparto por tipo y salen intercaladas.
  115. El Excel de UTP se importa desde esta pantalla y llena la tabla; lo que no calza con el catálogo del nivel se dice, no se descarta en silencio.
  116. Sin curso, la tabla no muestra las columnas de logro ni el selector de curso, y queda en el orden del currículo.
  117. Con curso, sólo se ofrecen los cursos del nivel elegido arriba.
  118. Cada pantalla muestra su propio título: la tabla de especificaciones no se anuncia como «la situación del curso».
  119. Un clic sobre las casillas del alumno en la hoja abre el modal que las configura.
  120. Se puede ocultar una casilla sin perderla, agregar una del catálogo de WebClass, crear una propia con el nombre que sea y reordenarlas arrastrando.
  121. Las de WebClass se marcan como tales y no se pueden borrar, sólo ocultar; las propias sí.
  122. Con más de tres casillas visibles la ficha pasa a dos filas.
  123. Deshacer devuelve una casilla borrada.
  124. Elegir uno o varios alumnos cambia el logro de la tabla al de ellos, y el título y las migas dicen de quién es.
  125. El campo de alumnos ofrece el curso completo, filtra al escribir ignorando las tildes, agrega con Enter y quita la última ficha con Retroceso.
  126. Un alumno descendido muestra más objetivos bajos que el promedio de su curso; volver a «Todo el curso» restituye la tabla.
  127. Cambiar de curso limpia los alumnos elegidos: son de otro curso.
  128. En la tabla de especificaciones se puede cambiar de nivel y de asignatura, y lo ya pedido no se pierde: se acumula y se ve en el resumen, con lo de otro nivel marcado.
  129. Una prueba con filas de dos niveles trae preguntas del banco de cada nivel, y las del nivel ajeno llegan marcadas como tales.
  130. La cantidad se ajusta con botones −/+, y el origen con dos botones donde el del banco muestra cuántos items tiene.
  131. El pie queda fijo abajo: el total y el botón de crear se ven sin llegar al final de la tabla.
  132. La tabla trae todos los objetivos del nivel, no sólo los ya evaluados, y los nunca evaluados van primero y dicen «Nunca», no 0%.
  133. El selector de origen muestra cuántos items tiene el banco de ese objetivo, y queda deshabilitado cuando tiene cero.
  134. Pedir del banco más de las que hay se dice en la fila y se completa con IA; el costo cuenta sólo las de IA.
  135. Proponer no pide preguntas de los objetivos ya logrados.
  136. Cambiar de curso cambia el catálogo de objetivos y reinicia lo pedido; si el curso es de otro nivel, se avisa que manda el del curso.
  137. Lo traído del banco entra listo y lo generado como borrador, y todo llega categorizado.
  138. Guardar con dos alternativas iguales avisa, dice qué pregunta y qué texto, ofrece ir a ella y deja guardar igual.
  139. Ese aviso ignora mayúsculas, etiquetas, espacios de más y el punto final, y no se dispara con las alternativas vacías.
  140. También avisa de la columna B repetida en términos pareados —distractores incluidos— y de las respuestas aceptadas repetidas.
  141. El banco ya no tiene búsqueda por texto del enunciado: se filtra por eje, objetivo, indicador y habilidad.
  142. Cada opción del filtro dice cuántos items tiene detrás, y ninguna lleva a cero resultados.
  143. Elegir un eje acota los objetivos y elegir un objetivo acota los indicadores; cambiar el de arriba suelta los de abajo.
  144. Una acción de IA descuenta exactamente lo que anunció, y si el proveedor falla no descuenta nada.
  145. Con tokens insuficientes se explica cuántos faltan; no hay error genérico.
  146. El profesor gasta contra su cupo, no contra el total del colegio, y el saldo que se le muestra es el suyo.
  147. Al agotarse el cupo se le dice que no le quedan créditos y quién se los amplía; lo que no cuesta tokens —banco, lectura de PDF, OCR— sigue funcionando.
  148. La suma de los cupos repartidos no puede pasar la bolsa del colegio, y esa validación es del servidor.
  149. Guardar con preguntas sin categorizar avisa qué falta, guarda igual y deja la prueba fuera del banco.
  150. Cada forma generada trae su propia pauta, y la pauta de la forma A es la del orden original.
  151. Intentar editar una prueba ya rendida ofrece duplicarla en vez de permitir el cambio.
  152. El menú de agregar ofrece los siete tipos de WebClass, y cada uno se crea con un ejemplo utilizable, no vacío.
  153. En varias correctas: marcar una segunda alternativa reparte 100 % entre las marcadas; dejar la suma en otro valor avisa bajo la pregunta y bloquea Guardar diciendo cuánto suma.
  154. Escribir un porcentaje mayor que cero marca sola la alternativa como correcta, y bajarlo a cero la desmarca.
  155. La pauta de una pregunta de varias correctas es un grupo de letras; la de pareados no es una letra; la de desarrollo y respuesta corta es un guión.
  156. En pareados: la columna B se imprime revuelta, la clave se calcula sola y no cambia entre repintados; «Revolver B» la cambia y la clave se actualiza.
  157. Agregar o quitar un par renumera la columna A y vuelve a revolver la B.
  158. Un par con una columna vacía bloquea Guardar.
  159. «+ distractor» agrega a la columna B una opción sin fila en la A: la B queda más larga que la A y las letras siguen correlativas.
  160. El señuelo se revuelve junto con los pares —no queda fijo al final— y la clave de pantalla lo lista aparte como «sin pareja».
  161. En el papel el señuelo es indistinguible de las demás opciones de la B: no se imprime su rótulo ni su botón de quitar.
  162. Un señuelo sin texto bloquea Guardar; quitarlo no toca la columna A ni el puntaje de la pregunta.
  163. En respuesta corta: se pueden agregar varias respuestas aceptadas con su porcentaje, y sin ninguna Guardar se bloquea.
  164. Una pregunta de desarrollo nace con rúbrica: tres niveles de logro y criterios con descriptores, y cada celda muestra cuántos puntos vale.
  165. La rúbrica no se dibuja sobre la hoja: es una opción del carril lateral que sólo aparece en las preguntas de desarrollo, y al pincharla se abre en un modal ancho.
  166. Si los criterios no suman el puntaje de la pregunta, el modal lo dice, el carril muestra «rúbrica no suma» sin cerrar el modal, y Guardar se bloquea indicando cuánto suma. Un criterio sin nombre o una celda sin descriptor también lo bloquean.
  167. Cambiar el puntaje de un criterio o el % de un nivel recalcula las celdas en el momento.
  168. Un nivel nuevo entra antes del último, y todas las filas ganan su celda; quitarlo se la saca a todas.
  169. Al descargar Para el estudiante la hoja sale sin rúbrica; en la Pauta de corrección aparece bajo cada pregunta de desarrollo como una tabla sin campos ni botones, y al terminar la hoja vuelve a quedar limpia.
  170. La rúbrica se puede quitar y volver a poner desde el modal, sin tocar el puntaje de la pregunta, y la marca del carril pierde y recupera su ✓.
  171. El generador de imágenes declara su límite antes de generar, rechaza una petición fuera de ese límite sin cobrar tokens y diciendo cuál fue el motivo.
  172. Una petición válida cobra los tokens una sola vez, deja el consumo registrado, muestra la vista previa y pide revisarla antes de insertar.
  173. La imagen insertada conserva el texto con que se pidió (data-peticion), lleva marca IA en el editor y no en el papel.
  174. Desde la barra del editor, la imagen se inserta donde está el cursor.
  175. El aviso de Guardar dice qué le falta a cada pregunta, no un texto genérico igual para todas.
  176. La pantalla de creación muestra el título de la herramienta y, bajo él, el nombre del recurso con su etiqueta «Nombre:»; hacer clic en la etiqueta enfoca el campo.
  177. La barra del editor ocupa una sola línea: pestañas, Opciones y Herramientas de IA al mismo nivel, sin segunda fila de menú.
  178. Las cuatro opciones del encabezado se configuran dentro de Opciones, y cada cambio se ve en la hoja al instante.
  179. El encabezado de la hoja no trae QR, y la insignia va a la izquierda con el título centrado respecto de la hoja.
  180. La línea de datos bajo el título viene apagada; el interruptor de Opciones la enciende y muestra asignatura, nivel, tipo, cuántas preguntas y el puntaje total, una sola vez y en la primera hoja.
  181. Esa línea se arma sola: agregar una pregunta cambia la cuenta y el puntaje, y cambiar la asignatura en Opciones la actualiza. No se escribe a mano.
  182. Encenderla y apagarla es un cambio como cualquier otro: deshacer la repone.
  183. Activar la casilla de fecha pasa la ficha a dos filas y corre los rótulos al costado izquierdo.
  184. Las instrucciones se editan sobre la hoja y vacías no se imprimen, pero siguen siendo clickeables en el editor.
  185. El nombre de la evaluación se edita sobre el título de la hoja, la miga de pan lo sigue, y no hay campo de nombre en la barra.
  186. Un clic sobre el enunciado, sobre una alternativa o sobre las instrucciones abre el editor en un modal, con la barra de formato fija arriba del área de escritura, y el título dice qué se está editando.
  187. Aplicar vuelca el texto a la hoja y repagina; Cancelar y Esc lo descartan; clic fuera equivale a Aplicar.
  188. Con el editor abierto, Esc sobre un modal de fórmula, tabla o gráfico cierra sólo ese y devuelve al texto sin perderlo.
  189. Los campos de una sola línea (nombre de la prueba, pares, respuestas aceptadas) se siguen escribiendo sobre la hoja, sin modal y sin barra.
  190. Los cuatro botones de alineación actúan sobre la fila del cursor: alinear una no mueve a las demás, y el botón correspondiente queda hundido.
  191. Una imagen del texto se alinea a izquierda, centro o derecha, y se mueve de verdad dentro de su fila. Con el cursor en un párrafo, alinear ese párrafo no mueve la imagen.
  192. Se puede deshacer y rehacer con Ctrl+Z / Ctrl+Y, y el aviso dice qué se deshizo. Incluye «Revolver B», quitar una pregunta y quitar la rúbrica.
  193. Una pregunta se puede duplicar —la copia entra justo debajo y con ids propios: marcar una correcta en ella no toca al original— y eliminar, con confirmación.
  194. El borrador se guarda solo, se ofrece al volver con su fecha y su número de preguntas, y Guardar lo limpia.
  195. Las preguntas, alternativas y pares se reordenan con el teclado desde su asa (flechas arriba/abajo), y una imagen se redimensiona con las flechas izquierda/derecha.
  196. El banco filtra por nivel, asignatura, tipo y dificultad, busca por texto, muestra % de logro y las preguntas llegan ya categorizadas.
  197. El generador de preguntas pide nivel, asignatura y OA, con los de la evaluación por defecto, y el catálogo de objetivos cambia al cambiar el nivel.
  198. La tabla de especificaciones se descarga como planilla, con una fila por pregunta, y se abre en Excel en español sin quedar toda en una columna.
  199. Un PDF escaneado ofrece reconocer el texto además de recortar a mano, no descuenta tokens —el OCR es Tesseract, no un proveedor que cobre por uso—, y lo reconocido entra marcado como borrador.
  200. Una pregunta cuyas alternativas son dibujos entra como selección múltiple con cuatro imágenes, una por alternativa, con sus letras en orden y sin la figura entera duplicada. Se avisa en la lista previa.
  201. Cada recorte llega sin el rótulo dibujado —la alternativa no puede decir «A)» dos veces— y ajustado a su dibujo, no al alto de la banda completa.
  202. Una figura suelta no se parte en alternativas: si un trozo se lleva más de la mitad del ancho, o los blancos que separan apenas rozan el umbral, la pregunta sigue entrando con su figura entera.
  203. El ensayo SIMCE de referencia entra completo: 40 de 40 preguntas con sus 4 alternativas.
  204. La barra ofrece los dos caminos por separado: subir una imagen y generarla con IA.
  205. Una imagen de 2000 px entra achicada a 1400, con la proporción intacta, y el aviso dice cuánto se achicó y cuánto pesa.
  206. Un PNG sigue siendo PNG después de achicarse: no se le pone fondo blanco.
  207. La imagen subida se redimensiona y se alinea igual que la generada.
  208. Una imagen del texto se selecciona con un clic y muestra cuatro tiradores; arrastrando cualquier esquina cambia de tamaño manteniendo la proporción, con la medida a la vista.
  209. El ancho máximo al que se puede estirar es el de la columna de la hoja, no el del modal: el tamaño que se ve al dimensionar es exactamente el que sale impreso.
  210. No baja de 60 px ni pasa del ancho de la columna, y el tamaño sobrevive al Aplicar y sale igual en el PDF.
  211. Con la imagen seleccionada, los botones de alineación la mueven y los de formato de texto quedan desactivados.
  212. El HTML guardado no contiene ni el marco, ni los tiradores, ni la marca de selección.
  213. Una fórmula sigue siendo reeditable: al abrir el campo y hacerle clic dentro del editor, reaparece su LaTeX original.
  214. Elegir un camino de creación entra al editor sin botón «Crear»; sin nivel o asignatura avisa cuál falta.
  215. La pestaña Retroalimentación ofrece los cuatro textos de la pregunta, y el de parcial aparece sólo en los tipos que reparten puntaje.
  216. En verdadero o falso aparecen además los dos textos de V y de F.
  217. En Retroalimentación todas las alternativas tienen campo, incluida la correcta.
  218. La palabra «distractor» aparece sólo en el botón de los términos pareados —su único sentido en WebClass— y en ningún otro lugar de la interfaz.
  219. El editor no tiene pestaña General ni Formas, ni interruptor de «marcar respuesta correcta», ni icono de usuario. Nivel, asignatura y tipo viven en Opciones.
  220. Cambiar el nivel o la asignatura desde Opciones no borra ninguna categorización, y avisa cuántas preguntas quedaron con objetivos ajenos; volver al valor original apaga el aviso.
  221. Cambiar el tipo de evaluación no toca la categorización.
  222. El editor no pide ni muestra la exigencia, y el resumen dice que el puntaje del 4,0 se define al asignar la prueba a un curso.
  223. Descargar pregunta si el archivo lleva la clave; «para el estudiante» viene preseleccionado y el editor queda con las marcas después de generar el PDF.

11Qué hay que confirmar antes de programar

Esta lista se acorta leyendo el código del producto, no preguntando. Varios puntos que estuvieron acá ya se cerraron así —el porcentaje por alternativa, la fórmula del logro, las columnas de pregunta_atributo— y quedaron escritos en su sección. Lo que sigue acá es lo que de verdad no se puede resolver mirando: decisiones de negocio, y datos que sólo están en la base en producción.

  1. Si se aprueba la rúbrica por pregunta funcionalidad nueva — es lo único de este documento que no existe hoy (§6.4). Si entra, hay que decidir tres cosas:
    • ¿La rúbrica de una pregunta se puede guardar en el banco de Rúbricas de aprendizaje para reutilizarla en otra prueba, o vive sólo dentro de la evaluación? El modelo propuesto lo permite con poner id_pregunta en NULL.
    • ¿Es obligatoria en toda pregunta de desarrollo, o se puede quitar? La maqueta la crea sola y deja quitarla: la nota la pone el profesor, no el sistema.
    • ¿La justificación de una V/F con justificación merece lo mismo? También se corrige a mano y tiene puntaje propio.
  2. El logro por objetivo: sólo falta si cuentan las pruebas no validadas. La fórmula está resuelta —es EvaluacionDao::getPuntajePorAtributo, transcrita abajo— y la ventana de tiempo también: el año en curso solamente, decidido por WebClass el 23-09. Un objetivo medido hace dos años, con otra composición de curso, no dice lo mismo. Queda sólo:
    • ¿Cuentan las pruebas no validadas y los ensayos, o sólo las calificadas?
    La fórmula del logro, tal cual está en el producto
    CASE WHEN r.puntaje >= tp.puntaje THEN 1
         WHEN r.puntaje <  tp.puntaje AND r.puntaje > 0 THEN r.puntaje / tp.puntaje
         ELSE 0 END
    FROM resultados r
    JOIN test_pregunta tp     ON tp.test = r.test AND tp.pregunta = r.pregunta
    JOIN pregunta_atributo pa ON pa.pregunta = tp.pregunta
    WHERE pa.atributo = ?

    Dos cosas quedan respondidas de paso. El puntaje parcial ya existe: si el alumno obtuvo menos que el máximo, cuenta la fracción r.puntaje / tp.puntaje. Y una pregunta con dos objetivos cuenta entera en cada uno —el JOIN con pregunta_atributo produce una fila por atributo y cada una se lleva la fracción completa—, que es justo lo que este documento suponía correcto. Ya no hay que decidirlo: está decidido. Y el puntaje parcial de los términos pareados también es real: DatosTestDao acumula por cada par acertado, así que respuesta_enpareja_vinculo.puntaje sí se usa —otra pregunta que este documento tenía abierta y ya no—.

    Hay una segunda versión de la misma consulta que usa pregunta_atributo_adicional en vez de pregunta_atributo: los objetivos propios del profesor también cuentan para el logro. Ver abajo.

    Conviene además reusar la consulta del informe de aprendizaje en vez de escribir otra: dos cálculos del mismo número terminan dando distinto, y el profesor va a comparar las dos pantallas.
  3. El nivel del objetivo hay que agregarlo: hoy pregunta_atributo no lo tiene. Ya no es una pregunta, es un hecho verificado en el código del producto:
    INSERT INTO pregunta_atributo (pregunta, eje, tipo, atributo)
    Cuatro columnas, sin nivel. El nivel se deduce de la prueba (prueba.sector → sector.nivel). Con varios objetivos por pregunta y de niveles distintos (§6.5.b) esa deducción deja de ser posible, así que la categorización múltiple es un cambio de modelo y no sólo de pantalla. Lo que falta decidir es cómo: una columna nivel en pregunta_atributo, o que el catálogo al que apunta atributo ya lo traiga.
  4. El objetivo propio del profesor: pregunta_atributo_adicional (id, pregunta_id, tipo, caracteristica). Es el mecanismo con el que hoy se le pone a una pregunta un objetivo que no está en el catálogo: caracteristica es texto libre. Lo confirmó WebClass, y en el código se ve que cuenta para el logro igual que un objetivo del catálogo, y que se copia al duplicar una pregunta.
    Ya está incorporado, en la maqueta y en el documento: el cajón deja agregar un objetivo propio (§6.5.c) y la tabla de creación los muestra como filas (§5.2). Quedan dos cosas que el código no responde:
    • De dónde sale la lista de «ya usados»: de las preguntas del colegio, de las del profesor, o de todo WebClass. Es la misma pregunta que el banco de items (abajo), y conviene contestarlas juntas. La maqueta supone el colegio.
    • Si los tipos 1 y 2 —contenidos mínimos y aprendizajes esperados, del currículo anterior— se siguen usando en objetivos propios. La maqueta ofrece sólo 3, 4 y 7. Un select tipo, count(*) from pregunta_atributo_adicional group by tipo lo responde.
  5. Si se habilita el tipo de varias correctas sin tocar el corrector. La corrección queda fuera del alcance de este gadget —decidido: el gadget crea preguntas y la aplicación sigue el camino actual de WebClass—, pero eso obliga a mirar qué hace ese camino hoy: lee el porcentaje como bandera y entrega el puntaje completo a quien marque cualquier alternativa con fracción mayor que cero (§6.3.a). Una pregunta 50/50 daría 100% por la mitad de la respuesta. O se ajusta el corrector, o no se habilita el tipo: publicarlo así es entregar notas mal calculadas en silencio.
  6. La tolerancia de la respuesta corta: mayúsculas, tildes, espacios sobrantes y coma vs. punto decimal. Sin una regla escrita, el mismo alumno con la misma respuesta acierta o falla según cómo la escriba. Es la única pregunta de corrección que queda.
  7. Si algún tipo está en desuso en la base de producción. Un select tipo, count(*) from pregunta group by tipo lo responde, y evita construir pantalla para algo que nadie usa hace diez años.
  8. Cómo se generan los PDF con fórmulas: navegador headless o render de fórmulas a imagen desde el servidor (§6.2). Es la decisión técnica más cara de revertir de todo el gadget.
  9. Las plantillas de home/importarpreguntas del repo vanilla, antes de inventar un formato de Excel nuevo.
  10. Las tres preguntas de tokens que quedan abiertas en el §7: renovación o compra de la bolsa, qué pasa con el cupo no gastado, y el proveedor de IA con su acuerdo de tratamiento de datos. La bolsa ya se definió: es por colegio y la reparte el WebClass manager.
  11. Si el banco de items es por establecimiento, por sostenedor o compartido con WebClass.
  12. Dónde se guarda el TEXTO de un recurso compartido (§6.4.b). Verificado en el código del producto: pregunta.idrecurso apunta a archivo, o sea sirve para una imagen; para un texto falta dónde ponerlo. Hay dos salidas propuestas, y la decisión es de arquitectura. No guardarlo como archivo ni como imagen del texto.
  13. Barajar por bloques: hay que escribirlo, no existe. Se buscó expresamente y en los dos lugares que rinden una prueba el barajado es plano:
    • Web — AlumnoTestDao::getPreguntasPorIdTest: con barajar encendido la consulta termina en ORDER BY rand(), sin agrupar por nada.
    • App móvil — MobileApp/Evaluations/EvaluationsController: $preguntas->shuffle(), también plano.
    Ninguno menciona idrecurso. Hay que agrupar por recurso antes de revolver —revolver los grupos entre sí y las preguntas dentro de cada grupo— en los dos. Son pocas líneas, pero sin eso la funcionalidad no sirve: con el barajado encendido el texto queda separado de sus preguntas, que es justo lo que viene a resolver.
    Si existe un tercer lugar que rinda pruebas y no esté en los repos que se revisaron, hay que mirarlo también.
  14. Dónde vive la nómina PIE y cómo se relaciona con curso, y si el diagnóstico está codificado o es texto libre (§5.3). Es lo único que queda de este tema: mostrar los nombres ya está aprobado y las adecuaciones también, las dos cosas el 23-09.
  15. Dónde se guardan las imágenes y su recorte (§6.2): el recorte tiene que viajar como cuatro números junto a la URL, no como una imagen nueva, para poder cambiarlo después y para que dos preguntas usen dos recortes del mismo archivo. Va con la pregunta ya abierta de dónde viven los archivos (§6.2).
Sobre la maqueta

La maqueta es HTML autónomo, sin build ni CDN, y no guarda nada: al recargar vuelve al estado inicial. Los datos son de ejemplo. Sirve para acordar el comportamiento — el arrastre, la paginación, el editor de fórmulas, el carril de categorización — no como código a copiar: está escrita en JavaScript plano y el producto usa Vue 2.

Dos cosas de la maqueta que no hay que replicar: el renderizador de LaTeX es un subconjunto escrito a mano para poder mostrar el flujo sin depender de un CDN (en producción va KaTeX), y la barra de formato usa document.execCommand, que está obsoleto — en producción lo reemplaza el editor que ya viene con el producto.

Atajos para mostrarla en una reunión, agregados a la URL: ?editor=1 entra directo al editor con la prueba de ejemplo cargada, ?crear=tabla abre ese camino con la tabla ya analizada, y ?tokens=0 arranca sin créditos de IA, para poder enseñar qué ve el profesor cuando se le acaba el cupo sin tener que gastar 1.250 tokens de mentira de a 20.

← Todos los gadgets