def __init__(self, build_data, **options): super().setup('minimal', **options) level = int(build_data[5]) # super().setup('numbers', nb=, **options) # super().setup('nb_variants', **options) super().setup('length_units', **options) # We know the wording will be in two lines: super().setup('polygon', polygon_data=build_data, wlines_nb=2) self.wording = { 3: _(r'Perimeter of this triangle?\newline ' r'(length unit: {length_unit}) |hint:length_unit|'), 4: _(r'Perimeter of this quadrilateral?\newline ' r'(length unit: {length_unit}) |hint:length_unit|'), 5: _(r'Perimeter of this pentagon?\newline ' r'(length unit: {length_unit}) |hint:length_unit|'), 6: _(r'Perimeter of this hexagon?\newline ' r'(length unit: {length_unit}) |hint:length_unit|') }[len(self.polygon.sides)] self.transduration = 12 + 3 * (level - 1) setup_wording_format_of(self) self.wording = self.wording.format(**self.wording_format)
def __init__(self, build_data, **options): """ :param build_data: tuple containing: wording's context and type, the wording itself and two ClockTime objects: start and arrival hours. :type build_data: tuple """ super().setup("minimal", **options) wording_type = build_data[1] self.wording = _(build_data[2]) lang = settings.language[:2] start_time = ClockTime(build_data[3], context=TIME_CONTEXT[lang]) arrival_time = ClockTime(build_data[4], context=TIME_CONTEXT[lang]) duration_ctxt = TIME_CONTEXT[lang] if wording_type == 'duration' \ else DURATION_CONTEXT[lang] duration_time = ClockTime(arrival_time - start_time, context=duration_ctxt) self.start_time = start_time.printed self.arrival_time = arrival_time.printed self.duration_time = duration_time.printed self.solution = {'duration': duration_time, 'start': start_time, 'arrival': arrival_time}[wording_type] self.transduration = 24 self.time_unit = ('', TIME_CONTEXT[lang]['h'], '', TIME_CONTEXT[lang]['min']) setup_wording_format_of(self)
def __init__(self, build_data, **options): super().setup('minimal', **options) super().setup('numbers', nb=build_data, shuffle_nbs=False, **options) source_id = options.get('nb_source') if source_id == r'10%of...': self.transduration = 12 elif source_id in [r'25%of...', r'50%of...'] and self.nb2 < 40: self.transduration = 16 else: self.transduration = 20 if self.nb_variant.startswith('decimal'): deci_nb = int(self.nb_variant[-1]) self.nb2 = self.nb2 / Number(10) ** Number(deci_nb) self.result = self.nb1 * self.nb2 / Number(100) self.n1 = self.nb1.printed hint = '' if self.context == 'simple_unit': u = shared.unitspairs_source.next(direction='left', level=1)[0] pq = physical_quantity(u) self.n2 = Number(self.nb2, unit=Unit(u)).printed hint = ' |hint:{}_unit|'.format(pq) setattr(self, pq + '_unit', u) self.result = Number(self.result, unit=u) else: self.n2 = self.nb2.printed # This default wording is meant for mental calculation. self.wording = options.get('wording', _('{n1} {percent_symbol} of {n2}?') + hint) setup_wording_format_of(self)
def ow2ter(): o = raw_obj() o.nb1 = 27 o.wording = 'What\'s the area of the side of a cube whose volume '\ 'is {nb1} {volume_unit=cm}? |hint:area_unit|' setup_wording_format_of(o) return o
def _setup_ask_question(self, **kwargs): values = kwargs.get('values') self.wording = self.q_wordings_collection[kwargs['q_key']]\ .format(*values) if kwargs.get('fix_math_style2_fontsize', False): self.wording = fix_math_style2_fontsize(self.wording) setup_wording_format_of(self)
def ow2ter(): o = raw_obj() o.nb1 = 27 o.wording = 'What\'s the area of the side of a cube whose volume '\ 'is {nb1} {volume_unit=cm}? |hint:area_unit|' setup_wording_format_of(o) return o
def ow_units1(): o = raw_obj() o.nb1 = 7 o.wording = 'The first weighs {nb1} {mass_unit=kg} and the second\'s ' \ '{mass_unit}.' setup_wording_format_of(o) return o
def _setup_complement_wording(self, **kwargs): upper_bound = self.nb1 if self.context == 'complement_wording': self.context += str(random.choice([1, 2])) if self.context == 'complement_wording1': self.wording = _('What number must be added to' ' {number1} to make {number2}?')\ .format(number1=self.nb2.printed, number2=self.nb1.printed) elif self.context == 'complement_wording2': if upper_bound == 10: self.wording = _('What is the tens complement ' 'of {number}?')\ .format(number=self.nb2.printed) elif upper_bound == 100: self.wording = _('What is the hundreds complement ' 'of {number}?')\ .format(number=self.nb2.printed) else: self.wording = _('What is the complement to {number1} ' 'of {number2}?')\ .format(number1=self.nb1.printed, number2=self.nb2.printed) else: raise ValueError('Cannot recognize context: {}\n' .format(self.context)) setup_wording_format_of(self)
def ow1(): o = raw_obj() o.nb1 = 4 o.wording = 'Calculate the volume of a cube whose side\'s length is ' \ '{nb1} {length_unit=cm}. |hint:volume_unit|' setup_wording_format_of(o) return o
def __init__(self, build_data, **options): super().setup("minimal", **options) super().setup("numbers", nb=build_data, **options) super().setup("nb_variants", nb=build_data, **options) super().setup("length_units", **options) hypotenuse_length = \ Number(Number(build_data[0]) * Number(build_data[0]) + Number(build_data[1]) * Number(build_data[1]))\ .sqrt().rounded(Decimal('0.1')) super().setup("polygon", polygon_data=(3, 'triangle', 'right_triangle', 'triangle_1_1_1', 'all_different', 2, 1, 0, 0, 0, 0, 0, build_data[0], build_data[1], hypotenuse_length), wlines_nb=1) self.transduration = 21 if self.slideshow: self.polygon.scale = 2 self.wording = _('Area?') self.part2_wording = r'{\small' + _('(Length unit: {})')\ .format(self.length_unit) + '}' else: self.wording = _('Area of this triangle? |hint:area_unit|') self.part2_wording = r'{\small' + _('(Lengths in {})')\ .format(self.length_unit) + '}' setup_wording_format_of(self) self.polygon_area = Number(build_data[0] * build_data[1] / 2)\ .standardized()
def __init__(self, build_data, **options): super().setup("minimal", **options) super().setup("numbers", nb=build_data, **options) super().setup("nb_variants", nb=build_data, **options) super().setup("length_units", **options) super().setup("rectangle", **options) self.transduration = 14 if self.picture: if self.slideshow: self.wording = _('Area of this rectangle?') self.part2_wording = r'{\small' + _('(Length unit: {})')\ .format(self.length_unit) + '}' else: self.wording = _('Area of this rectangle? |hint:area_unit|') self.part2_wording = r'{\small' + _('(Lengths in {})')\ .format(self.length_unit) + '}' setup_wording_format_of(self) else: self.transduration = 20 self.nb1, self.nb2 = \ self.rectangle.lbl_width, self.rectangle.lbl_length self.wording = _("Area of a rectangle whose width is {nb1} \ {length_unit} and length is {nb2} {length_unit}? |hint:area_unit|") setup_wording_format_of(self)
def ow1(): o = raw_obj() o.nb1 = 4 o.wording = 'Calculate the volume of a cube whose side\'s length is ' \ '{nb1} {length_unit=cm}. |hint:volume_unit|' setup_wording_format_of(o) return o
def __init__(self, build_data, **options): super().setup("minimal", **options) if self.nb_source.startswith('complement'): maxi, mini = max(build_data), min(build_data) build_data = [mini, maxi - mini] super().setup("numbers", nb=build_data, **options) super().setup("nb_variants", nb=build_data, **options) super().setup("length_units", **options) super().setup("rectangle", **options) self.transduration = 14 if self.picture: if self.slideshow: self.wording = _('Perimeter of this rectangle?') self.part2_wording = r'{\small' + _('(Length unit: {})')\ .format(self.length_unit) + '}' else: self.wording = _('Perimeter of this rectangle? ' '|hint:length_unit|') self.part2_wording = r'{\small' + _('(Lengths in {})')\ .format(self.length_unit) + '}' setup_wording_format_of(self) else: self.transduration = 20 self.nb1, self.nb2 = \ self.rectangle.lbl_width, self.rectangle.lbl_length self.wording = _("Perimeter of a rectangle whose width " "is {nb1} {length_unit} and length is " "{nb2} {length_unit}? |hint:length_unit|") setup_wording_format_of(self)
def ow2bis(): o = raw_obj() o.nb1 = 4 o.nb2 = 7 o.wording = 'How much is {nb1} {length_unit1=dm} '\ '+ {nb2} {length_unit2=cm}? |hint:length_unit1|' setup_wording_format_of(o) return o
def ow2bis(): o = raw_obj() o.nb1 = 4 o.nb2 = 7 o.wording = 'How much is {nb1} {length_unit1=dm} '\ '+ {nb2} {length_unit2=cm}? |hint:length_unit1|' setup_wording_format_of(o) return o
def ow2qua(): o = raw_obj() o.line1 = 'AB' o.line2 = 'MN' o.s = 'BC' o.wording = '({line1}) is parallel to ({line2}). '\ 'Calculate the length of segment [{s}].' setup_wording_format_of(o) return o
def ow2qua(): o = raw_obj() o.line1 = 'AB' o.line2 = 'MN' o.s = 'BC' o.wording = '({line1}) is parallel to ({line2}). '\ 'Calculate the length of segment [{s}].' setup_wording_format_of(o) return o
def __init__(self, build_data, **options): super().setup("minimal", **options) super().setup("length_units", **options) self.transduration = 16 if self.picture: self.transduration = 12 if self.context == "from_area": super().setup("division", nb=build_data, **options) self.nb1, self.nb2, self.nb3 = (self.result, self.divisor, self.dividend) super().setup("rectangle", **options) wordings = {'w': _("A rectangle has an area of {nb3} {area_unit} " "and a length of {nb2} {length_unit}. What is " "its width? |hint:length_unit|"), 'l': _("A rectangle has an area of {nb3} {area_unit} " "and a width of {nb2} {length_unit}. What is " "its length? |hint:length_unit|") } self.wording = wordings[self.subcontext] setup_wording_format_of(self) elif self.context == "from_perimeter": super().setup("numbers", nb=build_data, **options) super().setup("nb_variants", nb=build_data, **options) super().setup("rectangle", **options) self.subcontext = random.choice(['w', 'l']) self.nb1 = self.rectangle.lbl_perimeter if self.subcontext == 'l': self.nb2, self.nb3 = (self.rectangle.lbl_width, self.rectangle.lbl_width) else: self.nb2, self.nb3 = (self.rectangle.lbl_length, self.rectangle.lbl_width) self.result = self.nb3 wordings = {'w': _("What is the width of a rectangle whose " "perimeter is {nb1} {length_unit} and length " "is {nb2} {length_unit}? |hint:length_unit|"), 'l': _("What is the length of a rectangle whose " "perimeter is {nb1} {length_unit} and width " "is {nb2} {length_unit}? |hint:length_unit|") } self.wording = wordings[self.subcontext] setup_wording_format_of(self) else: raise RuntimeError('Impossible to create this question without ' 'any context.') if self.subcontext == 'w': self.rectangle.setup_labels(labels=[self.rectangle.lbl_width, self.rectangle.lbl_length], masks=[' ', ' ', None, '?']) elif self.subcontext == 'l': self.rectangle.setup_labels(labels=[self.rectangle.lbl_width, self.rectangle.lbl_length], masks=[' ', ' ', '?', None])
def __init__(self, build_data, **options): super().setup('minimal', **options) # if (self.nb1 > 20 and self.nb2 > 20 # and not self.nb1 % 10 == 0 and not self.nb2 % 10 == 0): # self.transduration = 12 unit1, unit2, direction, category, level, dimension = build_data self.transduration = {1: 15, 2: 20, 3: 25, 4: 25, 5: 25}\ .get(int(level), 30) unit1 = Unit(unit1) unit2 = Unit(unit2) if physical_quantity(unit1) == 'length' and dimension != 1: self.length_unit1 = unit1.content unit1 = Unit(unit1.content, exponent=dimension) if physical_quantity(unit2) == 'length' and dimension != 1: self.length_unit2 = unit2.content unit2 = Unit(unit2.content, exponent=dimension) if xor(hasattr(self, 'length_unit1'), hasattr(self, 'length_unit2')): if hasattr(self, 'length_unit1'): self.length_unit = getattr(self, 'length_unit1') else: self.length_unit = getattr(self, 'length_unit2') start_position = [Decimal('10'), Decimal('1'), Decimal('0.1')] if difference_of_orders_of_magnitude(unit1, unit2) >= Decimal('100'): start_position = [Decimal('1'), Decimal('0.1'), Decimal('0.01')] if difference_of_orders_of_magnitude(unit1, unit2) <= Decimal('0.01'): start_position = [Decimal('100'), Decimal('10'), Decimal('1')] sp = random.choice(start_position) nb1 = \ generate_random_decimal_nb(position=sp, width=random.choice([1, 2, 3]), unique_figures=options.get( 'unique_figures', False), generation_type='default')[0] super().setup('numbers', nb=[Number(nb1), # self.nb1 Number(Number(nb1, unit=unit1).converted_to(unit2), unit=None) # self.nb2 ], shuffle_nbs=False, standardize_decimal_numbers=True) self.answer = Number(self.nb2, unit=unit2).printed self.js_answer = self.nb2.uiprinted phq1 = physical_quantity(unit1) phq2 = physical_quantity(unit2) suffix1 = suffix2 = '' if phq1 == phq2: suffix1 = '1' suffix2 = '2' unit1_attr_name = phq1 + '_unit' + suffix1 unit2_attr_name = phq2 + '_unit' + suffix2 hint = ' |hint:{}_unit{}|'.format(phq2, suffix2) setattr(self, unit1_attr_name, unit1) setattr(self, unit2_attr_name, unit2) self.wording = '{{nb1}} {{{u1}}} = QUESTION_MARK~{{{u2}}}{h}'\ .format(u1=unit1_attr_name, u2=unit2_attr_name, h=hint) setup_wording_format_of(self)
def __init__(self, numbers_to_use, **options): super().setup("minimal", **options) super().setup("length_units", **options) if self.context == "from_area": super().setup("division", nb=numbers_to_use, **options) self.nb1, self.nb2 = self.dividend, self.divisor super().setup("rectangle", **options) wordings = { 'w': _("A rectangle has an area of {nb1} {area_unit} " "and a length of {nb2} {length_unit}. What is " "its width? |hint:length_unit|"), 'l': _("A rectangle has an area of {nb1} {area_unit} " "and a width of {nb2} {length_unit}. What is " "its length? |hint:length_unit|") } self.wording = wordings[self.subcontext] setup_wording_format_of(self) elif self.context == "from_perimeter": super().setup("numbers", nb=numbers_to_use, **options) super().setup("nb_variants", nb=numbers_to_use, **options) super().setup("rectangle", **options) self.subcontext = random.choice(['w', 'l']) self.nb1 = self.rectangle.perimeter if self.subcontext == 'l': self.nb2, self.nb3 = (self.rectangle.width, self.rectangle.length) else: self.nb2, self.nb3 = (self.rectangle.length, self.rectangle.width) self.result = self.nb3 wordings = { 'w': _("What is the width of a rectangle whose " "perimeter is {nb1} {length_unit} and length " "is {nb2} {length_unit}? |hint:length_unit|"), 'l': _("What is the length of a rectangle whose " "perimeter is {nb1} {length_unit} and width " "is {nb2} {length_unit}? |hint:length_unit|") } self.wording = wordings[self.subcontext] setup_wording_format_of(self) else: raise error.ImpossibleAction("Create this question without any " "context.") if self.subcontext == "w": self.rectangle.setup_labels([False, False, True, "?"]) elif self.subcontext == "l": self.rectangle.setup_labels([False, False, "?", True])
def _setup_mini_problem_wording(self, **kwargs): wording_kwargs = {'nb1_to_check': self.nb1, 'nb2_to_check': self.nb2} if kwargs.get('proportionality', False): source = shared.mini_problems_prop_wordings_source wording_kwargs.update({'coeff_to_check': self.coeff, 'nb3_to_check': self.nb3, 'solution_to_check': self.nb4, 'lock_equal_contexts': True}) if not is_integer(self.nb1): wording_kwargs.update({'nb1_may_be_deci': 1}) if not is_integer(self.nb2): wording_kwargs.update({'nb2_may_be_deci': 1}) if not is_integer(self.nb3): wording_kwargs.update({'nb3_may_be_deci': 1}) if not is_integer(self.nb4): wording_kwargs.update({'solution_may_be_deci': 1}) wording_kwargs.update(preprocess_qkw('mini_pb_prop_wordings', qkw=kwargs)) else: source = shared.mini_problems_wordings_source wording_kwargs.update({'q_id': kwargs['q_id']}) if 'back_to_unit' in kwargs: val = 1 if BOOLEAN[kwargs['back_to_unit']]() else 0 wording_kwargs.update({'back_to_unit': val}) drawn_wording = source.next(**wording_kwargs) self.wording = _(drawn_wording[1]) self.wording_context = drawn_wording[0] if kwargs.get('proportionality', False): self.solution = self.nb4 nb1_xcoeff = Number(str(drawn_wording[2])) nb2_xcoeff = Number(str(drawn_wording[3])) nb3_xcoeff = Number(str(drawn_wording[4])) if nb1_xcoeff != 1: self.nb1 *= nb1_xcoeff self.solution /= nb1_xcoeff if nb2_xcoeff != 1: self.nb2 *= nb2_xcoeff self.solution *= nb2_xcoeff if nb3_xcoeff != 1: self.nb3 *= nb3_xcoeff self.solution *= nb3_xcoeff if self.wording_context in ['price', 'groceries']: self.solution = self.solution.rounded(Number('0.01')) if self.solution.fracdigits_nb() > 0: self.solution = self.solution.quantize(Number('0.01')) else: if self.solution.fracdigits_nb() == 0: self.solution = self.solution.quantize(Number('1')) if self.nb3.fracdigits_nb() == 0: self.nb3 = self.nb3.quantize(Number('1')) setup_wording_format_of(self)
def __init__(self, build_data, picture='true', **options): super().setup("minimal", **options) super().setup("length_units", **options) super().setup("right_triangle", **options) # There's no need to setup numbers for this question. if self.variant in ['default', 'random']: variant = shared.trigo_vocabulary_source.next()[0] else: variant = self.variant if variant not in ['adjacent', 'opposite']: raise ValueError('XMLFileFormatError: Invalid variant: {v}, ' .format(v=variant) + 'It should be in: ' '[\'adjacent\', \'opposite\']') angle_nb = random.choice([0, 2]) self.right_triangle.setup_for_trigonometry( angle_nb=angle_nb, trigo_fct='cos', down_length_val=Value(''), up_length_val=Value(''), length_unit=self.length_unit, only_mark_unknown_angle=True) self.acute_angle = shared.machine.write_math_style2( self.right_triangle.angle[angle_nb].printed) self.wording = { 'adjacent': _('Which side is adjacent to {acute_angle} ?'), 'opposite': _('Which side is opposite to {acute_angle} ?') }[variant] setup_wording_format_of(self) side_getter = getattr(self.right_triangle, 'side_' + variant + '_to') self.correct_answer = side_getter( angle=self.right_triangle.angle[angle_nb]).length_name self.answer_wording = { 'adjacent': _('The side adjacent to {acute_angle} is:' ' {correct_answer}'), 'opposite': _('The side opposite to {acute_angle} is:' ' {correct_answer}') }[variant] setup_wording_format_of(self, w_prefix='answer_') self.q_nb_included_in_wording = False
def __init__(self, build_data, picture='true', **options): super().setup("minimal", **options) super().setup("length_units", **options) super().setup("right_triangle", **options) # nb1 and nb2 are sides' lengths, # they may require to be ordered, later on... super().setup("numbers", nb=build_data, shuffle_nbs=False, sort_nbs=True, **options) if self.variant in ['default', 'random']: variant = shared.trigo_functions_source.next()[0] else: variant = self.variant if variant not in ['cos', 'sin', 'tan']: raise ValueError('XMLFileFormatError: invalid variant: {v}, ' .format(v=variant) + 'It should be in: ' '[\'cos\', \'sin\', \'tan\']') # nb2 being the greatest length (the numbers have been ordered at # setup), it must be used as hypotenuse's length in cosine and sine # cases up_val = self.nb1 down_val = self.nb2 if variant == 'tan' and random.choice([True, False]): up_val, down_val = down_val, up_val self.right_triangle.setup_for_trigonometry( angle_nb=random.choice([0, 2]), trigo_fct=variant, down_length_val=down_val, up_length_val=up_val, length_unit=self.length_unit) self.wording = '' setup_wording_format_of(self) trigo_eq = self.right_triangle.trigonometric_equality(autosetup=True) self.resolution = trigo_eq.auto_resolution( dont_display_equations_name=True, skip_fraction_simplification=True, decimal_result=self.decimal_result, unit='\\textdegree') self.answer_wording = \ _('The triangle {triangle_name} has a right angle in' ' {right_vertex_name}. {newline} Hence: {resolution}') self.triangle_name = self.right_triangle.name self.right_vertex_name = self.right_triangle.vertex[1].name setup_wording_format_of(self, w_prefix='answer_')
def __init__(self, build_data, **options): super().setup("minimal", **options) # Possible options: allow_null_remainder (defaults to False) # force_null_remainder (defaults to False) super().setup("euclidean_division", nb=build_data, **options) self.transduration = 15 if self.divisor > 5 and self.divisor % 10 != 0: self.transduration += 3 if self.divisor > 10 and self.divisor % 10 != 0: self.transduration += 3 self.wording = _('Euclidean division of {dividend} by {divisor}?') setup_wording_format_of(self) # This is actually meant for self.preset == 'mental calculation' self.answer = '{quotient} r {remainder}'\ .format(quotient=self.quotient, remainder=self.remainder)
def __init__(self, numbers_to_use, **options): super().setup("minimal", **options) super().setup("numbers", nb=numbers_to_use, **options) super().setup("nb_variants", nb=numbers_to_use, **options) super().setup("length_units", **options) super().setup("rectangle", **options) if self.picture: self.wording = _("Area of this rectangle? |hint:area_unit|") setup_wording_format_of(self) else: self.nb1, self.nb2 = self.rectangle.width, self.rectangle.length self.wording = _("Area of a rectangle whose width is {nb1} \ {length_unit} and length is {nb2} {length_unit}? |hint:area_unit|") setup_wording_format_of(self)
def __init__(self, numbers_to_use, **options): super().setup("minimal", **options) super().setup("numbers", nb=numbers_to_use, **options) super().setup("nb_variants", nb=numbers_to_use, **options) super().setup("length_units", **options) super().setup("square", **options) if self.picture: self.wording = _("Perimeter of this square? |hint:length_unit|") setup_wording_format_of(self) else: self.nb1 = self.square.side_length self.wording = _("Perimeter of a square whose side's length \ is {nb1} {length_unit}? |hint:length_unit|") setup_wording_format_of(self)
def __init__(self, build_data, picture='true', **options): super().setup("minimal", **options) super().setup("length_units", **options) super().setup("right_triangle", **options) # There's no need to setup numbers for this question. if self.variant in ['default', 'random']: variant = shared.trigo_functions_source.next()[0] else: variant = self.variant if variant not in ['cos', 'sin', 'tan']: raise ValueError('XMLFileFormatError: invalid variant: {v}, ' .format(v=variant) + 'It should be in: ' '[\'cos\', \'sin\', \'tan\']') angle_nb = random.choice([0, 2]) self.right_triangle.setup_for_trigonometry( angle_nb=angle_nb, trigo_fct=variant, down_length_val=Value(''), up_length_val=Value(''), length_unit=self.length_unit, only_mark_unknown_angle=True) self.trigo_fct = variant self.the_formula_of_trigo_fct = { 'cos': _('the formula of cosine'), 'sin': _('the formula of sine'), 'tan': _('the formula of tangent')}[variant] self.acute_angle = shared.machine.write_math_style2( self.right_triangle.angle[angle_nb].printed) self.wording = options.get('text', options.get('wording', '')) if self.wording: self.wording = _(self.wording) setup_wording_format_of(self) self.formula = shared.machine.write_math_style1( self.right_triangle.trigonometric_equality( angle=self.right_triangle.angle[angle_nb], trigo_fct=variant).printed) self.answer_wording = \ _('The formula is: {formula}') setup_wording_format_of(self, w_prefix='answer_') self.q_nb_included_in_wording = False
def __init__(self, build_data, **kwargs): """ The two numbers in build_data are the factors of the product. kwargs may contain a 'variant' parameter. It can contain these values: - 'random' (default), then it will randomly be replaced by 'true' or 'false' - 'true', then the answer will be true - 'false', then it will randomly replaced by 'remainder' or 'reversed' - 'remainder' then a non zero remainder will be added: result = nb1 × nb2 + remainder and the answer will be false - 'reversed' then the result and nb1 or nb2 will be exchanged and the answer will be false :param nb_to_use: a tuple of 2 numbers :type nb_to_use: tuple """ super().setup('minimal', **kwargs) # super().setup("numbers", nb=nb_to_use, **kwargs) # super().setup("nb_variants", nb=nb_to_use, **kwargs) super().setup('division', nb=build_data, **kwargs) variant = kwargs.get('variant', 'random') if variant == 'random': variant = random.choice(['true', 'false']) if variant == 'true': self.n2 = self.dividend self.n1 = self.divisor self.answer = _('True') else: if variant == 'false': variant = random.choice(['remainder', 'reversed']) self.answer = _('False') if variant == 'remainder': remainder = random.randint(1, self.divisor - 1) self.n2 = self.dividend + remainder self.n1 = self.divisor elif variant == 'reversed': self.n1 = self.dividend self.n2 = self.divisor statement = _(next(shared.divisibility_statements_source)[0]) nl = r'\newline' if self.slideshow else '' self.wording = r'{} {} {}'.format(statement, nl, _('(True or false?)')) setup_wording_format_of(self) self.transduration = 18
def __init__(self, build_data, picture='true', **options): super().setup("minimal", **options) super().setup("intercept_theorem_figure", set_lengths=False, butterfly=True, **options) all_segments = self.figure.small + self.figure.side self.figure.setup_labels([False for _ in range(len(all_segments))], segments_list=all_segments) self.ratios = shared.machine.write_math_style1( self.figure.ratios_equalities().into_str()) self.wording = _(' {line1} {parallel_to} {line2}') self.line1 = self.figure.small[1].length_name self.line2 = self.figure.side[1].length_name setup_wording_format_of(self)
def __init__(self, nbs_to_use, **kwargs): result_fct = kwargs.pop('result_fct', None) wording = kwargs.pop('wording', "") super().setup("minimal", **kwargs) super().setup("numbers", nb=nbs_to_use, **kwargs) super().setup("nb_variants", nb=nbs_to_use, **kwargs) self.result = Value(result_fct(self.nb1, self.nb2).evaluate()).into_str() if 'swap_nb1_nb2' in kwargs and kwargs['swap_nb1_nb2']: self.nb1, self.nb2 = self.nb2, self.nb1 if ('permute_nb1_nb2_result' in kwargs and kwargs['permute_nb1_nb2_result']): # __ self.nb1, self.nb2, self.result = self.result, self.nb1, self.nb2 self.nb1 = Value(self.nb1) self.nb2 = Value(self.nb2) self.wording = wording setup_wording_format_of(self)
def __init__(self, numbers_to_use, picture='true', **options): super().setup("minimal", **options) super().setup("intercept_theorem_figure", set_lengths=False, **options) all_segments = self.figure.small \ + self.figure.side \ + [self.figure.u, self.figure.v]\ + self.figure.chunk self.figure.setup_labels([False for _ in range(len(all_segments))], segments_list=all_segments) self.ratios = shared.machine.write_math_style1( self.figure.ratios_equalities().into_str( as_a_quotients_equality=True)) self.wording = _(' {line1} {parallel_to} {line2}') self.line1 = self.figure.small[1].length_name self.line2 = self.figure.side[1].length_name setup_wording_format_of(self)
def __init__(self, build_data, **options): super().setup('minimal', **options) super().setup('numbers', nb=build_data, **options) super().setup('length_units', **options) direction = options.get('direction', shared.directions_source.next()[0]) if 'variant' in options: variant = int(options['variant']) else: faces_nb, variant = shared.rightcuboids_source.next() labels = [n.standardized() for n in self.nb_list] super().setup('rightcuboid', variant=variant, labels=labels, direction=direction) self.wording = _(r'Volume of this right cuboid?\newline ' r'(length unit: {length_unit}) |hint:volume_unit|') self.transduration = 21 setup_wording_format_of(self) self.wording = self.wording.format(**self.wording_format)
def test_setup_wording_format_of_01(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert ow2.wording == 'Just a try for a {name}, a {nb_capacity_unit}; '\ 'a {nb1_length_unit1} and finally '\ '{nb3_volume_unit3}.'
def setup(self, arg, shuffle_nbs=True, **options): if arg == "minimal": self.newline = '\\newline' self.parallel_to = '$\parallel$' self.belongs_to = '$\in$' if 'variant' in options and options['variant'] == 'decimal': options['variant'] = random.choice(['decimal1', 'decimal2']) self.variant = options.get('variant', "default") self.context = options.get('context', "default") self.picture = XML_BOOLEANS[options.get('picture', "false")]() elif arg == "length_units": if 'unit' in options: self.unit_length = Unit(options['unit']) self.unit_area = Unit(self.unit_length.name, exponent=2) self.length_unit = self.unit_length.name else: if hasattr(self, 'length_unit'): self.unit_length = Unit(self.length_unit) self.unit_area = Unit(self.unit_length.name, exponent=2) elif hasattr(self, 'unit_length'): self.length_unit = self.unit_length.name self.unit_area = Unit(self.unit_length.name, exponent=2) else: length_units_names = copy.deepcopy(COMMON_LENGTH_UNITS) self.unit_length = Unit(random.choice(length_units_names)) self.unit_area = Unit(self.unit_length.name, exponent=2) self.length_unit = self.unit_length.name elif arg == "numbers": nb_list = list(options['nb']) if shuffle_nbs: random.shuffle(nb_list) for i in range(len(nb_list)): setattr(self, 'nb' + str(i + 1), nb_list[i]) self.nb_nb = len(nb_list) elif arg == "nb_variants": if self.variant.startswith('decimal'): deci_nb = int(self.variant[-1]) # so, from decimal1 up to 9 chosen_ones = random.sample([i for i in range(self.nb_nb)], deci_nb) for i in chosen_ones: setattr(self, 'nb' + str(i + 1), getattr(self, 'nb' + str(i + 1)) / 10) elif arg == "division": nb_list = list(options['nb']) self.divisor = self.result = self.dividend = 0 self.result_str = self.quotient_str = "" if '10_100_1000' in options and options['10_100_1000']: self.divisor, self.dividend = nb_list[0], nb_list[1] self.result = Quotient(('+', self.dividend, self.divisor))\ .evaluate() else: self.divisor = nb_list.pop(random.choice([0, 1])) self.result = nb_list.pop() if self.variant[:-1] == 'decimal': self.result /= 10 self.dividend = Product([self.divisor, self.result]).evaluate() if self.context == "from_area": self.subcontext = "w" if self.result < self.divisor else "l" self.dividend_str = Item(self.dividend).printed self.divisor_str = Item(self.divisor).printed self.result_str = Item(self.result).printed q = Quotient(('+', self.dividend, self.divisor), use_divide_symbol=True) self.quotient_str = q.printed elif arg == "rectangle": if hasattr(self, 'nb1') and hasattr(self, 'nb2'): nb1, nb2 = self.nb1, self.nb2 elif 'nb' in options: nb1, nb2 = options['nb'][0], options['nb'][1] else: raise error.ImpossibleAction("Setup a rectangle if no width " "nor length have been provided" " yet.") if (not hasattr(self, 'unit_length') or not hasattr(self, 'unit_area')): self.setup(self, "units", **options) # nb1 = Decimal(str(nb1)) # nb2 = Decimal(str(nb2)) w = Value(min([nb1, nb2]), unit=self.unit_length) l = Value(max([nb1, nb2]), unit=self.unit_length) rectangle_name = "DCBA" if self.picture: rectangle_name = next(shared.four_letters_words_source) self.rectangle = Rectangle([Point([rectangle_name[3], (0, 0)]), 3, 1.5, rectangle_name[2], rectangle_name[1], rectangle_name[0]], read_name_clockwise=True) self.rectangle.set_lengths([l, w]) self.rectangle.setup_labels([False, False, True, True]) elif arg == "square": if hasattr(self, 'nb1'): nb1 = self.nb1 elif 'nb' in options: nb1 = options['nb'][0] else: raise error.ImpossibleAction("Setup a square if no side's " "length have been provided " "yet.") if (not hasattr(self, 'unit_length') or not hasattr(self, 'unit_area')): # __ self.setup(self, "units", **options) square_name = "DCBA" if self.picture: square_name = next(shared.four_letters_words_source) self.square = Square([Point([square_name[3], (0, 0)]), 2, square_name[2], square_name[1], square_name[0]], read_name_clockwise=True) self.square.set_lengths([Value(nb1, unit=self.unit_length)]) self.square.setup_labels([False, False, True, False]) self.square.set_marks(random.choice(["simple", "double", "triple"])) elif arg == 'intercept_theorem_figure': butterfly = options.get('butterfly', False) set_lengths = options.get('set_lengths', True) if set_lengths: if not all([hasattr(self, 'nb1'), hasattr(self, 'nb2'), hasattr(self, 'nb3'), hasattr(self, 'nb4')]): # __ raise error.ImpossibleAction("Setup an intercept theorem " "figure without a " "coefficient and 3 other " "lengths provided.") points_names = next(shared.five_letters_words_source) if butterfly: points_names = list(rotate(points_names, -1)) (points_names[0], points_names[1]) = (points_names[1], points_names[0]) points_names = ''.join(points_names) else: points_names = rotate(points_names, random.choice(range(5))) alpha, beta = next(shared.angle_ranges_source) rotation_angle = alpha + random.choice(range(beta - alpha)) self.figure = InterceptTheoremConfiguration( points_names=points_names, build_ratio=random.choice(range(25, 75)) / 100, sketch=False, butterfly=butterfly, build_dimensions={ False: {'side0': Decimal('5'), 'angle1': Decimal(str(random.choice(range(45, 120)))), 'side1': Decimal(str(random.choice(range(20, 60)) / 10))}, True: {'side0': Decimal('4'), 'angle1': Decimal(str(random.choice(range(55, 110)))), 'side1': Decimal(str(random.choice(range(15, 50)) / 10))} }[butterfly], rotate_around_isobarycenter=rotation_angle) if set_lengths: self.figure.set_lengths([self.nb2, self.nb3, self.nb4], Value(self.nb1)) self.figure.side[2].invert_length_name() self.figure.small[2].invert_length_name() self.point0_name = self.figure.point[0].name self.point1_name = self.figure.point[1].name self.main_vertex_name = self.figure.vertex[0].name self.vertex1_name = self.figure.vertex[1].name self.vertex2_name = self.figure.vertex[2].name self.side0_length_name = self.figure.side[0].length_name self.small0_length_name = self.figure.small[0].length_name self.chunk0_length_name = self.figure.chunk[0].length_name self.side0_length = str(self.figure.side[0].length) self.small0_length = str(self.figure.small[0].length) self.chunk0_length = str(self.figure.chunk[0].length) self.side1_length_name = self.figure.side[2].length_name self.small1_length_name = self.figure.small[2].length_name self.chunk1_length_name = self.figure.chunk[1].length_name self.side1_length = str(self.figure.side[2].length) self.small1_length = str(self.figure.small[2].length) self.chunk1_length = str(self.figure.chunk[1].length) elif arg == 'mini_problem_wording': self.wording = _(shared.mini_problems_wordings_source .next(q_id=options['q_id'], nb1_to_check=self.nb1, nb2_to_check=self.nb2)) setup_wording_format_of(self)
def test_setup_wording_format_of_exceptions2(owbuggy2): """Check if a wrong hint correctly raises an exception.""" with pytest.raises(RuntimeError): setup_wording_format_of(owbuggy2)
def test_setup_wording_format_of_05(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert hasattr(ow2, 'nb_capacity_unit')
def test_setup_wording_format_of_04(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert ow2.nb1_length_unit1.startswith('\\SI{8}{')
def __init__(self, numbers_to_use, picture='true', **options): super().setup("minimal", **options) if numbers_to_use[0] < 11: raise ValueError('numbers_to_use[0] == {} whereas it should be ' '>= 11'.format(str(numbers_to_use[0]))) numbers_to_use = (numbers_to_use[0] / 10, ) + numbers_to_use[1:] super().setup("numbers", nb=numbers_to_use, shuffle_nbs=False, **options) super().setup("length_units", **options) super().setup("intercept_theorem_figure", butterfly=True, **options) if self.variant == 'default': variant = ['random', 'random'] else: if self.variant.count('_') != 1: raise error.XMLFileFormatError('The variant for ' 'intercept_theorem_butterfly ' 'shoud contain one _') variant = self.variant.split(sep='_') valid_variant = [['random', 'oneside', 'twosides'], ['random', 'all', 'twocouples']] for v, valid, n in zip(variant, valid_variant, ['first', 'second', 'third']): if v not in valid: raise error.XMLFileFormatError('Invalid {} part of the ' 'variant. It should be in: {}' .format(n, str(valid))) if variant[0] == 'random': if variant[1] == 'twocouples': variant[0] = 'oneside' else: variant[0] = random.choice(['oneside', 'twosides']) if variant[1] == 'random': if variant[0] == 'twosides': variant[1] = 'twocouples' else: variant[1] == random.choice(['all', 'twocouples']) if variant == ['twosides', 'twocouples']: raise error.XMLFileFormatError('The twosides_twocouples ' 'variant is impossible.') # The order is: # small[0] small[1] small[2] side[0] side[1] side[2] labels_configurations = { 'oneside_all': [ ['?', True, True, True, True, True], [True, '?', True, True, True, True], [True, True, '?', True, True, True], [True, True, True, '?', True, True], [True, True, True, True, '?', True], [True, True, True, True, True, '?'] ], 'oneside_twocouples': [ ['?', True, False, True, True, False], [False, True, '?', False, True, True], [True, True, False, True, '?', False], [False, True, True, False, '?', True], ['?', False, True, True, False, True], [True, False, '?', True, False, True], [True, '?', False, True, True, False], [False, '?', True, False, True, True], [False, True, True, False, True, '?'], [True, True, False, '?', True, False], [True, False, True, True, False, '?'], [True, False, True, '?', False, True], ], 'twosides_all': [ ['?', '?', True, True, True, True], ['?', True, '?', True, True, True], [True, '?', '?', True, True, True], ['?', True, True, True, '?', True], ['?', True, True, True, True, '?'], [True, '?', True, '?', True, True], [True, '?', True, True, True, '?'], [True, True, '?', True, '?', True], [True, True, '?', '?', True, True], [True, True, True, '?', '?', True], [True, True, True, '?', True, '?'], [True, True, True, True, '?', '?'], ] } variant_key = '_'.join(variant) labels_conf = random.choice(labels_configurations[variant_key]) self.figure.setup_labels(labels_conf, segments_list=self.figure.small + self.figure.side) lengths_to_calculate = [s.length_name for s in self.figure.small + self.figure.side if s.label == Value('?')] self.line1 = self.figure.small[1].length_name self.line2 = self.figure.side[1].length_name self.length1_name = lengths_to_calculate[0] if len(lengths_to_calculate) == 2: self.length2_name = lengths_to_calculate[1] if len(lengths_to_calculate) == 1: self.wording = _('The drawn figure is out of shape. {newline} ' 'The lengths are given in {length_unit}. ' '{newline} ' 'The {line1} is parallel to {line2}. {newline} ' '{newline} ' 'Determine the length of {length1_name}.') else: self.wording = _('The drawn figure is out of shape. {newline} ' 'The lengths are given in {length_unit}. ' '{newline} ' 'The {line1} is parallel to {line2}. {newline} ' '{newline} ' 'Determine the lengths of {length1_name} ' 'and {length2_name}.') setup_wording_format_of(self) self.ratios = shared.machine.write_math_style1( self.figure.ratios_equalities() .into_str(as_a_quotients_equality=True)) self.ratios_substituted = shared.machine.write_math_style1( self.figure.ratios_equalities_substituted() .into_str(as_a_quotients_equality=True)) self.resolution0 = self.figure.ratios_equalities_substituted()\ .into_crossproduct_equation(Item(lengths_to_calculate[0]))\ .auto_resolution(dont_display_equations_name=True, skip_first_step=True, skip_fraction_simplification=True, decimal_result=2, unit=self.length_unit, underline_result=True) lengths_resolutions_part = _('hence: {resolution0} ') if len(lengths_to_calculate) == 2: self.resolution1 = self.figure.ratios_equalities_substituted()\ .into_crossproduct_equation(Item(lengths_to_calculate[1]))\ .auto_resolution(dont_display_equations_name=True, skip_first_step=True, skip_fraction_simplification=True, decimal_result=2, unit=self.length_unit, underline_result=True) lengths_resolutions_part = shared.machine.write( lengths_resolutions_part + _('and: {resolution1} '), multicolumns=2) ans_variant = options.get('ans_variant', 'default') ans_texts = { 'default': _('As: {line1} {parallel_to} {line2}, ' '{main_vertex_name} {belongs_to} {chunk0_length_name}' ' and ' '{main_vertex_name} {belongs_to} {chunk1_length_name}' ', then by the intercept theorem: {newline} ' '{ratios} ' 'thus: {ratios_substituted} '), 'alternative1': _('As {line1} is parallel to {line2}, ' 'and as the line {chunk0_length_name} cuts ' 'the line {chunk1_length_name} at point ' '{main_vertex_name}, ' 'then by the intercept theorem: {newline} ' '{ratios} ' 'thus: {ratios_substituted} '), 'alternative2': _('As: {line1} is parallel to {line2}, ' 'and as {point0_name}, {main_vertex_name} and ' '{vertex1_name} on one hand, ' '{point1_name}, {main_vertex_name} and ' '{vertex2_name} on the other hand,' 'are aligned in the same order, ' 'then by the intercept theorem: {newline} ' '{ratios} ' 'thus: {ratios_substituted} ') } self.answer_wording = ans_texts[ans_variant] + lengths_resolutions_part setup_wording_format_of(self, w_prefix='answer_')
def test_setup_wording_format_of_05(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert hasattr(ow2, 'nb_capacity_unit')
def test_setup_wording_format_of_01(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert ow2.wording == 'Just a try for a {name}, a {nb_capacity_unit}; '\ 'a {nb1_length_unit1} and finally '\ '{nb3_volume_unit3}.'
def test_setup_wording_format_of_02(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert hasattr(ow2, 'name')
def test_setup_wording_format_of_03(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert ow2.nb3_volume_unit3 == '\\SI{11}{cm^{\\text{3}}}'
def __init__(self, numbers_to_use, picture='true', **options): super().setup("minimal", **options) if numbers_to_use[0] < 11: raise ValueError('numbers_to_use[0] == {} whereas it should be ' '>= 11'.format(str(numbers_to_use[0]))) numbers_to_use = (numbers_to_use[0] / 10, ) + numbers_to_use[1:] super().setup("numbers", nb=numbers_to_use, shuffle_nbs=False, **options) super().setup("length_units", **options) super().setup("intercept_theorem_figure", **options) if self.variant == 'default': variant = ['oneside', 'random', 'false'] else: if self.variant.count('_') != 2: raise error.XMLFileFormatError('The variant for ' 'intercept_theorem_triangle ' 'shoud contain two _') variant = self.variant.split(sep='_') valid_variant = [[ 'onerandom', 'tworandom', 'random', 'oneside', 'onechunk', 'twosides', 'twochunks', 'onesideonechunk' ], ['random', 'all', 'twocouples'], ['random', 'true', 'false']] for v, valid, n in zip(variant, valid_variant, ['first', 'second', 'third']): if v not in valid: raise error.XMLFileFormatError( 'Invalid {} part of the ' 'variant. It should be in: {}'.format(n, str(valid))) if variant[0] == 'onerandom': variant[0] = random.choice(['oneside', 'onechunk']) elif variant[0] == 'tworandom': if variant[1] == 'twocouples': raise error.XMLFileFormatError('The tworandom_twocouples_* ' 'variants are impossible.') if variant[2] == 'random': variant[2] = random.choice(['true', 'false']) if variant[2] == 'false': variant[0] = random.choice( ['twosides', 'twochunks', 'onesideonechunk']) elif variant[2] == 'true': variant[0] = random.choice(['twosides', 'onesideonechunk']) else: raise error.XMLFilFormatError('The third part of the variant ' 'should be "true" or "false".') # The order is: # small[0] small[1] small[2] side[0] side[1] side[2] chunk[0] chunk[1] # 'hid' means 'hidden', e.g. the length won't be displayed but can be # easily calculated before using the intercept theorem. labels_configurations = { 'oneside_all_false': [['?', True, True, True, True, True, False, False], [True, '?', True, True, True, True, False, False], [True, True, '?', True, True, True, False, False], [True, True, True, '?', True, True, False, False], [True, True, True, True, '?', True, False, False], [True, True, True, True, True, '?', False, False]], 'oneside_all_true': [ ['?', True, True, True, True, 'hid', False, True], [True, '?', True, 'hid', True, 'hid', True, True], [True, '?', True, 'hid', True, True, True, False], [True, '?', True, True, True, 'hid', False, True], [True, True, '?', 'hid', True, True, True, False], [True, True, True, '?', True, 'hid', False, True], [True, True, True, True, '?', 'hid', False, True], [True, True, True, 'hid', '?', 'hid', True, True], [True, True, True, 'hid', '?', True, True, False], [True, True, True, 'hid', True, '?', True, False], ], 'onechunk_all_false': [[True, True, True, False, True, True, '?', False], [True, True, True, True, True, False, False, '?']], 'onechunk_all_true': [[True, True, True, False, True, 'hid', '?', True], [True, True, True, 'hid', True, False, True, '?']], 'twosides_all_false': [ ['?', '?', True, True, True, True, False, False], ['?', True, '?', True, True, True, False, False], [True, '?', '?', True, True, True, False, False], ['?', True, True, True, '?', True, False, False], ['?', True, True, True, True, '?', False, False], [True, '?', True, '?', True, True, False, False], [True, '?', True, True, True, '?', False, False], [True, True, '?', True, '?', True, False, False], [True, True, '?', '?', True, True, False, False], [True, True, True, '?', '?', True, False, False], [True, True, True, '?', True, '?', False, False], [True, True, True, True, '?', '?', False, False], ], 'twosides_all_true': [ ['?', '?', True, True, True, 'hid', False, True], [True, '?', '?', 'hid', True, True, True, False], ['?', True, True, True, '?', 'hid', False, True], [True, '?', True, '?', True, 'hid', False, True], [True, '?', True, False, True, '?', True, False], [True, True, '?', False, '?', True, True, False], [True, True, True, '?', '?', 'hid', False, True], [True, True, True, 'hid', '?', '?', True, False], ], 'twochunks_all_false': [ [False, True, False, True, True, True, '?', '?'], [True, True, False, False, True, True, '?', '?'], [False, True, True, True, True, False, '?', '?'], [True, True, True, False, True, False, '?', '?'], ], 'onesideonechunk_all_false': [ [False, '?', True, True, True, True, '?', False], [True, '?', False, True, True, True, False, '?'], [True, '?', True, False, True, True, '?', False], [True, '?', True, True, True, False, False, '?'], [False, True, '?', True, True, True, '?', False], ['?', True, False, True, True, True, False, '?'], [True, True, '?', False, True, True, '?', False], ['?', True, True, True, True, False, False, '?'], [True, True, True, False, True, '?', '?', False], [True, True, True, '?', True, False, False, '?'], [False, True, True, True, True, '?', '?', False], [True, True, False, '?', True, True, False, '?'], [False, True, True, True, '?', True, '?', False], [True, True, False, True, '?', True, False, '?'], [True, True, True, False, '?', True, '?', False], [True, True, True, True, '?', False, False, '?'], ], 'onesideonechunk_all_true': [ [True, '?', True, False, True, 'hid', '?', True], [True, '?', True, 'hid', True, False, True, '?'], [False, '?', True, True, True, 'hid', '?', True], [True, '?', False, 'hid', True, True, True, '?'], [True, True, True, False, '?', 'hid', '?', True], [True, True, True, 'hid', '?', False, True, '?'], [False, True, True, True, '?', 'hid', '?', True], [True, True, False, 'hid', '?', True, True, '?'], ], 'oneside_twocouples_false': [ ['?', True, False, True, True, False, False, False], [False, True, '?', False, True, True, False, False], [True, True, False, True, '?', False, False, False], [False, True, True, False, '?', True, False, False], ['?', False, True, True, False, True, False, False], [True, False, '?', True, False, True, False, False], [True, '?', False, True, True, False, False, False], [False, '?', True, False, True, True, False, False], [False, True, True, False, True, '?', False, False], [True, True, False, '?', True, False, False, False], [True, False, True, True, False, '?', False, False], [True, False, True, '?', False, True, False, False], ], 'oneside_twocouples_true': [ ['?', False, True, True, False, 'hid', False, True], [True, False, '?', 'hid', False, True, True, False], [True, '?', False, 'hid', True, False, True, False], [False, '?', True, False, True, 'hid', False, True], [True, True, False, 'hid', '?', False, True, False], [False, True, True, False, '?', 'hid', False, True], [True, False, True, '?', False, 'hid', False, True], [True, False, True, 'hid', False, '?', True, False], ], 'onechunk_twocouples_false': [ [True, True, False, False, True, False, '?', False], [False, True, True, False, True, False, False, '?'], [True, False, True, False, False, True, '?', False], [True, False, True, True, False, False, False, '?'], ], 'onechunk_twocouples_true': [ [True, False, True, False, False, 'hid', '?', True], [True, False, True, 'hid', False, False, True, '?'], ] } random_nb = variant.count('random') if random_nb == 3: variant = random.choice(list( labels_configurations.keys())).split(sep='_') elif random_nb == 2: if variant[0] == 'random' and variant[1] == 'random': if variant[2] == 'false': variant[0] = random.choice(ALL_LENGTHS_TO_CALCULATE) if variant[0] in [ 'twosides', 'twochunks', 'onesideonechunk' ]: variant[1] = 'all' else: variant[1] = random.choice(['all', 'twocouples']) elif variant[2] == 'true': variant[0] = random.choice( ['oneside', 'onechunk', 'twosides', 'onesideonechunk']) if variant[0] in ['oneside', 'onechunk']: variant[1] = random.choice(['all', 'twocouples']) else: variant[1] = 'all' elif variant[0] == 'random' and variant[2] == 'random': if variant[1] == 'all': variant[0] = random.choice(ALL_LENGTHS_TO_CALCULATE) if variant[0] == 'twochunks': variant[2] = 'false' else: variant[2] = random.choice(['true', 'false']) elif variant[1] == 'twocouples': variant[0] = random.choice(['oneside', 'onechunk']) variant[2] = random.choice(['true', 'false']) elif variant[1] == 'random' and variant[2] == 'random': if variant[0] in ['oneside', 'onechunk']: variant[1] = random.choice(['all', 'twocouples']) variant[2] = random.choice(['true', 'false']) elif variant[0] in ['twosides', 'onesideonechunk']: variant[1] = 'all' variant[2] = random.choice(['true', 'false']) elif variant[0] == 'twochunks': variant[1] = 'all' variant[2] = 'false' elif random_nb == 1: if variant[0] == 'random': if variant[1] == 'twocouples': variant[0] = random.choice(['oneside', 'onechunk']) elif variant[1] == 'all': if variant[2] == 'true': variant[0] = random.choice([ 'oneside', 'onechunk', 'twosides', 'onesideonechunk' ]) elif variant[2] == 'false': variant[0] = random.choice(ALL_LENGTHS_TO_CALCULATE) elif variant[1] == 'random': if variant[0] in ['oneside', 'onechunk']: variant[1] = random.choice(['all', 'twocouples']) elif variant[0] in ['twosides', 'onesideonechunk']: variant[1] = 'all' elif variant[0] == 'twochunks': if variant[2] == 'false': variant[1] = 'all' else: raise error.XMLFileFormatError('Invalid variants: ' '"twochunks_*_true".') elif variant[2] == 'random': if variant[0] in ['oneside', 'onechunk']: variant[2] = random.choice(['true', 'false']) elif variant[1] == 'twocouples': raise error.XMLFileFormatError('Invalid variants: ' '"two..._twocouples_*".') else: if variant[0] == 'twochunks': variant[2] = 'false' else: variant[2] = random.choice(['true', 'false']) variant_key = '_'.join(variant) labels_conf = random.choice(labels_configurations[variant_key]) self.figure.setup_labels( labels_conf, segments_list=self.figure.small + [self.figure.u, self.figure.side[1], self.figure.v] + self.figure.chunk) self.figure.setup_labels( [labels_conf[3], labels_conf[5]], segments_list=[self.figure.side[0], self.figure.side[2]]) lengths_to_calculate = [ s.length_name for s in self.figure.small + self.figure.side if s.label == Value('?') ] chunks_to_calculate = [] chunks_infos = [] if 'chunk' in variant_key: if len(lengths_to_calculate) == 1: chunks_to_calculate = [None] chunks_infos = [None] if labels_conf[6] == '?': # This matches chunk0 chunks_to_calculate += [self.figure.chunk[0].length_name] chunks_infos += [ (self.figure.side[0].length_name, self.figure.small[0].length_name, self.figure.side[0].length, self.figure.small[0].length) ] if not labels_conf[0]: lengths_to_calculate += [self.figure.small[0].length_name] else: lengths_to_calculate += [self.figure.side[0].length_name] if labels_conf[7] == '?': # This matches chunk1 chunks_to_calculate += [self.figure.chunk[1].length_name] chunks_infos += [ (self.figure.side[2].length_name, self.figure.small[2].length_name, self.figure.side[2].length, self.figure.small[2].length) ] if not labels_conf[2]: lengths_to_calculate += [self.figure.small[2].length_name] else: lengths_to_calculate += [self.figure.side[2].length_name] self.line1 = self.figure.small[1].length_name self.line2 = self.figure.side[1].length_name lengths_asked_for = [ s.length_name for s in self.figure.small + self.figure.side + self.figure.chunk if s.label == Value('?') ] self.length1_name = lengths_asked_for[0] if len(lengths_asked_for) == 2: self.length2_name = lengths_asked_for[1] if len(lengths_asked_for) == 1: self.wording = _('The drawn figure is out of shape. {newline} ' 'The lengths are given in {length_unit}. ' '{newline} ' 'The {line1} is parallel to {line2}. {newline} ' '{newline} ' 'Determine the length of {length1_name}.') else: self.wording = _('The drawn figure is out of shape. {newline} ' 'The lengths are given in {length_unit}. ' '{newline} ' 'The {line1} is parallel to {line2}. {newline} ' '{newline} ' 'Determine the lengths of {length1_name} ' 'and {length2_name}.') setup_wording_format_of(self) preamble = '' if variant_key.endswith('true'): self.pre_reso0 = self.pre_reso1 = '' if labels_conf[6] is True: pre_equality0 = SubstitutableEquality( [ Item(self.side0_length_name), Sum([ Item(self.small0_length_name), Item(self.chunk0_length_name) ]) ], { Value(self.small0_length_name): Value(self.figure.small[0].length), Value(self.chunk0_length_name): Value(self.figure.chunk[0].length) }) pre_equality0_str = pre_equality0.into_str() pre_equation0 = Equation(pre_equality0.substitute()) self.pre_reso0 = shared.machine.write_math_style1( pre_equality0_str) \ + pre_equation0.auto_resolution( dont_display_equations_name=True, decimal_result=2, unit=self.length_unit, underline_result=True) if labels_conf[7] is True: pre_equality1 = SubstitutableEquality( [ Item(self.side1_length_name), Sum([ Item(self.small1_length_name), Item(self.chunk1_length_name) ]) ], { Value(self.small1_length_name): Value(self.figure.small[2].length), Value(self.chunk1_length_name): Value(self.figure.chunk[1].length) }) pre_equality1_str = pre_equality1.into_str() pre_equation1 = Equation(pre_equality1.substitute()) self.pre_reso1 = shared.machine.write_math_style1( pre_equality1_str) \ + pre_equation1.auto_resolution( dont_display_equations_name=True, decimal_result=2, unit=self.length_unit, underline_result=True) if labels_conf[6] is True and labels_conf[7] is True: preamble = _('Note: {pre_reso0} {newline} and: {pre_reso1} ' '{newline} ') elif labels_conf[6] is True: preamble = _('Note: {pre_reso0} {newline} ') elif labels_conf[7] is True: preamble = _('Note: {pre_reso1} {newline} ') self.ratios = shared.machine.write_math_style1( self.figure.ratios_equalities().into_str( as_a_quotients_equality=True)) self.ratios_substituted = shared.machine.write_math_style1( self.figure.ratios_equalities_substituted().into_str( as_a_quotients_equality=True)) self.resolution0 = self.figure.ratios_equalities_substituted()\ .into_crossproduct_equation(Item(lengths_to_calculate[0]))\ .auto_resolution(dont_display_equations_name=True, skip_first_step=True, skip_fraction_simplification=True, decimal_result=2, unit=self.length_unit, underline_result=True) lengths_resolutions_part = _('hence: {resolution0} ') if len(lengths_to_calculate) == 2: self.resolution1 = self.figure.ratios_equalities_substituted()\ .into_crossproduct_equation(Item(lengths_to_calculate[1]))\ .auto_resolution(dont_display_equations_name=True, skip_first_step=True, skip_fraction_simplification=True, decimal_result=2, unit=self.length_unit, underline_result=True) lengths_resolutions_part = shared.machine.write( lengths_resolutions_part + _('and: {resolution1} '), multicolumns=2) chunks_part = '' if len(chunks_to_calculate): if chunks_to_calculate[0] is not None: chunk_equality0 = SubstitutableEquality( [ Item(chunks_to_calculate[0]), Sum([ Item(chunks_infos[0][0]), Item(('-', chunks_infos[0][1])) ]) ], { Value(chunks_infos[0][0]): Value(chunks_infos[0][2]), Value(chunks_infos[0][1]): Value(chunks_infos[0][3]) }) chunk_equality0_str = chunk_equality0.into_str() chunk_equation0 = Equation(chunk_equality0.substitute()) self.chunk_reso0 = shared.machine.write_math_style1( chunk_equality0_str) \ + chunk_equation0.auto_resolution( dont_display_equations_name=True, decimal_result=2, unit=self.length_unit, underline_result=True) chunks_part += _('so: {chunk_reso0} ') else: chunks_part += '~\n\n\\newline\\newline\\newline\\newline\n\n' if len(chunks_to_calculate) == 2: chunk_equality1 = SubstitutableEquality( [ Item(chunks_to_calculate[1]), Sum([ Item(chunks_infos[1][0]), Item(('-', chunks_infos[1][1])) ]) ], { Value(chunks_infos[1][0]): Value(chunks_infos[1][2]), Value(chunks_infos[1][1]): Value(chunks_infos[1][3]) }) chunk_equality1_str = chunk_equality1.into_str() chunk_equation1 = Equation(chunk_equality1.substitute()) self.chunk_reso1 = shared.machine.write_math_style1( chunk_equality1_str) \ + chunk_equation1.auto_resolution( dont_display_equations_name=True, decimal_result=2, unit=self.length_unit, underline_result=True) chunks_part = shared.machine.write(chunks_part + _('so: {chunk_reso1} '), multicolumns=2) ans_variant = options.get('ans_variant', 'default') ans_texts = { 'default': _('As: {line1} {parallel_to} {line2}, ' '{point0_name} {belongs_to} {side0_length_name} and ' '{point1_name} {belongs_to} {side1_length_name}, ' 'then by the intercept theorem: {newline} ' '{ratios} ' 'thus: {ratios_substituted} '), 'alternative1': _('As {line1} is parallel to {line2}, ' 'and as the line {chunk0_length_name} cuts ' 'the line {chunk1_length_name} at point ' '{main_vertex_name}, ' 'then by the intercept theorem: {newline} ' '{ratios} ' 'thus: {ratios_substituted} '), 'alternative2': _('As: {line1} is parallel to {line2}, ' 'and as {vertex1_name}, {point0_name} and ' '{main_vertex_name} on one hand, ' '{vertex2_name}, {point1_name} and ' '{main_vertex_name} on the other hand,' 'are aligned in the same order, ' 'then by the intercept theorem: {newline} ' '{ratios} ' 'thus: {ratios_substituted} ') } self.answer_wording = preamble \ + ans_texts[ans_variant] \ + lengths_resolutions_part \ + chunks_part setup_wording_format_of(self, w_prefix='answer_')
def test_setup_wording_format_of_03(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert ow2.nb3_volume_unit3 == '\\SI{11}{cm^{3}}'
def __init__(self, build_data, **kwargs): """ The two numbers in build_data are the factors of the product. The first number will be the possible divisor (i.e. questions will be: "... is divisible by nb1. (True or false?)"). kwargs may contain a 'variant' parameter. It can contain these values: - 'random' (default), then it will randomly be replaced by 'true' or 'false' - 'true', then the answer will be true - 'false', then a non zero remainder will be added: result = nb1 × nb2 + remainder and the answer will be false :param build_data: a tuple of 2 numbers :type build_data: tuple """ super().setup('minimal', **kwargs) super().setup('division', nb=build_data, order='divisor,quotient', **kwargs) variant = kwargs.get('variant', 'random') variant2 = kwargs.get('variant2', 'default') if variant == 'random': variant = random.choice(['true', 'false']) self.n1 = self.divisor if variant == 'true': self.answer = _('True') self.n2 = self.dividend if (self.n1 == 4 and variant2 == 'ensure_no_confusion_between_rules'): if Number(self.n2).digits_sum() % 4 == 0: self.n2 += 100 else: self.answer = _('False') remainder = random.randint(1, self.divisor - 1) correction = 0 if variant2 == 'ensure_no_confusion_between_rules': if self.n1 == 3: if ((self.dividend - 1) % 100) % 3 == 0: remainder = -1 else: remainder = 1 elif self.n1 == 9: remainder = 9 - (self.dividend % 100) % 9 elif self.n1 == 4: remainder = 2 mod4 = Number(self.dividend + remainder).digits_sum() % 4 if mod4 != 0: if Number(self.dividend + remainder).digit(100) < 7: correction = 100 * (4 - mod4) else: correction = -100 * mod4 self.n2 = self.dividend + remainder + correction statement = _('{n2} is divisible by {n1}.') nl = r'\newline' if self.slideshow else '' self.wording = r'{} {} {}'.format(statement, nl, _('(True or false?)')) setup_wording_format_of(self) self.transduration = 21
def test_setup_wording_format_of_04(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert ow2.nb1_length_unit1.startswith('\\SI{8}{')
def test_setup_wording_format_of_02(ow2): """Checks if obj.wording is correctly setup.""" setup_wording_format_of(ow2) assert hasattr(ow2, 'name')
def __init__(self, numbers_to_use, picture='true', **options): super().setup("minimal", **options) if numbers_to_use[0] < 11: raise ValueError('numbers_to_use[0] == {} whereas it should be ' '>= 11'.format(str(numbers_to_use[0]))) numbers_to_use = (numbers_to_use[0] / 10, ) + numbers_to_use[1:] super().setup("numbers", nb=numbers_to_use, shuffle_nbs=False, **options) super().setup("length_units", **options) super().setup("intercept_theorem_figure", butterfly=True, **options) self.figure.setup_labels([True, False, True, True, False, True], segments_list=self.figure.small + self.figure.side) self.line1 = self.figure.small[1].length_name self.line2 = self.figure.side[1].length_name self.wording = _('The drawn figure is out of shape. {newline} ' 'The lengths are given in {length_unit}. ' '{newline} {newline} ' 'Prove that {line1} is parallel to {line2}.') setup_wording_format_of(self) self.ratio1 = shared.machine.write_math_style1( Equality([ Quotient(('+', self.figure.small[0].length_name, self.figure.side[0].length_name)), Quotient(('+', self.figure.small[0].length, self.figure.side[0].length)) ]).printed) self.ratio2 = shared.machine.write_math_style1( Equality([ Quotient(('+', self.figure.small[2].length_name, self.figure.side[2].length_name)), Quotient(('+', self.figure.small[2].length, self.figure.side[2].length)) ]).printed) self.crossproduct = shared.machine.write_math_style1( Equality([ Quotient(('+', Product([ Item(self.figure.small[0].length), Item(self.figure.side[2].length) ]), Item(self.figure.side[0].length))), Item(self.figure.small[2].length) ]).printed) self.equal_ratios = shared.machine.write_math_style1( self.figure.ratios_for_converse().into_str( as_a_quotients_equality=True)) ans_variant = options.get('ans_variant', 'default') ans_texts = { 'default': _('\\begin{tabular}{ll}' 'We have: & ' '{main_vertex_name} {belongs_to} {chunk0_length_name}' ' \\\\ ' ' & ' '{main_vertex_name} {belongs_to} {chunk1_length_name}' ' \end{tabular}'), 'alternative2': _('{vertex1_name}, {main_vertex_name} and ' '{point0_name} on one hand, ' '{vertex2_name}, {main_vertex_name} and ' '{point1_name} on the other hand,' 'are aligned in the same order. ') } ratios = _('\\begin{multicols}{2} ' 'On one hand: {ratio1} ' 'and on the other hand: {ratio2} ' '\end{multicols} ' 'ans as: {crossproduct} ' 'then: {equal_ratios} {newline} ') conclusion = _('Hence by the converse of the intercept theorem, ' '{line1} is parallel to {line2}.') self.answer_wording = ans_texts[ans_variant] + ratios + conclusion setup_wording_format_of(self, w_prefix='answer_')