Tabla de Contenidos
Uso de plantillas JSP
JSP (Java Servlet Pages) es el mecanismo mediante el cual se puede integrar codigo del lenguaje de programación Java en una página web HTML. Para ello, JSP utiliza una serie de etiquetas en las que inserta el codigo en Java. Siette internamente compone en una misma página todo el código que se haya introducido en las secciones Enunciado
, Respuestas
o Patrones
, Ejemplo
, Ayuda
y Refuerzo
, crea una página en JSP, a partir de ella crea una instancia de la pregunta, utilizando un generador de números aleatorios propio y devuelve esa instancia para presentarla como una pregunta al alumno.
A lo largo de estos ejemplos se irán introduciendo los distintos conceptos e instrucciones necesarias para escribir este tipo de plantillas.
Ejemplo 1
Enunciado | <% Random r; int x,y; r = new Random(); x = r.nextInt(2,5); y = r.nextInt(6,9); %> Calcular el resultado de la siguiente operacion: <%= x %> * <%= y %> |
---|---|
Patron respuesta | <%= x*y %> |
Este ejemplo genera una pregunta de respuesta abierta, donde se generan dos números al azar x e y, el primero entre 2 y 5 y el otro entre 6 y 9, y se pide el valor del producto. El patrón de respuesta se calcula dinámicamente. La siguiente imagen muestran una instancia obtenida a partir de esta plantilla:
Lo primero que llama la atención es el uso de un objeto de la clase Random
. Esta clase existe en Java, en el paquete java.util.Random
, per Siette captura todas las llamadas a esta clase y las redirige a una clase propia siette.util.Random
, que extiende la clase java.util.Random
e incorpora algunos métodos que facilitan la generación de números y algunas otras operaciones de selección aleatoria. Para mas detalles vea la documentación completa de la clase siette.util.Random.
Al capturar todas las llamadas a la clase Random
, Siette controla la instancia que se genera, de manera que una misma semilla produce siempre la misma instancia. Esto es importante porque Siette debe ser capaz de volver a presentar exactamente la misma instancia si el alumno pierde la sesion y debe reiniciar el test, o si avanza y retrocede en el test. Siette no guarda las instancias generadas, sino sólamente la semilla a partir de la cual se generó la instancia. Es importante tener esto en cuenta si de alguna manera se modifica una plantilla que ya ha sido usada. Puede que en este caso la pregunta formulada no se la misma que la que se muestre en los listados. Siette no puede saber si esto ocurre, pero como medida de control Siette guarda tambien una cadena de control (checksum) y si éste cambia muestra un aviso.
Ejemplo 2
Enunciado | <% int x = Random.nextInt(1,9); int y = Random.nextInt(1,9); %> Calcular el resultado de la siguiente operacion: <%= x %> * <%= y %> |
---|---|
Respuesta correcta | <%= x*y %> |
Alternativa 1 | <%= x+y %> |
Alternativa 2 | <%= (x+1)*y %> |
Alternativa 3 | <%= x*(y+1) %> |
Las preguntas de respuesta abierta se adaptan bien a las preguntas generativas, no obstante puede utilizarse cualquier tipo de pregunta como base de las preguntas generativas. El ejemplo anterior se ha transformado en una pregunta de opción múltiple con respuesta única.
Sin embargo, hay que tener cuidado en este caso de que las distintas respuestas no sean iguales unas con otras. Por ejemplo, en el caso anterior si $x=2$ y $y=2$, la respuesta correcta coincide con la alternativa 1. Además si $x=y$ la alternativa 2 y 3 son iguales. Por tanto habría que programar las alternativas de manera que no se solapasen en ningun caso. (Por ejemplo, proponiendo otra fórmula para la alternativa, o imponiendo la condición $x\neq y$ al generar los números).
Ejemplo 3
Enunciado | <% double h = Random.nextDouble(5,10, 0.5); int m = Random.nextInt(1,5); double g = 9.81; double t = Math.sqrt(2*h / g); double v = Math.sqrt(2*g*h); %> Un solido de <%= m %> kg. se deja caer dentro de un tubo al vacio desde una altura de <%= h %> metros sobre la superficie de la tierra. Determinar el tiempo que tarda el solido en recorrer en tubo. |
---|---|
Patrón respuesta | #<%= t %> s#2% |
Ejemplo | <%= Random.format(t,"#.###") %> segundos |
Ayuda | El resultado es el mismo si la masa fuese de <%= m*2 %> kg. |
En este caso se hace uso de las distintas funciones de la clase siette.util.Random para generar un Enunciado coherente. Por ejemplo, la altura es un número entre 5 y 10 metros a intervalos exactos de medio metro. Esto se consigue con el método nextDouble
. (Por cuestiones estéticas quedaría un tanto extraño que el enunciado dijera … desde una altura de 9877.9128731 metros …
). Al calcular el valor de la solución se ha tenido en cuenta que el alumno puede considerar como valor para la aceleración de la graveda, bien el valor 9.81 o 10; por lo que se establece en el patrón una horquilla del 2% admisible en la respuesta. La instanciación de la plantilla se ejecuta ANTES que la verificación del patrón, por lo que al instanciar simplemente se sustituye en el texto HTML la secuencia <%= t %>
por su valor.
Al definir el patrón no es necesario redondear el valor, sin embargo en el Ejemplo que se muestra como solución al alumno, tambien es necesario mostrar una precisión de no más de tres decimales, suficiente para el problema, por lo que se usa la función format
. Finalmente, nótese que la Ayuda tambien se personaliza, instanciandose a la par que el enunciado.
Ejemplo 4
Enunciado Pregunta Compuesta | <% double h = Random.nextDouble(5,10, 0.5); int m = Random.nextInt(1,5); double g = 9.81; %> Un solido se deja caer en un tubo de vacio en la superficie de la tierra desde una altura de <%= h %> metros |
---|---|
Enunciado Subpregunta 1 | <% double t = Math.sqrt(2*h / g); %> Determinar el tiempo que tarda el solido en recorrer en tubo. |
Patrón Subpregunta 1 | #<%= t %> s#2% |
Enunciado Subpregunta 2 | <% double v = Math.sqrt(2*g*h); %> Determinar la velocidad al llegar al suelo. |
Patrón Subpregunta 2 | #<%= v %> m/s#2% |
Las preguntas compuestas tambien pueden ser preguntas generativas. La instanciación de preguntas compuestas se hace conjuntamente para todas las subpreguntas, componiendo previamente la pregunta, de manera que las variables que se definen en el enunciado de la pregunta compuesta, están ya definidas en os enunciados de las subpreguntas y en las subsecciones de patrones, ayudas, etc..
En el caso de las preguntas compuestas se recomienda meter la mayor parte del código en el enunciado de la pregunta compuesta, y resolver ahí la programación de la plantilla, de manera que las subpreguntas puedan alterar el orden sin por ello comprometer la instanciación.