diff --git a/.gitignore b/.gitignore index 7bd1165a32fb31075471368e925f415581b1d296..0c8dd6311b0c94b655c76c98c8fc75e6d004799f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ __pycache__/ *$py.class output/* +hallgrim.egg-info/* notes.html README.html .DS_Store diff --git a/config.sample.ini b/config.sample.ini deleted file mode 100644 index cfe9d5401aa5ad856a600c28388889c1df047167..0000000000000000000000000000000000000000 --- a/config.sample.ini +++ /dev/null @@ -1,9 +0,0 @@ -[META] -author = your name - - -[UPLAODER] -user = root -pass = homer -host = http://localhost:8000/ -rtoken = c13456ec3d71dc657e19fb826750f676 diff --git a/deprecated_scripts/01_basics.py b/deprecated_scripts/01_basics.py deleted file mode 100644 index d733ff197797d9888dd425b848a5073c7cf5f966..0000000000000000000000000000000000000000 --- a/deprecated_scripts/01_basics.py +++ /dev/null @@ -1,53 +0,0 @@ -import re - - -def gap(content, points): - return "[gap({points}P)]{gap}[/gap]".format(points=points, gap=content) - -def p(content): - return '<p>{}</p>\n'.format(content) - -def li(content): - return '<li>{}</li>\n'.format(content) - -def tex(content): - return ('<span class="latex">' + content + '</span>').replace('\\', '\\\\') - -def generate_ilias(): - aufgabe = p('Berechnen Sie:') - - aufgabe += li(tex(r'\{a,b\} \cdot \{\varepsilon, cd\} = \{') + gap('a, acd, b, bcd', 0.5) + tex('\}')) - aufgabe += li(tex(r'\{\varepsilon, cd\} \cdot \{a, b\} = \{') + gap('a, b, cda, cdb', 0.5) + tex('\}')) - aufgabe += li(tex(r'\{\varepsilon, a, ab\}^2 = \{') + gap('eps, a, aa, aab, aba, abab', 0.5) + tex('\}')) - aufgabe += li(tex(r'\{\varepsilon\} \cdot \{\varepsilon\} = \{') + gap('eps', 0.5) + tex('\}')) - aufgabe += li(tex(r'\{\varepsilon\} \cdot \emptyset = ') + gap('{}', 0.5)) - aufgabe += li(tex(r'\{\varepsilon\} \cdot \emptyset = ') + gap('{}', 0.5)) - aufgabe += li(tex(r'\emptyset^2 = ') + gap('{}', 0.5)) - aufgabe += li(tex(r'\emptyset^* = \{') + gap('eps', 0.5) + tex('\}')) - aufgabe += li(tex(r'\{\varepsilon\}^* = \{') + gap('eps', 0.5) + tex('\}')) - aufgabe += li(tex(r'\{\varepsilon, a\}^+ = \{') + gap('a*', 0.5) + tex('\}')) - - aufgabe += ''' Verwenden Sie <code>eps</code> für {eps} und - <code>{{}}</code> für {empty}. Geben Sie alle Elemente der neuen Menge in - lexikographischer Reihenfolge an und verwenden Sie Leerzeichen nach einem - Komma. (Z.B. eps, a, ab, acd, ba)'''.format(eps=tex(r'\varepsilon'), empty=tex(r'\emptyset')) - - - return aufgabe.replace(r'"', r'\"') - -def generate_solution(): - solution = "<h3>Musterloesung</h3><br>" - solution += re.sub(r'\[gap\(\d+P\)\](.+)\[\/gap\]', - r'\1', generate_ilias()) - return solution - - -### END OF SCRIPT ######################################################## -meta = { - "type": "GAP", - "title": "Grundlagen", - "author": "Jan Maximilian Michal", - "gapLength": 10, - "question": generate_ilias(), - "solution": generate_solution(), -} diff --git a/deprecated_scripts/02_chomsky_grammar.py b/deprecated_scripts/02_chomsky_grammar.py deleted file mode 100644 index 092f63d0f496c865dbc8731912f1c16274149cf7..0000000000000000000000000000000000000000 --- a/deprecated_scripts/02_chomsky_grammar.py +++ /dev/null @@ -1,89 +0,0 @@ -from itertools import product - - -delta = """ - S := AB | ABA - A := aA | a - B := Bb | eps -""" - -class rule: - __slots__ = ['left', 'right'] - def __init__(self, left, right, sep=""): - self.left = left - self.right = [c for c in right] if right != "eps" else [] - - def __str__(self): - return self.left + " := " + ''.join(self.right) - - def __hash__(self): - return hash(str(self)) - - def __eq__(self, other): - return self.left == other.left and self.right == other.right - - -def parse(grammer): - grammer = grammer.strip() - terminals = set() - non_terms = set() - rules = set() - - for line in grammer.split("\n"): - N, rule_list = line.split(":=") - rules |= {rule(N.strip(), right.strip()) for right in rule_list.split("|")} - non_terms |= {N} - - for r in rules: - if r.right != 'eps': - terminals |= {T for T in r.right if T.islower()} - - return rules, terminals, non_terms - -P, T, N = parse(delta) - -# print(('\n'.join(map(str, P)))) -# print() - -letters_to_kill = {p.left for p in P if not p.right} -new_P = set() | P -for p in P: - for l in letters_to_kill: - n = p.right.count(l) - r = ''.join(p.right).replace(l, "{}") - - # 0 is a placeholder for empty string - for prod in product(l + "0", repeat=n): - new_P |= {rule(p.left, r.format(*prod).replace("0", ""))} - -P = {p for p in new_P if p.right} -# print(('\n'.join(map(str, P)))) -# print() - -for t in T: - P |= {rule("T_" + t, t)} - -# print(T) - -new_P = set() | P -for p in P: - p.right = ["T_" + p if p in T else p for p in p.right] - -P = new_P -# print(('\n'.join(map(str, P)))) -# print() - -new_P = set() | P -for p in P: - if len(p.right) > 2: - pass - -### END OF SCRIPT ############################################################## -meta = { - "type" : "GAP", - "title" : "Grammatik in Chomsky Normalform umwandeln", - "author" : "Jan Maximilian Michal", - "gapLength" : 10, - "question" : "Empty", - "solution" : "TODO", -} \ No newline at end of file diff --git a/deprecated_scripts/04_minimize_dea.py b/deprecated_scripts/04_minimize_dea.py deleted file mode 100644 index 3c2fa64a42007b21a029e34d23500b768d53aedc..0000000000000000000000000000000000000000 --- a/deprecated_scripts/04_minimize_dea.py +++ /dev/null @@ -1,173 +0,0 @@ -import re - -from itertools import product -from graphviz import Digraph - -# relative imports - -def gap(content, points): - return "[gap({points}P)]{gap}[/gap]".format(points=points, gap=content) - -def tex(content): - return ('<span class="latex">' + content + '</span>').replace('\\', '\\\\') - - -class Automaton: - - """docstring for Automaton""" - __slots__ = ['states', 'sigma', 'delta', 'q0', 'F'] - - def __init__(self, states, sigma, delta, q0, F): - self.states = states - self.sigma = set(sigma) - self.delta = delta - self.q0 = q0 - self.F = set(F) - - def state_pairs(self): - return filter(lambda p: p[0] != p[1], product(self.states[:-1], self.states[1:])) - - def bisimilar(self, k, z1, z2): - if k == 0: - return (z1 in self.F) == (z2 in self.F) - - return self.bisimilar(k-1, z1, z2) and \ - all(self.bisimilar(k-1, self.delta(z1, a), self.delta(z2, a)) - for a in self.sigma) - - def minimize(self): - # Initialize - k = 0 - change = True - marker = { - pair: 0 for pair in self.state_pairs() if not self.bisimilar(0, *pair)} - - # Iterate - while change: - change = False - for z1, z2 in (pair for pair in self.state_pairs() if pair not in marker): - if any(not self.bisimilar(k, self.delta(z1, a), self.delta(z2, a)) for a in self.sigma): - marker[(z1, z2)] = k+1 - change = True - k += 1 - - # Finalize TODO - return marker - - def generate_form(self): - marker = self.minimize() - - form = '\n\n<p><table border-collapse: collapse; border-style: hidden; rules=\"all\">\n' - form += '<tr>\n\t<td> </td>\n\t<td>' + \ - '</td>\n\t<td>'.join(self.states[1:]) + '</td></tr>\n' - for i, z1 in enumerate(self.states[:-1]): - form += '<tr>\n\t<td>{}</td>\n'.format(z1) - for j, z2 in enumerate(self.states[1:]): - content = '\t<td>{}</td>\n' - if j < i: - content = content.format(' ') - elif (z1, z2) not in marker: - content = content.format(gap('X', 1)) - else: - content = content.format(gap(marker[(z1, z2)], 1)) - form += content - form += '</tr>\n' - form += '</table></p>' - - return form - - def generate_task(self): - - aufgabe = '''Minimieren Sie den folgenden deterministischen Automaten -{[tex]M = \\{\\{%s\\},\\{%s\\},\\\\delta,\\{%s\\},\\{%s\\}\\}[/tex]} oder zeigen Sie, dass der Automat -bereits minimal ist. Geben Sie die Tabelle mit den Zustandspaaren an, sowie den -minimierten Graphen.<br>\n\n''' % (', '.join(self.states), ', '.join(self.sigma), - str(self.q0), ', '.join(self.F)) - - aufgabe += '<p>' + self.graph_output() + '</p>' - - aufgabe += self.generate_form() - - return aufgabe.replace(r'"', r'\"') - - def graph_output(self, file_format='svg'): - f = Digraph('finite_state_machine', format=file_format, engine='dot') - f.body.extend(['rankdir=LR', 'size="8,5"']) - - f.attr('node', shape='doublecircle') - for node in self.F: - f.node(node) - - f.attr('node', shape='circle') - f.node('', style='invis') - f.edge('', self.q0) - for state in self.states: - for a in self.sigma: - f.edge(state, self.delta(state, a), label=a) - - return str(f.pipe(), encoding='utf-8') - - def generate_solution(self): - solution = "<h3>Musterloesung</h3><br>" - solution += re.sub(r'\[gap\(\d+P\)\](.+)\[\/gap\]', - r'\1', self.generate_form()) - return solution.replace(r'"', r'\"') - - -def delta(state, char): - return { - ('s0', 'a'): 's3', - ('s0', 'b'): 's1', - ('s1', 'a'): 's2', - ('s1', 'b'): 's4', - ('s2', 'a'): 's2', - ('s2', 'b'): 's4', - ('s3', 'a'): 's3', - ('s3', 'b'): 's1', - ('s4', 'a'): 's4', - ('s4', 'b'): 's4' - }[(state, char)] - - -def delta2(state, char): - return { - ('s0', 'a'): 's2', - ('s0', 'b'): 's2', - - ('s1', 'a'): 's0', - ('s1', 'b'): 's3', - - ('s2', 'a'): 's1', - ('s2', 'b'): 's4', - - ('s3', 'a'): 's4', - ('s3', 'b'): 's3', - - ('s4', 'a'): 's5', - ('s4', 'b'): 's4', - - ('s5', 'a'): 's3', - ('s5', 'b'): 's6', - - ('s6', 'a'): 's6', - ('s6', 'b'): 's6', - }[(state, char)] - -states = ["s{}".format(i) for i in range(5)] -states2 = ["s{}".format(i) for i in range(7)] - -F = ["s2"] -F2 = ["s0", "s3", "s4", "s6"] - -A = Automaton(states, "ab", delta, "s0", F) - - -### END OF SCRIPT ######################################################## -meta = { - "type": "GAP", - "title": "Minimieren eines deterministischen Automaten small", - "author": "Jan Maximilian Michal", - "gapLength": 10, - "question": A.generate_task(), - "solution": A.generate_solution(), -} diff --git a/deprecated_scripts/05_nea_to_dea.py b/deprecated_scripts/05_nea_to_dea.py deleted file mode 100644 index 6d67db55f167f544ead725f9e44c8100d2ad1424..0000000000000000000000000000000000000000 --- a/deprecated_scripts/05_nea_to_dea.py +++ /dev/null @@ -1,133 +0,0 @@ -from collections import deque -from functools import reduce -from graphviz import Digraph - -import re - - -def gap(content, points): - return "[gap({points}P)]{gap}[/gap]".format(points=points, gap=content) - -def p(content): - return '<p>{}</p>\n'.format(content) - -def tex(content): - return ('<span class="latex">' + content + '</span>').replace('\\', '\\\\') - - -class NEA: - - """docstring for NEA""" - __slots__ = ['states', 'sigma', 'delta', 'q0', 'F'] - - def __init__(self, states, sigma, delta, q0, F): - self.states = states - self.sigma = sigma - self.delta = delta - self.q0 = q0 - self.F = set(F) - - def to_dea(self): - done = [] - new_steps = deque([{self.q0}]) - table = [] - - while new_steps: - cur = new_steps.popleft() - table.append([cur]) - for a in self.sigma: - next = reduce(lambda a, b: a | b, (self.delta(s, a) for s in cur)) - table[-1].append(next) - if next not in done: - new_steps.append(next) - done.append(next) - - return table - - def graph_output(self, file_format='svg'): - f = Digraph('finite_state_machine', format=file_format, engine='dot') - f.body.extend(['rankdir=LR', 'size="8,5"']) - - f.attr('node', shape='doublecircle') - for node in self.F: - f.node(node) - - f.attr('node', shape='circle') - f.node('', style='invis') - f.edge('', self.q0) - for state in self.states: - for a in self.sigma: - for next in self.delta(state, a): - f.edge(str(state), next, label=a) - - return str(f.pipe(), encoding='utf-8') - - def generate_form(self): - table = self.to_dea() - tr = '<tr>\n{}</tr>\n' - td = '\t<td>{}</td>\n' - - aufgabe = '<table border-collapse: collapse; border-style: hidden; rules=\"all\">\n' - aufgabe += tr.format(''.join(td.format(s) - for s in [tex(r'\delta'), "a", "b"])) - for row in table: - first, second, third = map(', '.join, (sorted(s) for s in row)) - aufgabe += tr.format(td.format(first) + - td.format(gap(second, 1)) + - td.format(gap(third, 1))) - aufgabe += '</table>' - - return aufgabe - - def generate_ilias(self): - aufgabe = '''Wandeln Sie M in einen DEA M' um, indem Sie die - Potenzmenge der Zustände aus M in M' als neue Zustände einfügen - (Eine Anleitung befindet sich im Skript von Dr. Müller S. 25).\n\n''' - - aufgabe += p(self.graph_output()) - aufgabe += p('''Füllen Sie diese Tabelle nach dem Vorbild im Müller - Skript aus. Achten Sie dabei darauf alle Zustände in lexikographischer - Reihenfolge aufzulisten (Zum Beispiel: s1, s2, s4) und alle Zustände - müssen mit Komma und Leerzeichen getrennt werden.''') - aufgabe += p(self.generate_form()) - - return aufgabe.replace('"', r'\"') - - def generate_solution(self): - solution = "<h3>Musterloesung</h3><br>" - solution += re.sub(r'\[gap\(\d+P\)\](.+)\[\/gap\]', - r'\1', self.generate_form()) - return solution.replace(r'"', r'\"') - - -# Define one Automaton -def delta(state, char): - return { - ('s0', 'a'): {'s0', 's1'}, - ('s0', 'b'): {'s0', 's2'}, - - ('s1', 'a'): {'s1', 's3'}, - ('s1', 'b'): {'s1'}, - - ('s2', 'a'): {'s2'}, - ('s2', 'b'): {'s2', 's3'}, - - ('s3', 'a'): set(), - ('s3', 'b'): set(), - }[(state, char)] - -states = ["s{}".format(i) for i in range(4)] -F = ["s3"] - -# create -N = NEA(states, "ab", delta, 's0', F) - -### END OF SCRIPT ######################################################## -meta = { - "type": "GAP", - "title": "NEA in DEA umwandeln", - "author": "Jan Maximilian Michal", - "gapLength": 10, - "question": N.generate_ilias(), - "solution": N.generate_solution(), -} diff --git a/deprecated_scripts/README.md b/deprecated_scripts/README.md deleted file mode 100644 index 5f9441fe252f8656772cf2ee2751c4febc613293..0000000000000000000000000000000000000000 --- a/deprecated_scripts/README.md +++ /dev/null @@ -1,3 +0,0 @@ -These scripts can no longer function with Hallgrim, since they rely on autoilias -which will become obsolete once hallgrim is feature complete. They are kept here -so their logic can be translated into proper scripts. diff --git a/deprecated_scripts/__init__.py b/deprecated_scripts/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/deprecated_scripts/util.py b/deprecated_scripts/util.py deleted file mode 100644 index 85341592c3fb6a55076f30e9889afd94e87a409e..0000000000000000000000000000000000000000 --- a/deprecated_scripts/util.py +++ /dev/null @@ -1,4 +0,0 @@ - -def gap(content, points): - return "[gap({points}P)]{gap}[/gap]".format(points=points, gap=content) - diff --git a/hallgrim/IliasXMLCreator/gap.py b/hallgrim/IliasXMLCreator/gap.py index 936c66a3dc9af1ca595b4b3e15018195719f2f12..523f5e9875ad085689ee55b088da253652ac7e38 100644 --- a/hallgrim/IliasXMLCreator/gap.py +++ b/hallgrim/IliasXMLCreator/gap.py @@ -1,6 +1,6 @@ import xml.etree.ElementTree as et -from hallgrim.IliasXMLCreator.xmlBuildingBlocks import * +from .xmlBuildingBlocks import * def xml_print(element, **kwargs): import xml.dom.minidom diff --git a/hallgrim/IliasXMLCreator/multi.py b/hallgrim/IliasXMLCreator/multi.py index b7a4d2c2d3afcfbc650550c7a8d085b80dd4c088..fa62314065ad94c673dbeca03949ad36763a521b 100644 --- a/hallgrim/IliasXMLCreator/multi.py +++ b/hallgrim/IliasXMLCreator/multi.py @@ -1,6 +1,6 @@ import xml.etree.ElementTree as et -from hallgrim.IliasXMLCreator.xmlBuildingBlocks import * +from .xmlBuildingBlocks import * class MultipleChoiceQuestion: diff --git a/hallgrim/IliasXMLCreator/packer.py b/hallgrim/IliasXMLCreator/packer.py index f3cccb6cc47a1f726aa2c4c511fca37a121c9ceb..f82504c7a6cb3ae46b6067c7dfee6c182edaf820 100644 --- a/hallgrim/IliasXMLCreator/packer.py +++ b/hallgrim/IliasXMLCreator/packer.py @@ -1,6 +1,6 @@ import xml.etree.ElementTree as et -from hallgrim.IliasXMLCreator import multi, single, gap +from . import multi, single, gap def create_xml_tree(item_list): root = et.Element('questestinterop') diff --git a/hallgrim/IliasXMLCreator/single.py b/hallgrim/IliasXMLCreator/single.py index 747fd686649447e6308582db15b13e9f743569d1..38c65230682d65bdf270cfec063a38f7a418c7f7 100644 --- a/hallgrim/IliasXMLCreator/single.py +++ b/hallgrim/IliasXMLCreator/single.py @@ -1,6 +1,6 @@ import xml.etree.ElementTree as et -from hallgrim.IliasXMLCreator.multi import * +from .multi import * class SingleChoiceQuestion(MultipleChoiceQuestion): diff --git a/hallgrim/IliasXMLCreator/xmlBuildingBlocks.py b/hallgrim/IliasXMLCreator/xmlBuildingBlocks.py index 238591e5a922720e5197250f9ec50acf8f03a69c..dd9a9a28c868bb013b0272e544c905f8c97a7aa0 100644 --- a/hallgrim/IliasXMLCreator/xmlBuildingBlocks.py +++ b/hallgrim/IliasXMLCreator/xmlBuildingBlocks.py @@ -150,7 +150,3 @@ def response_num(ident, columns, _min, _max, numtype='Decimal'): render_fib = et.Element('render_fib', attrib={'columns': str(columns), 'fibtype': numtype, 'maxnumber': _max, 'minnumber': _min, 'prompt': "Box"}) response_num.append(render_fib) return response_num - - -# xml_print(response_choice(2, ['a', 'b', 'c'])) - diff --git a/hallgrim/__init__.py b/hallgrim/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..803f7ff936f5b32b02922092e27c905556058dc5 100644 --- a/hallgrim/__init__.py +++ b/hallgrim/__init__.py @@ -0,0 +1,9 @@ + +__title__ = 'hallgrim' +__version__ = '0.1' +__author__ = 'Jan Maximilian Michal' +__license__ = 'MIT' +__copyright__ = 'Copyright 2016 Jan Maximilian Michal' + +# for the executable +from .hallgrim import parseme diff --git a/hallgrim/bin/hallgrim b/hallgrim/bin/hallgrim new file mode 100644 index 0000000000000000000000000000000000000000..7de9d220eb6af00968d4beafef945064b63cea28 --- /dev/null +++ b/hallgrim/bin/hallgrim @@ -0,0 +1,4 @@ +import hallgrim + +if __name__ == '__main__': + hallgrim.parseme() \ No newline at end of file diff --git a/grim.py b/hallgrim/hallgrim.py similarity index 94% rename from grim.py rename to hallgrim/hallgrim.py index 516c26160bbd02903270e697d26baed11b86f421..0eabbe00c3f1a0817e3a5d386b11cef61265287f 100755 --- a/grim.py +++ b/hallgrim/hallgrim.py @@ -1,4 +1,4 @@ -#!/usr/local/bin/python3 +#!/usr/bin/env python3 ########################################################################## # @@ -17,18 +17,22 @@ # ########################################################################## -import importlib +import importlib.util import argparse import os import sys import configparser # local import -from hallgrim.IliasXMLCreator import packer -from hallgrim.custom_markdown import get_markdown -from hallgrim.messages import * -from hallgrim.parser import * -from hallgrim.uploader import send_script +from .IliasXMLCreator import packer +from .custom_markdown import get_markdown +from .messages import * +from .parser import choice_parser, gap_parser +from .uploader import send_script +from .templates import scaffolding + +# set markdown +markdown = get_markdown() def get_config(): @@ -38,7 +42,7 @@ def get_config(): error('Could not find config file.') error('Please edit config.sample.ini and move it to config.ini') error('Continue with default values. Script might fail.') - config.read('config.sample.ini') + config['META'] = {'author' : '__default__'} return config def file_to_module(name): @@ -158,7 +162,10 @@ def delegator(output, script_list, instances): instances {int} -- number of instances that should be generated """ for script_name in filter(lambda a: a.endswith('.py'), script_list): - script = importlib.import_module(file_to_module(script_name)) + module_name = os.path.basename(script_name) + spec = importlib.util.spec_from_file_location(module_name, script_name) + script = importlib.util.module_from_spec(spec) + spec.loader.exec_module(script) handler = { 'gap': handle_gap_questions, 'single': handle_choice_questions, @@ -245,8 +252,6 @@ def handle_new_script(name, qtype, author, points): author {str} -- the author of the script points {float} -- number of points for the task """ - from hallgrim.templates import scaffolding - with open('scripts/' + name + '.py', 'w') as new_script: choice = '' if qtype in ['multiple choice', 'single choice']: @@ -277,7 +282,3 @@ def handle_upload(script_path, config): ) info("Uploaded %s. Status code looks %s." % (script_path, "good" if r else "bad")) - -if __name__ == '__main__': - markdown = get_markdown() - parseme() diff --git a/hallgrim/parser.py b/hallgrim/parser.py index 70d7e5002abaf92f1bb7b9d560c396442360e363..3ccb74119f2ef3d11c0925f06eeef972eb69cdd7 100644 --- a/hallgrim/parser.py +++ b/hallgrim/parser.py @@ -1,8 +1,7 @@ import re +import collections -from hallgrim.custom_markdown import get_markdown -from collections import deque -from pprint import pprint +from .custom_markdown import get_markdown def choice_parser(raw_choices, points): @@ -23,28 +22,31 @@ def choice_parser(raw_choices, points): markdown(text), True if mark != ' ' else False, float(mark) if mark not in ' X' else points) - for mark, _, text in parse] + for mark, _, text in parse] return final + def gap_parser(task): markdown = get_markdown() # '\[gap\]([\w\W]+?)\[\/gap\]' # '\[select\]([\w\W]+?)\[\/select\]' # '\[numeric\]([\w\W]+?)\[\/numeric\]' - # We match against one big regex that consists of three smaller ones (see above) + # We match against one big regex that consists of three smaller ones (see + # above) _all = re.compile('(\[numeric\((([0-9]*[.])?[0-9]+)P\)\]([\w\W]+?)(\[\/numeric\])|(\[select\])([\w\W]+?)\[\/select\]|\[gap\((([0-9]*[.])?[0-9]+)P\)\]([\w\W]+?)(\[\/gap\]))', re.MULTILINE) for m in re.finditer(_all, task): ('[gap]' in m.groups()) - gaps = deque() + gaps = collections.deque() for m in re.finditer(_all, task): if '[select]' in m.groups(): match = m.group(7) lines = match.strip().split('\n') regex = re.compile('\[(([0-9]*[.])?[0-9]+| )\]\s?([\w\W]+)', re.MULTILINE) parse = [re.search(regex, line).groups() for line in lines] - gaps.append(([(text, float(points) if not points == ' ' else 0) for points, _, text in parse], 999)) + gaps.append(([(text, float(points) if not points == ' ' else 0) + for points, _, text in parse], 999)) if '[/gap]' in m.groups(): match = m.group(10) @@ -63,9 +65,9 @@ def gap_parser(task): source = re.sub(_all, 'AISBLAKJSD', task) source = markdown(source) - texts = deque(source.split('AISBLAKJSD')) + texts = collections.deque(source.split('AISBLAKJSD')) - final = deque() + final = collections.deque() for _ in range(min(len(texts), len(gaps))): text = texts.popleft() if text != "": diff --git a/hallgrim/ilias_templates/gap/1478024104__9310__qpl_82996.xml b/hallgrim/res/ilias_templates/gap/1478024104__9310__qpl_82996.xml similarity index 100% rename from hallgrim/ilias_templates/gap/1478024104__9310__qpl_82996.xml rename to hallgrim/res/ilias_templates/gap/1478024104__9310__qpl_82996.xml diff --git a/hallgrim/ilias_templates/gap/1478024104__9310__qti_82996.xml b/hallgrim/res/ilias_templates/gap/1478024104__9310__qti_82996.xml similarity index 100% rename from hallgrim/ilias_templates/gap/1478024104__9310__qti_82996.xml rename to hallgrim/res/ilias_templates/gap/1478024104__9310__qti_82996.xml diff --git a/hallgrim/ilias_templates/multiple choice/1478003900__9310__qpl_82996.xml b/hallgrim/res/ilias_templates/multiple choice/1478003900__9310__qpl_82996.xml similarity index 100% rename from hallgrim/ilias_templates/multiple choice/1478003900__9310__qpl_82996.xml rename to hallgrim/res/ilias_templates/multiple choice/1478003900__9310__qpl_82996.xml diff --git a/hallgrim/ilias_templates/multiple choice/1478003900__9310__qti_82996.xml b/hallgrim/res/ilias_templates/multiple choice/1478003900__9310__qti_82996.xml similarity index 100% rename from hallgrim/ilias_templates/multiple choice/1478003900__9310__qti_82996.xml rename to hallgrim/res/ilias_templates/multiple choice/1478003900__9310__qti_82996.xml diff --git a/hallgrim/ilias_templates/single choice/1478020233__9310__qpl_82996.xml b/hallgrim/res/ilias_templates/single choice/1478020233__9310__qpl_82996.xml similarity index 100% rename from hallgrim/ilias_templates/single choice/1478020233__9310__qpl_82996.xml rename to hallgrim/res/ilias_templates/single choice/1478020233__9310__qpl_82996.xml diff --git a/hallgrim/ilias_templates/single choice/1478020233__9310__qti_82996.xml b/hallgrim/res/ilias_templates/single choice/1478020233__9310__qti_82996.xml similarity index 100% rename from hallgrim/ilias_templates/single choice/1478020233__9310__qti_82996.xml rename to hallgrim/res/ilias_templates/single choice/1478020233__9310__qti_82996.xml diff --git a/hallgrim/test.py b/hallgrim/test.py deleted file mode 100644 index 289453af3e27f95dd95b1e66c47d7cc834316fbb..0000000000000000000000000000000000000000 --- a/hallgrim/test.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: utf-8 -*- - -from custom_markdown import get_markdown -from collections import deque -from pprint import pprint - - -task = """[gap]LALAL2[/gap] KJAakjsfdaskdjfnalksdf - - -```java -[select] - [3] `int n_ze = m.length;` - [ ] `int n_ze = m[0].length;` - [ ] `int n_ze = m.length();` - [ ] `int n_ze = m[0].length();` -[/select] - -[gap]LALAL1[/gap][gap]LALAL2[/gap] - -public static void main { - System.out.println("TATAT"); -} -[numeric]3.4,-1, 34.7[/numeric][numeric]4,+5,6[/numeric][numeric]4[/numeric] -``` - - -HALLO WO BIN ICH - -[select] - [4] `int n_ze = m.length;` - [ ] `asdlkjasld;` -[/select] - -END""" - -import re - -markdown = get_markdown() - - -# '\[gap\]([\w\W]+?)\[\/gap\]' -# '\[select\]([\w\W]+?)\[\/select\]' -# '\[numeric\]([\w\W]+?)\[\/numeric\]' -# We match against one big regex that consists of three smaller ones (see above) -_all = re.compile('(\[numeric\]([\w\W]+?)(\[\/numeric\])|(\[select\])([\w\W]+?)\[\/select\]|\[gap\]([\w\W]+?)(\[\/gap\]))', re.MULTILINE) -for m in re.finditer(_all, task): - ('[gap]' in m.groups()) - -gaps = deque() -for m in re.finditer(_all, task): - if '[select]' in m.groups(): - match = m.group(5) - lines = match.strip().split('\n') - regex = re.compile('\[(([0-9]*[.])?[0-9]+| )\]\s?([\w\W]+)', re.MULTILINE) - parse = [re.search(regex, line).groups() for line in lines] - gaps.append([(text, float(points) if not points == ' ' else 0) for points, _, text in parse]) - - if '[/gap]' in m.groups(): - match = m.group(6).strip('\n\t ') - gaps.append((match, 4)) ## ADD POINTS !! - - if '[/numeric]' in m.groups(): - match = m.group(2) - regex = re.compile('[-+]?\d*\.\d+|\d+') - parse = re.findall(regex, match) - if len(parse) == 1: - gaps.append(((parse[0], parse[0], parse[0]), 4)) - elif len(parse) == 3: - gaps.append((tuple(parse), 4)) - else: - raise Exception("Numeric gap takes either exactly one value or (value, min, max).") - -n = re.sub(_all, 'GAPGAP', task) -n = markdown(n) -t = deque(n.split('GAPGAP')) - -final = deque() -while text or gaps: - if text[0] != "": - final.append(text.popleft()) - final.append(gap.popleft()) - -return final \ No newline at end of file diff --git a/scripts/Eine Methode (I1-ID: 75li4j91gdg0).py b/scripts/Eine Methode (I1-ID: 75li4j91gdg0).py deleted file mode 100644 index 1ab1b5c639c9a5d907c1c90ad848a62393638d21..0000000000000000000000000000000000000000 --- a/scripts/Eine Methode (I1-ID: 75li4j91gdg0).py +++ /dev/null @@ -1,51 +0,0 @@ -meta = { - 'author': 'ILIAS Author', - 'title': 'Eine Methode (I1-ID: 75li4j91gdg0)', - 'type': 'gap', - 'points': 5.0, -} - -gap1 = "[select][0.0]final\n [0.5]static\n [0]void\n [0]private\n [/select]" -gap2 = "[select][0]string\n [0]int\n [0.5]boolean\n [0]class\n [/select]" -gap3 = "[select][1]return\n [0]system.out.println\n [0]=\n [0]set\n [/select]" -gap4 = "[select][0]j % 4\n [0]j : 4\n [0.5]j % 4 == 0\n [0]j : 4 == 0\n [/select]" -gap5 = "[select][0.5]&&\n [0.5]||\n [0.5]&\n [0]^\n [/select]" -gap6 = "[select][0]j : 100 != 0 || j : 400 == 0\n [0]j % 100 != 0 || j % 400 = 0\n [0]j : 100 != 0 || j : 400 = 0\n [1]j % 100 != 0 || j % 400 == 0\n [/select]" - -task = """ - -Ein Jahr ist ein Schaltjahr, wenn es durch 4 aber nicht durch 100 teilbar ist -oder aber, wenn es durch 400 teilbar ist. Ergänzen Sie den folgenden Quelltext -so, dass die Methode genau dann den Wert true liefert, wenn Jahr j ein -Schaltjahr ist. - -```java -class Schaltjahr { - public static void main(String[] args) { - int jahr = Integer.parseInt(args[0]); - System.out.println(schaltjahr(jahr)); - } - public %s %s schaltjahr (int j) { - %s (%s %s %s); - } -} -``` - -""" % (gap1, gap2, gap3, gap4, gap5, gap6) - - -feedback = """ -Der vollständige Code: - -```java_copy -class Schaltjahr { - public static void main(String[] args) { - int jahr = Integer.parseInt(args[0]); - System.out.println(schaltjahr(jahr)); - } - public static boolean schaltjahr (int j) { - return (j % 4 == 0 && j % 100 != 0 || j % 400 == 0); - } -} -``` -""" diff --git a/scripts/Polynome (I1-ID: 177d1ez05pg0).py b/scripts/Polynome (I1-ID: 177d1ez05pg0).py deleted file mode 100644 index a7d5646617e9ef135756f3391a4aceb5489708b2..0000000000000000000000000000000000000000 --- a/scripts/Polynome (I1-ID: 177d1ez05pg0).py +++ /dev/null @@ -1,75 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Polynome (I1-ID: 177d1ez05pg0)', - 'type': 'gap', - 'points': 0.0, -} - -task = """ -Vervollständigen Sie die folgende Klasse: - -```java -public class Polynom { - // diese Klasse dient dazu, Polynome (also Funktionen der Gestalt - // a(x) = a0 + a1*x + a2*x^2 + ... + ad*x^d) als statische - // Java-Funktionen bereitzustellen - - /* Argumente: double-Feld (fuer Koeffizienten a0, a1, .., ad) und Zahl x - Ergebniswert: Wert des Polynoms an der Stelle x (Typ double)*/ - public static double p([gap(0.5P)]double[] a[/gap], double x) { - // Sonderfall: das Nullpolynom - int d = [gap(0.5P)]a.length - 1[/gap]; // Polynomgrad - if ( d == -1) - return 0; - // ansonsten: berechne gesuchten Wert nach dem Horner-Schema: - double v = 0; - for (int i = d; i [gap(0.5P)]>=[/gap] 0; i--) { - v [gap(0.5P)]*=[/gap] x; - v += a[i]; - } - return v; - } - - public static void main(String[] args) { /* Unit-Test */ - [gap(0.5P)]double[][/gap] a = {2,1,-1,3}; - System.out.println(p([gap(0.5P)]a[/gap], 10)); - } -} -``` - -Welcher Wert wird bei dem Unit-Test ausgegeben? [gap(1P)]2912[/gap] -""" - -feedback = """ -Der vollständige Quelltext - -```java -public class Polynom { - // diese Klasse dient dazu, Polynome (also Funktionen der Gestalt - // a(x) = a0 + a1*x + a2*x^2 + ... + ad*x^d) als statische - // Java-Funktionen bereitzustellen - - /* Argumente: double-Feld (fuer Koeffizienten a0, a1, .., ad) und Zahl x - Ergebniswert: Wert des Polynoms an der Stelle x (Typ double)*/ - public static double p(double[] a, double x) { - // Sonderfall: das Nullpolynom - int d = a.length - 1; // Polynomgrad - if ( d == -1) - return 0; - // ansonsten: berechne gesuchten Wert nach dem Horner-Schema: - double v = 0; - for (int i = d; i >= 0; i--) { - v *= x; - v += a[i]; - } - return v; - } - - public static void main(String[] args) { /* Unit-Test */ - double[] a = {2,1,-1,3}; - System.out.println(p(a, 10)); - } -} -``` - - """ diff --git a/scripts/Rekursion (I1-ID: vi02mcw0lfh0).py b/scripts/Rekursion (I1-ID: vi02mcw0lfh0).py deleted file mode 100644 index cd6e0301cb6d8c14358b6f102ac119acfac6336e..0000000000000000000000000000000000000000 --- a/scripts/Rekursion (I1-ID: vi02mcw0lfh0).py +++ /dev/null @@ -1,35 +0,0 @@ -meta = { - 'author': 'ILIAS Author', - 'title': 'Rekursion (I1-ID: vi02mcw0lfh0)', - 'type': 'gap', - 'points': 4, -} - -task = """ -Welchen String liefert der Aufruf exB(5)? - -```java_copy -public static String exB(int n) { - if (n <= 0) - return ""; - return exB(n-2) + (n+1) + exB(n-1); -} -``` - -Geben Sie die Ziffern hintereinander an, d.h. ohne Leerzeichen o.ä.: [gap(4P)]243263252432[/gap] -""" - -feedback = """ - -Der Rekursionsbaum stellt die Aufrufe durch Knoten dar, die jeweils mit dem -Aufrufargument markiert sind. Die äußeren Knoten (ganz unten) entsprechen -Basisfällen, sie tragen nicht zum Ergebnisstring bei (denn sie liefern nur das -leere Wort). Die anderen (inneren) Knoten tragen bei, und zwar in unserem Fall -je eine Ziffer. - -glw4u2g0xfg0.png - -Traversiert man den Baum in Inorder-Reihenfolge, so ist die Reihenfolge der -Aufrufargumente genau `1, 3, 2, 1, 5, 2, 1, 4, 1, 3, 2, 1`. Die entsprechenden -Ziffern sind immer um 1 höher, also lautet der Ergebnisstring: 243263252432 -""" diff --git a/scripts/Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0).py b/scripts/Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0).py deleted file mode 100644 index 68cd72145e3e60b07a5a054c069fc2436362995a..0000000000000000000000000000000000000000 --- a/scripts/Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0).py +++ /dev/null @@ -1,32 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0)', - 'type': 'multiple choice', - 'points': 0.5, -} - -task = """ Kreuzen Sie alles an, was im weitesten Sinne wahr ist (wahre Aussagen, korrekte Formulierungen, Ausdrücke mit Wert true): """ - -choices = """ -[X] Formalparameter sind lokale Variablen. -[X] Die JVM interpretiert Java-Bytecode. -[X] (false ? true : false) == (true ? false : true) -[ ] Das rekursive Grundschema lautet: Rekurriere - Finalisiere (falls trivial) -[ ] Die Java-Laufzeitumgebung beinhaltet Compiler, Klassenbibliotheken und die (JVM) Java Virtual Machine. -[ ] An Ausdrücke dürfen keine Zuweisungen erfolgen. -[ ] Methoden mit Signatur int (int) werden mit call-by-reference aufgerufen. -[ ] (false ? false : true) == (false ? true : false) -""" - -feedback = """ -| Aussage | Wert | Begründung | -|---------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Formalparameter sind lokale Variablen. | TRUE | Die im Methodenkopf definierten Parameter heißen auch Formalparameter und werden innerhalb der Methode als Variable gebraucht. Tatsächliche Parameter sind die im Programmablauf übergebenen Werte oder Referenzen. | -| Die JVM interpretiert Java-Bytecode. | TRUE | Java-Bytecode ist das Instruction-Set der Java-Virtual-Machine | -| (false ? true : false) == (true ? false : true) | TRUE | (false ? true : false) == (true ? false : true) -> false == false -> true | -| Das rekursive Grundschema lautet: Rekurriere - Finalisiere (falls trivial) | FALSE | Das rekursive Grundschema lautet: Finalisiere (falls trivial) - Rekurriere | -| Die Java-Laufzeitumgebung beinhaltet Compiler, Klassenbibliotheken und die (JVM) Java Virtual Machine. | FALSE | Wikipedia: "Allgemein besteht die Laufzeitumgebung aus der Java Virtual Machine (Java VM), die für die Ausführung der Java-Anwendungen verantwortlich ist, einer Programmierschnittstelle (API, für Application and Programming Interface) und weiteren Programmbibliotheken." Ein Compiler gehört nicht dazu. | -| An Ausdrücke dürfen keine Zuweisungen erfolgen. | FALSE | Da zum Beispiel x[0] = 1 | -| Methoden mit Signatur int (int) werden mit call-by-reference aufgerufen. | FALSE | Sämtliche Java Methoden werden mit call-by-value aufgerufen. Eine gute Erklärung zu den Unterschieden finden Sie hier. | -| (false ? false : true) == (false ? true : false) | FALSE | (false ? false : true) == (false ? true : false) -> true == false -> false | -""" diff --git a/scripts/examples/feldarbeit_param.py b/scripts/examples/feldarbeit_param.py deleted file mode 100644 index b803eca2aba19ae4754050cd78f4a31cbdb7c8b5..0000000000000000000000000000000000000000 --- a/scripts/examples/feldarbeit_param.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- - -from random import shuffle, sample - -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Feldarbeit (I1-ID: p0kaixs0lyg0)', - 'type': 'single choice', - 'points': 1, # per correct choice -} - - -def list_to_str(lst): - return str(lst).strip('[]') - - -N = 8 -a = sample(range(20), N) -o = list(a) -for i in range(N): - a[i] = a[(i + 1) % N] - -c = a[:-1] + [o[0]] - -task = """ -Welche Ausgabe erzeugt folgender Code: - -```java -public class Feldarbeit { - public static void main(String[] args) { - int[] a = { %s }; - int N = a.length; - for (int i = 0; i < N; i++) { - a[i] = a[(i+1) %% N]; - } - for (int i = 0; i < N; i++) - System.out.print(a[i] + " "); - System.out.println(); - } -} -``` -""" % list_to_str(o) - -choices = """ -[4] `%s` -[2] `%s` -[ ] `1 1 1 1 1 1 1 1` -[ ] `%s` -""" % (list_to_str(a), list_to_str(c), list_to_str(shuffle(o))) - -feedback = """ - -Betrachten Sie die folgenden Zeilen: -```java -for (int i = 0; i < N; i++) { - a[i] = a[(i+1) %% N]; -} -``` - -Der Inhalt jeder Zelle des Arrays jeweils durch den linken Nachbarn ersetzt, -wobei an den Rändern zyklisch verfahren wird. Dadurch, dass *in-place* verfahren -wird, also keine Kopie erstellt wird, wird der neue Inhalt der 0. Zelle in die -letzte geschrieben, daher enthält das neue Array keine %d mehr.""" % o[0] diff --git a/scripts/examples/multi_proto.py b/scripts/examples/multi_proto.py deleted file mode 100644 index 266816ad7c5dea64f5101f6a81266aff3f35c3aa..0000000000000000000000000000000000000000 --- a/scripts/examples/multi_proto.py +++ /dev/null @@ -1,40 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Sortieren nach Punkten (I1-ID: nipe84411eh0)', - 'type': 'multiple choice', - 'points': 0.5, # per correct choice -} - -task = """ -Hier der Anfang der Datei `punkte.csv`, die Komma-getrennte Angaben -zu erreichten Übungspunkten enthält [[Example Formula \\sum_{i=0}^n i]]: - -``` -21600001,Herr,Bollman,Fritze-Peter,15 -21600002,Frau,Bollwoman,Franzi,19 -21600003,Herr,Lindemann,Erwin,17 -21600004,Frau,Lindefrau,Edelgard Martha,12 -21600005,Herr,Machtnix,Mike,2 -..... -``` - -Welches Shell-Kommando ist geeignet, die Zeilen nach fallender Punktzahl -sortiert auszugeben (also erst große, dann kleinere Punktzahlen)? """ - -choices = """ -[ ] `sort --reverse --k 5 --numeric-sort punkte.csv` -[ ] `sort --r --field-separator=, -k 5 --n punkte.csv` -[ ] `sort -r -t="," -k 5 --n punkte.csv` -[X] `sort --reverse -t "," -k 5 -n punkte.csv` -[ ] `sort -r --field-separator "," -k 4 -numeric punkte.csv` -[ ] `sort -r --field-separator "," -k 4 punkte.csv` -""" - -feedback = """ -* [ ] `sort --reverse --k 5 --numeric-sort punkte.csv` falsch (u.a.: ungültiges Argument --k) -* [ ] `sort --r --field-separator=, -k 5 --n punkte.csv` falsch (u.a.: bei kurzem Argument -k darf kein = stehen) -* [ ] `sort -r -t="," -k 5 --n punkte.csv` falsch (siehe oben) -* [X] `sort --reverse -t "," -k 5 -n punkte.csv` richtig -* [ ] `sort -r --field-separator "," -k 4 -numeric punkte.csv` falsch (u.a.: Punkte stehen in Spalte 5) -* [ ] `sort -r --field-separator "," -k 4 punkte.csv` falsch (u.a.: keine numerische Sortierung) -""" \ No newline at end of file diff --git a/scripts/examples/param_example.py b/scripts/examples/param_example.py deleted file mode 100644 index ef47ec2f2d366cef13a75bf4ba7d0772a0b2096c..0000000000000000000000000000000000000000 --- a/scripts/examples/param_example.py +++ /dev/null @@ -1,24 +0,0 @@ -from random import randint, sample - -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Parameter example', - 'type': 'single choice', - 'points': 4, # for correct answer -} - -a = randint(-50, 49) -b = randint(-50, 49) - - -def get_answers(right, count=4): - possible = sample(range(-100, a+b), count//2) + \ - sample(range(a+b+1, 100), count//2-1) + [a+b] - return [('X' if answer == right else ' ', answer) for answer in possible] - - -task = """ What is the answer to the question {} + {}?""".format(a, b) - -choices = '\n'.join('[%s] a + b = %d' % c for c in get_answers(a+b)) - -feedback = "[[a + b = {}]]".format(a + b) diff --git a/scripts/examples/select.py b/scripts/examples/select.py deleted file mode 100644 index 6eac93ef553bc176a8e903e1d7aa39d4d81563e8..0000000000000000000000000000000000000000 --- a/scripts/examples/select.py +++ /dev/null @@ -1,94 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Zeilen sind anders, Spalten auch (I1-ID: lhu27691fzg0)', - 'type': 'gap', -} - - -gap_1 = """[select] -[1] int n_ze = m.length; -[ ] int n_ze = m[0].length; -[ ] int n_ze = m.length(); -[ ] int n_ze = m[0].length(); -[/select]""" - -gap_2 = """[select] -[ ] int n_sp = m.length(); -[ ] int n_sp = m[0].length(); -[ ] int n_sp = m.length; -[1] int n_sp = m[0].length; -[/select]""" - -gap_3 = """[select] -[ ] for (int i = 1; i <= n_ze; i++) -[1] for (int i = 0; i < n_ze; i++) -[ ] for (int i = 1; i <= n_sp; i++) -[ ] for (int i = 0; i < n_sp; i++) -[/select]""" - -gap_4 = """[select] -[ ] ms[i] = ms[i] + m[j][i]*s[i]; -[ ] ms[i] = ms[i] + m[i][j]*s[i]; -[ ] ms[i] = ms[i] + m[j][i]*s[j]; -[1] ms[i] = ms[i] + m[i][j]*s[j]; -[/select]""" - - -task = """ Folgendes Codefragment soll die Multiplikation eines Zeilenvektors mit einer Matrix sowie einer Matrix mit einem Spaltenvektor realisieren. Wählen Sie die fehlenden Zeilen unten entsprechend aus: - -```java -01: int[][] m = {{ 0, 1, 2, 3}, // Matrix -02: { 4, 5, 6, 7}, -03: {8, 9, 10, 11}}; -04: int[] z = { 12, 13, 14}; // Zeile -05: int[] s = {15, 16, 17, 18}; // Spalte -06: -07: %s // Zeilenanzahl der Matrix -08: %s // Spaltenanzahl der Matrix -09: -10: /* 1: Zeile mal Matrix */ -11: int[] zm = new int[n_sp]; -12: for (int j = 0; j < n_sp; j++) { -13: zm[j] = 0; -14: %s -15: zm[j] = zm[j] + z[i]*m[i][j]; -16: } -17: /* 2: Matrix mal Spalte */ -18: int[] ms = new int[n_ze]; -19: for (int i = 0; i < n_ze; i++) { -20: ms[i] = 0; -21: for (int j = 0; j < n_sp; j++) -22: %s -23: -``` -""" % (gap_1, gap_2, gap_3, gap_4) - -feedback = """ - -Der vollständige Code: - -```java -int[][] m = {{ 0, 1, 2, 3}, // Matrix - { 4, 5, 6, 7}, - {8, 9, 10, 11}}; -int[] z = { 12, 13, 14}; // Zeile -int[] s = {15, 16, 17, 18}; // Spalte - -int n_ze = m.length; // Zeilenanzahl der Matrix -int n_sp = m[0].length; // Spaltenanzahl der Matrix - -/* 1: Zeile mal Matrix */011: int[] zm = new int[n_sp]; -for (int j = 0; j < n_sp; j++) { - zm[j] = 0; - for (int i = 0; i < n_ze; i++) - zm[j] = zm[j] + z[i]*m[i][j]; -} -/* 2: Matrix mal Spalte */ -int[] ms = new int[n_ze]; -for (int i = 0; i < n_ze; i++) { - ms[i] = 0; - for (int j = 0; j < n_sp; j++) - ms[i] = ms[i] + m[i][j]*s[j]; - -``` -""" \ No newline at end of file diff --git a/scripts/examples/single_proto.py b/scripts/examples/single_proto.py deleted file mode 100644 index f96e4de18c1f8aa642f8bcc5bbc96c9ba083a22c..0000000000000000000000000000000000000000 --- a/scripts/examples/single_proto.py +++ /dev/null @@ -1,41 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Sortieren nach Punkten (I1-ID: nipe84411eh0)', - 'type': 'single choice', - 'points': 4, # for correct answer -} - -task = """ Hier der Anfang der Datei `punkte.csv`, die Komma-getrennte Angaben -zu erreichten Übungspunkten enthält: - -``` -21600001,Herr,Bollman,Fritze-Peter,15 -21600002,Frau,Bollwoman,Franzi,19 -21600003,Herr,Lindemann,Erwin,17 -21600004,Frau,Lindefrau,Edelgard Martha,12 -21600005,Herr,Machtnix,Mike,2 -..... -``` - -Welches Shell-Kommando ist geeignet, die Zeilen nach fallender Punktzahl -sortiert auszugeben (also erst große, dann kleinere Punktzahlen)? """ - -choices = """ -[ ] `sort --reverse --k 5 --numeric-sort punkte.csv` -[2] `sort --r --field-separator=, -k 5 --n punkte.csv` -[ ] `sort -r -t="," -k 5 --n punkte.csv` -[4] `sort --reverse -t "," -k 5 -n punkte.csv` -[ ] `sort -r --field-separator "," -k 4 -numeric punkte.csv` -[ ] `sort -r --field-separator "," -k 4 punkte.csv` -""" - -feedback = """ -``` -[ ] sort --reverse --k 5 --numeric-sort punkte.csv falsch (u.a.: ungültiges Argument --k) -[ ] sort --r --field-separator=, -k 5 --n punkte.csv falsch (u.a.: bei kurzem Argument -k darf kein = stehen) -[ ] sort -r -t="," -k 5 --n punkte.csv falsch (siehe oben) -[X] sort --reverse -t "," -k 5 -n punkte.csv richtig -[ ] sort -r --field-separator "," -k 4 -numeric punkte.csv falsch (u.a.: Punkte stehen in Spalte 5) -[ ] sort -r --field-separator "," -k 4 punkte.csv falsch (u.a.: keine numerische Sortierung) -``` -""" diff --git a/scripts/feld_umgraben.py b/scripts/feld_umgraben.py deleted file mode 100644 index abb0542eebf050ba0c18a95d26e136212120a5d9..0000000000000000000000000000000000000000 --- a/scripts/feld_umgraben.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- - -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Feld umgraben (I1-ID: xu71ubs0lyg0)', - 'type': 'single choice', - 'shuffle' : False, - 'points': 1, # per correct choice -} - -task = """Die Reihenfolge der Elemente im Feld `a` der Länge **N** soll umgekehrt werden. Wählen -Sie den Code aus, der diese Aufgabe am besten löst:""" - -choices = [ -"""[4] -``` -for (int i = 0; i < N/2; i++) { - int tmp = a[i]; - a[i] = a[N-i-1]; - a[N-i-1] = tmp; -} -``` -""", - -"""[ ] -``` -int[] b = new int[N]; -for (int i = 0; i < N; i++) - b[i] = a[N-i-1]; -a = b; -``` -""", - -"""[ ] -``` -for (int i = 0; i < N; i++) { - int tmp = a[i]; - a[i] = a[N-i-1]; - a[N-i-1] = tmp; -}``` -""", - -"""[ ] -``` -for (int i = 0; i < N/2; i++) { - int tmp = a[i]; - a[i] = a[N-i]; - a[N-i] = tmp; -}``` -""" - - -] - -feedback = """ -1. löst die Aufgabe, indem alle Elemente "um die Mitte herum rotiert" werden. Das sind maximal n/2 Operationen. -2. löst die Aufgabe NICHT, denn nach n/2 Tauschoperationen wird nochmal zurückgetauscht und alles steht am alten Platz. -3. löst die Aufgabe, verbraucht aber doppelt soviel Speicher wie nötig. -4. löst die Aufgabe NICHT: bei der ersten Iteration wird auf das nicht existente Element a[N] zugegriffen. -""" \ No newline at end of file diff --git a/scripts/feldarbeit.py b/scripts/feldarbeit.py deleted file mode 100644 index 8e11ad59d47a18ee81990b6d7928a43e323c1e72..0000000000000000000000000000000000000000 --- a/scripts/feldarbeit.py +++ /dev/null @@ -1,47 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Feldarbeit (I1-ID: p0kaixs0lyg0)', - 'type': 'single choice', - 'points': 1, # per correct choice -} - -task = """ -Welche Ausgabe erzeugt folgender Code: - -```java -public class Feldarbeit { - public static void main(String[] args) { - int[] a = { 0, 1, 2, 3, 4, 5, 6, 7}; - int N = a.length; - for (int i = 0; i < N; i++) { - a[i] = a[(i+1) % N]; - } - for (int i = 0; i < N; i++) - System.out.print(a[i] + " "); - System.out.println(); - } -} -``` -""" - -choices = """ -[4] `1 2 3 4 5 6 7 1` -[2] `1 2 3 4 5 6 7 0` -[ ] `1 1 1 1 1 1 1 1` -[ ] `7 0 1 2 3 4 5 6` -""" - -feedback = """ -Betrachten Sie die folgenden Zeilen: -```java -for (int i = 0; i < N; i++) { - a[i] = a[(i+1) % N]; -} -``` - -Der Inhalt jeder Zelle des Arrays jeweils durch den linken Nachbarn ersetzt, -wobei an den Rändern zyklisch verfahren wird. Dadurch, dass *in-place* verfahren -wird, also keine Kopie erstellt wird, wird der neue Inhalt der 0. Zelle in die -letzte geschrieben, daher enthält das neue Array keine 0 mehr. """ - - diff --git a/scripts/info1_02_klausur.py b/scripts/info1_02_klausur.py deleted file mode 100644 index 3ebc25c119a6a4ea2cb440ebb1f34397a9c525d8..0000000000000000000000000000000000000000 --- a/scripts/info1_02_klausur.py +++ /dev/null @@ -1,30 +0,0 @@ -meta = { - 'author': 'Carsten Damm', - 'title': 'Vermischtes zu elementaren Daten (I1-ID: e638zfi0qtg0)', - 'type': 'multiple choice', - 'points': 0.5, # per correct choice -} - -task = """ Markieren Sie alle zutreffenden Aussagen: """ - -choices = """ -[ ] `int x = Integer.MAX_VALUE; x++;` verursacht eine OverflowException. -[ ] Steuerzeichen werden vom Steuerwerk interpretiert. -[X] `if (b > 0 && a/b < 2)` ... ist besser als `if (a/b < 2 && b > 0)` ... -[ ] Umlaute im Quelltext verursachen Compilezeitfehler. -[X] `"h\u00F6chstens 6 Zeichen"` ist ein Literal. -[ ] `Integer.MAX_VALUE++;` verursacht einen Ganzzahlüberlauf. -[ ] UTF-8 ordnet jedem Zeichen eine Folge von 8 Bytes zu. -[X] Ganzzahl-Arithmetik ist schneller als Gleitkomma-Arithmetik. -""" - -feedback = """ -Die folgenden Aussagen sind korrekt: - -* `if (b > 0 && a/b < 2)` ... ist besser als `if (a/b < 2 && b > 0)` ... - * *Begründung:* `a/b < 2` ist aufwändiger zu berechnen als `b > 0`. Bei einer Prüfung des Wahrheitswerts einer Konjunktion muss der zweite Term nicht betrachtet werden, wenn der erste falsch ist. -* `"h\u00F6chstens 6 Zeichen"` ist ein Literal. - * *Begründung:* Da der String eine konstanten Wert darstellt ist er als Literal zu bezeichnen. -* Ganzzahl-Arithmetik ist schneller als Gleitkomma-Arithmetik. - * *Begründung:* Floating Point Arithmetik ist wesentlich aufwändiger als Integer Arithmetik (siehe zum Vergleich: Zweitkomplement und IEE-754) -""" \ No newline at end of file diff --git a/scripts/nur_sterne_sehen.py b/scripts/nur_sterne_sehen.py deleted file mode 100644 index f9e07c93a0e9ccb9a23888d28ba69db6d0e5841a..0000000000000000000000000000000000000000 --- a/scripts/nur_sterne_sehen.py +++ /dev/null @@ -1,43 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Nur Sterne sehen (I1-ID: cgu8rno0kyg0)', - 'type': 'single choice', - 'points': 1, # per correct choice -} - -task = """ - -Das folgende Programm (nach [Sedgewick/Wayne]) erzeugt als Ausgaben mehrere -Zeilen mit Ziffern (hier genau vier): - -```java -public class Ruler { - public static void main(String[] args) { - String ruler1 = "1"; System.out.println(ruler1); - String ruler2 = ruler1 + "2" + ruler1; System.out.println(ruler2); - String ruler3 = ruler2 + "3" + ruler2;or System.out.println(ruler3); - String ruler4 = ruler3 + "4" + ruler3; System.out.println(ruler4); - // usw. - } -}``` - -Wäre `main` auf genügend Codezeilen nach dem gleichen Schema ergänzt, wieviele -Zahlen würde bei Ausführung die n-te Ausgabezeile enthalten? """ - -choices = """ -[ ] [[n]] -[4] [[2^n−1]] -[ ] [[2^n]] -[ ] [[2n+1]]""" - -feedback = r""" -Die erste Zeile ergibt genau die Ausgabe `1`. In jeder folgenden -Zeile wird die Anzahl der Zahlen verdoppelt und um eine weitere Zahl ergänzt. -Die Anzahl der Zahlen [[a_n]] im Schritt [[n]] ist daher: [[a_n = 2a_{n-1} + -1]]. -Als natürlche Folge ergibt sich: - -* [[S_n = a_0 + 2a_0 + 4a_0 + \dots + 2^{n-1}a_0 = a_0 (2^n - 1)]] - -Weil [[a_0 = 1]] ist [[2^n−1]] die korrekte Antwort. -""" \ No newline at end of file diff --git a/scripts/originale_kopien.py b/scripts/originale_kopien.py deleted file mode 100644 index 09e87e08c7628d1903b85b3e4fe038c8a8f1e4be..0000000000000000000000000000000000000000 --- a/scripts/originale_kopien.py +++ /dev/null @@ -1,40 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Originale Kopien? (I1-ID: 0c05by80syg0)', - 'type': 'gap', - 'points': 0.5, # per correct choice -} - - -task = """ `a`, `b` sind Variablen vom Typ `char[]` und `c`, `d` sind Variablen -vom Typ `String`. `a`, `b`, `c` und `d` sind bereits korrekt mit Zeichenfolgen -der Länge 2 initialisiert (d.h. die jeweiligen Felder/Strings belegen -Speicherplatz und man kann auf ihre Inhalte zugreifen). Welcher Code ist -geeignet, um festzustellen, ob die in a und b bzw. in c und d gespeicherten -Zeichenfolgen gleich sind? - -* `if (a == b) ...` [select][ ]geeignet\n[0.5]ungeeignet[/select] -* `if (a.equals(b)) ...` [select][ ]geeignet\n[0.5]ungeeignet[/select] -* `if (a[0] == b[0] || a[1] == b[1]) ...` [select][ ]geeignet\n[0.5]ungeeignet[/select] -* `if (a[0] == b[0] && a[1] == b[1]) ...` [select][0.5]geeignet\n[ ]ungeeignet[/select] -* `if (c == d) ...` [select][ ]geeignet\n[0.5]ungeeignet[/select] -* `if (c.equals(d)) ...` [select][0.5]geeignet\n[ ]ungeeignet[/select] -* `if (c.compareTo(d) == 0) ...` [select][0.5]geeignet\n[ ]ungeeignet[/select] -* `if (c[0] == d[0] && c[1] == d[1]) ...` [select][ ]geeignet\n[0.5]ungeeignet[/select] -""" - -# Antworten bitte aus drop-down-Menü wählen lassen: -# Auswahl jeweils geeignet/nicht geeignet - - -feedback = """ - -Wichtig ist darauf zu achten, dass Objekte vom Typ String spezifische Methoden -exportieren, die das vergleichen oder bearbeiten von Zeichenketten erlauben. -Einfache `char[]` Arrays erlauben das nicht. - -Da der Objekte vom Typ String jedoch `char` Arrays enthalten ist es möglich -über Indizierung den Vergleich 'per Hand' durchzuführen. - -""" - diff --git a/scripts/vermischtes.py b/scripts/vermischtes.py deleted file mode 100644 index 8e662c692aa5410001ccaef95be2d7fa9c2a722c..0000000000000000000000000000000000000000 --- a/scripts/vermischtes.py +++ /dev/null @@ -1,32 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0)', - 'type': 'multiple choice', - 'points': 0.5, -} - -task = """ Kreuzen Sie alles an, was im weitesten Sinne wahr ist (wahre Aussagen, korrekte Formulierungen, Ausdrücke mit Wert true): """ - -choices = """ -[X] Formalparameter sind lokale Variablen. -[X] Die JVM interpretiert Java-Bytecode. -[X] (false ? true : false) == (true ? false : true) -[ ] Das rekursive Grundschema lautet: Rekurriere - Finalisiere (falls trivial) -[ ] Die Java-Laufzeitumgebung beinhaltet Compiler, Klassenbibliotheken und die (JVM) Java Virtual Machine. -[ ] An Ausdrücke dürfen keine Zuweisungen erfolgen. -[ ] Methoden mit Signatur int (int) werden mit call-by-reference aufgerufen. -[ ] (false ? false : true) == (false ? true : false) -""" - -feedback = """ -| Aussage | Wert | Begründung | -|---------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| Formalparameter sind lokale Variablen. | TRUE | Die im Methodenkopf definierten Parameter heißen auch Formalparameter und werden innerhalb der Methode als Variable gebraucht. Tatsächliche Parameter sind die im Programmablauf übergebenen Werte oder Referenzen. | -| Die JVM interpretiert Java-Bytecode. | TRUE | Java-Bytecode ist das Instruction-Set der Java-Virtual-Machine | -| (false ? true : false) == (true ? false : true) | TRUE | (false ? true : false) == (true ? false : true) -> false == false -> true | -| Das rekursive Grundschema lautet: Rekurriere - Finalisiere (falls trivial) | FALSE | Das rekursive Grundschema lautet: Finalisiere (falls trivial) - Rekurriere | -| Die Java-Laufzeitumgebung beinhaltet Compiler, Klassenbibliotheken und die (JVM) Java Virtual Machine. | FALSE | Wikipedia: "Allgemein besteht die Laufzeitumgebung aus der Java Virtual Machine (Java VM), die für die Ausführung der Java-Anwendungen verantwortlich ist, einer Programmierschnittstelle (API, für Application and Programming Interface) und weiteren Programmbibliotheken." Ein Compiler gehört nicht dazu. | -| An Ausdrücke dürfen keine Zuweisungen erfolgen. | FALSE | Da zum Beispiel x[0] = 1 | -| Methoden mit Signatur int (int) werden mit call-by-reference aufgerufen. | FALSE | Sämtliche Java Methoden werden mit call-by-value aufgerufen. Eine gute Erklärung zu den Unterschieden finden Sie hier. | -| (false ? false : true) == (false ? true : false) | FALSE | (false ? false : true) == (false ? true : false) -> true == false -> false | -""" diff --git a/scripts/zeilen_sind_anders.py b/scripts/zeilen_sind_anders.py deleted file mode 100644 index 4aefe5dd25382d10f130e650155dc86b46653626..0000000000000000000000000000000000000000 --- a/scripts/zeilen_sind_anders.py +++ /dev/null @@ -1,105 +0,0 @@ -meta = { - 'author': 'Jan Maximilian Michal', - 'title': 'Zeilen sind anders, Spalten auch (I1-ID: lhu27691fzg0)', - 'type': 'gap', -} - - -gap_1 = """[select] -[1] int n_ze = m.length; -[ ] int n_ze = m[0].length; -[ ] int n_ze = m.length(); -[ ] int n_ze = m[0].length(); -[/select]""" - -gap_2 = """[select] -[ ] int n_sp = m.length(); -[ ] int n_sp = m[0].length(); -[ ] int n_sp = m.length; -[1] int n_sp = m[0].length; -[/select]""" - -gap_3 = """[select] -[ ] for (int i = 1; i <= n_ze; i++) -[1] for (int i = 0; i < n_ze; i++) -[ ] for (int i = 1; i <= n_sp; i++) -[ ] for (int i = 0; i < n_sp; i++) -[/select]""" - -gap_4 = """[select] -[ ] ms[i] = ms[i] + m[j][i]*s[i]; -[ ] ms[i] = ms[i] + m[i][j]*s[i]; -[ ] ms[i] = ms[i] + m[j][i]*s[j]; -[1] ms[i] = ms[i] + m[i][j]*s[j]; -[/select]""" - - -task = """ Folgendes Codefragment soll die Multiplikation eines Zeilenvektors mit einer Matrix sowie einer Matrix mit einem Spaltenvektor realisieren. Wählen Sie die fehlenden Zeilen unten entsprechend aus: - -```java -01: int[][] m = {{ 0, 1, 2, 3}, // Matrix -02: { 4, 5, 6, 7}, -03: {8, 9, 10, 11}}; -04: int[] z = { 12, 13, 14}; // Zeile -05: int[] s = {15, 16, 17, 18}; // Spalte -06: -07: /* CODEZEILE AUSWÄHLEN */ // Zeilenanzahl der Matrix -08: /* CODEZEILE AUSWÄHLEN */ // Spaltenanzahl der Matrix -09: -10: /* 1: Zeile mal Matrix */011: int[] zm = new int[n_sp]; -12: for (int j = 0; j < n_sp; j++) { -13: zm[j] = 0; -14: /* CODEZEILE AUSWÄHLEN */ -15: zm[j] = zm[j] + z[i]*m[i][j]; -16: } -17: /* 2: Matrix mal Spalte */ -18: int[] ms = new int[n_ze]; -19: for (int i = 0; i < n_ze; i++) { -20: ms[i] = 0; -21: for (int j = 0; j < n_sp; j++) -22: /* CODEZEILE AUSWÄHLEN */ -23: -``` - -**Zeile 7:** -%s - -**Zeile 8:** -%s - -**Zeile 14:** -%s - -**Zeile 22:** -%s -""" % (gap_1, gap_2, gap_3, gap_4) - -feedback = """ - -Der vollständige Code: - -```java -int[][] m = {{ 0, 1, 2, 3}, // Matrix - { 4, 5, 6, 7}, - {8, 9, 10, 11}}; -int[] z = { 12, 13, 14}; // Zeile -int[] s = {15, 16, 17, 18}; // Spalte - -int n_ze = m.length; // Zeilenanzahl der Matrix -int n_sp = m[0].length; // Spaltenanzahl der Matrix - -/* 1: Zeile mal Matrix */011: int[] zm = new int[n_sp]; -for (int j = 0; j < n_sp; j++) { - zm[j] = 0; - for (int i = 0; i < n_ze; i++) - zm[j] = zm[j] + z[i]*m[i][j]; -} -/* 2: Matrix mal Spalte */ -int[] ms = new int[n_ze]; -for (int i = 0; i < n_ze; i++) { - ms[i] = 0; - for (int j = 0; j < n_sp; j++) - ms[i] = ms[i] + m[i][j]*s[j]; - -``` -""" \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..5c6e82979e9ccbdea3fa3e7c33f0d7c7d521b14c --- /dev/null +++ b/setup.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- + +from setuptools import setup, find_packages + + +with open('README.md') as f: + readme = f.read() + +with open('LICENSE') as f: + license = f.read() + +setup( + name='hallgrim', + version='0.1', + description='A script generator for the ILIAS platform', + long_description=readme, + author='Jan Maximilian Michal', + author_email='mail-github@jmx.io', + url='https://gitlab.gwdg.de/j.michal/ilias-generator', + license=license, + scripts=['hallgrim/bin/hallgrim'], + install_requires=['mistune', 'pygments', 'requests', 'requests_toolbelt'], + packages=['hallgrim'] +)