mathmaker  0.6(alpha)
mamk_misc/doc/mathmaker4doxygen/sheet/S_Structure.py
00001 # -*- coding: utf-8 -*-
00002 
00003 # Mathmaker creates automatically maths exercises sheets
00004 # with their answers
00005 # Copyright 2006-2014 Nicolas Hainaux <nico_h@users.sourceforge.net>
00006 
00007 # This file is part of Mathmaker.
00008 
00009 # Mathmaker is free software; you can redistribute it and/or modify
00010 # it under the terms of the GNU General Public License as published by
00011 # the Free Software Foundation; either version 3 of the License, or
00012 # any later version.
00013 
00014 # Mathmaker is distributed in the hope that it will be useful,
00015 # but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 # GNU General Public License for more details.
00018 
00019 # You should have received a copy of the GNU General Public License
00020 # along with Mathmaker; if not, write to the Free Software
00021 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023 from lib import error
00024 from lib.common.cst import *
00025 
00026 # ------------------------------------------------------------------------------
00027 # --------------------------------------------------------------------------
00028 # ------------------------------------------------------------------------------
00029 ##
00030 # @class S_Structure
00031 # @brief Abstract mother class of all sheets !
00032 # The constructor only has to be reimplemented, it is useless to reimplement
00033 # other methods
00034 class S_Structure(object):
00035 
00036 
00037 
00038 
00039     # --------------------------------------------------------------------------
00040     ##
00041     #   @brief /!\ Must be redefined. Constructor.
00042     #   @warning Exception NotInstanciableObject.
00043     #   @param embedded_machine The machine to be used
00044     #   @param **options Any options
00045     def __init__(self, embedded_machine, font_size_offset,
00046                  sheet_layout_unit, sheet_layout, layout_type,
00047                  **options):
00048         try:
00049             self.derived
00050         except AttributeError:
00051             raise error.NotInstanciableObject(self)
00052 
00053         self.machine = embedded_machine.clone(embedded_machine.language_code)
00054         self.machine.set_redirect_output_to_str(True)
00055         self.exercises_list = list()
00056         self.machine.set_font_size_offset(font_size_offset)
00057 
00058         self.sheet_layout_unit = sheet_layout_unit
00059         self.layout_type = layout_type
00060         self.write_texts_twice = False
00061 
00062         if 'write_texts_twice' in options \
00063             and options['write_texts_twice'] in YES:
00064         #___
00065             self.write_texts_twice = True
00066 
00067         # Some tests on sheet_layout before using it ;
00068         # but it's a bit complicated to write a complete set of tests on it ;
00069         # e.g. if the user doesn't use the same number of exercises in the
00070         # 'exc' key as in 'ans' key (which would be stupid) this
00071         # won't be checked here and so it won't work.
00072         if type(sheet_layout) != dict:
00073             raise error.UncompatibleType(str(type(sheet_layout)),
00074                                          'dict')
00075 
00076         if len(sheet_layout) != 2:
00077             raise error.WrongArgument('SHEET_LAYOUT should have two keys',
00078                                       'it has ' + str(len(sheet_layout)) \
00079                                       + ' keys')
00080 
00081         for k in ['exc', 'ans']:
00082             if not k in sheet_layout:
00083                 raise error.WrongArgument('SHEET_LAYOUT should have a key ' \
00084                                           + k,
00085                                           'it has no such key')
00086 
00087             if type(sheet_layout[k]) != list:
00088                 raise error.WrongArgument('SHEET_LAYOUT[' + k + '] should be' \
00089                                           + ' a list',
00090                                           str(type(sheet_layout[k])))
00091 
00092             if len(sheet_layout[k]) % 2:
00093                 raise error.WrongArgument('SHEET_LAYOUT[' + k + '] should have'\
00094                                           + ' an even number of elements',
00095                                           str(len(sheet_layout[k])) \
00096                                           + ' elements')
00097 
00098             for i in range(int(len(sheet_layout[k]) // 2)):
00099                 if not (sheet_layout[k][2*i] is None \
00100                     or type(sheet_layout[k][2*i])== list \
00101                     or sheet_layout[k][2*i] == 'jump'):
00102                 #___
00103                     raise error.WrongArgument('SHEET_LAYOUT[' + k + '][' \
00104                                               + str(2*i) + '] should be either'\
00105                                               + ' a list or None or "jump"',
00106                                               str(type(sheet_layout[k][2*i]))
00107                                               )
00108                 elif sheet_layout[k][2*i] is None:
00109                     if not (type(sheet_layout[k][2*i+1]) == int \
00110                         or sheet_layout[k][2*i+1] == 'all' \
00111                         or sheet_layout[k][2*i+1] == 'all_left' \
00112                         or sheet_layout[k][2*i+1] == 'jump'):
00113                     #___
00114                         raise error.WrongArgument('SHEET_LAYOUT[' + k + '][' \
00115                                               + str(2*i+1) + '] should be an '\
00116                                               + 'int since it follows the None'\
00117                                               + 'keyword',
00118                                               type(sheet_layout[k][2*i+1]))
00119 
00120                 elif sheet_layout[k][2*i] == 'jump':
00121                     if not sheet_layout[k][2*i+1] == 'next_page':
00122                         raise error.WrongArgument('SHEET_LAYOUT[' + k + '][' \
00123                                               + str(2*i+1) + '] should be : '\
00124                                               + 'next_page since it follows ' \
00125                                               + 'the jump' \
00126                                               + ' keyword',
00127                                               type(sheet_layout[k][2*i+1]))
00128 
00129                 elif type(sheet_layout[k][2*i]) == list:
00130                     if not type(sheet_layout[k][2*i+1]) == tuple:
00131                         raise error.WrongArgument('SHEET_LAYOUT[' + k + '][' \
00132                                               + str(2*i+1) + '] should be a '\
00133                                               + 'tuple',
00134                                               type(sheet_layout[k][2*i+1]))
00135 
00136                     if not len(sheet_layout[k][2*i+1]) \
00137                        == (len(sheet_layout[k][2*i])-1)*sheet_layout[k][2*i][0]:
00138                     #___
00139                         raise error.WrongArgument('SHEET_LAYOUT[' + k + '][' \
00140                                               + str(2*i+1) + '] should have ' \
00141                                               + ' as many elements as the ' \
00142                                               + 'number of cols described in '\
00143                                               + 'SHEET_LAYOUT[' + k + '][' \
00144                                               + str(2*i) + ']',
00145                                               str(len(sheet_layout[k][2*i+1])) \
00146                                               + ' instead of ' \
00147                                               + str(len(sheet_layout[k][2*i]) \
00148                                                     - 1)
00149                                               )
00150                 else:
00151                     raise error.WrongArgument('SHEET_LAYOUT[' + k + '][' \
00152                                               + str(2*i) + '] is not of any ' \
00153                                               + ' of the expected types or ' \
00154                                               + 'values.',
00155                                               str(len(sheet_layout[k][2*i]))
00156                                               )
00157 
00158         self.sheet_layout = sheet_layout
00159 
00160 
00161 
00162 
00163 
00164     # --------------------------------------------------------------------------
00165     ##
00166     #   @brief Writes the whole sheet's content to the output.
00167     def __str__(self):
00168         result = ""
00169         if self.layout_type == 'std' or self.layout_type == 'equations':
00170             result += self.machine.write_document_header()
00171             result += self.machine.write_document_begins()
00172             result += self.sheet_header_to_str()
00173             result += self.sheet_title_to_str()
00174             result += self.sheet_text_to_str()
00175             result += self.texts_to_str('exc', 0)
00176             result += self.machine.write_jump_to_next_page()
00177             result += self.answers_title_to_str()
00178             result += self.texts_to_str('ans', 0)
00179             result += self.machine.write_document_ends()
00180 
00181         elif self.layout_type == 'short_test':
00182             result += self.machine.write_document_header()
00183             result += self.machine.write_document_begins()
00184 
00185             n = 1
00186             if self.write_texts_twice:
00187                 n = 2
00188 
00189             for i in range(n):
00190                 result += self.sheet_header_to_str()
00191                 result += self.sheet_title_to_str()
00192                 result += self.sheet_text_to_str()
00193                 result += self.texts_to_str('exc', 0)
00194                 result += self.machine.write_new_line_twice()
00195 
00196                 result += self.sheet_header_to_str()
00197                 result += self.sheet_title_to_str()
00198                 result += self.sheet_text_to_str()
00199                 result += self.texts_to_str('exc', len(self.exercises_list) // 2)
00200                 result += self.machine.write_new_line_twice()
00201 
00202                 if n == 2 and i == 0:
00203                     result += self.machine.insert_dashed_hline()
00204                     result += self.machine.write_new_line()
00205                     result += self.machine.insert_vspace()
00206                     result += self.machine.write_new_line_twice()
00207 
00208 
00209             result += self.machine.write_jump_to_next_page()
00210 
00211             result += self.answers_title_to_str()
00212             result += self.texts_to_str('ans', 0)
00213             result += self.machine.write_jump_to_next_page()
00214             result += self.answers_title_to_str()
00215             result += self.texts_to_str('ans', len(self.exercises_list) // 2)
00216             result += self.machine.write_document_ends()
00217 
00218         elif self.layout_type == 'mini_test':
00219             result += self.machine.write_document_header()
00220             result += self.machine.write_document_begins()
00221 
00222             for i in range(3):
00223                 result += self.sheet_header_to_str()
00224                 result += self.sheet_title_to_str()
00225                 result += self.sheet_text_to_str()
00226                 result += self.texts_to_str('exc', 0)
00227                 result += self.machine.write_new_line_twice()
00228                 result += self.sheet_header_to_str()
00229                 result += self.sheet_title_to_str()
00230                 result += self.sheet_text_to_str()
00231                 result += self.texts_to_str('exc', len(self.exercises_list)//2)
00232                 result += self.machine.write_new_line_twice()
00233 
00234 
00235             #result += self.sheet_header_to_str()
00236             #result += self.sheet_title_to_str()
00237             #result += self.sheet_text_to_str()
00238             #result += self.texts_to_str('exc', len(self.exercises_list)/2)
00239             #result += self.machine.write_new_line_twice()
00240             #result += self.sheet_header_to_str()
00241             #result += self.sheet_title_to_str()
00242             #result += self.sheet_text_to_str()
00243             #result += self.texts_to_str('exc', 3*len(self.exercises_list)/4)
00244 
00245             result += self.machine.write_jump_to_next_page()
00246 
00247             result += self.answers_title_to_str()
00248             result += self.texts_to_str('ans', 0)
00249             result += self.machine.write_jump_to_next_page()
00250             result += self.answers_title_to_str()
00251             result += self.texts_to_str('ans', len(self.exercises_list)//2)
00252 
00253 
00254             #result += self.machine.write_jump_to_next_page()
00255             #result += self.answers_title_to_str()
00256             #result += self.texts_to_str('ans', len(self.exercises_list)/2)
00257             #result += self.machine.write_jump_to_next_page()
00258             #result += self.answers_title_to_str()
00259             #result += self.texts_to_str('ans', 3*len(self.exercises_list)/4)
00260 
00261             result += self.machine.write_document_ends()
00262 
00263         elif self.layout_type == 'mini_training':
00264             result += self.machine.write_document_header()
00265             result += self.machine.write_document_begins()
00266 
00267             for i in range(6):
00268                 result += self.texts_to_str('exc', 0)
00269                 result += self.machine.write_new_line_twice()
00270 
00271             result += self.machine.write_jump_to_next_page()
00272 
00273             result += self.answers_title_to_str()
00274             result += self.texts_to_str('ans', 0)
00275 
00276             result += self.machine.write_document_ends()
00277 
00278         elif self.layout_type == 'mental':
00279             result += self.machine.write_document_header()
00280             result += self.machine.write_document_begins()
00281             result += self.sheet_header_to_str()
00282             result += self.sheet_title_to_str()
00283             result += self.sheet_text_to_str()
00284             result += self.texts_to_str('exc', 0)
00285             result += self.machine.write_document_ends()
00286 
00287         else:
00288             raise error.OutOfRangeArgument(self.layout_type,
00289                                 "std|short_test|mini_test|equations|mental")
00290 
00291         return result
00292 
00293 
00294 
00295 
00296 
00297     # --------------------------------------------------------------------------
00298     ##
00299     #   @brief Return as str exercises' or answers'texts
00300     def texts_to_str(self, ex_or_answers, n_of_first_ex):
00301         M = self.machine
00302 
00303         result = ""
00304 
00305         result += M.reset_exercises_counter()
00306         result += M.write_set_font_size_to('large')
00307         layout = self.sheet_layout[ex_or_answers]
00308 
00309         ex_n = n_of_first_ex
00310 
00311         for k in range(int(len(layout) // 2)):
00312             if layout[2*k] is None:
00313                 how_many = layout[2*k+1]
00314 
00315                 if layout[2*k+1] == 'all_left' or layout[2*k+1] == 'all':
00316                     how_many = len(self.exercises_list) - ex_n
00317                     if (self.layout_type == 'short_test' \
00318                         or self.layout_type == 'mini_test') \
00319                         and ex_n < len(self.exercises_list) // 2:
00320                     #___
00321                         how_many = len(self.exercises_list) // 2 - ex_n
00322                     #elif self.layout_type == 'mini_test':
00323                     #    if ex_n < len(self.exercises_list) / 4:
00324                     #        how_many = len(self.exercises_list) / 4 - ex_n
00325                     #    elif ex_n < len(self.exercises_list) / 2:
00326                     #        how_many = len(self.exercises_list) / 2 - ex_n
00327                     #    elif ex_n < 3*len(self.exercises_list) / 4:
00328                     #        how_many = 3*len(self.exercises_list) / 4 - ex_n
00329 
00330                 for i in range(how_many):
00331                     if not self.layout_type == 'mental':
00332                         result += M.write_exercise_number()
00333                     result += self.exercises_list[ex_n].to_str(ex_or_answers)
00334                     result += M.write_new_line(check=result[len(result)-2:])
00335                     #if not (ex_or_answers == 'ans' \
00336                     #    and self.layout_type == 'equations'):
00337                     #___
00338                     #    result += M.write_new_line()
00339                     ex_n += 1
00340 
00341             elif layout[2*k] == 'jump' and layout[2*k+1] == 'next_page':
00342                 result += M.write_jump_to_next_page()
00343 
00344             else:
00345                 nb_of_lines = layout[2*k][0]
00346                 nb_of_cols = len(layout[2*k]) - 1
00347                 col_widths = layout[2*k][1:len(layout[2*k])]
00348                 content = []
00349                 for i in range(nb_of_lines):
00350                     for j in range(nb_of_cols):
00351                         nb_of_ex_in_this_cell = layout[2*k + 1][i*nb_of_cols+j]
00352                         cell_content = ""
00353                         for n in range(nb_of_ex_in_this_cell):
00354                             if not self.layout_type == 'mental':
00355                                 cell_content += M.write_exercise_number()
00356                             cell_content += \
00357                                 self.exercises_list[ex_n].to_str(ex_or_answers)
00358                             ex_n += 1
00359                         content += [cell_content]
00360 
00361                 result += M.write_layout((nb_of_lines, nb_of_cols),
00362                                           col_widths,
00363                                           content)
00364 
00365         return result
00366 
00367 
00368 
00369     # --------------------------------------------------------------------------
00370     ##
00371     #   @brief Writes to the output the header of the sheet to be generated
00372     #   This header is written in a large size. A new line follow it.
00373     #   It's useful to write headers for test sheets, for example.
00374     def sheet_header_to_str(self):
00375         result = ""
00376         if self.header != "":
00377             result += self.machine.write_set_font_size_to('large')
00378             result += self.header
00379             result += self.machine.write_new_line()
00380 
00381         return result
00382 
00383 
00384 
00385 
00386     # --------------------------------------------------------------------------
00387     ##
00388     #   @brief Writes to the output the title of the sheet to be generated
00389     def sheet_title_to_str(self):
00390         result = ""
00391         result += self.machine.write_set_font_size_to('LARGE')
00392         result += self.machine.write(self.title, emphasize='bold')
00393         if self.subtitle != "":
00394             result += self.machine.write_new_line()
00395             result += self.machine.write(self.subtitle, emphasize='bold')
00396         result += self.machine.write_new_line_twice()
00397 
00398         return result
00399 
00400 
00401 
00402 
00403 
00404     # --------------------------------------------------------------------------
00405     ##
00406     #   @brief Writes to the output the sheet's text
00407     def sheet_text_to_str(self):
00408         result = ""
00409         if self.text != "":
00410             result += self.machine.write(self.text)
00411             result += self.machine.write_new_line_twice()
00412 
00413         return result
00414 
00415 
00416 
00417 
00418 
00419 
00420     # --------------------------------------------------------------------------
00421     ##
00422     #   @brief Writes to the output title of the answers' sheet to be generated
00423     def answers_title_to_str(self):
00424         result = ""
00425 
00426         result += self.machine.write_set_font_size_to('LARGE')
00427         result += self.machine.write(self.answers_title, emphasize='bold')
00428         result += self.machine.write_new_line_twice()
00429 
00430         return result
00431 
00432 
00433 
00434 
00435 
00436     # --------------------------------------------------------------------------
00437     ##
00438     #   @brief Writes to the output all exercises' texts
00439     #def write_texts(self):
00440     #    self.machine.reset_exercises_counter()
00441     #    self.machine.write_set_font_size_to('large')
00442     #    for e in self.exercises_list:
00443     #        self.machine.write_exercise_number()
00444     #        e.write_text()
00445     #        self.machine.write_new_line()
00446 
00447 
00448 
00449 
00450 
00451     # --------------------------------------------------------------------------
00452     ##
00453     #   @brief Writes to the output all exercises' answers
00454     #def write_answers(self):
00455     #    self.machine.reset_exercises_counter()
00456     #    self.machine.write_set_font_size_to('large')
00457     #    for e in self.exercises_list:
00458     #        self.machine.write_exercise_number()
00459     #        e.write_answer()
00460     #        self.machine.write_new_line()
00461 
00462 
00463 
00464 
00465