def round(self, precision): if not self.is_numeric(): raise error.UncompatibleType(self, "numeric Value") elif (not (precision in [UNIT, TENTH, HUNDREDTH, THOUSANDTH, TEN_THOUSANDTH] or (type(precision) == int and 0 <= precision <= 4))): # __ raise error.UncompatibleType( precision, "must be UNIT or" + "TENTH, " + "HUNDREDTH, " + "THOUSANDTH, " + "TEN_THOUSANDTH, " + "or 0, 1, 2, 3 or 4.") else: result_value = None if type(precision) == int: result_value = Value( round(self.raw_value, Decimal(PRECISION[precision]), rounding=ROUND_HALF_UP)) else: result_value = Value( round(self.raw_value, Decimal(precision), rounding=ROUND_HALF_UP)) if self.needs_to_get_rounded(precision): result_value.set_has_been_rounded(True) return result_value
def translate_font_size(self, arg): if not type(arg) == str: raise error.UncompatibleType(arg, "String") elif arg not in TEXT_SCALES: raise error.UncompatibleType(arg, "a text size (see TEXT_SCALES)") arg_num = TEXT_RANKS[arg] size_to_use = self.font_size_offset + arg_num if size_to_use < 0: size_to_use = 0 elif size_to_use > len(self.text_sizes) - 1: size_to_use = len(self.text_sizes) - 1 return self.text_sizes[size_to_use]
def is_a_perfect_square(self): if not self.is_numeric(): raise error.UncompatibleType(self, "numeric Value") if self.is_an_integer(): return not self.sqrt().needs_to_get_rounded(0) else: return len(str(self.raw_value)) > len(str(self.raw_value.sqrt()))
def type_string(self, objct, **options): if isinstance(objct, Printable): options.update({'force_expression_begins': True}) return objct.into_str(**options) elif is_.a_number(objct) or is_.a_string(objct): return str(objct) else: raise error.UncompatibleType(objct, "String|Number|Printable")
def digits_number(self): if not self.is_numeric(): raise error.UncompatibleType(self, "numeric Value") else: temp_result = len( str((self.raw_value - round( self.raw_value, Decimal(UNIT), rounding=ROUND_DOWN)))) - 2 if temp_result < 0: return 0 else: return temp_result
def set_sign(self, arg): if is_.a_sign(arg): self._sign = arg elif arg == 1: self._sign = '+' elif arg == -1: self._sign = '-' elif isinstance(arg, Calculable): if arg.is_displ_as_a_single_1(): self._sign = '+' elif arg.is_displ_as_a_single_minus_1(): self._sign = '-' else: raise error.UncompatibleType(self, "'+' or '-' or 1 or -1")
def needs_to_get_rounded(self, precision): if (not (precision in [UNIT, TENTH, HUNDREDTH, THOUSANDTH, TEN_THOUSANDTH] or (type(precision) == int and 0 <= precision <= 4))): # __ raise error.UncompatibleType( precision, "must be UNIT or" + "TENTH, " + "HUNDREDTH, " + "THOUSANDTH, " + "TEN_THOUSANDTH, " + "or 0, 1, 2, 3 or 4.") precision_to_test = 0 if type(precision) == int: precision_to_test = precision else: precision_to_test = PRECISION_REVERSED[precision] return self.digits_number() > precision_to_test
def __init__(self, arg, **options): Signed.__init__(self) self._has_been_rounded = False self._unit = "" if 'unit' in options: self._unit = Unit(options['unit']) if (type(arg) == float or type(arg) == int or type(arg) == Decimal): # __ self._raw_value = Decimal(str(arg)) if arg >= 0: self._sign = '+' else: self._sign = '-' elif type(arg) == str: if is_.a_numerical_string(arg): self._raw_value = Decimal(arg) else: self._raw_value = arg if len(arg) >= 1 and arg[0] == '-': self._sign = '-' elif isinstance(arg, Value): self._raw_value = arg.raw_value self._has_been_rounded = arg.has_been_rounded self._unit = arg.unit self._sign = arg.sign # All other unforeseen cases: an exception is raised. else: raise error.UncompatibleType(arg, "Number|String") if self._sign == '-': if isinstance(self._raw_value, str): self._abs_value = self._raw_value[1:] else: self._abs_value = -self._raw_value else: self._abs_value = self._raw_value
def is_an_integer(self): if not self.is_numeric(): raise error.UncompatibleType(self, "numeric Value") getcontext().clear_flags() self.raw_value.to_integral_exact() return getcontext().flags[Rounded] == 0
def sqrt(self): if self.is_numeric(): return Value(self.raw_value.sqrt()) else: raise error.UncompatibleType(self, "numeric Value")
def evaluate(self): if not self.is_numeric(): raise error.UncompatibleType(self, "numeric Value") else: return self.raw_value
def get_first_letter(self): if self.is_literal(): return self.raw_value else: raise error.UncompatibleType(self, "str, i.e. literal Value")
def set_font_size_offset(self, arg): if not is_.an_integer(arg): raise error.UncompatibleType(arg, "Integer") else: self.font_size_offset = arg
def __init__(self, x_kind, AVAILABLE_X_KIND_VALUES, X_LAYOUTS, X_LAYOUT_UNIT, number_of_questions=6, **options): try: self.derived except AttributeError: raise error.NotInstanciableObject(self) self.questions_list = list() # OPTIONS ------------------------------------------------------------- # It is necessary to define an options field to pass the # possibly modified value to the child class self.options = options try: AVAILABLE_X_KIND_VALUES[x_kind] except KeyError: raise error.OutOfRangeArgument(x_kind, str(AVAILABLE_X_KIND_VALUES)) x_subkind = 'default' if 'x_subkind' in options: x_subkind = options['x_subkind'] # let's remove this option from the options # since we re-use it recursively temp_options = dict() for key in options: if key != 'x_subkind': temp_options[key] = options[key] self.options = temp_options if x_subkind not in AVAILABLE_X_KIND_VALUES[x_kind]: raise error.OutOfRangeArgument( x_subkind, str(AVAILABLE_X_KIND_VALUES[x_kind])) self.x_kind = x_kind self.x_subkind = x_subkind # Start number self.start_number = 0 if 'start_number' in options: if not is_.an_integer(options['start_number']): raise error.UncompatibleType(options['start_number'], "integer") if not (options['start_number'] >= 1): raise error.OutOfRangeArgument(options['start_number'], "should be >= 1") self.start_number = options['start_number'] # Number of questions if (not isinstance(number_of_questions, int) and number_of_questions >= 1): # __ raise ValueError("The number_of_questions keyword argument should " "be an int and greater than 6.") self.q_nb = number_of_questions self.layout = options.get('layout', 'default') self.x_layout_unit = X_LAYOUT_UNIT if (self.x_kind, self.x_subkind) in X_LAYOUTS: self.x_layout = X_LAYOUTS[(self.x_kind, self.x_subkind)] else: self.x_layout = X_LAYOUTS[self.layout] # The slideshow option (for MentalCalculation sheets) self.slideshow = options.get('slideshow', False)
def __init__(self, font_size_offset, sheet_layout_unit, sheet_layout, layout_type, **options): try: self.derived except AttributeError: raise error.NotInstanciableObject(self) self.exercises_list = list() shared.machine.set_font_size_offset(font_size_offset) self.sheet_layout_unit = sheet_layout_unit self.layout_type = layout_type self.write_texts_twice = False if 'write_texts_twice' in options and options['write_texts_twice']: self.write_texts_twice = True # Some tests on sheet_layout before using it ; # but it's a bit complicated to write a complete set of tests on it ; # e.g. if the user doesn't use the same number of exercises in the # 'exc' key as in 'ans' key (which would be stupid) this # won't be checked here and so it won't work. if type(sheet_layout) != dict: raise error.UncompatibleType(str(type(sheet_layout)), 'dict') if len(sheet_layout) != 2: raise error.WrongArgument('SHEET_LAYOUT should have two keys', 'it has ' + str(len(sheet_layout)) + ' keys') for k in ['exc', 'ans']: if k not in sheet_layout: raise error.WrongArgument('SHEET_LAYOUT should have a key ' + k, 'it has no such key') if type(sheet_layout[k]) != list: raise error.WrongArgument('SHEET_LAYOUT[' + k + '] should be' + ' a list', str(type(sheet_layout[k]))) if len(sheet_layout[k]) % 2: raise error.WrongArgument('SHEET_LAYOUT[' + k + '] should have' + ' an even number of elements', str(len(sheet_layout[k])) + ' elements') for i in range(int(len(sheet_layout[k]) // 2)): if (not (sheet_layout[k][2 * i] is None or type(sheet_layout[k][2 * i]) == list or sheet_layout[k][2 * i] == 'jump')): # __ raise error.WrongArgument('SHEET_LAYOUT[' + k + '][' + str(2 * i) + '] should be ' 'either a list ' 'or None or "jump"', str(type( sheet_layout[k][2 * i]))) elif sheet_layout[k][2 * i] is None: if (not (type(sheet_layout[k][2 * i + 1]) == int or sheet_layout[k][2 * i + 1] in ['all', 'all_left', 'jump'])): # __ raise error.WrongArgument( 'SHEET_LAYOUT[' + k + '][' + str(2 * i + 1) + '] should be an ' + 'int since it follows the None' + 'keyword', type(sheet_layout[k][2 * i + 1])) elif sheet_layout[k][2 * i] == 'jump': if not sheet_layout[k][2 * i + 1] == 'next_page': raise error.WrongArgument( 'SHEET_LAYOUT[' + k + '][' + str(2 * i + 1) + '] should be: ' + 'next_page since it follows ' + 'the jump keyword', type(sheet_layout[k][2 * i + 1])) elif type(sheet_layout[k][2 * i]) == list: if not type(sheet_layout[k][2 * i + 1]) == tuple: raise error.WrongArgument( 'SHEET_LAYOUT[' + k + '][' + str(2 * i + 1) + '] should be a tuple', type(sheet_layout[k][2 * i + 1])) if (not len(sheet_layout[k][2 * i + 1]) == (len(sheet_layout[k][2 * i]) - 1) * sheet_layout[k][2 * i][0]): # __ raise error.WrongArgument( 'SHEET_LAYOUT[' + k + '][' + str(2 * i + 1) + '] should have ' + ' as many elements as the ' + 'number of cols described in ' + 'SHEET_LAYOUT[' + k + '][' + str(2 * i) + ']', str(len(sheet_layout[k][2 * i + 1])) + ' instead of ' + str(len(sheet_layout[k][2 * i]) - 1)) else: raise error.WrongArgument( 'SHEET_LAYOUT[' + k + '][' + str(2 * i) + '] is not of any ' + ' of the expected types or ' + 'values.', str(len(sheet_layout[k][2 * i]))) self.sheet_layout = sheet_layout