Skip to content
Snippets Groups Projects
Commit 2a012ebf authored by Jan Maximilian Michal's avatar Jan Maximilian Michal
Browse files

Cleaning argparse. Added more info to README

parent a37441cb
No related branches found
No related tags found
No related merge requests found
*Add a good description / documenation # Hallgrim - an ILIAS task generator in Python
\ No newline at end of file
## Usage
Invoke the script with `python3 gen.py -h` in order to see usage. Very limited
until now.
Example scripts can be found in `scripts/`.
A first version of the tool that relied on autoilias is still in the repository
(see `generator.py`). It will be removed as soon as the necessary features are
implemented.
## TODO
* Add a good description / documentation.
* Add instruction to produce multiple (parametrized) instances of a single
question.
* Add more functionality (gap, alignment, etc.)
* Make parsers more robust.
* reverse ILIAS authentication mechanism for automated upload.
### Notes
The final data is produced in three steps:
1. A python script file with predefined structure that has to export certain
variables in a specified format.
2. An intermediate representation (probably an array that contains relevant
data and assumes unknown properties)
3. The XML structure for one or multiple questions, readable by Ilias.
4. An Ilias object packed as .zip file, ready for upload.
gen.py 100644 → 100755
#!/usr/local/bin/python3
try: try:
import mistune import mistune
except ImportError as err: except ImportError as err:
...@@ -14,32 +16,36 @@ from hallgrim.IliasXMLCreator import multi, single ...@@ -14,32 +16,36 @@ from hallgrim.IliasXMLCreator import multi, single
import hallgrim.parser import hallgrim.parser
from hallgrim.messages import * from hallgrim.messages import *
def filename_to_module(name): def filename_to_module(name):
return name.rstrip('.py').replace('/', '.') return name.rstrip('.py').replace('/', '.')
def type_selector(type): def type_selector(type):
if 'multiple' in type: if 'multiple' in type:
return multi return multi
if 'single' in type: if 'single' in type:
return single return single
def parseme(): def parseme():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument( parser.add_argument(
'-o', '-o',
'--out', '--out',
help='Output file', help='''Specifiy different output file. If no argument is given the Name
of the script is used.''',
type=argparse.FileType('w'), type=argparse.FileType('w'),
metavar='FILE') metavar='FILE')
parser.add_argument( parser.add_argument(
'-i', 'input',
'--input',
help='Script to execute', help='Script to execute',
metavar='FILE') metavar='FILE')
args = parser.parse_args() args = parser.parse_args()
return args.out, args.input return args.out, args.input
def main(): def main():
output, script_name = parseme() output, script_name = parseme()
script = importlib.import_module(filename_to_module(script_name)) script = importlib.import_module(filename_to_module(script_name))
...@@ -53,9 +59,10 @@ def main(): ...@@ -53,9 +59,10 @@ def main():
'questions': hallgrim.parser.choice_parser(script.choices), 'questions': hallgrim.parser.choice_parser(script.choices),
} }
output = os.path.join('output', script.meta['title']) + '.xml' if not output else output output = os.path.join(
'output', script.meta['title']) + '.xml' if not output else output
type_selector(script.meta['type']).convert_and_print(data, output) type_selector(script.meta['type']).convert_and_print(data, output)
info('Processed "{}" and wrote xml to "{}".'.format(script_name, output)) info('Processed "{}" and wrote xml to "{}".'.format(script_name, output))
if __name__ == '__main__': if __name__ == '__main__':
main() main()
\ No newline at end of file
...@@ -30,8 +30,6 @@ def itemmetadata(type, author, feedback_setting=1): ...@@ -30,8 +30,6 @@ def itemmetadata(type, author, feedback_setting=1):
return root return root
########################################################################## ##########################################################################
def material(content): def material(content):
material = et.Element('material') material = et.Element('material')
material.append(simple_elemet( material.append(simple_elemet(
...@@ -65,8 +63,6 @@ def presentation(title, question_text, questions, shuffle=True): ...@@ -65,8 +63,6 @@ def presentation(title, question_text, questions, shuffle=True):
return root return root
########################################################################## ##########################################################################
def respcondition(points, count, correct=True): def respcondition(points, count, correct=True):
root = et.Element('respcondition', attrib={'continue': 'Yes'}) root = et.Element('respcondition', attrib={'continue': 'Yes'})
conditionvar = et.Element('conditionvar') conditionvar = et.Element('conditionvar')
......
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Test
SYSTEM 'http://www.ilias.uni-koeln.de/download/dtd/ilias_co.dtd'>
<!--Export of ILIAS Test Questionpool 82996 of installation .-->
<ContentObject Type="Questionpool_Test">
<MetaData>
<General Structure="Hierarchical">
<Identifier Catalog="ILIAS" Entry="il_9310_qpl_82996"/>
<Title Language="de">Aufgabentypen aus ILIAS</Title>
<Language Language="de"/>
<Description Language="de">Eine Sammlung von Prototypen, um Aufgabe automatisch generieren zu können.</Description>
<Keyword Language="de"/>
</General>
</MetaData>
<Settings>
<ShowTaxonomies>0</ShowTaxonomies>
<NavTaxonomy>0</NavTaxonomy>
<SkillService>0</SkillService>
</Settings>
<PageObject>
<PageContent>
<Question QRef="il_9310_qst_1662666"/>
</PageContent>
</PageObject>
</ContentObject>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE questestinterop
SYSTEM 'ims_qtiasiv1p2p1.dtd'>
<!--Generated by ILIAS XmlWriter-->
<questestinterop>
<item ident="il_9310_qst_1662666" maxattempts="0" title="template Gap ">
<qticomment>Description</qticomment>
<duration>P0Y0M0DT0H30M0S</duration>
<itemmetadata>
<qtimetadata>
<qtimetadatafield>
<fieldlabel>ILIAS_VERSION</fieldlabel>
<fieldentry>5.1.8 2016-08-03</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>QUESTIONTYPE</fieldlabel>
<fieldentry>CLOZE QUESTION</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>AUTHOR</fieldlabel>
<fieldentry>Jan Maximilian Michal</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>additional_cont_edit_mode</fieldlabel>
<fieldentry>default</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>externalId</fieldlabel>
<fieldentry>5818dab7ebe8e4.96644801</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>textgaprating</fieldlabel>
<fieldentry>ci</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>fixedTextLength</fieldlabel>
<fieldentry>20</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>identicalScoring</fieldlabel>
<fieldentry>1</fieldentry>
</qtimetadatafield>
<qtimetadatafield>
<fieldlabel>combinations</fieldlabel>
<fieldentry>W10=</fieldentry>
</qtimetadatafield>
</qtimetadata>
</itemmetadata>
<presentation label="template Gap ">
<flow>
<material>
<mattext texttype="text/xhtml">&lt;p&gt;Question text&lt;/p&gt;</mattext>
</material>
<material>
<mattext texttype="text/xhtml">&lt;p&gt;Ich habe eine lila Lücke </mattext>
</material>
<response_str ident="gap_0" rcardinality="Single">
<render_fib columns="10" fibtype="String" prompt="Box"/>
</response_str>
<material>
<mattext texttype="text/xhtml">.&lt;/p&gt;
&lt;p&gt;Auswahl Lücke </mattext>
</material>
<response_str ident="gap_1" rcardinality="Single">
<render_choice shuffle="Yes">
<response_label ident="0">
<material>
<mattext>Answer 2.1</mattext>
</material>
</response_label>
<response_label ident="1">
<material>
<mattext>Answer 2.2</mattext>
</material>
</response_label>
<response_label ident="2">
<material>
<mattext>Answer 2.3</mattext>
</material>
</response_label>
</render_choice>
</response_str>
<material>
<mattext texttype="text/xhtml">&lt;/p&gt;
&lt;p&gt;Numerische Lücke</mattext>
</material>
<response_num ident="gap_2" numtype="Decimal" rcardinality="Single">
<render_fib columns="30" fibtype="Decimal" maxnumber="1" minnumber="-1" prompt="Box"/>
</response_num>
<material>
<mattext texttype="text/xhtml">&amp;lt;/p&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;</mattext>
</material>
</flow>
</presentation>
<resprocessing>
<outcomes>
<decvar/>
</outcomes>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="gap_0">Answer 1</varequal>
</conditionvar>
<setvar action="Add">3</setvar>
<displayfeedback feedbacktype="Response" linkrefid="0_Response_0"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="gap_1">Answer 2.1</varequal>
</conditionvar>
<setvar action="Add">20</setvar>
<displayfeedback feedbacktype="Response" linkrefid="1_Response_0"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="gap_1">Answer 2.3</varequal>
</conditionvar>
<setvar action="Add">0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="1_Response_2"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="gap_1">Answer 2.2</varequal>
</conditionvar>
<setvar action="Add">0</setvar>
<displayfeedback feedbacktype="Response" linkrefid="1_Response_1"/>
</respcondition>
<respcondition continue="Yes">
<conditionvar>
<varequal respident="gap_2">0</varequal>
</conditionvar>
<setvar action="Add">33</setvar>
<displayfeedback feedbacktype="Response" linkrefid="2_Response_0"/>
</respcondition>
</resprocessing>
<itemfeedback ident="0" view="All">
<flow_mat>
<material>
<mattext texttype="text/plain"/>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="1" view="All">
<flow_mat>
<material>
<mattext texttype="text/plain"/>
</material>
</flow_mat>
</itemfeedback>
<itemfeedback ident="2" view="All">
<flow_mat>
<material>
<mattext texttype="text/plain"/>
</material>
</flow_mat>
</itemfeedback>
</item>
</questestinterop>
\ No newline at end of file
### Notes
Every task has to follow a certain structur:
* generate_form
* generate_solution
* generate_task
* other outputs
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment