Parser of berki style problems and generator of latex file
Samo Penic
2018-10-31 b5b680023edb80d1795e5cfdef3a097fa2cb5f49
Shuffling answers and testing proximity finished.
3 files modified
1 files added
120 ■■■■ changed files
testcases/err_dispneja.txt 15 ●●●●● patch | view | raw | blame | history
tools/Exceptions.py 3 ●●●●● patch | view | raw | blame | history
tools/Problem.py 86 ●●●● patch | view | raw | blame | history
tools/Template.py 16 ●●●● patch | view | raw | blame | history
testcases/err_dispneja.txt
New file
@@ -0,0 +1,15 @@
#StartUvod
Dispneja je:
#EndUvod
#StartRezultat
TeX:
izpis:        str
enota:
formula:    'neprijeten občutek neprimerno napornejšega dihanja'
napacna:    'znak'
napacna:    'znak1'
napacna:    'bradipnea'
#EndRezultat
tools/Exceptions.py
@@ -6,3 +6,6 @@
class NoResult(Exception):
    pass
class AnswerProximityError(Exception):
    pass
tools/Problem.py
@@ -4,39 +4,78 @@
from math import *
from random import shuffle
class Problem:
    def __init__(self, source=None, shuffle=True, MaxShuffleAttempts=100, AnsDiff=0.05):
    def __init__(
        self,
        source=None,
        shuffle=True,
        MaxShuffleAttempts=40,
        MaxRegenerateAttempts=100,
        AnsDiff=0.05,
    ):
        self.source = source
        self.MaxShuffleAttempts=MaxShuffleAttempts
        self.MaxShuffleAttempts = MaxShuffleAttempts
        self.MaxRegenerateAttempts = MaxRegenerateAttempts
        self.AnsDiff = AnsDiff
        self.source.generateVariables()
        self.source.generateSolutions()
        self.problem = self.source.generateProblem()
        if shuffle:
            self.problem['solutions']=self.shuffleAnswers(self.problem['solutions'])
            for i in range(0, self.MaxRegenerateAttempts):
                try:
                    self.problem["solutions"] = self.shuffleAnswers(
                        self.problem["solutions"]
                    )
                except Exceptions.AnswerProximityError:
                    self.source.generateVariables()
                    self.source.generateSolutions()
                    self.problem = self.source.generateProblem()
                    continue
                else:
                    break
            if i == self.MaxRegenerateAttempts - 1:
                raise Exceptions.AnswerProximityError(
                    "Could not shuffle answers and get answers that are not too close together :: "
                    + self.problem["introduction"]
                )
    def shuffleAnswers(self,solList):
        shuffList=[]
    def shuffleAnswers(self, solList):
        shuffList = []
        for cont in solList:
            for i in range(0, self.MaxShuffleAttempts):
                wrong=cont['wrong']
                wrong = cont["wrong"]
                shuffle(wrong)
                ans=[*zip(cont['correct'],list('1'*len(cont['correct']))), *zip(wrong,list('0'*len(wrong)))]
                ans=ans[0:4]
                if self.checkAnsProximity(ans)==False:
                ans = [
                    *zip(cont["correct"], list("1" * len(cont["correct"]))),
                    *zip(wrong, list("0" * len(wrong))),
                ]
                ans = ans[0:4]
                if self.checkAnsProximity(ans) == False:
                    break
            if i == self.MaxShuffleAttempts - 1:
                raise Exceptions.AnswerProximityError(
                    "Could not shuffle answers and get answers that are not too close together"
                )
            shuffle(ans)
            cont['shuffled']=ans
            cont["shuffled"] = ans
            shuffList.append(cont)
        return solList
    def checkAnsProximity(self, ans):
        for idx1,val1 in ans:
            for idx2, val2 in ans:
                if(abs(val1.get_formatted_value()-val2.get_formatted_value())<self.AnsDiff):
                    return True
        for idx1, (val1, cor) in enumerate(ans):
            for idx2, (val2, cor) in enumerate(ans):
                if idx1 == idx2:
                    continue
                if not val1.is_float() or not val2.is_float():
                    if val1.get_formatted_value() == val2.get_formatted_value():
                        return True
                else:
                    if (
                        abs(val1.get_formatted_value() - val2.get_formatted_value())
                        < self.AnsDiff * val1.get_formatted_value()
                    ):
                        return True
        return False
@@ -73,13 +112,15 @@
            __ps["wrong"] = []
            for __corr in __s["correct"]:
                for __corrsplit in __corr.split(";"):
                    __result=None
                    __result = None
                    if __corrsplit.find("=") >= 0:
                        exec(self.substitute_octave(__corrsplit))
                    else:
                        __result = eval(self.substitute_octave(__corrsplit))
                if (__result is  None):
                    raise Exceptions.NoResult("Result cannot be calculated. Be sure to specify last term without = sign!")
                if __result is None:
                    raise Exceptions.NoResult(
                        "Result cannot be calculated. Be sure to specify last term without = sign!"
                    )
                __ps["correct"].append(Variable(__result, formatting=__s["type"]))
            for __corr in __s["wrong"]:
                for __corrsplit in __corr.split(";"):
@@ -88,8 +129,10 @@
                        exec(self.substitute_octave(__corrsplit))
                    else:
                        __result = eval(self.substitute_octave(__corrsplit))
                if(__result is None):
                    raise Exceptions.NoResult("Result cannot be calculated. Be sure to specify last term without = sign!")
                if __result is None:
                    raise Exceptions.NoResult(
                        "Result cannot be calculated. Be sure to specify last term without = sign!"
                    )
                __ps["wrong"].append(Variable(__result, formatting=__s["type"]))
            __ps["glyph"] = __s["glyph"]
            __ps["unit"] = __s["unit"]
@@ -119,4 +162,3 @@
            sp.append(self.substitute_variables(p))
        sol = self.generateSolutions()
        return {"introduction": intro, "subproblems": sp, "solutions": sol}
tools/Template.py
@@ -37,10 +37,10 @@
                retstr += Template(self.template["subproblem"]).substitute(
                    {
                        "text": sp,
                        "ans1": sol["correct"][0].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                        "ans2": sol["wrong"][0].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                        "ans3": sol["wrong"][1].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                        "ans4": sol["wrong"][2].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                        "ans1": sol["shuffled"][0][0].format_as_tex(glyph=sol['glyph'], unit=sol['unit']), #sol["correct"][0].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                        "ans2": sol["shuffled"][1][0].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                        "ans3": sol["shuffled"][2][0].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                        "ans4": sol["shuffled"][3][0].format_as_tex(glyph=sol['glyph'], unit=sol['unit']),
                    }
                )
            retstr += Template(self.template["subproblem_end"]).substitute()
@@ -49,10 +49,10 @@
                {
                    "problem_number": 0,
                    "text": problem_dict["introduction"],
                    "ans1": problem_dict["solutions"][0]["correct"][0].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"]),
                    "ans2": problem_dict["solutions"][0]["wrong"][0].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"]),
                    "ans3": problem_dict["solutions"][0]["wrong"][1].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"]),
                    "ans4": problem_dict["solutions"][0]["wrong"][2].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"])
                    "ans1": problem_dict["solutions"][0]["shuffled"][0][0].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"]),
                    "ans2": problem_dict["solutions"][0]["shuffled"][1][0].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"]),
                    "ans3": problem_dict["solutions"][0]["shuffled"][2][0].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"]),
                    "ans4": problem_dict["solutions"][0]["shuffled"][3][0].format_as_tex(glyph=problem_dict["solutions"][0]["glyph"],unit=problem_dict["solutions"][0]["unit"])
                }
            )
        return retstr