Mostrando entradas con la etiqueta docap. Mostrar todas las entradas
Mostrando entradas con la etiqueta docap. Mostrar todas las entradas

jueves, 26 de febrero de 2026

Evaluación. Memoria

ENFEN. Fluidez verbal (III)

En esta entrada vamos a tratar con cierto detalle la configuración del procedimiento de análisis de los resultados y la propuestas de automatización del informe tal y como se plantean (inicialmente, vamos a decir ahora) en el DocAp que presenté en la entrada anterior. Pretendo desarrollar este análisis tomando como referencia, además de lo evidente (el soporte Calc el código OOo Basic disponibles), la documentación expuesta en las entradas sobre el paradigma experto-IA (ver entradas en Orient-IA).

Con este análisis pretendo reflexionar sobre hasta qué punto los sistemas de corrección y lo que en este blog se ha planteado en múltiples ocasiones al proponer recursos de evaluación comparten, en gran medida, ese enfoque de trabajo, aunque con limitaciones, deficiencias e insuficiencias añadidas.

Sobre cómo abordan las plataformas la automatización de sus análisis algo hemos dicho en entradas anteriores y algo diremos también aquí, pero el objetivo es centrarme más bien en lo que he planeado con cierta frecuencia como soluciones de automatización tipo DocAp. Cierto es, además, que esta propuesta de solución también ha bebido de esas fuentes, como no puede ser de otro modo, ya que las plataformas de corrección son referentes obligados en términos de forma y de contenido.

En cuanto a estas cuestiones, la fuente o base de conocimiento se explicita en los informes resultantes como análisis descriptivo de la prueba, siempre al inicio del documento y de forma variablemente extensa y detallada. Replicar este contenido en un procedimiento DocAp no ha ofrecido especial dificultad, aunque lo que me genera dudas es su utilidad y, por tanto, su pertinencia. A veces tengo la impresión de que este tipo de contenido sirven de poco y da la impresión de estar ahí para ocultar el escaso contenido de algunos informes. En todo caso, de tener utilidad real la tiene para el profesional (generalmente al profano poco le aporta), siendo que es precisamente éste quien (se supone) menos la necesita.

La segunda cuestión ya presenta mayor complejidad y requiere, por ello, mayor atención: me refiero a las reglas que determinan la relevancia de los datos y el modo en que éstos se analizan. Todavía no estamos aplicando procedimientos del tipo de los explicitados en esta entrada como estrategias de razonamiento, pero son la base para ese paso. Aquí, y en referencia a este DocAp (ENFEN-Fluidez) me tengo que detener ahora.

Diré, en primer lugar, que los datos relevantes son, obviamente, el número de palabras correctamente expresadas por el sujeto, datos estos que se enmarcan dentro de la edad del sujeto, puesto que el análisis está mediatizado por esa única variable. La consecuancia es que el DocAp debe recopilar esa información cuantitativa como base para realizar el posterior análisis de datos. Para ello se desarrolla el siguiente procedimiento:


Sub PuntuarPrueba

Dim oHoja As Object, oCelda As Object
Dim iEdad As Integer, iF1Pd As Integer, iF2Pd As Integer, iDif As Integer
Dim mDif(6) As Double
Dim dDifEsperada As Double
Dim iDifValora As Integer

MF1_Decatipo
MF2_Decatipo

mDif() = Array(4.98,4.53,4.91,5.63,6.15,5.77)

oHoja = ThisComponent.getSheets().getByName("Datos")
oCelda = oHoja.getCellRangeByName("B9")
iEdad = oCelda.getValue()

Select case iEdad
	Case 6
		dDifEsperada = mDif(0)	
	Case 7
		dDifEsperada = mDif(1)	
	Case 8
		dDifEsperada = mDif(2)	
	Case 9
		dDifEsperada = mDif(3)	
	Case 10
		dDifEsperada = mDif(4)	
	Case 11
		dDifEsperada = mDif(5)	
	Case 12
		dDifEsperada = mDif(6)	
End Select

oCelda = oHoja.getCellRangeByName("B10")
iF1Pd = oCelda.getValue()
oCelda = oHoja.getCellRangeByName("B13")
iF2Pd = oCelda.getValue()

iDif = iF2Pd - iF1Pd

If iDif - dDifEsperada > 0  Then
	iDifValora = 1
Else
	iDifValora = 0
End If

oCelda = oHoja.getCellRangeByName("B17")
oCelda.setValue(iDifValora)

	vHoja(0,True)
	PasoHoja (1)
	vHoja(1,False)

End Sub

Mediante este script accedemos a tres celdas ubicadas en la hoja Datos, las cuales contienen el dato edad (B9) y las puntuaciones directas de F1 (B10) y F2 (B13). Lo que sigue se desarrollar mediante llamadas a sendas funciones que calculan los valores de las PD como decatipos según los datos de baremos de la prueba. Me refiero, por ejemplo, a este script para el cálculo del valor decatipo de F1.



Sub MF1_Decatipo

Dim oHoja As Object, oCelda As Object

Dim mF16a(13) As Integer, mF17a(14) As Integer, mF18a(16) As Integer, mF19a(17) As Integer, mF110a(18) As Integer, mF111a(21) As Integer
Dim mF1() As Integer
Dim iEdad As Integer, iF1pd As Integer, iF1Decatipo As Integer, i As Integer, iF1Categoria As Integer

oHoja = ThisComponent.getSheets().getByName("Datos")

mF16a() = Array(1,2,3,4,4,5,6,7,8,8,9,9,9,10)
mF17a() = Array(1,1,1,2,3,3,4,5,5,6,7,8,8,9,10)
mF18a() = Array(1,1,1,1,2,3,4,4,5,6,7,7,8,9,9,9,10)
mF19a() = Array(1,1,1,1,2,3,3,4,5,6,6,7,7,8,8,9,9,10)
mF110a = Array(1,1,1,1,1,1,2,3,3,4,5,6,6,7,7,8,8,9,10)
mF111a() = Array(1,1,1,1,1,1,1,2,2,3,3,4,5,5,6,6,7,8,8,9,9,10)

oCelda = oHoja.getCellRangeByName("B9")
iEdad = oCelda.getValue()

Select Case iEdad
	Case 6
		mF1() = mF16a()
	Case 7
		mF1() = mF17a()
	Case 8
		mF1() = mF18a()
	Case 9
		mF1() = mF19a()
	Case 10
		mF1() = mF110a()
	Case >= 11
		mF1() = mF111a()
End Select

oCelda = oHoja.getCellRangeByName("B10")
iF1pd = oCelda.getValue()

For i = 0 To UBound(mF1())
	mF1(i)
	If i = iF1pd Then
		iF1Decatipo = mF1(i)
		Exit For
	End If
Next

oCelda = oHoja.getCellRangeByName("B11")
oCelda.setValue(iF1Decatipo)

Select Case iF1Decatipo
	Case <= 2
		iF1Categoria = 0
	Case 3
		iF1Categoria = 1
	Case 4
		iF1Categoria = 2
	Case 5
		iF1Categoria = 3
	Case 6
		iF1Categoria = 3
	Case 7
		iF1Categoria = 4
	Case 8
		iF1Categoria = 5
	Case >= 9
		iF1Categoria = 6
End Select

oCelda = oHoja.getCellRangeByName("B12")
oCelda.setValue(iF1Categoria)

End Sub

Aunque este procedimiento no sólo es válido, sino que se puede considerar el único ajustado al procedimiento normativo de análisis del test, implica también aceptar como únicamente válido el modelo clínico subyacente, lo que no es compartido por quienes consideran que la evaluación eductiva, que está orientada a la detección de necesidades específicas de apoyo educativo, se debe diferenciar de la evaluación clínica.

Además, desde una perspectiva de carácter procedimental se puede plantear que en realidad poca información y/o información poco relevente podemos sacar de un análisis como el que se deriva de la aplicación de este tipo de script.

Para finalizar con esta línea de análisis falta analizar cual es la propuesta interpretativa que se planea en estos momentos y en función de ese enfoque, la cual está contenida en el script InfoIndiv(mResultados() del módulo ModExternos, que reproduzco a continuación.



Sub InfoIndiv(mResultados() As Variant)

Dim sRuta As String
Dim mArg()
Dim oNuevoDoc As Object, oTexto As Object

Dim sDatosAlumno As String, sPresenta As String, sPrueba As String
Dim sF1presenta As String, sF1Resulta As String, sF1PDz As String, sF1DecatCat As String, sF1DeCatAnalisis
Dim sF2presenta As String, sF2Resulta As String, sF2PDz As String, sF2DecatCat As String
Dim sF1F2Compara As String
Dim sValora As String, sImplica As String
Dim sTextoInforme As String

'Crear nuevo documento

sRuta = "private:factory/swriter"
oNuevoDoc = StarDesktop.loadComponentFromURL( sRuta, "_default", 0, mArg())

'Construcción del contenido 

'Datos de identificación

sDatosAlumno = "Alumno/a: " & mResultados(0) & " " & mResultados(1) & " Curso: " & mResultados(5)

sPresenta = "ENFE. Funciones ejecutivas. Fluidez"

'Análisis de la prueba ENFEN

sPrueba = "ENFEN (Portellano, Martínez y Zumárraga (2009)) es una batería de pruebas que tienen como objetivo evaluar el nivel de madurez y el rendimiento cognitivo en actividades relacionadas con las funciones ejecutivas. " &_
		  "A nivel psicométrico, la bataría ENFEN está formada por un conjunto de test normativos, cuyas puntuaciones tipificadas se expresan como decatipos (media 5,5; Dt 2). Cada test de la prueba cuenta con un baremos por edades (de 6 años a 11/12 años), lo que nos permite transformar las PD en el decatipo correspondiente en función de la edad. " &_
		  "ENFEN también nos proporciona los estadísticos básicos de cada grupo de edad (Md y Dt), lo que permite analizar la PD del individuo en relación a los resultados medios de su grupo de edad." & Chr(13) & Chr(13) &_
		  "La Fluidez verbal se incluyen en ENFEN como proceso en el que están implicadas funciónes ejecutivas básicas, dada la incidencia de procesos atencionales y de memoria de trabajo. También es posible entender la fluidez verbal como indicador de la capacidad de acceder a la memoria verbal a largo plazo para recuperar la información verbal almacenada en ella. " &_
		  " Además también nos aporta datos relativos al nivel de desarrollo del lenguaje del sujeto." & Chr(13) & Chr(13) &_
		  "En ENFEN se hace uso de dos pruebas de Fluidez verbal, una por clave fonológica (F1) y otra por clave semántica (F2); esto permite realizar comparaciones del rendimiento en ambas en términos normativos y a nivel ipsativo. " &_
		  "A nivel normativo, los datos observados en ambos test son coherentes con los estudios realizados al respecto, mostrando la existencia de una diferencia invariablemente positiva a favor de F2, la cual se mantiene estable en el proceso evolutivo. " &_
		  "Esto se puede entender como consecuencia de la mayor dificultad de la clave fonológica en la recuperación de la información en comparación con el uso de la clave semántica; pero también en el procesamiento del contenido de la memoria a corto plazo."

'Análisis de los resultados en F1

sF1presenta = "Analizamos a continuación los resultados de " & mResultados(0) & " en la prueba de Fluidez Fonológica (F1)" & Chr(13) & Chr(13) &_
			  "La Fluidez fonológica se evalúa en ENFEN solicitando al sujeto la producción de palabras que empiecen por la letra/el sonido 'M'. " &_
			  "En ENFEN se incluye esta prueba para evaluar las funciones ejecutivas por resultar inusual la generación de palabras en base a un criterio fonológico, siendo la habitual el uso de estrategias de base léxico-semántica. Por ello esta exigencia obliga a la persona " &_
			  "a generar estrategias no habituales, requiriendo una organización eficiente de la recuperación verbal, autocontrol e inhibición de las respuestas inapropiadas. " &_
			  "Dado que se exige recuperación de información verbal, también se pone a prueba tanto el mecanismo de acceso al léxico como la propia memoria verbal a largo plazo. Además, el uso de claves fonológicas implica procesos de decodificación y codificación, fundamentales en la lecto-escritura. " &_
			  "Por todo ello la evaluación de la fluidez verbal es de interés para la evaluación de las dificultades de aprendizaje."
			  
'Valoración de la PD en F1

sF1PDz = CalculoZ("F1",mResultados(0),mResultados(8),mResultados(9))

'Valoración del decatipo del sujeto

sF1DecatCat = CatDecatipo(mResultados(11))

sF1DeCatAnalisis = "El decatipo correspondiente a la PD antes analizada es, según el baremo de su grupo etario, " & mResultados(10) & " el cual permite calificar su rendimiento como de nivel " & sF1DecatCat & "."

'Creación del texto de análisis de F1

sF1Resulta = sF1presenta & Chr(13) & Chr(13) & sF1PDz  & Chr(13) & Chr(13) & sF1DeCatAnalisis

'Escritura del contenido

oTexto = oNuevoDoc.Text

oTexto.insertString(oTexto.getEnd(),sDatosAlumno & Chr(13) & Chr(13), False)
oTexto.insertString(oTexto.getEnd(),sPresenta & Chr(13) & Chr(13), False)
oTexto.insertString(oTexto.getEnd(),sPrueba & Chr(13) & Chr(13), False)
oTexto.insertString(oTexto.getEnd(),sF1Resulta & Chr(13) & Chr(13), False)
'oTexto.insertString(oTexto.getEnd(),sTextoInforme, False)

End Sub


Como puedes ver, se trata de una subrutina que genera un documento en base a Writer. Como subrutina es activada desde el script DocumentosExternos mediante la llamada InfoIndiv(mDatos()) que pasa a la subrutina el contenido de la matriz mDatos().

Esta subrutina no está completamente desarrollada (o lo está parcialmente) ya que se limita al análisis de F1, pero contiene suficiente información como para servirnos de base para este análisis.

Empezaré diciendo que aparentemente resulta más compleja de lo que sería deseable, ya que contiene un número muy elevado de variables, lo que indica que posiblemente no se haya realizado un buen análisis previo de estrategias de automatización de los datos. Sobre esta cuestión trataremos en una próxima entrada, ya que ahora interesa que nos centremos en lo que tenemos delante y la alternativa que emerga de este análisis sea suficientemente compleja como para merecer ser expuesta en una entrada diferente.

Volviendo sobre lo observable, la estructura de contenido es la siguiente: datos de identificación del sujeto + descripción de la prueba (2 niveles: general + específico) + análisis de resultados.

Los dos primeros componentes no son de mayor interés ni ofrecen dificultades de implementació, al margen de las dudas ya expuestas sobre su utilidad; pero contienen un volumen total de información nada desdeñable, especialmente en casos como el actual en el que primero se decribe la prueba en su conjunto (ENFEN-Fluidez) y después cada una de las subpruebas que la conforman (en este caso sólo F1. Fluidez fonológica). Sin entrar en el interés que estas descripciones puedan tener, lo cierto es que es muy posible que existan otras formas más adecuadas y útil de manejar toda esta información sin que resulte abrumadora (y hasta distractora) al inicio del informe.

No obstante, se presentan dudas en la tercera fase, en la que se debería concretar la implementación de las reglas de interpretación de los resultados. Es aquí donde este modelo revela sus limitaciones precisamente por la manifiesta ausencia de esas reglas, limitándose a presentar datos (sF1Resulta=sF1presenta&Chr(13)&Chr(13)&sF1PDz&Chr(13)&Chr(13)&sF1DeCatAnalisis) que resultan de la aplicación de determinads funciones como CatDecatipo() a la que llama en sF1DecatCat = CatDecatipo(mResultados(11)). Esta, y no la ausencia de análisis de F2, es la principal carencia de este script.

Esta estrategia, evidentemente muy básica, se puede denominar como "expositiva", pero ponerle un nombre no es suficiente para encubrir lo que no deja de ser la evidencia de una carencia: la falta de criterios de análisis revela la ausencia de teorización sobre la prueba y el significado de los resultados que obtenemos con ella. Implica, en definitiva, carecer de una estrategia de interpretación condicionada.

Al carecer de dicha condicionalidad no es posible identificar en el DocAp ninguna estrategia de análisis, lo que parece (y es) contraproducente con el objetivo que animó la creación del instrumento. Pero "curiosamente" se trata de una "estrategias" de uso mucho más frecuente de lo esperable: al carecer de una teorización sobre el significado de las puntuaciones o al no querer comprometerla, con demasiada frecuencia se opta por la mera exposición de los datos, especialmente en los sistemas de corrección automatizada. En ellos se puede añadir el adorno de alguna categorización, lo cual tampoco compromete gran cosa, dado que corre a cuenta del aparato estadístico de la prueba. El resto queda a la libre y profesional interpretación del especialista, expediente éste perfectamente válido en otros contextos, pero aquí simplemente útil por admitido.

Esta socorrida "solución expositiva" puede ser válida para herramientas de automatización como los sistemas de corrección on-line, lo que dice mucho sobre la utilidad real de los informes que emiten, pero no lo es cuando somos nosotros mismos los que, como profesionales y especialistas, diseñamos nuestras propias herramientas de automatización, bajo nuestros criterios y en función de nuestros objetivos. En estos casos o somos capaces de implementar procedimientos y reglas de análisis o la herramienta que creemos servirá de bien poco.

Cierto es, no obstante, que también podemos limitar conscientemente nuestro proyecto de "automatización" a explicar cuestiones generales sobre el instrumento y sus características, y a formalizar la exposición de resultados. Hacer esto puede ser un objetivo válido y suficiente para algunos y/o en determinadas circunstancias, pero evidentemente deja pendiente el pleno desarrollo de lo que el modelo experto IA promete.

La concreción de esta promesa en el caso concreto de ENFEN-Fluidez queda pendiente para la próxima entrada.

lunes, 23 de febrero de 2026

Evaluación. Memoria

ENFEN. Fluidez verbal (II)

El análisis que de ENFEN-Fluidez realizamos en la entrada anterior es justificación suficiente para el desarrollo de este DocAp, aunque no condiciona el modo en que se concrete. Explicarlo es el cometido de esta entrada.

Como recurso de evaluación, sitúo ENFEN-Fluidez en el segundo nivel de intervención dentro del proceso de evaluación; aquel que implica la intervención individualizada con el alumno, por contraposición al primer nivel o de evaluación de base grupal y/o del alumno en el contexto del aula. Cierto que la simplicidad de la aplicación de esta prueba no impide radicalmente su aplicación en el grupo, pero parece más apropiado aplicarla como parte de la evaluación individual.

Otra cosa es si podemos pensarla dentro de un contexto de colaboración con servicios clínicos externos, lo cual es perfectamente factible, pero realmente esa es una cuestión secundaria: aplicar ENFEN-Fluidez está suficientemente justificada por si misma en función de lo que aporta para la identificación diferenciada de dificultades de aprendizaje, por lo que aporta respecto a la evaluación de las capacidades de memoria verbal, y por lo que aporta para la identificación de posibles dificultades de naturaleza escolar y la incidencia en que ellas tienen factores ambientales y/o del desarrollo de procesos básicos de aprendizaje.

Aunque ambas cuestiones no dejan de tener interés para el diseño de la intervención, lo cierto es que en términos operativos, ahora resultan poco relevantes, dado el objetivo de la entrada. Corresponde, eso sí, explicar en qué consiste el DocAp.

Lo primero es decir, precisamente, que se trata de un Docap; esto es un recurso que integra una serie de procesos (que veremos después) basándose en los servicios de LibreOffice, y que es posible gracias al empleo del lenguaje OOo Basic.

Como DocAp se puede calificar como DocAp complejo dado que requiere de la intervención de dos servicios, aunque tal y como se configura podríamos identificarlo como DocAp simple, puesto que la versión que aquí presento no se ha desarrollado del todo, por lo que sólo se hace uso de Calc, quedando Writer como soporte complementario, únicamente "a modo de prueba".

La automatización es, pues, parcial, aunque lo es por motivos que explicaré en su momento; no precisamente por carecer de los medios técnicos para alcanzar niveles óptimos de desarrollo como DocAp: no culminar la lógica implícita (de automatización) es una decisión tomada conscientemente, a pesar de disponer de los medios para hacerlo. Nos quedamos a las puertas de automatizar la generación del informe de resultados (1) para dedicar una entrada específica a tratar este tema en el marco del análisis las opciones disponibles, concretamente de la viabilidad de lo que podríamos llamar de forma un tanto grandilocuente modelo experto de automatización (2).

Por eso, hasta aquí me limito a presentar en esta entrada la automatización de la aplicación y la puntuación del test, quedando pendiente el análisis de resultados y la generación del informe individualizado. Todo ello se concreta un soporte Calc que deriva de otro utilizado hace tiempo para digitalizar y recoger datos de la escala ENFEN al completo (no exclusivamente de las pruebas de fluidez). En el original no existía prácticamente automatización, pero en el actual sí, heredando en ello el modelo aplicado en una antigua versión Filemaker que sí automatizaba la puntuación, un somero análisis de los datos y la emisión de un breve informe personalizado de resultados.

El DocAp actual consta formalmente de tres hojas (Id, Pruebas y Datos), de las cuales sólo la primera está visible al abrir el documento. Pero la complejidad real del DocAp está en el código, responsable de su funcionamiento, visible desde el IDE y que contiene lo siguiente:

Como ves, se diferencian 6 módulos y 22 script. Este conjunto de elementos hace posible que se desarrollen los procesos de automatización del DocAp y que explicaré resumidamente en base a lo que la visualización de la interface permite entrever.

En hoja Id encuentras un formulario basado en celdas, destinado a recoger los datos de identificación del alumno, y lo que es la síntesis de resultados de la aplicación del test.

Además tienes dos comandos: uno (APLICAR TEST) para continuar con la aplicación de la prueba y otro (BORRAR) para borrar el contenido antiguo, si es que está aun visible. Como sabes, ambos están asociados a la ejecución de sendos script.

La segunda hoja queda accesible al activar el botón APLICAR TEST y contiene, como cabe esperar, el sistema de recogida de datos y el de puntuación del test. Ambos funcionan mediante los comandos respectivos: Contador F1 Y Contador F2 para capturar las respuestas (el número de respuestas) y PUNTUAR para realizar la puntuación del test en función de los estadísticos de la prueba.

En este caso sí me interesa detenerme en la explicación del funcionamiento de estos comandos, ya que presenta cierta diferencia respecto a los procedimientos conocidos de puntuación de la ejecución. Esto es así porque en estas pruebas de fluidez lo que nos interesa es capturar el número de respuestas correctas que emita el sujeto, y nada más. De ahí que hayamos ideado un procedimiento de contador de aciertos que se concreta en dos script, uno por cada prueba (Fonológica - Semántica) asociados a sendos comandos (aquí el script del contador F1)...



Sub ContadorF1

Dim oHoja As Object, oCelda As Object
Dim i As Integer

'Acceso a la hoja Pruebas
oHoja = ThisComponent.getSheets().getByName("Pruebas")

'Acceso a la celda contador
oCelda = oHoja.getCellRangeByName("G2")
i = oCelda.getValue

i = Contador(i)

oCelda.setValue(i)

End Sub

... y ambos script a la función Contador()

Function Contador(i As Integer) As Integer

Contador = i + 1

End Function


El comando PUNTUAR presenta un código más complejo, que conforma los tres script (un script y dos subrutinas) que contiene el módulo ModPuntuar, al que te remito: básicamente consiste en lo siguiente:

  • El comando PUNTUAR permite acceder al script PuntuarPrueba, el cual captura el valor del contador de las celdas F1 (G2) y F2 (G12) y se lo pasa a sendas subrutinas, una para puntuar cada una de las pruebas atendiendo a la edad del niño y a los datos estadísticos de los respectivos baremos.
  • Finalmente traslada los datos resultantes también a la hoja Datos.

Dada la extensión de estos script, remito al IDE para su lectura y análisis. La explicación que sea pertinente para retomar la actualización del soporte se realizará en ese momento.

Para finalizar ahora esta entrada, sólo resta señalar que la hoja Datos contiene una sencilla tabla de datos con los de identificación y los resultados de ambos test.

A partir de estos datos será posible crear una base de datos acumulativa, y desarrollar un modelo de informe de resultados, única fase de la automatización de este test que aunque ha sido desarrollada, no se muestra accesible mediante un botón de comando.

No obstante, si lo deseas y a modo de borrador, puedes generar un modelo de informe sobre Writer activando directamente el script DocumentosExternos ubicado en el módulo ModExternos.

Documento. Descarga del DocAp de la prueba

Notas:

1 En realidad también queda pendiente la generación de la base de datos, pero en este caso es más una cuestión de simplificación del procedimiento, mucho menos justificable que lo anterior.
2 Tiempo habrá de bajar expectativas, pero lo cierto es que, en esencia, es precisamente de lo que se trata aquí: ¿es posible diseñar contantemente alternativas de automatización basadas en el conocimiento (teóricamente) del experto?. ¿cuáles son realmente las alternativas disponibles?. Se comprenderá que, así presentada la cuestión, sea conveniente abordar este tema de forma específica. Bien vale una entrada... cuanto menos.

jueves, 18 de diciembre de 2025

Matemáticas

Cálculo básico

PCA. Canarias. DocAp

Concretando el procedimiento de análisis de resultados esbozado en la [entrada precedente], presento en ésta una propuesta de DocAp, compuesto por un gestor, una base de datos (ambos Calc) y un modelo de informe (Writer).




El gestor o soporte es el documento principal, ya que es el que contiene el código del DocAp. Volveremos sobre este soporte para analizar su contenido.

La base de datos es un documento Calc preconfigurado como base de datos, esto es, para contener el listado de los resultados de todas las aplicaciones de la prueba. El objetivo de este documento es recopilar los datos que permitirá desarrollar baremos locales en su momento, y a medio plazo facilitar el análisis de los datos recogidos.

Finalmente, el informe es un documento Writer que se genera automáticamente mediante código y que contiene la información resultante del análisis de cada ejecución individual. En teoría este informe se incorpora al expediente SEO de cada alumno y/o a un directorio de resultados grupales.

Dicho lo anterior, describo ahora el funcionamiento general del DocAp. Después analizaré el código que lo hace posible.

En estos momentos el DocAp está pensado para ser usado por el OE a modo de corrector de la ejecución del alumnado. Supuesta una aplicación grupal (aunque también es posible el uso en evaluación individual), en la que el alumnado emplea el documento que contiene las operaciones y las resuelve como prueba de lápiz y papel, el orientador recoge los materiales e individualmente va trasladando, uno por uno, los datos al soporte.

Se inicia el procedimiento introduciendo los datos de identificación en el formulario de la primera hoja del gestor...


... y se pulsa en el comando RESOLVER OPERACIONES , lo que activa el script encargado de facilitar el acceso al proceso siguiente. El comando BORRAR DATOS, está pensado para facilitar el manejo del DocAp permitiendo la eliminación automática de los datos del alumno anterior.

La segunda fase consiste en la introducción de los resultados (numéricos) de todas las operaciones resueltas por el alumno, lógicamente, en la posición que corresponde al identificador de la operación. Todo esto tiene lugar en la hoja Operaciones, que inicialmente está oculta.


El tercer y último paso consiste en pulsar en el comando FINALIZAR PRUEBA, una vez cumplimentado el conjunto del listado. El resto del procedimiento se desarrolla de forma automática (por medio de código), que reside en el IDE del soporte y cuya estructura de contenidos te muestro en la captura de pantalla siguiente.



El script principal (Main) queda diferenciado del resto para facilitar su localización. Desde él se activa la mayor parte del procedimiento del DocAp, aunque en el módulo auxiliares puedes encontrar algunos script que se asocian a procedimientos complementarios, de funcionamiento independiente, como es el caso del script BorrarDatos, cuya función ya te expliqué en relación al comando del mismo nombre.

Sub Main

Dim oHoja As Object, oCelda As Object
Dim i As Integer
Dim mRespuestas(36) As Variant
Dim mDatos(43) As Variant

'Acceso a la hoja Operaciones
oHoja = ThisComponent.getSheets().getByName("Operaciones")
'Copia de los datos de respuesta
For i = 0 To UBound(mRespuestas())
oCelda = oHoja.getCellRangeByName("D" & i+5)
mRespuestas(i)= oCelda.getString
Next

'Acceso a los datos del alumno
oHoja = ThisComponent.getSheets().getByName("Datos")
'Copia de las respuestas
For i = 0 To UBound(mRespuestas())
oCelda = oHoja.getCellRangeByName("C" & i+7)
oCelda.setString(mRespuestas(i))
Next 
'Paso de datos a matriz de resultados
For i = 0 To 43
oCelda = oHoja.getCellRangeByName("B" & i+1)
mDatos(i) = oCelda.getString
Next

' Acceso a base de datos
AccesoBD(mDatos())

'Creación de informe individualizado
InfoIndiv(mDatos())

'Movimiento a la hoja DatosId (retorno)
vHoja(0,True)
PasoHoja(0)
vHoja(1,False)

End Sub

La función real de este script es gestionar parte importante de los procedimientos fundamentales del DocAp, pero otras partes corren a cargo de script teóricamente secundarios (subrutinas y funciones) pero que son tan importantes como el propio script principal. Es el caso del script que se encarga de trasladar los datos a la base de datos y del conjunto de estructuras que permiten el análisis de los resultados y la composición y posterior escritura del informe individualizado. Ambos subprocedimientos se ubican en sus respectivos módulos y el acceso o llamada a ellos está indicada en negrita en la representación anterior del código de Main.

Además de estas llamadas, Main desarrolla el procedimiento consistente en capturar el listado de puntuaciones que el usuario introduce en Operaciones y trasladarlo a la hoja Datos (también oculta), para después copiar en una matriz (mDatos()) todos los datos relevantes de esta hoja para su traslado como parámetro al código de los script de procesamiento (vg. AccesoBD(mDatos())). En lo fundamental, todas estas manipulaciones de datos se realiza mediante bucles, vg...

'Acceso a los datos del alumno
oHoja = ThisComponent.getSheets().getByName("Datos")
'Copia de las respuestas
For i = 0 To UBound(mRespuestas())
oCelda = oHoja.getCellRangeByName("C" & i+7)
oCelda.setString(mRespuestas(i))
Next 

... lo que ahorra líneas de código y permite que la ejecución sea más eficiente y rápida.

El traslado de los datos a la base de datos se realiza mediante esta subrutina que recibe la matriz que contiene el conjunto de datos como parámetro (Sub AccesoBD(Datos() As Variant))

Sub AccesoBD(Datos() As Variant)

Dim sRuta As String
Dim mArg()
Dim oBD As Object, oHojaBD As Object, oCeldaCampo As Object, oCeldaNuevoRegistro As Object
Dim i As Integer, a As Integer, b As Integer
Dim sEntrada1 As String

'Acceso a los objetos documento (BD_PCA.ods) y Hoja (DatosPrueba)

sRuta = ConvertToUrl("D:/RecursosEvaluacion/Matematicas/CalculoCanariasPCA/BD_PCA.ods")
oBD = StarDesktop.loadComponentFromURL(sRuta, "_blank", 0, mArg())
oHojaBD = oBD.getCurrentController.getActiveSheet()

'Búsqueda del primer registro vacío

For i = 0 To 200
oCeldaCampo = oHojaBD.getCellRangeByName("A" & CStr(i+1))
sEntrada1 = oCeldaCampo.getString()
If sEntrada1 = "" Then
a = i
Exit For
End If
Next

'Escritura de los datos en el registro vacío

For b = 0 To UBound(Datos())
oCeldaNuevoRegistro = oHojaBD.getCellByPosition(b,a)
oCeldaNuevoRegistro.setString(Datos(b))
Next

'Guardar cambios

oBD.store()

'Cerrar BDPruebas.ods

oBD.close(True)

End Sub

Su funcionamiento, ya descrito en una entrada anterior, queda descrito en los comentarios y consiste, en resumen, en acceder al documento  BD_PCA.ods, buscar el primer registro (fila) libre y copiar en él los datos de la matriz-parámetro. Posteriormente se graba el archivo (oBD.store()) y se cierra (oBD.close(True)). Este funcionamiento implica que cada nuevo registro (alumno) se debe volver a repetir todo el procedimiento, pero su ejecución pasa desapercibida para el usuario del DocAP, ya que está totalmente automatizado.

También está automatizado el análisis de los resultados y la escritura del informe, subproceso que corre a cargo del conjunto de script ubicados en el módulo informe

Dada la complejidad de este procedimiento he optado por dividirlo en tres partes: la primera y principal (Sub InfoIndiv(mResultados() As Variant)) es una subrutina que recibe como parámetro los datos resultantes de la aplicación y que llama a dos funciones para procesarlos desde dos perspectivas diferentes y complementarias. Además, esta subrutina tiene como función la composición del texto del informe, la creación del documento y la escritura del contenido.

Sub InfoIndiv(mResultados() As Variant)

'Variables para análisis de datos

Dim mDatPer(5) As String

Dim mPtos(36) As Integer

Dim curso As String

Dim PD As Integer

'Variable para texto de la valoración

Dim PruebaId As String, PruebaDescrip As String

Dim DatosId1 As String, DatosId2 As String

Dim ValorResulta As String,txtInfoCurso As String

Dim ValoraTipOpera As String,txtContenApoyo AS String

'Variables para la creación y la escritura del informe

Dim sRuta As String

Dim mArg()

Dim oNuevoDoc As Object, oTexto As Object

Dim TextoInforme As String

'Pasar datos de la matriz original a las de procesamiento

For i = 0 To 5

mDatPer(i) = mResultados(i) ' Para datos personales

Next

For i = 0 To UBound(mPtos())

mPtos(i) = CInt(mResultados(i+6)) ' Para las puntuaciones de los ítem

Next

PD = CInt(mResultados(43)) ' Para la puntuación total o PD

curso = mResultados(3)    ' Para identificar el curso

'Análisis condicionado al curso sobre la puntuación directa

txtInfoCurso = InfoCurso(curso,PD)

'Análisis condicionado sobre contenidos de los apoyos

txtContenApoyo =  ContenApoyo(curso, mPtos())

'Construcción del contenido del informe

PruebaId = "Prueba de Cálculo Aritmético (PCA). Canarias" & Chr(13) & Chr(13)

DatosId1 = "Centro escolar " & mDatPer(4) & "  " & Chr(13) & "Alumno/a " & mDatPer(0) & " " & mDatPer(1) & " Curso " & curso & Chr(13)

DatosId2 = "Fecha de evaluación " & CStr(mDatPer(5)) & Chr(13) & Chr(13)

PruebaDescrip = "La Prueba de Cálculo Aritmético de Canarias (PCA) tiene como finalidad conocer el nivel competencial de los escolares de Educación Primaria en las cuatro operaciones básicas (suma, resta, multiplicación y división), el empleo de los decimales y de las fracciones. Por ello se puede utilizar para identificar la dificultades específicas de aprendizaje del cálculo en la etapa de E. Primaria." & Chr(13) & "Esta prueba está formada por 37 operaciones. Las 20 primeras son de sumas y restas y se distribuyen entre sumas con una o más cifras, con o sin llevadas, y restas con una o más cifras, con o sin llevadas. Las 17 restantes abarcan operaciones con multiplicaciones de una o dos cifras, con y sin decimales; divisiones por una y dos cifras, con y sin decimales; y finalmente el empleo simple de las fracciones." & Chr(13)

ValorResulta =  mDatPer(0) & " ha resuelto satisfactoriamente " & PD & " operaciones, por lo que, " & txtInfoCurso & Chr(13)

ValoraTipOpera = "Por lo que se refiere a la tipología de las operaciones aritméticas que comprender la PCA, los resultados de " & mDatPer(0) & " merecen las siguientes valoraciones: " & Chr(13) & txtContenApoyo & Chr(13) &  Chr(13) & "En consecuencia, de resultar necesaria algún tipo de intervención de apoyo, esta debería centrarse en las operaciones en las que sus resultados indican cierto grado de dificultad."

TextoInforme = PruebaId & DatosId1 & DatosId2 & Chr(13) & PruebaDescrip & Chr(13) & ValorResulta & Chr(13) & ValoraTipOpera

' Trabajo con el documento de texto y escritura del contenido

sRuta = "private:factory/swriter"

oNuevoDoc = StarDesktop.loadComponentFromURL( sRuta, "_default", 0, mArg())

oTexto = oNuevoDoc.Text

oTexto.insertString(oTexto.getEnd(),TextoInforme, False)

End sub

Los comentarios permiten identificar cada fase del desarrollo del script y en negrita se identifica el acceso a las funciones complementarias que muestro a continuación, empezando por el análisis de categorización...

Function InfoCurso (curso As String, pd As Integer) As String

'Datos condicionantes del análisis (por curso)

Dim i As Integer

Dim mCursos(4) As String

mCursos = Array("P2","P3","P4","P5","P6")

Dim CursoActual As String

Dim min(4) As Integer ' Valor de la puntución mínima

min= Array(3,6,9,12,9)

Dim moda(4) As Integer 'Valor de la moda

moda=Array(17,22,24,25,31)

Dim pc25(4) As Integer ' Valor inferior al pc 25

pc25=Array(13,17,19,22,24)

Dim pc75(4) As Integer 'Valor superior al pc 75

pc75=Array(20,23,26,29,32)

'Variables para construir el texto de respuesta

Dim txtNivelRendimiento As String

Dim txtPropuestaApoyo As String

Dim txtInfo As String

Dim txtInfoFinal As String

'Análisis en función del curso

For i = 0 To 4

CursoActual = mCursos(i)

If CursoActual = curso Then

If pd < min(i) Then

txtNivelRendimiento = "se considera que su nivel de rendimiento es extremadamente bajo."

txtPropuestaApoyo = "En consecuencia se requiere una intervención especializada de apoyo intensivo."

txtInfo = txtNivelRendimiento & " " & txtPropuestaApoyo

Else

If pd <= pc25(i) Then

txtNivelRendimiento = "su nivel de rendimiento se considera inferior al esperado."

txtPropuestaApoyo = "En consecuencia se requiere una intervención específica de apoyo."

txtInfo = txtNivelRendimiento & " " & txtPropuestaApoyo

Else

If pd > pc25(i) and pd < pc75(i) Then

txtNivelRendimiento = "se considera que su nivel de rendimiento se ajusta a lo esperado."

txtInfo = txtNivelRendimiento

Else

If pd >= pc75(i) Then

txtNivelRendimiento = "se considera que sus resultados se sitúan en niveles superiores a los esperados."

txtInfo = txtNivelRendimiento

End If

End If

End If

End If

End If

Next

txtInfo2 = "atendiendo a esos resultados y en función del curso (" & curso & "), " & txtInfo

InfoCurso = txtInfo2

End Function

... cuyo núcleo principal es la estructura de bucle + condicionales anidados que se encuentran a continuación del comentario 'Análisis en función del curso. Obsérvese el uso que se hace en él de la asociación del contenido de las matrices en función de la posición de los datos en términos de curso o nivel. En negrita se identifica lo que devuelve la función a la subrutina que la activa.

De forma similar sucede con la función que analiza los resultados en términos de categorías de operación aritmética...

Function ContenApoyo(curso As String, mPtos() As Integer) As String

Dim txtApoyo AS String

Dim i As Integer, j As Integer

Dim mCatPd(9) As Integer

mCatPd = Array (3,3,4,3,3,4,4,4,5,4)

Dim mResCat(9) As Integer

Dim ContCat(9) As String

Dim OperaTipo(9) As String

Dim mCategorias(36) As String

mcategorias=Array ("A","A","A","C","B","D","D","C","B","B","D","F","C","C","F","E","E","E","F","F","G","G","G","H","H","I","H","G","I","I","I","J","H","I","J","J","J")

'Operaciones de cada categoría

ContCat(0) = "sumas de un dígito sin llevadas (A)"

ContCat(1) = "sumas de dos y tres dígitos sin llevadas (B)"

ContCat(2) = "sumas de uno, dos y tres dígitos con llevadas (C)"

ContCat(3) = "restas de un dígitos sin llevadas (D)"

ContCat(4) = "restas de dos y tres dígitos sin llevadas (E)"

ContCat(5) = "restas de uno a tres dígitos con llevadas (F)"

ContCat(6) = "multiplicaciones por uno y dos dígitos (G)"

ContCat(7) = "divisiones por uno y dos dígitos (H)"

ContCat(8) = "multiplicaciones con decimales (I)"

ContCat(9) = "operaciones con fracciones (J)"

'Sumatorios de resultados por categorías

For i = 0 To UBound(mPtos())

If mcategorias(i) = "A" Then

mResCat(0) = mResCat(0) + mPtos(i)

End If

If mcategorias(i) = "B" Then

mResCat(1) = mResCat(1) + mPtos(i)

End If

If mcategorias(i) = "C" Then

mResCat(2) = mResCat(2) + mPtos(i)

End If

If mcategorias(i) = "D" Then

mResCat(3) = mResCat(3) + mPtos(i)

End If

If mcategorias(i) = "E" Then

mResCat(4) = mResCat(4) + mPtos(i)

End If

If mcategorias(i) = "F" Then

mResCat(5) = mResCat(5) + mPtos(i)

End If

If mcategorias(i) = "G" Then

mResCat(6) = mResCat(6) + mPtos(i)

End If

If mcategorias(i) = "H" Then

mResCat(7) = mResCat(7) + mPtos(i)

End If

If mcategorias(i) = "I" Then

mResCat(8) = mResCat(8) + mPtos(i)

End If

If mcategorias(i) = "J" Then

mResCat(9) = mResCat(9) + mPtos(i)

End If

Next

'Número de categorías a analizar en función del curso

If curso = "P2" Then

j = 4

ElseIf curso = "P3" Then

j = 5

ElseIf curso = "P4" or curso = "P5" Then

j = 6

ElseIf curso = "P6" Then

j = 7

End If

For i = 0 To j

If mResCat(i) =  mCatPd(i) Then

OperaTipo(i) = "* Resuelve satisfactoriamente " & ContCat(i)

ElseIf mResCat(i) =  (mCatPd(i)-1) Then

OperaTipo(i) = "* Podría presentar dificultades para resolver " & ContCat(i)

ElseIf mResCat(i) <=  (mCatPd(i)-2) Then

OperaTipo(i) = "* Presenta importantes dificultades para resolver " & ContCat(i)

End If

txtApoyo = txtApoyo & Chr(13) & OperaTipo(i)

Next

ContenApoyo = txtApoyo

End Function

En este caso, el objetivo es valorar las implicaciones de los resultados organizados en función de la tipología operacional en que se diferencian los distintos reactivos de que consta la prueba. La idea (en este momento) es que, al tratarse de una prueba de tipo screening, cualquier fallo en cualquier ítem (operación) implica un posible nivel de dificultad/riesgo en términos de limitación competencial específica. La ausencia de errores se entiende, en principio, como ausencia de dificultad.

Con esta idea (y sus implicaciones en términos de contenido en el apoyo educativo) como marco de referencia, se implementa también en el análisis la consideración del nivel escolar (curso) en que se sitúa el alumno, ya que los segmentos operatorios o tipo de operaciones que comprende un curso no son los que corresponden a otro, por lo que el enjuiciamiento sólo tiene sentido para aquellos (tipos de operaciones) que correspondan.

Lo que devuelve esta función (en negrita) es simplemente el listado de valoraciones de los bloques de contenido que corresponde emitir en función del curso o nivel del sujeto.

Documentos. Desde [este enlace] tienes acceso a los materiales que componen este DocAp. Es un archivo comprimido que podrás ubicar como carpeta donde desees, aunque deberás modificar la línea de código (sRuta = ConvertToUrl("D:/RecursosEvaluacion/Matematicas/CalculoCanariasPCA/BD_PCA.ods")) que localiza el documento de base de datos (subrutina Sub AccesoBD()).