Source code for mathmaker.lib.old_style_sheet.exercise.X_Factorization

# -*- coding: utf-8 -*-

# Mathmaker creates automatically maths exercises sheets
# with their answers
# Copyright 2006-2017 Nicolas Hainaux <nh.techn@gmail.com>

# This file is part of Mathmaker.

# Mathmaker is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# any later version.

# Mathmaker is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with Mathmaker; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import random
from string import ascii_uppercase as alphabet

from mathmaker.lib.core.calculus import Expression
from .X_Structure import X_Structure
from . import question

# Here the list of available values for the parameter x_kind='' and the
# matching self.x_subkind values
# Note: the bypass value allows to give the value of *x_subkind* directly to
# the matching question Constructor, bypassing the action of the present class
AVAILABLE_X_KIND_VALUES = \
    {'short_test': ['medium_level', 'hard_level'],
     'mini_test': ['two_factorizations'],
     'preformatted': ['level_01_easy', 'level_02_easy',
                      'level_02_intermediate', 'level_03_sum_squares',
                      'level_03_difference_squares',
                      'level_03_squares_differences',
                      'level_03_some_not_factorizable',
                      'level_03_all_kinds'],
     'bypass': ['level_01']
     }

X_LAYOUT_UNIT = "cm"
ALT_DEFAULT_LAYOUT = {'exc': [None, 'all'],
                      'ans': [[2, 9, 9], (1, 1,
                                          1, 1),
                              None, 1]
                      }
# ----------------------  lines_nb    col_widths   questions
# In each list, the first number is the number of lines (or the value '?'),
# then follow the columns widths. The tuple contains the questions per cell.
# For instance, [2, 6, 6, 6], (1, 1, 1, 1, 1, 1) means 2 lines, 3 cols (widths
# 6 cm each), then 1 question per cell.
X_LAYOUTS = {'default':
             {'exc': [None, 'all'],
              'ans': [[1, 6, 6, 6], (1, 1, 1)]
              },

             ('short_test', 'hard_level'):
             {'exc': [None, 'all'],
              'ans': [[4, 9, 9], (1, 1,
                                  1, 1,
                                  1, 1,
                                  1, 1)]
              },

             ('mini_test', 'two_factorizations'):
             {'exc': [None, 'all'],
              'ans': [None, 'all']
              },

             ('preformatted', 'level_01_easy'):
             {'exc': [None, 'all'],
              'ans': [['?', 6, 6, 6], 'all']
              },

             ('preformatted', 'level_02_easy'): ALT_DEFAULT_LAYOUT,

             ('preformatted', 'level_02_intermediate'): ALT_DEFAULT_LAYOUT,

             ('preformatted', 'level_03_some_not_factorizable'):
             {'exc': [None, 'all'],
              'ans': [['?', 6, 6, 6], 'all']
              },

             ('bypass', 'level_01'):
             {'exc': [None, 'all'],
              'ans': [['?', 9, 9], 'all']
              }
             }


# ------------------------------------------------------------------------------
# --------------------------------------------------------------------------
# ------------------------------------------------------------------------------
##
# @class X_Factorization
# @brief Factorization exercises.
[docs]class X_Factorization(X_Structure): # -------------------------------------------------------------------------- ## # @brief Constructor. # @param **options Options detailed below: # - start_number=<integer> # (should be >= 1) # - number_of_questions=<integer> # /!\ only useful if you use x_kind and not preformatted # (should be >= 1) # - x_kind=<string> # ... # ... # - preformatted=<string> # /!\ preformatted is useless with short_test # /!\ number_of_questions is useless with preformatted # /!\ if you use it with the x_kind option, ensure there's a # preformatted possibility with this option # 'yes' # 'OK' # any other value will be understood as 'no' # - short_test=bool # /!\ the x_kind option above can't be used along this option # use subtype if you need to make different short_test exercises # 'yes' # 'OK' # any other value will be understood as 'no' # - subtype=<string> # ... # ... # @todo Complete the description of the possible options ! # @return One instance of exercise.Factorization def __init__(self, x_kind='default_nothing', **options): self.derived = True X_Structure.__init__(self, x_kind, AVAILABLE_X_KIND_VALUES, X_LAYOUTS, X_LAYOUT_UNIT, **options) # The purpose of this next line is to get the possibly modified # value of **options options = self.options # BEGINING OF THE ZONE TO REWRITE ------------------------------------- default_question = question.Q_Factorization # TEXTS OF THE EXERCISE self.text = {'exc': _("Factorise: "), 'ans': "" } # alternate texts section if self.x_kind == 'level_02_easy' \ or self.x_kind == 'level_02_intermediate': self.text = {'exc': _("Factorise:"), 'ans': "" } elif (self.x_kind == 'level_03_some_not_factorizable' or (self.x_kind, self.x_subkind) == ('mini_test', 'two_factorizations')): # __ self.text = {'exc': _("Factorise, if possible:"), 'ans': "" } # SHORT TEST & OTHER PREFORMATTED EXERCISES if self.x_kind == 'short_test': if self.x_subkind == 'easy_level': # NOTE: the algebra (easy) short test uses directly one # question and passes its arguments (x_kind...) directly # to question.Factorization() (see below, at the end) pass elif self.x_subkind == 'medium_level': lil_box = [] lil_box.append(default_question(q_kind='level_01', q_subkind='ax² + bx', expression_number=0)) if random.choice([True, False]): lil_box.append(default_question(q_kind='level_01', q_subkind='ax² + b', expression_number=0)) else: lil_box.append(default_question(q_kind='level_01', q_subkind='ax + b', expression_number=0)) lil_box.append(default_question(q_kind='level_01', q_subkind='not_factorizable', expression_number=0)) random.shuffle(lil_box) for i in range(len(lil_box)): q = lil_box.pop() q.expression.name = alphabet[i] for expression in q.steps: expression.name = alphabet[i] self.questions_list.append(q) elif self.x_subkind == 'hard_level': lil_box = [] l03_kinds = ['sum_square_mixed', 'difference_square_mixed', random.choice(['squares_difference', 'squares_difference_mixed']), random.choice(['fake_01', 'fake_01_mixed', 'fake_02', 'fake_02_mixed', 'fake_03', 'fake_03_mixed']), 'fake_04_any_mixed'] for n in range(len(l03_kinds)): lil_box.append(default_question( q_kind='level_03', q_subkind=l03_kinds[n], expression_number=n + 1)) l02_kinds = [('type_2_A1', False), ('type_2_A0', True), ('type_4_A0', False)] for n in range(len(l02_kinds)): lil_box.append(default_question( q_kind='level_02', q_subkind=l02_kinds[n][0], max_coeff=10, minus_sign=l02_kinds[n][1], expression_number=n + len(l03_kinds) + 1)) random.shuffle(lil_box) for i in range(len(lil_box)): q = lil_box.pop() q.expression.name = alphabet[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet[i] self.questions_list.append(q) elif self.x_kind == 'mini_test': if self.x_subkind == 'two_factorizations': lil_box = [] lil_box.append(default_question( q_kind='level_03', q_subkind=random.choices(['any_fake', 'any_true'], cum_weights=[0.2, 1])[0], expression_number=1)) l02_kinds = [('type_2_A1', False), ('type_2_A0', True), ('type_4_A0', False)] n = random.choice([0, 1, 2]) lil_box.append(default_question(q_kind='level_02', q_subkind=l02_kinds[n][0], max_coeff=10, minus_sign=l02_kinds[n][1], expression_number=2)) random.shuffle(lil_box) for i in range(len(lil_box)): q = lil_box.pop() q.expression.name = alphabet[i + self.start_number] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet[i + self.start_number] self.questions_list.append(q) elif self.x_kind == 'preformatted': if self.x_subkind == 'level_01_easy': # n is the number of questions still left to do n = 10 lil_box = [] lil_box.append(default_question( q_kind='level_01', q_subkind='ax² + bx', expression_number=10 - n)) n -= 1 if random.choice([True, False]): lil_box.append(default_question(q_kind='level_01', q_subkind='ax² + bx', expression_number=10 - n)) n -= 1 lil_box.append(default_question( q_kind='level_01', q_subkind='ax² + b', expression_number=10 - n)) n -= 1 if random.choice([True, False]): lil_box.append(default_question( q_kind='level_01', q_subkind='ax² + b', expression_number=10 - n)) n -= 1 if random.choice([True, False]): lil_box.append(default_question( q_kind='level_01', q_subkind='ax² + b', expression_number=10 - n)) n -= 1 for i in range(n): lil_box.append(default_question( q_kind='level_01', q_subkind='ax + b', expression_number=n - i)) random.shuffle(lil_box) for i in range(len(lil_box)): q = lil_box.pop() q.expression.name = alphabet[i] for expression in q.steps: expression.name = alphabet[i] self.questions_list.append(q) elif self.x_subkind == 'level_02_easy': subkinds = ['type_1_A0', 'type_1_D0', 'type_1_G0'] n1 = len(subkinds) random.shuffle(subkinds) for i in range(n1): self.questions_list.append( default_question(q_kind='level_02', q_subkind=subkinds.pop(), minus_sign=False, expression_number=i)) subkinds = ['type_2_A0', 'type_2_D0'] random.shuffle(subkinds) n2 = len(subkinds) for i in range(n2): self.questions_list.append( default_question(q_kind='level_02', q_subkind=subkinds.pop(), minus_sign=False, expression_number=i + n1)) elif self.x_subkind == 'level_02_intermediate': subkinds = ['type_1_D', 'type_1_G0', 'type_1_1'] n1 = len(subkinds) random.shuffle(subkinds) for i in range(n1): self.questions_list.append( default_question(q_kind='level_02', q_subkind=subkinds.pop(), minus_sign=False, expression_number=i)) subkinds = random.choice([['type_2_A0', 'type_2_D1'], ['type_2_A1', 'type_2_D0']]) n2 = len(subkinds) random.shuffle(subkinds) for i in range(n2): self.questions_list.append( default_question(q_kind='level_02', q_subkind=subkinds.pop(), minus_sign=False, expression_number=i + n1)) elif self.x_subkind == 'level_03_sum_squares': lil_box = [] for n in range(2): lil_box.append(default_question( q_kind='level_03', q_subkind='sum_square', expression_number=n + 1)) lil_box.append(default_question(q_kind='level_03', q_subkind='sum_square_mixed', expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_difference_squares': lil_box = [] for n in range(2): lil_box.append(default_question( q_kind='level_03', q_subkind='difference_square', expression_number=n + 1)) lil_box.append(default_question(q_kind='level_03', subkind='difference_square' '_mixed', expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_squares_differences': lil_box = [] for n in range(2): lil_box.append(default_question( q_kind='level_03', q_subkind='squares_difference', expression_number=n + 1)) lil_box.append(default_question( q_kind='level_03', q_subkind='squares_difference_mixed', expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_some_not_factorizable': q1 = default_question(q_kind='level_03', q_subkind='any_true_mixed', expression_number=1) q2 = default_question(q_kind='level_03', q_subkind='any_fake_straight', expression_number=2) lil_box = [q1, q2] random.shuffle(lil_box) for n in range(3): lil_box.append(default_question(q_kind='level_03', q_subkind='any_true', expression_number=n + 3)) for n in range(2): lil_box.append(default_question(q_kind='level_03', q_subkind='any_fake', expression_number=n + 5)) for n in range(2): lil_box.append(default_question(q_kind='level_03', q_subkind='any', expression_number=n + 7)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet[i] self.questions_list.append(q) elif self.x_subkind == 'level_03_all_kinds': all_kinds = ['sum_square', 'sum_square_mixed', 'difference_square', 'difference_square_mixed', 'squares_difference', 'squares_difference_mixed', 'fake_01', 'fake_01_mixed', 'fake_02', 'fake_02_mixed', 'fake_03', 'fake_03_mixed', 'fake_04_A', 'fake_04_A_mixed', 'fake_04_B', 'fake_04_B_mixed', 'fake_04_C', 'fake_04_C_mixed', 'fake_04_D', 'fake_04_D_mixed'] lil_box = [] for n in range(len(all_kinds)): lil_box.append(default_question( q_kind='level_03', q_subkind=all_kinds[n], expression_number=n + 1)) for i in range(len(lil_box)): q = lil_box[i] q.expression.name = alphabet[i] for expression in q.steps: if isinstance(expression, Expression): expression.name = alphabet[i] self.questions_list.append(q) # OTHER EXERCISES (BY_PASS OPTION) else: for i in range(self.q_nb): self.questions_list.append( default_question(expression_number=i + self.start_number, q_kind=self.x_subkind, **options))