# coding=utf-8 from python.util import has_token_sequence from server.hints import Hint, HintSequence id = 1000 group = 'introduction' number = 2 visible = True solution = '''\ from math import * g = 10 kot = float(input("Vnesi kot (v stopinjah): ")) v = float(input("Vnesi hitrost (v m/s): ")) kot_rad = kot * 2 * pi / 360 razdalja = v ** 2 * sin(2 * kot_rad) / g print("Kroglo bo odneslo", razdalja, "metrov.") ''' hint_type = { 'plan': Hint('plan'), 'name_error': HintSequence('name_error'), 'unsupported_operand': HintSequence('unsupported_operand'), 'syntax_error' : HintSequence('syntax_error'), 'indentation_error': HintSequence('indentation_error'), 'no_input_call' : Hint('no_input_call'), 'radians': HintSequence('radians'), 'printing': Hint('printing'), 'math_functions': Hint('math_functions') } def almostEqual(a, b, prec=1): """ Compares values a and b using at most prec decimal values. """ return int(a*10**prec) == int(b*10**prec) def stringAlmostEqual(s, a): """ Searches string s for a value that is almost equal to a. Args: s (str): string to search a (float): value to find in string Returns: bool: True if successful, else False """ for v in s.split(): try: if almostEqual(float(v), a): return True return False def test(python, code): # List of inputs: (expression to eval, stdin). test_in = [ (None, '45\n100\n'), (None, '44\n100\n'), (None, '46\n100\n'), (None, '0\n100\n'), (None, '90\n100\n'), (None, '32\n747\n'), ] test_out = [ '1000', '999.39', '999.39', '0.0', '0.0', '50153.5' ] # List of outputs: (expression result, stdout, stderr, exception). answers = python(code=code, inputs=test_in, timeout=1.0) outputs = [ans[1] for ans in answers] n_correct = 0 for output, correct in zip(outputs, test_out): if stringAlmostEqual(output, correct): n_correct += 1 return n_correct, len(test_in) def hint(python, code): # run one test first to see if there are any exceptions test_in = [(None, '45\n')] answer = python(code=code, inputs=test_in, timeout=1.0) exc = answer[0][3] # if have an exception! if exc: if 'NameError' in exc: return [{'id':'name_error'}] if 'unsupported operand' in exc: return [{'id':'unsupported_operand'}] if 'SyntaxError' in exc: return [{'id':'syntax_error'}] if 'IndentationError' in exc: return [{'id':'indentation_error'}] # if result if 893.996, angle is not converted to radians if stringAlmostEqual(answer[0][1], 893.996): return [{'id': 'radians'}] # show plan if student is lost if not code or (not has_token_sequence(code, ['input']) and (has_token_sequence(code, ['pi']) or has_token_sequence(code, ['sin']) or has_token_sequence(code, ['print']))): return [{'id': 'plan'}] # if input is not present in code, student needs to learn about input if not has_token_sequence(code, ['input']) or \ not has_token_sequence(code, ['float']): return [{'id': 'no_input_call'}] # if tokens sqrt or ** are not in code, we have to teach them how to # use math functions. if (not has_token_sequence(code, ['sqrt']) or not has_token_sequence(code, ['**']): return [{'id' : 'math_functions'}] # student is not using print function if not has_token_sequence(code, ['print']): return [{'id' : 'printing'}] return None