Skip to main content

Genera variantes de preguntas de opción múltiple cuyas respuestas correctas se determinan automáticamente mediante cálculo proposicional. Combina supuestos e ítems de respuesta por combinatoria, calcula la veracidad o falsedad de cada ítem según las hipótesis activas y exporta el resultado a LaTeX (AMC) o Moodle (XML vía LaTeX).

Construido sobre calcprop.

Instalación

pip install calcprop calcprop-qbank

Con soporte para el editor visual en Jupyter:

pip install "calcprop-qbank[jupyter]"

Uso rápido

from qbank import *

p = ProblemaTipo([
    "Dado que ",
    [
        Supuesto("$\\mathcal{A}$ es verdadero, ", v("A")),
        Supuesto("$\\mathcal{B}$ es verdadero, ", v("B")),
    ],
    "indique qué opción es correcta: ",
    [
        Cuestion("$\\mathcal{A}$ es verdadero.", v("A")),
        Cuestion("$\\mathcal{B}$ es verdadero.", v("B")),
    ],
])

for etiqueta, enunciado, cuestiones in p:
    print(f"Variante {etiqueta}: {enunciado}")
    for texto, correcto, activa, exp in cuestiones:
        print(f"  {'✓' if correcto else '✗'} {texto}")

Características

Generación combinatoria de variantes

ProblemaTipo toma una lista de supuestos y cuestiones (cada uno con su semántica proposicional) y genera todas las combinaciones posibles. Para cada variante calcula automáticamente qué ítems son verdaderos y cuáles falsos. Las variantes con hipótesis incoherentes o precondiciones insatisfechas se descartan.

El método por_partes_profe() muestra todas las cuestiones de cada sublista (sin descartar, marcando las rechazadas por su precondición), facilitando la revisión del banco.

Preguntas multi-parte

La misma lista plana de componentes admite varias partes: cada vez que tras un bloque de cuestiones aparece texto o un Supuesto se abre una parte nueva. Es útil para preguntas AMC con múltiples apartados o para el formato cloze de Moodle. El método por_partes() devuelve, por variante, un par (enunciado, cuestiones) por parte:

from qbank import *

p = ProblemaTipo([
    "Suponga que ",
    [Supuesto("$A$ es verdadero, ", v("A")),
     Supuesto("$B$ es verdadero, ", v("B"))],
    "¿Cuál es el valor de $A$? ",
    [Cuestion("Verdadero.", v("A")), Cuestion("Falso.", -v("A"))],
    "¿Cuál es el valor de $B$? ",
    [Cuestion("Verdadero.", v("B")), Cuestion("Falso.", -v("B"))],
])

for etiqueta, partes in p.por_partes():
    for enunciado, cuestiones in partes:
        ...

(ProblemaMultiParte y SubPregunta siguen existiendo por compatibilidad, pero están deprecados y devuelven un ProblemaTipo equivalente.)

Preguntas paramétricas con setup

El parámetro setup permite que los valores numéricos o simbólicos cambien en cada variante. El texto de los slots admite marcadores @variable para interpolación:

import random

def numeros():
    a = random.randint(1, 9)
    b = random.randint(1, 9)
    return {'a': a, 'b': b, 'suma': a + b}

p = ProblemaTipo(
    ["Sean $a = @a$ y $b = @b$. ",
     [Cuestion("$a + b = @suma$", True),
      Cuestion("$a + b > 10$", lambda ns: ns['a'] + ns['b'] > 10)]],
    setup=numeros,
)

Persistencia en formato JSON

Guarda y carga problemas (ProblemaTipo, ProblemaVF) sin reescribir el código Python:

from qbank import load_problema, save_problema

p = load_problema('mi_problema.json')
save_problema(p, 'copia.json')

Para bancos de múltiples problemas: load_banco / save_banco.

Editor visual en Jupyter

ProblemaTipoEditor es un formulario interactivo (requiere ipywidgets) que permite construir, previsualizar y guardar problemas sin escribir código:

from qbank import ProblemaTipoEditor

editor = ProblemaTipoEditor()           # editor vacío
editor = ProblemaTipoEditor('p.json')  # cargar desde fichero

p = editor.to_problema()               # obtener el ProblemaTipo

Ver Manual.org si los widgets se muestran como texto en lugar del formulario.

Exportación a AMC y Moodle

Formato AMC (LaTeX)

Función de bajo nivel que devuelve un bloque LaTeX listo para escribir al fichero:

with open("preguntas.tex", "w") as f:
    for etiqueta, partes in p.por_partes():
        for enunciado, cuestiones in partes:
            f.write(AMCblock("MiCuestionario", etiqueta, enunciado, cuestiones))

Vista aplanada para el profesor (todas las cuestiones con marcas):

n = QuizAMCProfe("MiCuestionario", "exportaciones/", p)
print(f"{n} bloque(s) escritos")

Para preguntas multi-parte en un único questionmult: AMC_multipart.

Formato Moodle (XML vía LaTeX)

# Vista alumno
n = QuizMoodle("MiCuestionario", "exportaciones/", p, last_choice=True)
print(f"{n} variante(s) escritas")

# Vista profe (fracciones de puntuación visibles)
QuizMoodleProfe("MiCuestionario", "exportaciones/", p)

# Con paquete LaTeX adicional y texto comodín personalizados
QuizMoodle("MiCuestionario", "exportaciones/", p,
           aux_latex=r"\usepackage{nacal-moodle}",
           last_choice_text="Las demás opciones son falsas")

QuizMoodle y QuizMoodleProfe devuelven un int con el número de variantes escritas, útil para logging en scripts de build.

Para preguntas ProblemaVF: QuizVFMoodle.

Exportación a código Python editable

save_problema_py genera un fichero .py con la definición del problema como listas editables:

from qbank import save_problema_py

save_problema_py(p, 'mi_problema.py')

El fichero resultante puede abrirse con cualquier editor, modificarse y ejecutarse directamente con Python.

Comprobación automática de preguntas (lint)

lint revisa un problema (objeto, dict o ruta a JSON) sin modificar nada ni compilar LaTeX y devuelve una lista de Aviso(nivel, codigo, mensaje, donde) con nivel ERROR, AVISO o INFO:

from qbank import lint, tabla_mundos

for a in lint("preguntas/L-01-ejemplo.json"):
    print(a)
print(tabla_mundos("preguntas/L-01-ejemplo.json"))   # Cuestion × mundo

Desde la línea de órdenes (código de salida 1 si hay algún ERROR):

python -m qbank.lint preguntas/*.json [--instances N] [--seed S] [--tabla] [--quiet]
qbank-lint preguntas/*.json --quiet      # equivalente; omite INFO y ficheros OK

Comprueba, entre otras cosas, la garantía de mezcla (1 < correctas <= opciones-1= en toda variante, contando la opción por defecto de last_choice), el número de variantes, negaciones -v('X') que nunca podrían deducirse por falta de un unoDe(...), interpolaciones @{var} sin resolver, etiquetas huérfanas, la estructura del JSON y caracteres que rompen la exportación a Moodle. La tabla de mundos muestra el valor de cada Cuestion en cada combinación de Supuesto (V, F o - si la rechaza su precond), para localizar distractores constantes.

Documentación

  • Manual.org — manual de usuario con ejemplos.
  • Tutorial.ipynb y ejemplosManual/Demo.ipynb — cuadernos ejecutables (también en MyBinder).
  • CalcPropQuiz.org y CalcPropExport.org — código fuente comentado (programación literate) de los módulos _quiz, _json, _widgets, _lint y _export. Son la fuente de src/qbank/: los .py se generan con org-babel-tangle o, sin Emacs, con python tools/orgtangle.py write; tests/test_literate.py comprueba que coinciden.

Tests

pytest

Autoría y licencia

Copyright (C) 2020-2026 Andrés Bujosa, Marcos Bujosa (_quiz)
Copyright (C) 2020-2026 Marcos Bujosa (_export, _json, _widgets)

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

See the LICENSE file for details.

Metadata

Release files for calcprop-qbank 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for calcprop-qbank 0.5.0
File Size Uploaded Provenance
calcprop_qbank-0.5.0.tar.gz 47.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for calcprop-qbank 0.5.0
File Interpreter ABI Platform
calcprop_qbank-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 95.7 kB

Release files / calcprop_qbank-0.5.0.tar.gz

Download URL calcprop_qbank-0.5.0.tar.gz
Size 47.7 kB
Tags Source
SHA-256 checksum
How to use checksums
e6402e61e40dca5886a8271d107df9369aa27a8c13e3f62c1413fc64bbe6d17d
BLAKE2b-256 checksum
How to use checksums
49c80af2606b8dde1b9d11d1f463bb040fdef1d89a5bfe9a0e8638a573538a62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.2

Release files / calcprop_qbank-0.5.0-py3-none-any.whl

Download URL calcprop_qbank-0.5.0-py3-none-any.whl
Size 48.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
dcb0aa7a54bd7890bf4eb31a473c29261aa8d608d286cd76fd01d746ade22222
BLAKE2b-256 checksum
How to use checksums
57a0678cd397ea7d9bb66575bafa58e46b5a7549a28e1e483850c80bcb2d2ef0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.2

Security for calcprop-qbank 0.5.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page