Пример #1
0
def test_r1_into_euk():
    """Check Rectangle's generated euk file."""
    r1 = Rectangle([Point(["A", (0.5, 0.5)]), 4, 3, "B", "C", "D"])
    r1.side[2].label = Value(4, unit='cm')
    r1.side[3].label = Value(3, unit='cm')
    assert r1.into_euk() == \
        'box -0.1, -0.1, 5.1, 4.1\n\n'\
        'A = point(0.5, 0.5)\n'\
        'B = point(4.5, 0.5)\n'\
        'C = point(4.5, 3.5)\n'\
        'D = point(0.5, 3.5)\n'\
        '\n'\
        'draw\n'\
        '  (A.B.C.D)\n'\
        '  $\\rotatebox{0}{\sffamily 4~cm}$ C 180 - 7.5 deg 6.4\n'\
        '  $\\rotatebox{90}{\sffamily 3~cm}$ D 270 - 9 deg 4.9\n'\
        '  "A" A 225 deg, font("sffamily")\n'\
        '  "B" B 315 deg, font("sffamily")\n'\
        '  "C" C 45 deg, font("sffamily")\n'\
        '  "D" D 135 deg, font("sffamily")\n'\
        'end\n\n'\
        'label\n'\
        '  B, A, D right\n'\
        '  C, B, A right\n'\
        '  D, C, B right\n'\
        '  A, D, C right\n'\
        'end'
Пример #2
0
 def a(self, **options):
     v = None
     if hasattr(self, 'hint'):
         v = Value(self.result, unit=self.hint)\
             .into_str(display_SI_unit=True)
     else:
         v = Value(self.result).into_str()
     return v
Пример #3
0
 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)
Пример #4
0
def p1():
    p1 = Polygon([Point(["A", (0.5, 0.5)]),
                  Point(["B", (3, 1)]),
                  Point(["C", (3.2, 4)]),
                  Point(["D", (0.8, 3)])
                  ])
    p1.side[0].label = Value(4, unit='cm')
    p1.side[1].label = Value(3, unit='cm')
    p1.side[2].label = Value(2, unit='cm')
    p1.side[3].label = Value(6.5, unit='cm')
    p1.angle[0].label = Value(64, unit="\\textdegree")
    p1.angle[1].label = Value(128, unit="\\textdegree")
    p1.angle[2].label = Value(32, unit="\\textdegree")
    p1.angle[3].label = Value(256, unit="\\textdegree")
    p1.angle[0].mark = 'simple'
    p1.angle[1].mark = 'simple'
    p1.angle[2].mark = 'simple'
    p1.angle[3].mark = 'simple'
    return p1
Пример #5
0
    def __init__(self, numbers_to_use, **options):
        nb_list = list(numbers_to_use)
        hole = Item(Value('...'))
        self.hidden_one = None
        visible_one = None
        self.product = Item(Product([nb_list[0], nb_list[1]]).evaluate())

        if isinstance(nb_list[1], Fraction):
            self.hidden_one = nb_list[1]
            visible_one = nb_list[0]
        else:
            nb1 = randomly.pop(nb_list)
            nb2 = randomly.pop(nb_list)
            nb_list = [nb1, nb2]
            self.hidden_one = Item(randomly.pop(nb_list))
            visible_one = randomly.pop(nb_list)

        factors = [visible_one, hole]
        self.holed_product = Product([randomly.pop(factors),
                                      randomly.pop(factors)])
        self.holed_product.set_compact_display(False)
Пример #6
0
def test_t1_into_euk():
    """Check Triangle's generated euk file."""
    t1 = Triangle((("Z", "E", "P"), {
        'side0': 4,
        'angle1': 64,
        'side1': 5
    }),
                  rotate_around_isobarycenter=115)
    t1.side[0].label = Value(4, unit='cm')
    t1.side[1].label = Value(5, unit='cm')
    t1.side[2].label = Value(4.84, unit='cm')
    t1.angle[0].label = Value('?')
    t1.angle[1].label = Value(64, unit='\\textdegree')
    t1.angle[2].label = Value(35, unit='\\textdegree')
    t1.angle[0].mark = 'simple'
    t1.angle[1].mark = 'double'
    t1.angle[2].mark = 'dotted'
    assert t1.into_euk() == \
        'box -1.32, -0.48, 4.71, 4.6\n\n'\
        'Z = point(4.11, 0.37)\n'\
        'E = point(2.42, 4)\n'\
        'P = point(-0.72, 0.12)\n'\
        '\n'\
        'draw\n'\
        '  (Z.E.P)\n'\
        '  $\\rotatebox{-65}{\sffamily 4~cm}$ Z 115 - 7.5 deg 6.5\n'\
        '  $\\rotatebox{51}{\sffamily 5~cm}$ E 231 - 6.5 deg 8\n'\
        '  $\\rotatebox{3}{\sffamily 4.84~cm}$ P 3 - 6.7 deg 7.8\n'\
        '  $\\rotatebox{-31.2}{\sffamily ?}$ Z 148.8 deg 2.7\n'\
        '  $\\rotatebox{82.9}{\sffamily 64\\textdegree}$ E 262.9 deg 2.7\n'\
        '  $\\rotatebox{27}{\sffamily 35\\textdegree}$ P 27 deg 2.7\n'\
        '  "Z" Z 328.8 deg, font("sffamily")\n'\
        '  "E" E 82.9 deg, font("sffamily")\n'\
        '  "P" P 207 deg, font("sffamily")\n'\
        'end\n\n'\
        'label\n'\
        '  E, Z, P simple\n'\
        '  P, E, Z double\n'\
        '  Z, P, E dotted\n'\
        'end'
Пример #7
0
def negv():
    return Value(-4.2)
Пример #8
0
def v3():
    return Value(4.257)
Пример #9
0
def v4():
    return Value(4.2571)
Пример #10
0
def v1():
    return Value(4.2)
Пример #11
0
def v2():
    return Value(4.25)
Пример #12
0
    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_')
Пример #13
0
def v0():
    return Value(4)
Пример #14
0
    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)
Пример #15
0
 def a(self, **options):
     return Value(self.result).into_str()
Пример #16
0
    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_')
Пример #17
0
 def h(self, **options):
     if hasattr(self, 'hint'):
         return "\hfill" + Value("", unit=self.hint)\
             .into_str(display_SI_unit=True)
     else:
         return ""
Пример #18
0
def merge_nb_unit_pairs(arg: object, w_prefix=''):
    r"""
    Merge all occurences of {nbN} {\*_unit} in arg.wording into {nbN\_\*_unit}.

    In the same time, the matching attribute arg.nbN\_\*_unit is set with
    Value(nbN, unit=Unit(arg.\*_unit)).into_str(display_SI_unit=True)
    (the possible exponent is taken into account too).

    :param arg: the object whose attribute wording will be processed. It must
      have a wording attribute as well as nbN and \*_unit attributes.
    :type arg: object
    :rtype: None

    :Example:

    >>> class Object(object): pass
    ...
    >>> arg = Object()
    >>> arg.wording = 'I have {nb1} {capacity_unit} of water.'
    >>> arg.nb1 = 2
    >>> arg.capacity_unit = 'L'
    >>> merge_nb_unit_pairs(arg)
    >>> arg.wording
    'I have {nb1_capacity_unit} of water.'
    >>> arg.nb1_capacity_unit
    '\\SI{2}{L}'
    """
    w_object_wording = getattr(arg, w_prefix + 'wording')
    logger = settings.dbg_logger.getChild('wording.merge_nb_unit_pairs')
    logger.debug("Retrieved wording: " + w_object_wording + "\n")
    new_words_list = []
    words = w_object_wording.split()
    skip_next_w = False
    for i, w in enumerate(words):
        next_w = words[i + 1] if i <= len(words) - 2 else None
        logger.debug("w= " + w + " next_w= " + str(next_w))
        next_w_is_a_unit = False
        if next_w is not None and (is_unit(next_w) or is_unitN(next_w)):
            next_w_is_a_unit = True
        logger.debug(" next_w_is_a_unit: " + str(next_w_is_a_unit) + "\n")
        if is_wrapped(w) and w[1:3] == "nb" and next_w_is_a_unit:
            n = w[1:-1]
            u = ""
            if is_wrapped(next_w):
                u = next_w[1:-1]
                p = ""
            elif is_wrapped_P(next_w):
                u = next_w[1:-2]
                p = next_w[-1]
            new_attr_name = n + "_" + u
            expnt = 1
            if u.startswith('area'):
                expnt = 2
            elif u.startswith('volume'):
                expnt = 3
            new_val = Value(getattr(arg, n),
                            unit=Unit(getattr(arg, u),
                                      exponent=Value(expnt)))\
                .into_str(display_SI_unit=True)
            new_words_list += ["{" + new_attr_name + "}" + p]
            logger.debug(" setattr: name=" + str(new_attr_name) + "; val= " +
                         str(new_val) + "\n")
            setattr(arg, new_attr_name, new_val)
            skip_next_w = True
        elif skip_next_w:
            skip_next_w = False
        else:
            new_words_list += [w]
    new_wording = " ".join(new_words_list)
    logger.debug(" setattr: name=" + w_prefix + 'wording' + "; val= " +
                 new_wording + "\n")
    setattr(arg, w_prefix + 'wording', new_wording)
Пример #19
0
 def q(self, **options):
     return _("In the multiplication tables (from 2 to 9), "
              "which product is equal to {n}?")\
         .format(n=Value(self.product).into_str())
Пример #20
0
def level_02(q_subkind, **options):

    max_coeff = 20

    if 'max_coeff' in options and is_.an_integer(options['max_coeff']):
        max_coeff = options['max_coeff']

    attribute_a_minus_sign = 'randomly'

    if 'minus_sign' in options and options['minus_sign']:
        attribute_a_minus_sign = 'yes'

    elif 'minus_sign' in options and not options['minus_sign']:
        attribute_a_minus_sign = 'no'

    # Creation of the objects

    # The three Monomials: ax², bx and c
    # Maybe we don't need to keep the integer values...
    a_val = randomly.integer(1, max_coeff)
    b_val = randomly.integer(1, max_coeff)
    c_val = randomly.integer(1, max_coeff)

    if q_subkind in [
            'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1',
            'type_1_C1'
    ]:
        # __
        c_val = randomly.integer(2, max_coeff)

    ax2 = Monomial((randomly.sign(), a_val, 2))
    bx = Monomial((randomly.sign(), b_val, 1))
    c = Monomial((randomly.sign(), c_val, 0))

    # deg1: mx + p
    # and we need two of them
    deg1 = []
    for i in range(2):
        deg1_mx = Monomial((randomly.sign(), randomly.integer(1,
                                                              max_coeff), 1))
        deg1_p = None

        if q_subkind in [
                'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_D0',
                'type_1_E0', 'type_1_F0', 'type_1_G0', 'type_1_H0',
                'type_1_I0', 'type_1_A1', 'type_1_B1', 'type_1_D1',
                'type_1_E1', 'type_1_G1', 'type_1_H1', 'type_4_A0'
        ]:
            # __
            deg1_p = Monomial(
                (randomly.sign(), randomly.integer(1, max_coeff), 0))
        else:
            deg1_p = Monomial(
                (randomly.sign(), randomly.integer(0, max_coeff), 0))

        if not deg1_p.is_null():
            lil_box = [deg1_mx, deg1_p]
            deg1.append(
                Polynomial([randomly.pop(lil_box),
                            randomly.pop(lil_box)]))

        else:
            deg1.append(deg1_mx)

    # deg2: mx² + px + r
    # and we also need two of them
    deg2 = []
    for i in range(2):
        deg2_mx2 = Monomial((randomly.sign(), randomly.integer(1,
                                                               max_coeff), 2))

        deg2_px = None
        deg2_r = None

        if q_subkind in [
                'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_D0',
                'type_1_E0', 'type_1_F0', 'type_1_G0', 'type_1_H0',
                'type_1_I0', 'type_1_A1', 'type_1_B1', 'type_1_D1',
                'type_1_E1', 'type_1_G1', 'type_1_H1'
        ]:
            # __
            if randomly.heads_or_tails():
                deg2_px = Monomial(
                    (randomly.sign(), randomly.integer(1, max_coeff), 1))
                deg2_r = Monomial(
                    (randomly.sign(), randomly.integer(0, max_coeff), 0))
            else:
                deg2_px = Monomial(
                    (randomly.sign(), randomly.integer(0, max_coeff), 1))
                deg2_r = Monomial(
                    (randomly.sign(), randomly.integer(1, max_coeff), 0))
        else:
            deg2_px = Monomial(
                (randomly.sign(), randomly.integer(0, max_coeff), 1))
            deg2_r = Monomial(
                (randomly.sign(), randomly.integer(0, max_coeff), 0))

        lil_box = [deg2_mx2]

        if not deg2_px.is_null():
            lil_box.append(deg2_px)
        if not deg2_r.is_null():
            lil_box.append(deg2_r)

        monomials_list_for_deg2 = []
        for i in range(len(lil_box)):
            monomials_list_for_deg2.append(randomly.pop(lil_box))

        deg2.append(Polynomial(monomials_list_for_deg2))

    # Let's attribute the common factor C according to the required type
    # (NB: expression ± C×F1 ± C×F2)
    C = None

    if q_subkind in [
            'type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1'
    ]:
        # __
        C = c

    elif q_subkind in [
            'type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_D1', 'type_1_E1'
    ]:
        # __
        C = bx

    elif q_subkind in [
            'type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_G1', 'type_1_H1'
    ]:
        # __
        C = ax2

    elif q_subkind in [
            'type_2_A0', 'type_2_B0', 'type_2_C0', 'type_2_A1', 'type_2_B1',
            'type_4_A0'
    ]:
        # __
        C = Polynomial([bx, c])

    elif q_subkind in [
            'type_2_D0', 'type_2_E0', 'type_2_F0', 'type_2_D1', 'type_2_E1'
    ]:
        # __
        C = Polynomial([ax2, c])

    elif q_subkind in [
            'type_3_A0', 'type_3_B0', 'type_3_C0', 'type_3_A1', 'type_3_B1'
    ]:
        # __
        C = Polynomial([ax2, bx, c])

    # Let's attribute F1 and F2 according to the required type
    # (NB: expression ± C×F1 ± C×F2)
    F1 = None
    F2 = None

    if q_subkind in [
            'type_1_A0', 'type_1_A1', 'type_1_D0', 'type_1_D1', 'type_1_G0',
            'type_1_G1', 'type_2_A0', 'type_2_A1', 'type_2_D0', 'type_2_D1',
            'type_3_A0', 'type_3_A1'
    ]:
        # __
        F1 = deg1[0]
        F2 = deg1[1]

    elif q_subkind in [
            'type_1_B0', 'type_1_B1', 'type_1_E0', 'type_1_E1', 'type_1_H0',
            'type_1_H1', 'type_2_B0', 'type_2_B1', 'type_2_E0', 'type_2_E1',
            'type_3_B0', 'type_3_B1'
    ]:
        # __
        F1 = deg2[0]
        F2 = deg2[1]

    elif q_subkind in [
            'type_1_C0', 'type_1_F0', 'type_1_I0', 'type_2_C0', 'type_2_F0',
            'type_3_C0'
    ]:
        # __
        F1 = deg1[0]
        F2 = deg2[0]

    # The special case type_4_A0: (ax+b)² + (ax+b)×deg1'
    #                       aka    C² + C×F1
    elif q_subkind == 'type_4_A0':
        F1 = C.clone()
        F2 = deg1[0]

    # Let's put a "1" somewhere in the type_*_*1
    if q_subkind in [
            'type_1_A1', 'type_1_D1', 'type_1_G1', 'type_2_A1', 'type_2_D1',
            'type_3_A1', 'type_1_B1', 'type_1_E1'
            'type_1_H1', 'type_2_B1', 'type_2_E1', 'type_3_B1'
    ]:
        # __
        if randomly.heads_or_tails():
            F1 = Item(1)
        else:
            F2 = Item(1)

    # Let's possibly attribute a minus_sign
    # (NB: expression ± C×F1 ± C×F2)
    minus_sign = None
    # this will contain the name of the factor having
    # a supplementary minus sign in such cases:
    # C×F1 - C×F2# - C×F1 + C×F2

    # in all the following cases, it doesn't bring anything to attribute
    # a minus sign
    if ((q_subkind
         in ['type_1_A0', 'type_1_B0', 'type_1_C0', 'type_1_A1', 'type_1_B1']
         and c_val < 0) or
        ((q_subkind
          in ['type_1_D0', 'type_1_E0', 'type_1_F0', 'type_1_D1', 'type_1_E1'])
         and b_val < 0) or
        ((q_subkind
          in ['type_1_G0', 'type_1_H0', 'type_1_I0', 'type_1_G1', 'type_1_H1'])
         and a_val < 0)):
        # __
        pass  # here we let minus_sign equal to None

    # otherwise, let's attribute one randomly,
    # depending on attribute_a_minus_sign
    else:
        if attribute_a_minus_sign in ['yes', 'randomly']:
            # __
            if (attribute_a_minus_sign == 'yes' or randomly.heads_or_tails()):
                # __
                if randomly.heads_or_tails():
                    minus_sign = "F1"
                else:
                    minus_sign = "F2"
            else:
                pass  # here we let minus_sign equal to None

    # Now let's build the expression !
    expression = None
    box_product1 = [C, F1]
    box_product2 = [C, F2]

    if q_subkind == 'type_4_A0':
        CF1 = Product([C])
        CF1.set_exponent(Value(2))
    else:
        CF1 = Product([randomly.pop(box_product1), randomly.pop(box_product1)])

    CF2 = Product([randomly.pop(box_product2), randomly.pop(box_product2)])

    if minus_sign == "F1":
        if len(F1) >= 2:
            CF1 = Expandable((Item(-1), CF1))
        else:
            CF1 = Product([Item(-1), CF1])

    elif minus_sign == "F2":
        if len(F2) >= 2:
            CF2 = Expandable((Item(-1), CF2))
        else:
            CF2 = Product([Item(-1), CF2])

    expression = Sum([CF1, CF2])

    # Now let's build the factorization steps !
    steps = []
    steps.append(expression)

    F1F2_sum = None

    if minus_sign is None:
        F1F2_sum = Sum([F1, F2])

    elif minus_sign == "F1":
        if len(F1) >= 2:
            F1F2_sum = Sum([Expandable((Item(-1), F1)), F2])
        else:
            F1F2_sum = Sum([Product([Item(-1), F1]), F2])

    elif minus_sign == "F2":
        if len(F2) >= 2:
            F1F2_sum = Sum([F1, Expandable((Item(-1), F2))])
        else:
            F1F2_sum = Sum([F1, Product([Item(-1), F2])])

    temp = Product([C, F1F2_sum])
    temp.set_compact_display(False)
    steps.append(temp)

    F1F2_sum = F1F2_sum.expand_and_reduce_next_step()

    while F1F2_sum is not None:
        steps.append(Product([C, F1F2_sum]))
        F1F2_sum = F1F2_sum.expand_and_reduce_next_step()

    # This doesn't fit the need, because too much Products are
    # wrongly recognized as reducible !
    if steps[len(steps) - 1].is_reducible():
        steps.append(steps[len(steps) - 1].reduce_())

    return steps
Пример #21
0
def perfect_square():
    return Value(16)
Пример #22
0
 def a(self, **options):
     v = Value(self.result, unit=self.hint).into_str(display_SI_unit=True)
     return v
Пример #23
0
def perfect_decimal_square():
    return Value(1.96)
Пример #24
0
    def __init__(self, q_kind='default_nothing', **options):
        self.derived = True

        # The call to the mother class __init__() method will set the
        # fields matching optional arguments which are so far:
        # self.q_kind, self.q_subkind
        # plus self.options (modified)
        Q_Structure.__init__(self,
                             q_kind, AVAILABLE_Q_KIND_VALUES,
                             **options)
        # The purpose of this next line is to get the possibly modified
        # value of **options
        options = self.options

        # Set the default values of the different options
        use_pythagorean_triples = False
        if (('use_pythagorean_triples' in options
             and options['use_pythagorean_triples'])
            or (self.q_kind == 'converse_of_pythagorean_theorem')):
            # __
            use_pythagorean_triples = True

        use_decimals = True
        if 'use_decimals' in options and not options['use_decimals']:
            use_decimals = False

        self.round_to = ""

        if 'round_to' in options and options['round_to'] in PRECISION:
            self.round_to = options['round_to']

        if not use_pythagorean_triples:
            if self.round_to == "":
                if use_decimals:
                    self.round_to = HUNDREDTH
                else:
                    self.round_to = TENTH

        self.use_pythagorean_triples = use_pythagorean_triples

        self.figure_in_the_text = True

        if ('figure_in_the_text' in options
            and not options['figure_in_the_text']):
            # __
            self.figure_in_the_text = False

        rotation_option = 'no'

        if 'rotate_around_barycenter' in options:
            rotation_option = options['rotate_around_barycenter']

        self.final_unit = ""

        if ('final_unit' in options
            and options['final_unit'] in LENGTH_UNITS):
            # __
            self.final_unit = options['final_unit']

        sides_units = [self.final_unit,
                       self.final_unit,
                       self.final_unit]

        # Later, allow to use a different length unit for the sides
        # than the final expected unit ; allow different units for different
        # sides (for instance giving a list in option 'sides_units')...
        # So far we will do with only ONE unit
        # if 'sides_units' in options \
        #    and options['sides_units'] in LENGTH_UNITS:
        #     # __
        #    sides_units = options['sides_units']

        self.right_triangle = None

        self.unknown_side = None
        self.known_sides = []

        # Now set some randomly values
        letters = [elt for elt in alphabet.UPPERCASE]

        vertices_names = (randomly.pop(letters),
                          randomly.pop(letters),
                          randomly.pop(letters))

        # Here you can begin to write code for the different
        # q_kinds & q_subkinds
        if self.q_kind == 'pythagorean_theorem':
            sides_values = [None, None, None]

            if use_pythagorean_triples:
                triples = pythagorean.ALL_TRIPLES_5_100

                if use_decimals:
                    triples = pythagorean.ALL_TRIPLES_5_100 \
                        + pythagorean.TRIPLES_101_200_WO_TEN_MULTIPLES

                sides_values = randomly.pop(triples)

                if use_decimals:
                    sides_values = \
                        [Decimal(str(Decimal(sides_values[0]) / 10)),
                         Decimal(str(Decimal(sides_values[1]) / 10)),
                         Decimal(str(Decimal(sides_values[2]) / 10))]

                if self.q_subkind == 'calculate_hypotenuse':
                    sides_values[2] = ""
                    sides_units[2] = ""

                else:
                    # case: self.q_subkind == 'calculate_one_leg'
                    leg0_or_1 = randomly.pop([0, 1])
                    sides_values[leg0_or_1] = ""
                    sides_units[leg0_or_1] = ""

            else:
                # NO pythagorean triples.
                # The two generated values must NOT match any pythagorean
                # triple
                if use_decimals:
                    min_side_value = 5
                    max_side_value = 200
                else:
                    min_side_value = 5
                    max_side_value = 100

                if self.q_subkind == 'calculate_hypotenuse':
                    first_leg = randomly.integer(min_side_value,
                                                 max_side_value)

                    # we will take the leg values between
                    # at least 25% and at most 150% of the length of first leg
                    # (and smaller than max_side_value)
                    second_leg_values = []
                    for i in range(int(first_leg * 1.5)):
                        if (i + int(first_leg * 0.25) <= 1.5 * first_leg
                            and i + int(first_leg * 0.25) <= max_side_value):
                            # __
                            second_leg_values += [i + int(first_leg * 0.25)]

                    second_leg_unauthorized_values = \
                        pythagorean.get_legs_matching_given_leg(first_leg)

                    second_leg_possible_values = \
                        list(set(second_leg_values)
                             - set(second_leg_unauthorized_values))

                    if randomly.heads_or_tails():
                        sides_values = \
                            [first_leg,
                             randomly.pop(second_leg_possible_values),
                             ""]
                        sides_units[2] = ""

                    else:
                        sides_values = \
                            [randomly.pop(second_leg_possible_values),
                             first_leg,
                             ""]
                        sides_units[2] = ""

                else:
                    # case: self.q_subkind == 'calculate_one_leg'

                    hypotenuse = randomly.integer(min_side_value,
                                                  max_side_value)

                    # we will take the leg values between
                    # at least 25% and at most 90% of the length of hypotenuse
                    # to avoid "weird" cases (with a very subtle difference
                    # between the given values and the one to calculate)
                    leg_values = []
                    for i in range(int(hypotenuse * 0.9)):
                        if i + int(hypotenuse * 0.25) <= 0.9 * hypotenuse:
                            leg_values += [i + int(hypotenuse * 0.25)]

                    leg_unauthorized_values = \
                        pythagorean\
                        .get_legs_matching_given_hypotenuse(hypotenuse)

                    leg_possible_values = list(set(leg_values)
                                               - set(leg_unauthorized_values))

                    if randomly.heads_or_tails():
                        sides_values = ["",
                                        randomly.pop(leg_possible_values),
                                        hypotenuse]
                        sides_units[0] = ""

                    else:
                        sides_values = [randomly.pop(leg_possible_values),
                                        "",
                                        hypotenuse]
                        sides_units[1] = ""

            self.right_triangle = \
                RightTriangle((vertices_names,
                               'sketch'),
                              rotate_around_isobarycenter=rotation_option)

            self.right_triangle.leg[0].label = Value(sides_values[0],
                                                     unit=sides_units[0])
            self.right_triangle.leg[1].label = Value(sides_values[1],
                                                     unit=sides_units[1])
            self.right_triangle.hypotenuse.label = Value(sides_values[2],
                                                         unit=sides_units[2])

            for side in self.right_triangle.side:
                if side.label.raw_value == "":
                    self.unknown_side = side.clone()
                else:
                    self.known_sides += [side.clone()]

        elif self.q_kind in ['converse_of_pythagorean_theorem',
                             'contrapositive_of_pythagorean_theorem']:
            # __
            sides_values = [None, None, None]
            triples = list(pythagorean.ALL_TRIPLES_5_100)

            if use_decimals:
                triples += list(pythagorean.TRIPLES_101_200_WO_TEN_MULTIPLES)

            sides_values = randomly.pop(triples)

            if self.q_kind == 'contrapositive_of_pythagorean_theorem':
                # We'll change exactly one value to be sure the triplet
                # is NOT pythagorean
                if randomly.heads_or_tails():
                    # We will decrease the lowest value
                    max_delta = int(0.1 * sides_values[0])
                    min_delta = 1
                    if min_delta > max_delta:
                        max_delta = min_delta
                    chosen_delta = randomly.pop(
                        [i + min_delta
                         for i in range(max_delta - min_delta + 1)])

                    sides_values = [sides_values[0] - chosen_delta,
                                    sides_values[1],
                                    sides_values[2]]

                else:
                    # We will increase the highest value
                    max_delta = int(0.1 * sides_values[2])
                    min_delta = 1
                    if min_delta > max_delta:
                        max_delta = min_delta
                    chosen_delta = randomly.pop(
                        [i + min_delta
                         for i in range(max_delta - min_delta + 1)])

                    sides_values = [sides_values[0],
                                    sides_values[1],
                                    sides_values[2] + chosen_delta]

            if use_decimals:
                sides_values = [Decimal(str(Decimal(sides_values[0]) / 10)),
                                Decimal(str(Decimal(sides_values[1]) / 10)),
                                Decimal(str(Decimal(sides_values[2]) / 10))]

            self.right_triangle = \
                RightTriangle((vertices_names,
                               'sketch'),
                              rotate_around_isobarycenter=rotation_option)

            self.right_triangle.leg[0].label = Value(sides_values[0],
                                                     unit=sides_units[0])
            self.right_triangle.leg[1].label = Value(sides_values[1],
                                                     unit=sides_units[1])
            self.right_triangle.hypotenuse.label = Value(sides_values[2],
                                                         unit=sides_units[2])

            self.right_triangle.right_angle.mark = ""