Con la entrada en vigor del currículo revisado de 2022, aumentaron las asignaturas y, en consecuencia, apareció la tarea de tener que redactar un nuevo plan de evaluación cada semestre.
El problema es que el plan de evaluación exige como trámite formal que se consignen todos los criterios de logro y niveles de logro por unidad.
Estos criterios no son algo que el docente redacte aparte, sino que simplemente se copian y pegan.
Por eso, después de organizar estos contenidos en una tabla, decidí combinarlos automáticamente usando las funciones FILTER y TEXTJOIN de Excel u hojas de cálculo.
1. Crear la base de datos de niveles de logro
Los niveles de logro de cada asignatura optativa se pueden obtener en el siguiente portal de apoyo a la evaluación del alumnado del KICE.
En el índice superior, basta con ir a [초/중/고] -> [교육과정 성취기준] -> [성취기준 자료실], buscar y descargar.
Por ejemplo, los niveles de logro de “세계시민과 지리” son como se muestra a continuación.
El problema es que estos criterios de logro son al menos 15, y hay que copiar y combinar los niveles de logro de cada criterio de logro desde A hasta E.
Ahora organicemos estos materiales en una tabla.

Primero, convierto el archivo en hwp a un archivo hwpx.
El archivo hwpx almacena la estructura interna del archivo como datos xml, por lo que permite analizar su interior con otros programas.

Luego, usando Python, extraigo las tablas internas del hwpx.
Por supuesto, el código de abajo fue elaborado con la ayuda del maestro chatGPT.
Como el archivo hwpx tiene una estructura zip + xml, se puede leer el xml interno con Python y extraer las tablas.
// 이 코드는 생성형 AI를 이용해 제작한 코드입니다.
import zipfile
import xml.etree.ElementTree as ET
from openpyxl import Workbook
hwpx_path = "사회과 선택과목 성취수준 현장 보급본.hwpx"
xlsx_path = "output.xlsx"
def tag_name(elem):
return elem.tag.split("}")[-1]
def collect_text(node):
texts = []
# tc 내부에 중첩 tbl이 있으면 그 하위 텍스트는 제외한다.
stack = [node]
while stack:
cur = stack.pop()
if cur is not node and tag_name(cur) == "tbl":
continue
if tag_name(cur) == "t" and cur.text:
t = cur.text.strip()
if t:
texts.append(t)
children = list(cur)
stack.extend(reversed(children))
return "\n".join(texts)
def is_title_like(text):
if not text:
return False
compact = text.replace(" ", "")
# 표 전체 내용을 붙여 놓은 긴 문장은 제목으로 취급하지 않는다.
if len(text) > 80:
return False
# 표 헤더/본문 키워드가 포함되면 제목 행으로 넣지 않는다.
if "성취기준" in compact and "성취수준" in compact:
return False
return True
wb = Workbook()
ws = wb.active
ws.title = "tables"
saved_table_count = 0
current_row = 1
with zipfile.ZipFile(hwpx_path, "r") as z:
section_files = sorted(
name for name in z.namelist()
if name.startswith("Contents/section") and name.endswith(".xml")
)
for section_file in section_files:
xml_data = z.read(section_file)
root = ET.fromstring(xml_data)
elems = list(root.iter())
for i, elem in enumerate(elems):
if tag_name(elem) != "tbl":
continue
tbl = elem
prev_text = ""
for j in range(i - 1, -1, -1):
if tag_name(elems[j]) != "p":
continue
texts = []
for x in elems[j].iter():
if tag_name(x) == "t" and x.text:
t = x.text.strip()
if t:
texts.append(t)
candidate = " ".join(texts)
if not candidate:
continue
if is_title_like(candidate):
prev_text = candidate
break
table_rows = []
for tr in tbl:
if tag_name(tr) != "tr":
continue
row_values = []
for tc in tr:
if tag_name(tc) != "tc":
continue
row_values.append(collect_text(tc))
if row_values:
table_rows.append(row_values)
if not table_rows:
continue
preview_text = "".join(table_rows[0])
# 1행 1셀 같은 요약성/오검출 표는 제외한다.
has_enough_shape = len(table_rows) >= 2 and any(len(r) >= 2 for r in table_rows)
if "성취기준별" in preview_text and "성취수준" in preview_text and has_enough_shape:
saved_table_count += 1
table_title = prev_text if is_title_like(prev_text) else ""
for row_values in table_rows:
# 1열에는 표 제목을 두고, 실제 표 데이터는 오른쪽(2열부터) 배치한다.
ws.cell(row=current_row, column=1, value=table_title)
first_value = row_values[0].strip() if row_values and isinstance(row_values[0], str) else ""
start_col = 3 if first_value in {"B", "C", "D", "E"} else 2
for col_idx, value in enumerate(row_values, start=start_col):
ws.cell(row=current_row, column=col_idx, value=value)
# 오른쪽으로 밀린(B/C/D/E) 행은 표의 첫 번째 열(2열)을 바로 윗행 값으로 채운다.
if start_col == 3 and current_row > 1:
ws.cell(row=current_row, column=2, value=ws.cell(row=current_row - 1, column=2).value)
current_row += 1
# 표 사이 한 줄 띄우기
current_row += 2
if saved_table_count == 0:
ws["A1"] = "조건에 맞는 표를 찾지 못했습니다."
wb.save(xlsx_path)
print(f"완료: {saved_table_count}개 표를 하나의 시트에 저장")Al hacerlo, las tablas internas se extraen como se muestra abajo.
Si aun así hay tablas que no se extraen correctamente, depuremos manualmente un poco los datos.

Simplemente utilicé el filtro y la opción de dividir texto en Excel para separar el código de criterio de logro, el contenido y el nivel de logro por criterio de logro.
Si los normalizáramos, el rendimiento mejoraría, pero como resultaría difícil de verificar para una persona, decidí dejarlos como columnas duplicadas.
Y después de hacer esto, me quedé pensando que quizá habría sido mejor solicitar la publicación de la base de datos.
2. Crear la hoja de cálculo
En la mayoría de las escuelas, en el plan de evaluación se incluyen el código de logro y el criterio de logro correspondientes a cada semana.
Por eso pensé que, si se configura de forma que al seleccionar solo el código de logro por mes se rellene automáticamente, la introducción del plan de evaluación sería mucho más sencilla.
La hoja de cálculo se creó combinando la asignatura, la unidad y el código de logro que se quiere introducir, mediante las funciones filter y unique.
Si resulta difícil, recomiendo probar a crearla junto con una IA.

En la primera pestaña, diseñé el sistema de modo que, al introducir mes, semana, nombre de la unidad y código de criterio de logro, solo haya que copiar y pegar desde la parte más a la derecha.
La casilla verde del centro la hice para comprobar los criterios de logro que yo mismo introduje.
De este modo, al seleccionar, se completan todos los criterios de logro y niveles de logro por unidad, así como los niveles de logro a nivel de semestre.

En realidad, en las asignaturas generales se incluyen todos los criterios de logro en el plan de evaluación, así que no importaría volcarlos todos, pero lo diseñé teniendo en cuenta la reconfiguración del currículo.
Estoy pensando si añadir también una hoja que simplemente combine todos los niveles de A a E.
Y preparé también una hoja para la evaluación del desempeño.

Si introduzco los códigos de criterio de logro que quiero incluir en la evaluación del desempeño, combina todos los niveles de A a E de forma que puedan insertarse en el plan de evaluación.
Lo que debemos reflexionar no es sobre copiar y pegar, sino sobre qué tipo de evaluación debe realizarse realmente.
3. Reseña de uso

Lamentablemente, a pesar de que muchos docentes dedican mucho tiempo al plan de evaluación, nadie en el aula siente curiosidad por las oraciones de los niveles de logro.
Esto se debe a que lo importante no es tanto el plan de evaluación como la evaluación misma, implementada de acuerdo con el plan.
Si preguntáramos a quienes se graduaron desde que se empezó a incluir los criterios de logro en los criterios de evaluación cuáles eran esos criterios de logro, puedo decir con confianza que nadie lo recordaría.
Por eso, se podría decir que incluir este tipo de frases en los criterios de evaluación no es más que un trámite formal sin sentido.
La realidad educativa que tiene lugar en la escuela no es estática como los códigos de logro o los criterios de logro, sino dinámica.
Siento que necesitamos dedicar más tiempo no tanto a la perfección documental del plan de evaluación, sino a reflexionar sobre los problemas cualitativos de la evaluación en sí.
Probablemente no podré publicar una reseña de uso adecuada hasta después de utilizarlo realmente, hacia julio u agosto.
Cuando compartí esta hoja de cálculo con el profesor de al lado, se alegró diciendo que parecía poder elaborar ahora mismo el plan de evaluación del segundo semestre.
Creo que será de gran ayuda para muchos.




댓글을 불러오는 중...