def test_check_calculation(self): valid = ["23", "2.123", "cos(12.2)", "tan(sin(atan(cosh(1))))", "pie", "1+2*3/4^5%6", "gamma(17)"] invalid = ["hello", "1&2", "$13.50", "1::", "cos(tan(12+t+15))"] for valid_str in valid: assert Commons.check_calculation(valid_str), "Valid string judged to be not calculation, "+valid_str for invalid_str in invalid: assert not Commons.check_calculation(invalid_str), "Invalid string judged to be calculation, "+invalid_str
def run(self, line, user_obj, destination_obj=None): line_clean = line.strip().lower() if line_clean.isdigit(): number = int(line_clean) elif Commons.check_calculation(line_clean): function_dispatcher = user_obj.server.hallo.function_dispatcher calc_func = function_dispatcher.get_function_by_name("calc") calc_obj = function_dispatcher.get_function_object(calc_func) # type: Calculate number_str = calc_obj.process_calculation(line_clean) if "." in number_str: return "Error, this calculation does not result in an integer. The answer is: " + number_str number = int(number_str) else: return "Error, this is not a valid number or calculation." prime_factors = self.find_prime_factors(number) return "The prime factors of " + str(number) + " are: " + 'x'.join(str(x) for x in prime_factors) + "."
def preflight_checks(self, calc): # strip spaces calc_clean = calc.replace(' ', '').lower() # make sure only legit characters are allowed if not Commons.check_calculation(calc_clean): # TODO use custom exception raise Exception('Error, Invalid characters in expression') # make sure open brackets don't out-number close if calc.count('(') > calc.count(')'): raise Exception('Error, too many open brackets') # Make sure close brackets don't out-number open. # Previously I thought it would be okay to skip this, but "(21/3))+2))*5" evaluates as 17, rather than 45 if calc.count(')') > calc.count('('): raise Exception('Error, too many close brackets') if len(calc) == 0: raise Exception("Error, empty calculation or brackets") return True
def passive_run(self, event, full_line, hallo_obj, server_obj=None, user_obj=None, channel_obj=None): """Replies to an event not directly addressed to the bot.""" # Check if fullLine is a calculation, and is not just numbers, and contains numbers. if not Commons.check_calculation(full_line): return None if Commons.check_numbers(full_line.replace(".", "")): return None if not any([char in full_line for char in [str(x) for x in range(10)] + ["e", "pi"]]): return None # Clean up the line and feed to the calculator. calc = full_line.replace(' ', '').lower() try: self.preflight_checks(calc) answer = self.process_calculation(calc) return answer except Exception as e: print("Passive calc failed: "+str(e)) return None
def run(self, line, user_obj, destination_obj=None): if line.count(' ') == 0: number = line lang = "american" elif line.split()[1].lower() in ["british", "english"]: number = line.split()[0] lang = "english" elif line.split()[1].lower() in ["european", "french"]: number = line.split()[0] lang = "european" else: number = line.split()[0] lang = "american" if Commons.check_numbers(number): number = number elif Commons.check_calculation(number): function_dispatcher = user_obj.server.hallo.function_dispatcher calc_func = function_dispatcher.get_function_by_name("calc") calc_obj = function_dispatcher.get_function_object(calc_func) # type: Calculate number = calc_obj.process_calculation(number) else: return "Error, you must enter a valid number or calculation." return self.number_word(number, lang) + "."