Generador offline de preguntas para MoodleEste pequeño programa en Python permite generar preguntas para
Moodle con formato XML, a partir de un archivo de texto con formato
YamlEsto permite editar, generar y modificar las preguntas con mayor rapidez que con la interface de Moodle.
Es necesario conocer bien previamente, cómo rellenar los formularios de Moodle para generar preguntas.
Tipos de preguntas Moodle que se pueden generar: Cloze, Multichoice, Matching,
Las preguntas también se pueden agrupar por categorías.
Un pequeño ejemplo incluído ayuda a entender el formato del archivo de datos Yaml.
Para manejar las plantillas se utiliza el sistema de plantillas
Jinja2.
Para ejecutar el programa, es necesario instalar previamente en el ordenador:
Python 2.7 Jinja 2 MarkupSafe YamlCódigo Python:
# -*- coding: utf-8 -*-
import jinja2
import codecs
import yaml
import os
# Establece las opciones por defecto
options = {
'template_path': 'templates',
'template': 'moodle.xml',
'feedback': '',
'shuffle': 0,
'grade': 1,
'penalty': 0.5,
'image': '',
}
def main():
for f in os.listdir('.'):
process(f)
def process(fi_name):
global options
# Comprueba que el fichero de entrada es de tipo yaml
if fi_name[-5:].lower() != '.yaml':
return
print 'Process', fi_name
# print yaml.dump([1,2,3, [4, 5, 6], 7])
# return
# Lee los datos del fichero yaml
text = codecs.open(fi_name, 'r', 'utf-8').read()
database = []
for data in yaml.load_all(text):
database.append(data)
# Lee las cuestiones
for data in database:
# Read external options
try:
opt = data[0]['options']
for item in opt:
options[item] = opt[item]
print ' Template =', options['template']
data = data[1:]
except:
pass
# Load and run template
templateEnv = jinja2.Environment(loader=jinja2.FileSystemLoader(options['template_path']))
template = templateEnv.get_template(options['template'])
outputText = template.render(database=data, opt=options)
# Elimina el BOM del fichero UTF8
while (outputText[:1].encode('ascii', 'xmlcharrefreplace') == ''):
outputText = outputText[1:].strip('\n\t ')
# Write output file
fout_name = fi_name[:-5] + '.xml'
fo = codecs.open(fout_name, 'w', 'utf-8-sig')
fo.write(outputText)
fo.close()
print ' Write', fout_name
main()
Codigo Jinja:
{#
moodle.xml
~~~~~~~~~~
Template for moodle questions
:license: Licencia Creative Commons Atribución Compartir Igual 3.0
#}
{###############################################################}
{%- macro category(name) %}
<!-- category -->
<question type="category">
<category><text>{{name}}</text></category>
</question>
{% endmacro -%}
{###############################################################}
{%- macro cloze(name, data, feedback="", shuffle=0) %}
<!-- cloze question: {{name}} -->
<question type="cloze">
<name><text>{{name}}</text></name>
<questiontext><text>
{%- block cloze_questiontext scoped -%} {{data}} {%- endblock %}
</text></questiontext>
<generalfeedback><text>{{feedback}}</text></generalfeedback>
<shuffleanswers>{{shuffle}}</shuffleanswers>
</question>
{% endmacro -%}
{###############################################################}
{%- macro matching(name, data, image='', feedback="", grade=1, penalty=0.5, shuffle=0) %}
<!-- matching question: {{name}} -->
<question type="matching">
<name><text>{{name}}</text></name>
<questiontext format="html"><text>{{data.0}}</text></questiontext>
<image>{{image}}</image>
<generalfeedback><text>{{feedback}}</text></generalfeedback>
<defaultgrade>{{grade}}</defaultgrade>
<penalty>{{penalty}}</penalty>
<hidden>0</hidden>
<shuffleanswers>{{shuffle}}</shuffleanswers>
{%- for question in data[1:] -%}
<subquestion>
<text>{{question.0}}</text><answer><text>{{question.1}}</text></answer>
</subquestion>
{%- endfor -%}
</question>
{% endmacro -%}
{###############################################################}
{%- macro multichoice(name, data, image='', feedback="", grade=1, penalty=0.5, shuffle=0) %}
<!-- multichoice question: {{name}} -->
<question type="multichoice">
<name><text>{{name}}</text></name>
<questiontext format="html"><text>{{data.0}}</text></questiontext>
<image>{{image}}</image>
<generalfeedback><text>{{feedback}}</text></generalfeedback>
<defaultgrade>{{grade}}</defaultgrade>
<penalty>{{penalty}}</penalty>
<hidden>0</hidden>
<shuffleanswers>{{shuffle}}</shuffleanswers>
<single>false</single>
<shuffleanswers>true</shuffleanswers>
<correctfeedback><text></text></correctfeedback>
<partiallycorrectfeedback><text></text></partiallycorrectfeedback>
<incorrectfeedback><text></text></incorrectfeedback>
<answernumbering>abc</answernumbering>
{%- for ans in data[1:] %}
<answer fraction="{{ans.0}}">
<text>{{ans.1}}</text> {# Respuesta correcta #}
<feedback><text>{{ans.2}}</text></feedback>
</answer>
{%- endfor %}
</question>
{% endmacro -%}
{###############################################################}
{%- macro all_quizs() -%}
{%- for data in database -%}
{%- if 'penalty' in data %} {% set penalty = data.penalty %} {% else %} {% set penalty = opt.penalty %} {% endif -%}
{%- if 'image' in data %} {% set image = data.image %} {% else %} {% set image = opt.image %} {% endif -%}
{%- if 'grade' in data %} {% set grade = data.grade %} {% else %} {% set grade = opt.grade %} {% endif -%}
{%- if 'feedback' in data %}{% set feedback = data.feedback %}{% else %} {% set feedback = opt.feedback %} {% endif -%}
{%- if 'shuffle' in data %} {% set shuffle = data.shuffle %} {% else %} {% set shuffle = opt.shuffle %} {% endif -%}
{%- if 'category' in data -%}
{{category(data.category)}}
{%- elif 'matching' in data -%}
{%- if 'name' in data %} {% set name = data.name %} {% else %} {% set name = data.matching[0] %} {% endif -%}
{%- if 'quiz' in data %} {% set quiz = data.quiz %} {% else %} {% set quiz = data.matching[1:] %} {% endif -%}
{{matching(name, quiz, image, feedback, grade, penalty, shuffle)}}
{%- elif 'multichoice' in data -%}
{%- if 'name' in data %} {% set name = data.name %} {% else %} {% set name = data.multichoice[0] %} {% endif -%}
{%- if 'quiz' in data %} {% set quiz = data.quiz %} {% else %} {% set quiz = data.multichoice[1:] %} {% endif -%}
{{multichoice(name, quiz, image, penalty, grade, feedback, shuffle)}}
{%- elif 'cloze' in data -%}
{%- if 'name' in data %} {% set name = data.name %} {% else %} {% set name = data.cloze[0] %} {% endif -%}
{%- if 'quiz' in data %} {% set quiz = data.quiz %} {% else %} {% set quiz = data.cloze[1:] %} {% endif -%}
{{cloze(name, quiz, feedback, shuffle)}}
{%- endif -%}
{%- endfor -%}
{%- endmacro -%}
{###############################################################}
{%- block main -%}
<?xml version="1.0" encoding="UTF-8"?>
<quiz>
{{all_quizs()}}
</quiz>
{%- endblock -%}
Archivo de ejemplo en
lenguaje Yaml:
#
# Examples of quizs for moodle
#
---
- options: {
template_path: templates,
template: examples.xml,
grade: 1,
penalty: 0.5,
shuffle: 1,
feedback: ''}
#
# Category: name of category
#
- category: $course$/ejemplos
#
# multichoice:
# data: quiz_name, question, [% points, answer1, feedback1], ...
# options: image, grade, penalty, shuffle, feedback
#
- multichoice:
- Name - Multichoice
- Question = Escoge las opciones correctas
- [50, 'uno mas uno es dos', Ok]
- [50, 'dos mas dos es cuatro', Ok]
- [-50, 'Tres más tres es cinco', 'Mal']
- [-50, 'Tres más cuatro es ocho', '']
penalty: 0.3
#
# matching:
# data: quiz_name, question, [% points, answer1, feedback1], ...
# options: image, grade, penalty, shuffle, feedback
#
- matching:
- Name - Matching
- Question = escoge la respuesta correcta en cada caso
- ['pregunta1', 'respuesta1']
- ['pregunta2', 'respuesta2']
- ['pregunta3', 'respuesta3']
grade: 2
#
# cloze options: shuffle, feedback
#
- cloze:
- Name - Cloze question
- [SaddleBrown, black, '#E8C840', '#E8C840']
- "{1:SHORTANSWER:%100%1.0~%100%1}"
shuffle: 1
feedback: 'Muy Bien'
Nota: Todos los programas se suministran bajo licencia GPL v3