mathmaker
0.4(alpha)
|
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 xrange(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 xrange(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 xrange(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 xrange(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 xrange(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 xrange(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 xrange(nb_of_lines): 00350 for j in xrange(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 xrange(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