Parser of berki style problems and generator of latex file
Samo Penic
2018-10-31 08b2a29a2370d3027f5424b92145b32351bdbf46
Attempting shuffling and proximity checks.
2 files modified
90 ■■■■■ changed files
tools/Problem.py 44 ●●●● patch | view | raw | blame | history
tools/Variable.py 46 ●●●●● patch | view | raw | blame | history
tools/Problem.py
@@ -2,17 +2,42 @@
import re
from . import Exceptions
from math import *
from random import shuffle
class Problem:
    def __init__(self, source=None):
    def __init__(self, source=None, shuffle=True, MaxShuffleAttempts=100, AnsDiff=0.05):
        self.source = source
        self.MaxShuffleAttempts=MaxShuffleAttempts
        self.AnsDiff = AnsDiff
        self.source.generateVariables()
        self.source.generateSolutions()
        self.problem = self.source.generateProblem()
        if shuffle:
            self.problem['solutions']=self.shuffleAnswers(self.problem['solutions'])
    def toTexFormatterDict(self, template=None):
        pass
    def shuffleAnswers(self,solList):
        shuffList=[]
        for cont in solList:
            for i in range(0, self.MaxShuffleAttempts):
                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:
                    break
            shuffle(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
        return False
class ProblemSource:
@@ -87,18 +112,11 @@
        text = re.sub(";", "\n", text)
        return text
    def generateProblem(self, shuffle=True):
    def generateProblem(self):
        intro = self.substitute_variables(self.introduction)
        sp = []
        for p in self.subproblems:
            sp.append(self.substitute_variables(p))
        sol = self.generateSolutions()
        # soltex = []
        # for s in sol:
        #    entry = {
        #        "correct": [("${}={}\mathrm{{{}}}$").format(s['glyph'], i.format_as_tex(), s['unit']) for i in s["correct"]],
        #        "wrong": [("${}={}\mathrm{{{}}}$").format(s['glyph'], i.format_as_tex(), s['unit']) for i in s["wrong"]],
        #    }
        #    soltex.append(entry)
        # return intro, sp, soltex
        return {"introduction": intro, "subproblems": sp, "solutions": sol}
tools/Variable.py
@@ -13,11 +13,17 @@
            self.type = FLOAT
        except (ValueError, TypeError):
            self.type = STRING
            self.value=value
            self.formatted_value=value
            self.value = value
            self.formatted_value = value
        if formatting is not None:
            self.format_float(formatting)
        self.formatting = formatting
    def is_float(self):
        if self.type==FLOAT:
            return True
        else:
            return False
    def format_float(self, formatting=None):
        if formatting is None:
@@ -29,16 +35,18 @@
        if formatting is None:
            formatting = self.formatting
        formatter = FormatterFactory.get_formatter(formatting)
        if formatting=="str":
        if formatting == "str":
            return formatter.toFormat(self.value)
        elif(glyph is None and unit is None):
        elif glyph is None and unit is None:
            return ("${}$").format(formatter.toFormat(self.value))
        elif(glyph is None and unit is not None):
            return ("${}\,\mathrm{{{}}}$").format(formatter.toFormat(self.value), unit)
        elif(glyph is not None and unit is None):
            return ("${}={}$").format(glyph,formatter.toFormat(self.value))
        elif glyph is None and unit is not None:
            return ("${}~\mathrm{{{}}}$").format(formatter.toFormat(self.value), unit)
        elif glyph is not None and unit is None:
            return ("${}={}$").format(glyph, formatter.toFormat(self.value))
        else:
            return ("${}={}\,\mathrm{{{}}}$").format(glyph,formatter.toFormat(self.value), unit)
            return ("${}={}~\mathrm{{{}}}$").format(
                glyph, formatter.toFormat(self.value), unit
            )
    def format_without_dollar(self, formatting=None):
        if formatting is None:
@@ -48,7 +56,7 @@
    def get_formatted_value(self):
        return self.formatted_value
        #if self.type != STRING else self.value
        # if self.type != STRING else self.value
    def __str__(self):
        return str(self.format_as_tex())
@@ -66,11 +74,11 @@
        if type == "sci":
            return SciFloatFormatter(arglist)
        elif type =="str":
        elif type == "str":
            return StringFormatter()
        elif type =="eng":
        elif type == "eng":
            return EngFloatFormatter(arglist)
        elif type =="dec":
        elif type == "dec":
            return DecFloatFormatter(arglist)
        else:
            return None
@@ -112,10 +120,14 @@
        exp = self.fexp(num)
        man = self.fman(num)
        if exp == 0:
            return ("{:." + str(self.precision - 1) + "f}").format(man)
            return (
                ("{:." + str(self.precision - 1) + "f}").format(man).replace(".", ",\!")
            )
        else:
            return ("{:." + str(self.precision - 1) + "f} \cdot 10^{{{}}}").format(
                man, int(exp)
            return (
                ("{:." + str(self.precision - 1) + "f} \cdot 10^{{{}}}")
                .format(man, int(exp))
                .replace(".", ",\!")
            )
    def getValue(self, num):
@@ -127,6 +139,8 @@
class DecFloatFormatter(SciFloatFormatter):
    pass
class EngFloatFormatter(SciFloatFormatter):
    pass