Newer
Older
#! /usr/bin/env python3
from jinja2 import Template, Environment, StrictUndefined
from course.content import (
process_yaml_for_expansion, YamlBlockEscapingFileSystemLoader)
QUESTIONS_ONLY_TEMPLATE = Template(r"""
Andreas Klöckner
committed
{% for q in questions %}
{{ q }}
{% endfor %}
""")
TEMPLATE = Template(r"""
\documentclass[11pt]{article}
\usepackage{akteach}
\usepackage{examtron}
\pagestyle{empty}
\usepackage{tikz}
\titleformat{\section}
{\normalfont\sffamily\large\bfseries}
\akteachheader{ {{- header -}} }{ {{- title -}} }
Andreas Klöckner
committed
{% for q in questions %}
{{ q }}
{% endfor %}
Andreas Klöckner
committed
""")
INCLUDE_GRAPHICS_MEDIA_RE = re.compile(r"\\includegraphics\{media:(.*)\}")
INCLUDE_GRAPHICS_REPO_RE = re.compile(r"\\includegraphics\{repo:(.*)\}")
FORMULA_ALIGN_RE = re.compile(
r"\\\["
r"\s*(\\begin\{align\*?\})"
r"(.*?)"
r"(\\end\{align\*?\})\s*"
r"\\\]", re.DOTALL)
Andreas Klöckner
committed
def convert_markup(s):
result = pypandoc.convert(s, 'latex', format='markdown')
result, _ = INCLUDE_GRAPHICS_MEDIA_RE.subn(
r"\\includegraphics[height=4cm]{media/\1}", result)
result, _ = INCLUDE_GRAPHICS_REPO_RE.subn(
r"\\includegraphics[height=4cm]{\1}", result)
result, _ = FORMULA_ALIGN_RE.subn(
r"\1\2\3", result)
Andreas Klöckner
committed
return result
if page.type == "Page":
return convert_markup(page.content)
elif page.type in ["TextQuestion", "SurveyTextQuestion"]:
Andreas Klöckner
committed
prompt = convert_markup(page.prompt) + "\n\\vspace*{2cm}"
elif page.type == "InlineMultiQuestion":
question, _ = re.subn(
r"\{\[\}\{\[\}\w+\{\]\}\{\]\}",
r"\\tikz [baseline=0]\\draw (0,-1ex) rectangle +(10em,3.5ex);",
convert_markup(page.question))
prompt = (
convert_markup(page.prompt)
+ "\n\n"
+ question
+ "\n\\vspace*{1cm}")
return (prompt)
elif page.type in [
"PythonCodeQuestion",
"PythonCodeQuestionWithHumanTextFeedback"]:
Andreas Klöckner
committed
prompt = convert_markup(page.prompt)
if hasattr(page, "initial_code"):
prompt += r"\begin{verbatim}%s\end{verbatim}" % page.initial_code
return (prompt)
elif page.type == "FileUploadQuestion":
Andreas Klöckner
committed
prompt = convert_markup(page.prompt) + "\n\\vspace*{5cm}"
return (prompt)
elif page.type in ["ChoiceQuestion", "MultipleChoiceQuestion",
"SurveyChoiceQuestion"]:
Andreas Klöckner
committed
prompt = convert_markup(page.prompt)
if page.type == "MultipleChoiceQuestion":
prompt += "\n\n(Select all that apply.)"
convert_markup(str(ch).replace("~CORRECT~", r"\correct "))
for ch in page.choices
if ch is not None]
return (
"{}\n"
r"\begin{{examtronchoices}}"
"\n"
"{}\n"
r"\end{{examtronchoices}}"
"\n"
.format(
prompt,
"\n".join(choices))
)
else:
print("*** WARNING: Unknown page type '%s'" % page.type,
file=sys.stderr)
def convert_page(page, wrap_in_problem_env):
title = getattr(page, "title", None)
if hasattr(page, "prompt") and title is None:
from course.content import extract_title_from_markup
title = extract_title_from_markup(page.prompt)
if title is None:
title = ""
result = convert_page_inner(page)
if wrap_in_problem_env:
return (
"\\begin{{examtronproblem}}{{{title}}}\n"
"{body}\n"
"\\end{{examtronproblem}}\n".format(
title=title,
body=result))
def main():
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-1", "--one", action="store_true")
parser.add_argument("-q", "--questions-only", action="store_true")
parser.add_argument("-p", "--examtron-problem", action="store_true")
parser.add_argument("--header", default="")
parser.add_argument("--title", default="Worksheet")
parser.add_argument("-r", "--repo-root", default=".")
parser.add_argument("input", default="-", nargs="?")
parser.add_argument("output", default="-", nargs="?")
args = parser.parse_args()
if args.input == "-":
data = sys.stdin.read()
else:
with open(args.input, "r") as inf:
data = inf.read()
data = process_yaml_for_expansion(data)
jinja_env = Environment(
loader=YamlBlockEscapingFileSystemLoader(args.repo_root),
undefined=StrictUndefined)
template = jinja_env.from_string(data)
data = template.render()
from yaml import load
from relate.utils import dict_to_struct
data = dict_to_struct(load(data))
questions = []
if not args.one:
flow_desc = data
if hasattr(flow_desc, "groups"):
pages = [
page
for grp in flow_desc.groups
for page in grp.pages]
else:
pages = flow_desc.pages
for page in pages:
print(page.id)
converted = convert_page(page, args.examtron_problem)
questions.append(converted)
template = TEMPLATE
if args.questions_only:
template = QUESTIONS_ONLY_TEMPLATE
data = template.render(
questions=questions,
title=args.title,
header=args.header)
data = convert_page(data, args.examtron_problem)