| | |
| | | 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 |
| | | |
| | | |
| | |
| | | __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(";"): |
| | |
| | | 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"] |
| | |
| | | sp.append(self.substitute_variables(p)) |
| | | sol = self.generateSolutions() |
| | | return {"introduction": intro, "subproblems": sp, "solutions": sol} |
| | | |