From 6aa1fd496bf04e2a3c7b2dcad702a430f9c3f090 Mon Sep 17 00:00:00 2001
From: janmax <j.michal@stud.uni-goettingen.de>
Date: Sun, 4 Feb 2018 01:22:29 +0100
Subject: [PATCH] Main functionality is now implemented

---
 hektor.py | 49 +++++++++++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 18 deletions(-)

diff --git a/hektor.py b/hektor.py
index 39818b2..67e848c 100644
--- a/hektor.py
+++ b/hektor.py
@@ -10,28 +10,28 @@ file_regex = re.compile(
     r'(\d+)__(\d+)__(?P<data>results|qti|tst)_(?P<id>\d+).xml')
 task_id_regex = re.compile(r'il_\d+_qst_(?P<task_id>\d+)')
 
-tasks_path = ('./assessment/section/item/itemmetadata/qtimetadata/'
-              'qtimetadatafield/fieldlabel[text()="QUESTIONTYPE"]'
-              '/../../../../..')
+tasks_path = ('./assessment/section')
 
 users = './tst_active/row'
 solutions = './tst_solutions/row[@question_fi="%s"]'
 
+lecturer_xpath = './MetaData/Lifecycle/Contribute[@Role="Author"]/Entity/text()' 
 
-def eat_qti(tree):
+def eat_qti(tree, only_of_type=('assSourceCode',), **kwargs):
     tasks = tree.xpath(tasks_path)[0]
 
     titles = tasks.xpath('./item/@title')
     types = tasks.xpath(
-            './item/itemmetadata/qtimetadata/qtimetadatafield/'
-            'fieldlabel[text()="QUESTIONTYPE"]/../fieldentry/text()')
+        './item/itemmetadata/qtimetadata/qtimetadatafield/'
+        'fieldlabel[text()="QUESTIONTYPE"]/../fieldentry/text()')
     ids = [re.search(task_id_regex, ident).group('task_id')
            for ident in tasks.xpath('./item/@ident')]
-    texts = ['\n'.join(flow.xpath('./material/mattext/text()')) 
-             for flow in tasks.xpath('./item/presentation/flow')] 
+    texts = ['\n'.join(flow.xpath('./material/mattext/text()'))
+             for flow in tasks.xpath('./item/presentation/flow')]
 
     return {id: {'title': title, 'text': text, 'type': type}
-            for id, type, title, text in zip(ids, types, titles, texts)}
+            for id, type, title, text in zip(ids, types, titles, texts)
+            if not only_of_type or type in only_of_type}
 
 
 def eat_users(results_tree):
@@ -44,7 +44,8 @@ def eat_solutions(results_tree, task_id):
             for row in results_tree.xpath(solutions % task_id)}
 
 
-def eat_results(tree, questions=("17639",)):
+def eat_results(tree, qti=(), **kwargs):
+    questions = qti
     users = eat_users(tree)
     for user in users.values():
         user['submissions'] = {}
@@ -57,18 +58,30 @@ def eat_results(tree, questions=("17639",)):
 
 def eat_tst(tree):
     title = tree.xpath('./MetaData/General/Title/text()')
-    lecturer = tree.xpath(
-        './MetaData/Lifecycle/Contribute[@Role="Author"]/Entity/text()')
+    lecturer = tree.xpath(lecturer_xpath)
     return {'exam': title[0], 'author': lecturer[0]}
 
 
+def eval_file(archive, match, cache):
+    funcname = 'eat_' + match.group('data')
+    with archive.open(match.string) as datafile:
+        tree = etree.parse(datafile)
+        return globals()[funcname](tree, **cache)
+
+
 def eat_archive(archive):
-    for match in filter(bool, (re.search(file_regex, name)
-                               for name in archive.NameToInfo)):
-        funcname = 'eat_' + match.group('data')
-        with archive.open(match.string) as datafile:
-            tree = etree.parse(datafile)
-            yield match.group('data'), globals()[funcname](tree)
+    files = {match.group('data'): match
+             for match in (re.search(file_regex, name)
+                           for name in archive.NameToInfo)
+             if match}
+
+    order = ('tst', 'qti', 'results')
+    cache = {}
+
+    for key in order:
+        cache[key] = eval_file(archive, files[key], cache)
+
+    return cache
 
 
 def add_meta(base, data):
-- 
GitLab