#!/usr/bin/python # -*- coding: utf-8 -*- # # Pyromaths # Un programme en Python qui permet de créer des fiches d'exercices types de # mathématiques niveau collège ainsi que leur corrigé en LaTeX. # Copyright (C) 2006 -- Jérôme Ortais (jerome.ortais@pyromaths.org) # # This program 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 2 of the License, or # (at your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # import random import math def nodesep(ligne): """ Défini les valeurs nodesep : 0 pour une extrémité, -0.5 pour une continuité @param ligne: droite, demi-droite, segment @type ligne: string """ if ligne == _(u'une droite'): retour = ['-6', '-6'] elif ligne == _(u'une demi-droite'): retour = ['0', '-6'] else: retour = ['0', '0'] return retour def choix_points(n): """ choisit n points parmi A, B, C, ..., Z @param n: nombre de points à choisir @type n: integer """ points = [chr(i + 65) for i in range(26)] liste = [] for i in range(n): liste.append(points.pop(random.randrange(len(points)))) return liste def choix_ligne(n): """ Retourne n propositions parmi droite, segment et demi-droite @param n: nombre de propositions @type n: interger """ lignes = [_(u'une droite'), _(u'une demi-droite'), _(u'un segment')] (liste_lignes, retour) = ([], []) for i in range((n - 1) // len(lignes) + 1): liste_lignes.extend(lignes) for i in range(n): retour.append(liste_lignes.pop(random.randrange(len(liste_lignes)))) return retour def symboles(ligne): """ Retourne les couples (), [] ou [) correspondant au type de ligne @param ligne: droite, demi-droite ou segment @type ligne: string """ if ligne == _(u'une droite'): retour = ['(', ')'] elif ligne == _(u'une demi-droite'): retour = ['[', ')'] else: retour = ['[', ']'] return retour def prepare_tuple(lpoints, ligne): """ Prepare deux tuples pour permettre l'affichage de la question et de la solution @param lpoints: les points de la figure @type lpoints: liste de lettres @param ligne: droite, demi-droite ou segment @type ligne: string """ (retour_exo, retour_sol) = ([], []) #choix des deux points permettant de tracer la ligne : templist = [i for i in range(len(lpoints))] deuxpoints = [] for i in range(2): deuxpoints.append(lpoints[templist.pop(random.randrange(len(templist)))]) #choix des symbole correspondant à la ligne : lsymboles = symboles(ligne) retour_sol.append(lsymboles[0]) retour_sol.extend(deuxpoints) retour_sol.append(lsymboles[1]) retour_sol.append(ligne) #choix des trous pour l'exercice : alea = random.randrange(3) if alea > 1: retour_exo = [_('\\ldots'), _('\\ldots'), _('\\ldots'), _('\\ldots'), _('\\dotfill')] elif alea > 0: retour_exo = [_('\\ldots')] retour_exo.extend(retour_sol[1:3]) retour_exo.extend([_('\\ldots'), retour_sol[4]]) else: retour_exo = retour_sol[:4] retour_exo.append(_('\\dotfill')) return (tuple(retour_exo), tuple(retour_sol)) def tex_figure(liste, lpoints, points_coord, nodesep=0): """ Écrit dans un fichier tex la construction de 3 points et éventuellement une droite, une demi-droite ou un segment. @param liste: liste d'exos ou corrigés @type liste: liste @param lpoints: liste de 3 points @type lpoints: liste de 3 strings @param nodesep: liste des dépassements pour pstricks @type nodesep: liste de 2 strings """ liste.append('\\begin{pspicture*}(-0.5,0.2)(4.5,2.2)') liste.append('\\psset{PointSymbol=x}') liste.append('\\pstGeonode[PosAngle=90](0.5,%s){%s}(2,%s){%s}(3.5,%s){%s}' % points_coord) if nodesep: liste.append('\\pstLineAB[nodesepA=%s, nodesepB=%s]{%s}{%s}' % tuple(nodesep)) liste.append('\\end{pspicture*}\\tabularnewline') def f_quiz(x, m_quiz, n_quiz): return m_quiz * x + n_quiz def corte_quiz(m_quiz, n_quiz, n=400): if m_quiz != 0: if abs(m_quiz) > 10000: return [[-n_quiz/m_quiz,0],[-n_quiz/m_quiz,n]] else: x_y = [] if n_quiz < n and n_quiz >= 0: x_y.append([0,n_quiz]) if -n_quiz/m_quiz < n and -n_quiz/m_quiz >= 0: x_y.append([-n_quiz/m_quiz,0]) if f_quiz(n, m_quiz, n_quiz) < n and f_quiz(n, m_quiz, n_quiz) >= 0: x_y.append([n,f_quiz(n, m_quiz, n_quiz)]) if (n-n_quiz)/m_quiz < n and (n-n_quiz)/m_quiz >= 0: x_y.append([(n-n_quiz)/m_quiz,n]) return x_y else: return [[0,n_quiz],[n,n_quiz]] def tex_figure_quiz(solution, quiz, lpoints, points_coord): """ Écrit dans un fichier tex la construction de 3 points et éventuellement une droite, une demi-droite ou un segment. @param liste: liste d'exos ou corrigés @type liste: liste @param lpoints: liste de 3 points @type lpoints: liste de 3 strings @param nodesep: liste des dépassements pour pstricks @type nodesep: liste de 2 strings """ quiz_nom = _(u'Droite, demi-droite et segment') quiz_exo = _(u"Observe la forme d'en bas et complète convenablement comme ligne droite ( ), demi-droite ( ] [ ) ou je segmente [ ]:
\n") quiz_cor = [] quiz_exo += ("$$\\fs3\\picture(200){") quiz_exo += ("(26,%s){\\bullet}(96,%s){\\bullet}(166,%s){\\bullet}" % (points_coord[0]*100-3, points_coord[2]*100-3, points_coord[4]*100-3)) quiz_exo += ("(25,%s){%s}(95,%s){%s}(165,%s){%s}" % (points_coord[0]*100+5, points_coord[1], points_coord[2]*100+5, points_coord[3], points_coord[4]*100+5, points_coord[5])) if solution[0] == "[" and solution[3] == "]": if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[3] == solution[1] or points_coord[3] == solution[2]): quiz_exo += ("(30,%s){\\line(70,%s)}}$$" % (points_coord[0]*100, (points_coord[2]-points_coord[0])*100)) if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): quiz_exo += ("(30,%s){\\line(140,%s)}}$$" % (points_coord[0]*100, (points_coord[4]-points_coord[0])*100)) if (points_coord[3] == solution[1] or points_coord[3] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): quiz_exo += ("(100,%s){\\line(70,%s)}}$$" % (points_coord[2]*100, (points_coord[4]-points_coord[2])*100)) quiz_cor.append("%s%s%s%s" % (solution[0], solution[1], solution[2], solution[3])) quiz_cor.append("%s%s%s%s" % (solution[0], solution[2], solution[1], solution[3])) if solution[0] == "(" and solution[3] == ")": if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[3] == solution[1] or points_coord[3] == solution[2]): m_quiz = (points_coord[2] - points_coord[0])*100/70 n_quiz = points_coord[0]*100 - m_quiz*30 x_y_quiz = corte_quiz(m_quiz,n_quiz,200) quiz_exo += ("(%s,%s){\\line(%s,%s)}}$$" % (x_y_quiz[0][0], x_y_quiz[0][1], (x_y_quiz[1][0]-x_y_quiz[0][0]), (x_y_quiz[1][1]-x_y_quiz[0][1]))) if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): m_quiz = (points_coord[4] - points_coord[0])*100/140 n_quiz = points_coord[0]*100 - m_quiz*30 x_y_quiz = corte_quiz(m_quiz,n_quiz,200) quiz_exo += ("(%s,%s){\\line(%s,%s)}}$$" % (x_y_quiz[0][0], x_y_quiz[0][1], (x_y_quiz[1][0]-x_y_quiz[0][0]), (x_y_quiz[1][1]-x_y_quiz[0][1]))) if (points_coord[3] == solution[1] or points_coord[3] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): m_quiz = (points_coord[4] - points_coord[2])*100/70 n_quiz = points_coord[2]*100 - m_quiz*100 x_y_quiz = corte_quiz(m_quiz,n_quiz,200) quiz_exo += ("(%s,%s){\\line(%s,%s)}}$$" % (x_y_quiz[0][0], x_y_quiz[0][1], (x_y_quiz[1][0]-x_y_quiz[0][0]), (x_y_quiz[1][1]-x_y_quiz[0][1]))) quiz_cor.append("%s%s%s%s" % (solution[0], solution[1], solution[2], solution[3])) quiz_cor.append("%s%s%s%s" % (solution[0], solution[2], solution[1], solution[3])) if solution[0] == "[" and solution[3] == ")": if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[3] == solution[1] or points_coord[3] == solution[2]): m_quiz = (points_coord[2] - points_coord[0])*100/70 n_quiz = points_coord[0]*100 - m_quiz*30 if points_coord[1] == solution[1]: quiz_exo += ("(30,%s){\\line(100,%s)}}$$" % (f_quiz(30, m_quiz, n_quiz), f_quiz(130, m_quiz, n_quiz)-f_quiz(30, m_quiz, n_quiz))) else: quiz_exo += ("(0,%s){\\line(100,%s)}}$$" % (f_quiz(0, m_quiz, n_quiz), f_quiz(100, m_quiz, n_quiz)-f_quiz(0, m_quiz, n_quiz))) if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): m_quiz = (points_coord[4] - points_coord[0])*100/140 n_quiz = points_coord[0]*100 - m_quiz*30 if points_coord[1] == solution[1]: quiz_exo += ("(30,%s){\\line(170,%s)}}$$" % (f_quiz(30, m_quiz, n_quiz), f_quiz(200, m_quiz, n_quiz)-f_quiz(30, m_quiz, n_quiz))) else: quiz_exo += ("(0,%s){\\line(170,%s)}}$$" % (f_quiz(0, m_quiz, n_quiz), f_quiz(170, m_quiz, n_quiz)-f_quiz(0, m_quiz, n_quiz))) if (points_coord[3] == solution[1] or points_coord[3] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): m_quiz = (points_coord[4] - points_coord[2])*100/70 n_quiz = points_coord[2]*100 - m_quiz*100 if points_coord[3] == solution[1]: quiz_exo += ("(100,%s){\\line(100,%s)}}$$" % (f_quiz(100, m_quiz, n_quiz), f_quiz(200, m_quiz, n_quiz)-f_quiz(100, m_quiz, n_quiz))) else: quiz_exo += ("(70,%s){\\line(100,%s)}}$$" % (f_quiz(70, m_quiz, n_quiz), f_quiz(170, m_quiz, n_quiz)-f_quiz(70, m_quiz, n_quiz))) quiz_cor.append("%s%s%s%s" % (solution[0], solution[1], solution[2], solution[3])) quiz_cor.append("%s%s%s%s" % ("(", solution[2], solution[1], "]")) if solution[0] == "(" and solution[3] == "]": if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[3] == solution[1] or points_coord[3] == solution[2]): m_quiz = (points_coord[2] - points_coord[0])*100/70 n_quiz = points_coord[0]*100 - m_quiz*30 if points_coord[1] == solution[1]: quiz_exo += ("(0,%s){\\line(100,%s)}}$$" % (f_quiz(0, m_quiz, n_quiz), f_quiz(100, m_quiz, n_quiz)-f_quiz(0, m_quiz, n_quiz))) else: quiz_exo += ("(30,%s){\\line(100,%s)}}$$" % (f_quiz(30, m_quiz, n_quiz), f_quiz(130, m_quiz, n_quiz)-f_quiz(30, m_quiz, n_quiz))) if (points_coord[1] == solution[1] or points_coord[1] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): m_quiz = (points_coord[4] - points_coord[0])*100/140 n_quiz = points_coord[0]*100 - m_quiz*30 if points_coord[1] == solution[1]: quiz_exo += ("(0,%s){\\line(170,%s)}}$$" % (f_quiz(0, m_quiz, n_quiz), f_quiz(170, m_quiz, n_quiz)-f_quiz(0, m_quiz, n_quiz))) else: quiz_exo += ("(30,%s){\\line(170,%s)}}$$" % (f_quiz(30, m_quiz, n_quiz), f_quiz(200, m_quiz, n_quiz)-f_quiz(30, m_quiz, n_quiz))) if (points_coord[3] == solution[1] or points_coord[3] == solution[2]) and (points_coord[5] == solution[1] or points_coord[5] == solution[2]): m_quiz = (points_coord[4] - points_coord[2])*100/70 n_quiz = points_coord[2]*100 - m_quiz*100 if points_coord[3] == solution[1]: quiz_exo += ("(70,%s){\\line(100,%s)}}$$" % (f_quiz(70, m_quiz, n_quiz), f_quiz(170, m_quiz, n_quiz)-f_quiz(70, m_quiz, n_quiz))) else: quiz_exo += ("(100,%s){\\line(100,%s)}}$$" % (f_quiz(100, m_quiz, n_quiz), f_quiz(200, m_quiz, n_quiz)-f_quiz(100, m_quiz, n_quiz))) quiz_cor.append("%s%s%s%s" % (solution[0], solution[1], solution[2], solution[3])) quiz_cor.append("%s%s%s%s" % ("[", solution[2], solution[1], ")")) lignes = [_(u'une droite'), _(u'une demi-droite'), _(u'un segment')] lignes_quiz = "" for i in range(3): if solution[4] == lignes[i]: lignes_quiz += ("~=" + lignes[i]) else: lignes_quiz += ("~" + lignes[i]) quiz_exo += (u"{1:SHORTANSWER:%s100%s%s%s100%s%s} es {1:MULTICHOICE:%s}" % ("~%", "%", quiz_cor[0], "~%", "%", quiz_cor[1], lignes_quiz)) quiz.append([quiz_nom, quiz_exo, ""]) def coord_points(lpoints): """Définit les ordonnées de trois points nommés dont les noms sont dans lpoints""" ordonnees = [random.randrange(5, 16)/10.for i in range(3)] while abs(2*ordonnees[1]-ordonnees[0]-ordonnees[2])<.5: ordonnees = [random.randrange(5, 16)/10.for i in range(3)] random.shuffle(ordonnees) for i in range(3): ordonnees.insert(2*i+1, lpoints[i]) return tuple(ordonnees) def tex_ligne_tableau(exo, cor, quiz, ligne): """ Écrit une ligne de tableau dans un fichier tex @param exo: fichier d'exercices @type exo: file @param cor: fichier de corrections @type cor: file @param ligne: droite, demi-droite ou segment @type ligne: string """ lpoints = choix_points(3) (exer, solution) = prepare_tuple(lpoints, ligne) exo.append(_(u'$%s %s%s %s$ est %s &') % exer) cor.append(_(u'$%s %s%s %s$ est %s &') % solution) lnodesep = nodesep(ligne) lnodesep.extend(solution[1:3]) points_coord=coord_points(lpoints) if exer != (_('\\ldots'), _('\\ldots'), _('\\ldots'), _('\\ldots'), _('\\dotfill')): tex_figure(exo, lpoints, points_coord) else: tex_figure(exo, lpoints, points_coord, lnodesep) tex_figure(cor, lpoints, points_coord, lnodesep) tex_figure_quiz(solution, quiz, lpoints, points_coord) exo.append('\\hline') cor.append('\\hline') def Droites(): """ Écrit les 5 lignes du tableau @param exo: fichier d'exercices @type exo: file @param cor: fichier de corrections @type cor: file @param quiz: fichier quiz @type quiz: file """ exo = ["\\exercice", _(u"Compléter les pointillés et les figures :\\par"), '\\renewcommand{\\tabularxcolumn}[1]{m{#1}}', '\\begin{tabularx}{\\linewidth}{|X|>{\\centering}m{5cm}|}', '\\hline', _(u'\\textbf{Phrase} & \\textbf{Figure} \\tabularnewline \\hline')] cor = ["\\exercice*", _(u"Compléter les pointillés et les figures :\\par"), '\\renewcommand{\\tabularxcolumn}[1]{m{#1}}', '\\begin{tabularx}{\\linewidth}{|X|>{\\centering}m{5cm}|}', '\\hline', _(u'\\textbf{Phrase} & \\textbf{Figure} \\tabularnewline \\hline')] quiz = [u"cloze"] line = choix_ligne(5) for i in range(5): tex_ligne_tableau(exo, cor, quiz, line[i]) exo.append('\\end{tabularx}') cor.append('\\end{tabularx}') return (exo, cor, quiz) #------------------------------------------------------------------------------ # Parallèles et perpendiculaires #------------------------------------------------------------------------------ #perp à (ac) passant par b => val2=('a', 'c', 'a', 'c', 'b', 'b', 'b', 'a' #para à (ab) passant apr d => val2=('a', 'b', 'a', 'b', 'd', 'd') def fig_perp(points, coor, solution=0, per=[], par=[]): val_enonce = ( points[0], points[1], coor[0], coor[1], coor[2], coor[3], points[2], points[3], coor[4], coor[5], coor[6], coor[7],) pts = ('a', 'b', 'c', 'd') text = \ """ \\begin{pspicture*}(-4,-4)(4,4) \psset{PointSymbol=x} \pstGeonode[PointName={%s,%s}](%s;%s){a}(%s;%s){b} \pstGeonode[PointName={%s,%s}](%s; %s){c}(%s; %s){d}""" % \ val_enonce if solution: val_soluce = ( pts[per[0]], pts[per[1]], pts[per[0]], pts[per[1]], pts[per[2]], pts[per[2]], pts[per[2]], pts[per[0]], pts[par[0]], pts[par[1]], pts[par[0]], pts[par[1]], pts[par[2]], pts[par[2]]) text = text + \ """ \pstLineAB[nodesep=-4, linecolor=DarkBlue]{%s}{%s} \pstProjection[PointName=none]{%s}{%s}{%s}[e]\pstLineAB[nodesep=-7, linecolor=DarkBlue]{%s}{e} \pstRightAngle[, linecolor=DarkBlue]{%s}{e}{%s} \pstLineAB[nodesep=-4, linecolor=DarkRed]{%s}{%s} \pstTranslation[PointName=none,PointSymbol=none]{%s}{%s}{%s}[f] \pstLineAB[nodesep=-7, linecolor=DarkRed]{%s}{f} \end{pspicture*}""" % \ val_soluce return text def fig_perp_quiz(quiz, points, coor, per=[], par=[]): coor_m = [] for x in range(len(coor)/2): coor_m.append(200 + round(coor[2*x]*50*math.cos(coor[2*x+1]*math.pi/180))) coor_m.append(200 + round(coor[2*x]*50*math.sin(coor[2*x+1]*math.pi/180))) quiz_txt = "$$\\fs3\\picture(410){" quiz_txt += ("(%s,%s){\\bullet}(%s,%s){\\bullet}(%s,%s){\\bullet}(%s,%s){\\bullet}" % (coor_m[0]-4, coor_m[1]-3, coor_m[2]-4, coor_m[3]-3, coor_m[4]-4, coor_m[5]-3, coor_m[6]-4, coor_m[7]-3)) quiz_txt += ("(%s,%s){%s}(%s,%s){%s}(%s,%s){%s}(%s,%s){%s}" % (coor_m[0]-5, coor_m[1]+5, points[0], coor_m[2]-5, coor_m[3]+5, points[1], coor_m[4]-5, coor_m[5]+5, points[2], coor_m[6]-5, coor_m[7]+5, points[3])) if (coor_m[2*per[0]+1] - coor_m[2*per[1]+1]) == 0: quiz_txt += ("(0,%s){\\line(400,0)}(%s,0){\\line(0,400)}" % (coor_m[2*per[0]+1], coor_m[2*per[2]+1])) elif (coor_m[2*per[0]] - coor_m[2*per[1]]) == 0: quiz_txt += ("(%s,0){\\line(0,400)}(0,%s){\\line(400,0)}" % (coor_m[2*per[0]], coor_m[2*per[2]])) else: m_quiz = (coor_m[2*per[0]+1] - coor_m[2*per[1]+1])/(coor_m[2*per[0]] - coor_m[2*per[1]]) n_quiz = coor_m[2*per[1]+1] - (m_quiz*coor_m[2*per[1]]) mp_quiz = -1/m_quiz np_quiz = coor_m[2*per[2]+1] - (mp_quiz*coor_m[2*per[2]]) x_y_quiz = corte_quiz(m_quiz,n_quiz) xp_yp_quiz = corte_quiz(mp_quiz,np_quiz) quiz_txt += ("(%s,%s){\\line(%s,%s)}(%s,%s){\\line(%s,%s)}" % (x_y_quiz[0][0], x_y_quiz[0][1], (x_y_quiz[1][0]-x_y_quiz[0][0]), (x_y_quiz[1][1]-x_y_quiz[0][1]), xp_yp_quiz[0][0], xp_yp_quiz[0][1], (xp_yp_quiz[1][0]-xp_yp_quiz[0][0]), (xp_yp_quiz[1][1]-xp_yp_quiz[0][1]))) if (coor_m[2*par[1]+1] - coor_m[2*par[0]+1]) == 0: quiz_txt += ("(0,%s){\\line(400,0)}(%s,0){\\line(0,400)}" % (coor_m[2*par[0]+1], coor_m[2*par[2]+1])) elif (coor_m[2*par[0]] - coor_m[2*par[1]]) == 0: quiz_txt += ("(%s,0){\\line(0,400)}(0,%s){\\line(400,0)}" % (coor_m[2*par[0]], coor_m[2*par[2]])) else: m_quiz = (coor_m[2*par[0]+1] - coor_m[2*par[1]+1])/(coor_m[2*par[0]] - coor_m[2*par[1]]) n_quiz = coor_m[2*par[1]+1] - (m_quiz*coor_m[2*par[1]]) np_quiz = coor_m[2*par[2]+1] - (m_quiz*coor_m[2*par[2]]) x_y_quiz = corte_quiz(m_quiz,n_quiz) xp_yp_quiz = corte_quiz(m_quiz,np_quiz) quiz_txt += ("(%s,%s){\\line(%s,%s)}(%s,%s){\\line(%s,%s)}" % (x_y_quiz[0][0], x_y_quiz[0][1], (x_y_quiz[1][0]-x_y_quiz[0][0]), (x_y_quiz[1][1]-x_y_quiz[0][1]), xp_yp_quiz[0][0], xp_yp_quiz[0][1], (xp_yp_quiz[1][0]-xp_yp_quiz[0][0]), (xp_yp_quiz[1][1]-xp_yp_quiz[0][1]))) quiz_txt += ("}$$") return quiz_txt def noms_sommets(nb): # renvoie nb noms de sommets (listenb, listepts) = ([], []) for i in range(26): listenb.append(i + 65) for i in range(nb): listepts.append(chr(listenb.pop(random.randrange(26 - i)))) listepts.sort() return tuple(listepts) def cree_coordonnees(long=3): from math import floor alpha = random.randrange(180) k0 = random.randrange(50, 100) / 100.0 a0 = alpha + random.randrange(30, 120) k1 = random.randrange(50, 100) / 100.0 a1 = alpha + random.randrange(210, 300) return (long, alpha, long, alpha + 180, floor((k0 * 10) * long) / 10.0, a0, floor((k1 * 10) * long) / 10.0, a1) def enonce_perp(exo, cor, quiz): coor = cree_coordonnees(3) noms = noms_sommets(4) par, per = [], [] lval = [0, 1, 2, 3] for i in range(3): par.append(lval.pop(random.randrange(len(lval)))) while per==[] or sorted(par) == sorted(per): lval = [0, 1, 2, 3] per = [] for i in range(3): per.append(lval.pop(random.randrange(len(lval)))) exo.append(fig_perp(noms, coor)) cor.append(fig_perp(noms, coor, 1, per, par)) exo.append('\end{pspicture*}\\par\n\\begin{enumerate}') cor.append('\\par\n\\begin{enumerate}') s_per = _(u"\\item Tracer la droite perpendiculaire à la droite $(%s%s)$ passant par $%s$") s_par = _(u"\\item Tracer la droite parallèle à la droite $(%s%s)$ passant par $%s$") s_per = s_per % (noms[per[0]], noms[per[1]], noms[per[2]]) s_par = s_par % (noms[par[0]], noms[par[1]], noms[par[2]]) quiz_nom = _(u"Droites perpendiculaires et parallèles") quiz_exo_cor = _(u"Observe la forme et complète avec le parallèle ou perpendiculaire:
\n") if random.randrange(2): exo.append(s_par) cor.append(s_par) exo.append(s_per) cor.append(s_per) quiz_exo_cor += (_(u"La droite $$(%s%s)$$ est {1:MULTICHOICE:~=paralela~perpendicular} à un qu'il passe par $$%s$$
\n") % (noms[par[0]], noms[par[1]], noms[par[2]])) quiz_exo_cor += (_(u"La droite $$(%s%s)$$ est {1:MULTICHOICE:~=perpendicular~paralela} à un qu'il passe par $$%s$$
\n") % (noms[per[0]], noms[per[1]], noms[per[2]])) else: exo.append(s_per) cor.append(s_per) exo.append(s_par) cor.append(s_par) quiz_exo_cor += (_(u"La droite $$(%s%s)$$ est {1:MULTICHOICE:~=perpendicular~paralela} à un qu'il passe par $$%s$$
\n") % (noms[per[0]], noms[per[1]], noms[per[2]])) quiz_exo_cor += (_(u"La droite $$(%s%s)$$ est {1:MULTICHOICE:~=paralela~perpendicular} à un qu'il passe par $$%s$$
\n") % (noms[par[0]], noms[par[1]], noms[par[2]])) quiz_exo_cor += fig_perp_quiz(quiz, noms, coor, per, par) quiz.append([quiz_nom, quiz_exo_cor, ""]) exo.append('\\end{enumerate}') cor.append('\\end{enumerate}') def Perpendiculaires(): exo = ["\\exercice", _(u"Réaliser les figures suivantes :\\par"), '\\begin{multicols}{2}'] cor = ["\\exercice*", _(u"Réaliser les figures suivantes :\\par"), '\\begin{multicols}{2}'] quiz = [u"cloze"] enonce_perp(exo, cor, quiz) exo.append('\\columnbreak') cor.append('\\columnbreak') enonce_perp(exo, cor, quiz) exo.append('\\end{multicols}') cor.append('\\end{multicols}') return (exo, cor, quiz) #------------------------------------------------------------------------------ # Propriétés #------------------------------------------------------------------------------ def fonction(angle, xa, ya, dist=0, droite='par'): """ Retourne une fonction à utiliser avec psplot @param angle: compris entre 1 et 89° ou 91 et 179°. Angle entre la droite et l'axe des abscisses @type angle: @param xa: abscisse d'un point de la droite @type xa: @param ya: ordonnée d'un point de la droite @type ya: @param dist: distance entre l'origine et la droite @type dist: @param droite: 'par' pour une parallèle et 'per' pour une perpendiculaire """ angle_rad = (angle * math.pi) / 180 if droite == 'par': coef = math.floor(math.tan(angle_rad) * 1000) / 1000.0 ord_or = math.floor(((ya - xa * math.tan(angle_rad)) - dist / math.cos(angle_rad)) * 1000) / 1000.0 return '{x %s mul %s add}' % (coef, ord_or) else: coef = math.floor(-1000 / math.tan(angle_rad)) / 1000.0 return '{x %s mul}' % coef def PointInter(angle, xa, ya, dist=0): angle_rad = (angle * math.pi) / 180 coef1 = math.floor(math.tan(angle_rad) * 1000) / 1000.0 ord_or1 = math.floor(((ya - xa * math.tan(angle_rad)) - dist / math.cos(angle_rad)) * 1000) / 1000.0 coef2 = math.floor(-1000 / math.tan(angle_rad)) / 1000.0 x = ord_or1 / (coef2 - coef1) y = x * coef2 return ',PosAngle=%s](%s,%s)' % (45 + angle, math.floor(x * 1000) / 1000.0, math.floor(y * 1000) / 1000.0) def Points(angle, xa, ya, dist=0): angle_rad = (angle * math.pi) / 180 coef = math.floor(math.tan(angle_rad) * 1000) / 1000.0 ord_or = math.floor(((ya - xa * math.tan(angle_rad)) - dist / math.cos(angle_rad)) * 1000) / 1000.0 lpos = [] if -1.5 < -2 * coef + ord_or < 1.5: x = -1.5 y = math.floor((x * coef + ord_or) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) if -1.5 < 2 * coef + ord_or < 1.5: x = 1.5 y = math.floor((x * coef + ord_or) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) if -2.1 < (1.5 - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / \ math.tan(angle_rad) < 2.1: y = 1.1 x = math.floor(((y - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / math.tan(angle_rad)) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) if -2.1 < (-1.5 - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / \ math.tan(angle_rad) < 2.1: y = -1.1 x = math.floor(((y - ya + dist / math.cos(angle_rad) + xa * math.tan(angle_rad)) / math.tan(angle_rad)) * 1000) / 1000.0 lpos.append('(%s,%s)' % (x, y)) return lpos def figure(angle, xa, ya, dist, lpoints, noms, par_per, dist2=0): """ @param angle: @param xa: @param ya: @param dist: @param lpoints: @param noms: 1: nomme la droite (AB) 2: nomme la droite (d1) @param par_per: 1: parallèles + perpendiculaires 2: 3 parallèles 3: 2 perpendiculaires """ ltxt = [] ltxt.append('\\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6)') ltxt.append('\\footnotesize') if par_per < 3: ltxt.append('\\psplot[linewidth=1.5\\pslinewidth]{-2.1}{2.1}%s' % fonction(angle, xa, ya)) ltxt.append('\\psplot[linewidth=1.5\\pslinewidth]{-2.1}{2.1}%s' % fonction(angle, xa, ya, dist)) else: ltxt.append('\\psplot{-2.1}{2.1}%s' % fonction(angle, xa, ya)) ltxt.append('\\psplot{-2.1}{2.1}%s' % fonction(angle, xa, ya, dist)) if par_per == 2: ltxt.append('\\psplot[linewidth=1.5\\pslinewidth]{-2.1}{2.1}%s' % fonction(angle, xa, ya, dist2)) else: ltxt.append('\\psplot{-2.1}{2.1}%s' % fonction(angle, xa, ya, droite='per')) if noms: #nomme les droites par deux points if par_per != 2: #2 points d'intersection ltxt.append('\\pstGeonode[PointSymbol={none,x},PointName={%s,%s} %s{i1}%s{a1}' % (lpoints[0], lpoints[1], PointInter(angle, xa, ya), Points(angle, xa, ya)[0])) ltxt.append('\\pstGeonode[PointSymbol={none,x},PointName={%s,%s} %s{i2}%s{b1}' % (lpoints[2], lpoints[3], PointInter(angle, xa, ya, dist), Points(angle, xa, ya, dist)[0])) ltxt.append('\\pstGeonode[PointSymbol=none,PointName=none]%s{c1}%s{c2}' % (Points(angle + 90, 0, 0)[0], Points(angle + 90, 0, 0)[1])) else: #pas de point d'intersection pts = Points(angle, xa, ya) ltxt.append('\\pstGeonode[PointSymbol=x,PosAngle=%s,PointName={%s,%s}]%s{a1}%s{a2}' % (angle + 45, lpoints[0], lpoints[1], pts[0], pts[1])) pts = Points(angle, xa, ya, dist) ltxt.append('\\pstGeonode[PointSymbol=x,PosAngle=%s,PointName={%s,%s}]%s{b1}%s{b2}' % (angle - (45.0 * dist) / abs(dist), lpoints[2], lpoints[3], pts[0], pts[1])) pts = Points(angle, xa, ya, dist2) ltxt.append('\\pstGeonode[PointSymbol=x,PosAngle=%s,PointName={%s,%s}]%s{c1}%s{c2}' % (angle - (45.0 * dist2) / abs(dist2), lpoints[4], lpoints[5], pts[0], pts[1])) else: #nomme les droites (d_1), ... if par_per != 2: #2 points d'intersection ltxt.append('\\pstGeonode[PointSymbol=none,PointName={none,%s} %s{i1}%s{a1}' % (lpoints[0], PointInter(angle, xa, ya), Points(angle, xa, ya)[0])) ltxt.append('\\pstGeonode[PointSymbol=none,PointName={none,%s} %s{i2}%s{b1}' % (lpoints[1], PointInter(angle, xa, ya, dist), Points(angle, xa, ya, dist)[0])) ltxt.append('\\pstGeonode[PointSymbol=none,PointName={none,%s}]%s{c1}%s{c2}' % (lpoints[2], Points(angle + 90, 0, 0)[0], Points(angle + 90, 0, 0)[1])) else: pts = Points(angle, xa, ya) ltxt.append('\\pstGeonode[PointSymbol=none,PosAngle=%s,PointName={%s,none}]%s{a1}%s{a2}' % (angle + 45, lpoints[0], pts[0], pts[1])) pts = Points(angle, xa, ya, dist) ltxt.append('\\pstGeonode[PointSymbol=none,PosAngle=%s,PointName={%s,none}]%s{b1}%s{b2}' % (angle - (45.0 * dist) / abs(dist), lpoints[1], pts[0], pts[1])) #FIXME list index out of range pts = Points(angle, xa, ya, dist2) ltxt.append('\\pstGeonode[PointSymbol=none,PosAngle=%s,PointName={%s,none}]%s{c1}%s{c2}' % (angle - (45.0 * dist2) / abs(dist2), lpoints[2], pts[0], pts[1])) if par_per != 2: if angle < 90: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c1}{i1}{a1}') else: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c2}{i1}{a1}') if par_per == 3: if angle < 90: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c1}{i2}{b1}') else: ltxt.append('\\pstRightAngle[RightAngleSize=.2]{c2}{i2}{b1}') ltxt.append('\\end{pspicture*}') return ltxt def valeurs_figures(par_per): noms = random.randrange(2) if noms: lpoints = noms_sommets(6) else: lindices = [1, 2, 3] lpoints = [] for i in range(3): lpoints.append('(d_%s)' % lindices.pop(random.randrange(len(lindices)))) angle = random.randrange(1, 90) + 90 * random.randrange(2) xa = random.randrange(-5, 5) / 10.0 ya = random.randrange(-3, 3) / 10.0 if random.randrange(2): dist = random.randrange(4, 9) / 10.0 else: dist = -random.randrange(4, 9) / 10.0 if par_per == 2: if dist > 0: dist2 = -random.randrange(4, 9) / 10.0 else: dist2 = random.randrange(4, 9) / 10.0 return (angle, xa, ya, dist, lpoints, noms, dist2) else: return (angle, xa, ya, dist, lpoints, noms) def enonce_prop(exo, cor, quiz): exo.append('\\renewcommand{\\tabularxcolumn}[1]{m{#1}}') exo.append('\\begin{tabularx}{\\textwidth}[t]{|m{3cm}|m{4cm}|X|m{3cm}|}') exo.append('\\hline') exo.append(_(u'\\multicolumn{1}{|c|}{\\bf Données} & \\multicolumn{1}{|c|}{\\bf Figure codée}')) exo.append(_(u'& \\multicolumn{1}{|c|}{\\bf Propriété} & \\multicolumn{1}{|c|}{\\bf Conclusion}\\\\')) cor.append('\\renewcommand{\\tabularxcolumn}[1]{m{#1}}') cor.append('\\begin{tabularx}{\\textwidth}[t]{|m{3cm}|m{4cm}|X|m{3cm}|}') cor.append('\\hline') cor.append(_(u'\\multicolumn{1}{|c|}{\\bf Données} & \\multicolumn{1}{|c|}{\\bf Figure codée}')) cor.append(_(u'& \\multicolumn{1}{|c|}{\\bf Propriété} & \\multicolumn{1}{|c|}{\\bf Conclusion}\\\\')) ltypes = [1, 2, 3] lexos = [] for i in range(3): lexos.append(ltypes.pop(random.randrange(len(ltypes)))) for i in range(3): exo.append('\\hline') cor.append('\\hline') v = valeurs_figures(lexos[i]) if lexos[i] == 2: if v[5]: #noms de la forme (AB), on ajoute des parenthèses exo.append(_(u'''$(%s%s)//(%s%s)$\\par et\\par $(%s%s)//(%s%s)$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''') % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][4], v[4][5])) cor.append(_(u'$(%s%s)//(%s%s)$\\par et\\par $(%s%s)//(%s%s)$ & ') % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][4], v[4][5])) quiz_nom = _(u'Propriété de la droite') quiz_exo = _(u"Complète la phrase:\n") quiz_exo += (_(u'Se tient trois droites: $$(%s%s)//(%s%s)$$ et $$(%s%s)//(%s%s)$$\n') % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][4], v[4][5])) else: exo.append(_(u'''$%s//%s$\\par et\\par $%s//%s$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''') % (v[4][0], v[4][1], v[4][0], v[4][2])) cor.append(_(u'$%s//%s$\\par et\\par $%s//%s$ & ') % (v[4][0], v[4][1], v[4][0], v[4][2])) quiz_nom = _(u'Propriété de la droite') quiz_exo = _(u"Complète la phrase:\n") quiz_exo += (_(u'Si se tient trois droites: $$%s//%s$$ et $$%s//%s$$\n') % (v[4][0], v[4][1], v[4][0], v[4][2])) cor.append('%s & ' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i], v[6])))#eror out of range in figure cor.append(_(u'Si deux droites sont parallèles, alors toute parallèle à l\'une est parallèle à l\'autre. &')) quiz_exo += (_(u'Utilisant la propriété: \"Si deux droites sont parallèles, alors toute parallèle à l\'une est parallèle à l\'autre.\"\n')) if v[5]: cor.append('$(%s%s)//(%s%s)$ \\\\\n \\hline' % (v[4][2], v[4][3], v[4][4], v[4][5])) quiz_exo += (_(u'On déduit que les droites $$(%s%s)$$ et $$(%s%s)$$ sont _____ ') % (v[4][2], v[4][3], v[4][4], v[4][5])) quiz_cor = _(u'parallèles') else: cor.append('$%s//%s$ \\\\\n \\hline' % (v[4][1], v[4][2])) quiz_exo += (_(u'On déduit que les droites $$%s$$ et $$%s$$ sont _____ ') % (v[4][1], v[4][2])) quiz_cor = _(u'parallèles') quiz.append([quiz_nom, quiz_exo, quiz_cor]) else: fig = random.randrange(2) if lexos[i] == 1: if v[5]: if not fig: exo.append(_(u'''$(%s%s)//(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''') % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][0], v[4][2])) cor.append(_(u'$(%s%s)//(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ &') % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][0], v[4][2])) quiz_nom = _(u'Propriété de la droite') quiz_exo = _(u"Complète la phrase:\n") quiz_exo += (_(u'Se tient trois droites: $$(%s%s)//(%s%s)$$ et $$(%s%s)\\perp(%s%s)$$\n') % (v[4][0], v[4][1], v[4][2], v[4][3], v[4][0], v[4][1], v[4][0], v[4][2])) else: if not fig: exo.append(_(u'''$%s//%s$\\par et\\par $%s\perp%s$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''') % (v[4][0], v[4][1], v[4][0], v[4][2])) cor.append(_(u'$%s//%s$\\par et\\par $%s\perp%s$ &') % (v[4][0], v[4][1], v[4][0], v[4][2])) quiz_nom = _(u'Propriété de la droite') quiz_exo = _(u"Complète la phrase:\n") quiz_exo += (_(u'Se tient trois droites: $$%s//%s$$ et $$%s\\perp %s$$\n') % (v[4][0], v[4][1], v[4][0], v[4][2])) if fig: exo.append('& %s & & \\\\' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append('%s & ' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append(_(u'Si deux droites sont parallèles, alors toute perpendiculaire à l\'une est perpendiculaire à l\'autre. &')) quiz_exo += (_(u'Utilisant la propriété: \"Si deux droites sont parallèles, alors toute perpendiculaire à l\'une est perpendiculaire à l\'autre.\"\n')) if v[5]: cor.append('$(%s%s)\\perp(%s%s)$ \\\\\n \\hline' % (v[4][2], v[4][3], v[4][0], v[4][2])) quiz_exo += (_(u'On déduit que les droites $$(%s%s)$$ et $$(%s%s)$$ sont _____ ') % (v[4][2], v[4][3], v[4][0], v[4][2])) quiz_cor = _(u'perpendiculaires') else: cor.append('$%s\perp%s$ \\\\\n \\hline' % (v[4][1], v[4][2])) quiz_exo += (_(u'On déduit que les droites $$%s$$ et $$%s$$ sont _____ ') % (v[4][1],v[4][2])) quiz_cor = _(u'perpendiculaires') quiz.append([quiz_nom, quiz_exo, quiz_cor]) else: if v[5]: if not fig: exo.append(_(u'''$(%s%s)\\perp(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''') % (v[4][0], v[4][1], v[4][0], v[4][2], v[4][2], v[4][3], v[4][0], v[4][2])) cor.append(_(u'$(%s%s)\\perp(%s%s)$\\par et\\par $(%s%s)\\perp(%s%s)$ &') % (v[4][0], v[4][1], v[4][0], v[4][2], v[4][2], v[4][3], v[4][0], v[4][2])) quiz_nom = _(u'Propriété de la droite') quiz_exo = _(u"Complète la phrase:\n") quiz_exo += (_(u'Se tient trois droites: $$(%s%s)\\perp(%s%s)$$ et $$(%s%s)\\perp(%s%s)$$\n') % (v[4][0], v[4][1], v[4][0], v[4][2], v[4][2], v[4][3], v[4][0], v[4][2])) else: if not fig: exo.append(_(u'''$%s\\perp%s$\\par et\\par $%s\perp%s$ & \\begin{pspicture*}[shift=-1.5](-2.1,-1.6)(2.1,1.6) \\end{pspicture*} & & \\\\''') % (v[4][0], v[4][2], v[4][1], v[4][2])) cor.append(_(u'$%s\\perp%s$\\par et\\par $%s\perp%s$ &') % (v[4][0], v[4][2], v[4][1], v[4][2])) quiz_nom = _(u'Propriété de la droite') quiz_exo = _(u"Complète la phrase:\n") quiz_exo += (_(u'Se tient trois droites: $$%s\\perp %s$$ et $$%s\\perp %s$$\n') % (v[4][0], v[4][2], v[4][1], v[4][2])) if fig: exo.append('& %s & & \\\\' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append('%s &' % ('\n').join(figure(v[0], v[1], v[2], v[3], v[4], v[5], lexos[i]))) cor.append(_(u'Si deux droites sont perpendiculaires à une même troisième alors elles sont parallèles entre elles. &')) quiz_exo += (_(u'Utilisant la propriété: \"Si deux droites sont perpendiculaires à une même troisième alors elles sont parallèles entre elles.\"\n')) if v[5]: cor.append('$(%s%s)//(%s%s)$ \\\\\n \\hline' % (v[4][0], v[4][1], v[4][2], v[4][3])) quiz_exo += (_(u'On déduit que les droites $$(%s%s)$$ et $$(%s%s)$$ sont _____ ') % (v[4][0], v[4][1], v[4][2], v[4][3])) quiz_cor = _(u'parallèles') else: cor.append('$%s//%s$ \\\\\n \\hline' % (v[4][0], v[4][1])) quiz_exo += (_(u'On déduit que les droites $$%s$$ et $$%s$$ sont _____ ') % (v[4][0], v[4][1])) quiz_cor = _(u'parallèles') quiz.append([quiz_nom, quiz_exo, quiz_cor]) exo.append('''\\hline \\end{tabularx} ''') cor.append('\\end{tabularx}') def Proprietes(): exo = ["\\exercice", _(u"Compléter le tableau suivant :\\par Les droites en gras sont parallèles.\\par ")] cor = ["\\exercice*", _(u"Compléter le tableau suivant :\\par Les droites en gras sont parallèles.\\par ")] quiz = [u"shortanswer"] enonce_prop(exo, cor, quiz) return (exo, cor, quiz)