Cuando pensé los pasos que debería dar para corregir el MiniMult en esta entrada. Especificaba que la primera parte sería la elección de ítem para la prueba. Algo que intenté explicar en la siguiente pero que creo que no me quedó suficientemente bien explicada. Como ya está publicada no sé si volver a ella y retocarla porque releyéndola me parece farragosa y confusa. Pero el caso es que allí podemos ver qué preguntas vamos a utilizar y cuáles son sus valores de plantilla (que aún no utilizamos). Con eso cumplimos el paso uno.
¡Bien! Ya tenemos decidido todo el test (preguntas, plantillas, escalas, etc.) y ahora queremos que nuestro Emacs lo pase por pantalla. Para ello vamos a ver lo que necesitamos.
A grosso modo lo que necesitamos para pasar la prueba por pantalla lo podemos resumir en los siguientes pasos:
- Crear un buffer donde mostrar la prueba:
- Generar los widgets en un buffer nuevo.
- Cambiar el foco al nuevo buffer.
- Al terminar la prueba devolver el foco al buffer anterior y devolver las respuestas.
Crear un buffer
Lo primero que tenemos que tener en cuenta es que al cambiar de buffer resultan inalcanzables las variables y valores del buffer que abandonamos. Si necesitamos cualquier valor lo debemos guardar para poder utilizarlo. Entre esos valores debemos guardar el buffer donde está la historia de nuestro paciente, entre otras cosas para poder volver.
Mirando la documentación de Emacs encontré un paquete que se llama widget y que viene con un ejemplo que resulta esclarecedor. Que comienza así:
(require 'widget)
(eval-when-compile
(require 'wid-edit))
Por lo que veo ahí existen dos paquetes que incluir. El primero es
widget
que lo cargará siempre y otro wid-edit
sólo se cargará
cuando se compile el módulo gracias al macro eval-when-compile
.
Consideraciones antes de crear el buffer
En el MiniMult hay pocas preguntas y es casi seguro que se contestarán en una sola sesión. Pero pensando en pruebas más largas que se podrían contestar en varias sesiones me he planteado ser lo más conservador posible con las respuestas del cliente. Es decir, si hay respuestas previas al test el sistema debería tomarlas y colocarlas en su sitio para que el sujeto pueda continuar o incluso modificar alguna si así lo considera oportuno.
Después de hacer algunas pruebas he visto que obtener y establecer
información guardada en un bloque de propiedades es sencillo
utilizando las funciones org-entry-get
y org-entry-put
. Para
obtener, por tanto, los valores de las respuestas utilizaremos una
línea que diga algo así como:
(defvar minimul-respuestas)
...
(setq minimult-respuestas (org-entry-get (point) "Respuestas"))
El formato en el que vamos a guardar las respuestas es muy simple. Una cadena de caracteres donde cada posición marca la respuesta para un ítem. Cada carácter puede tener tres valores posibles para cada uno «V», «F» o un espacio en blanco. El hacerlo así es por simplicidad: la respuesta al ítem 14 será el valor de la posición 14 de la cadena. Se guardan todas las respuestas en una sola variable y además ese formato es idéntico a lo que se generaría en una lectora de marcas, por ejemplo. Lo que serviría también para los casos en que las pruebas se hicieran con una hoja de respuestas mecanizada.
Crear un buffer y cambiar a él
En el mismo ejemplo de la documentación del paquete widget
aparece
cómo hacer para crear un buffer y cambiar a él y luego una serie de
operaciones antes de ponerse a añadir widgets.
(defun widget-example ()
"Create the widgets from the Widget manual."
(interactive)
(switch-to-buffer "*Widget Example*")
(kill-all-local-variables)
(make-local-variable 'widget-example-repeat)
(let ((inhibit-read-only t))
(erase-buffer))
(remove-overlays)
(widget-insert
...
(widget-setup))
En ese código podemos ver cómo se cambia con la función
switch-to-buffer
a un nuevo buffer. Limpia variables, le pone una
variable local widget-example-repeat
, inhibe el modo de solo
lectura y limpia el buffer y los límites si los hubiera.
El declarar la función como interactive
hace que se pueda llamar
desde la combinación de teclas M-x
.
Pasos que tendrá que hacer el código
Después de todas las consideraciones creo que los pasos que tendría que hacer el sistema sería algo así:
- Guardar el buffer donde están los datos.
- Obtener las respuestas anteriores si las hay.
- Cambiar al nuevo buffer creado.
- Mostrar en pantalla cada pregunta. Si hay respuestas debería mostrar también el valor actual.
- Guardar el contenido de los widgets de respuesta en una sola cadena.
- Cambiar el foco al buffer antiguo y guardar las respuestas.
- Destruir el buffer temporal.
Antes he dicho creo porque recuerdo que de lo que yo entiendo verdaderamente es de psicología. No soy informático aunque hago algunas veces mis pequeñas herramientas que me ayudan a hacer mi trabajo. Supongo que un informático ya habría terminado todo el proyecto que a mí me cuesta investigar día a día en ratos libres y lo tendría funcionando incluso habría hecho ya algunas mejoras.
Pero es lo que hay y mi filosofía última es «si funciona, vale». No entro en consideraciones de elegancia del código. Un concepto que nunca he entendido, porque lo que alguien encuentra elegante otro lo considera zafio o carente de estilo.
Ahora me pondré a codificar lo pensado hasta aquí y pondré en futuras
entradas del blog lo que me vaya encontrando por el camino y los
cambios que tenga que hacer. Como por ejemplo, en el código que ya hay
he cambiado el nombre de la variable que guarda los textos de las
preguntas por minimult-preguntas
. Eso hace que no haya colisiones de
nombres si por ejemplo existiera otro futuro programa de corrección de
test que no fuese el MiniMult.