Commit 6417e6cb authored by Olivier Cornu's avatar Olivier Cornu
Browse files

Introduit les classes d'exercices.

parent 33a93465
......@@ -73,51 +73,7 @@ ICONDIR = icon_dir()
HOME = home()
CONFIGDIR = configdir()
def _exercices(pkg):
''' Discover package exercises. '''
exercices = []
# search package modules
for _, name, ispkg in pkgutil.iter_modules(pkg.__path__, pkg.__name__+'.'):
# skip sub-packages (discovery is not recursive)
if ispkg: continue
# import discovered module
module = __import__(name, fromlist=pkg.__name__)
# search module for exercises: functions with a 'description' attribute
# of UnicodeType
for element in dir(module):
# list module elements
element = module.__dict__[element]
if not type(element) is types.FunctionType: continue
if 'description' not in dir(element): continue
description = element.__dict__['description']
if not isinstance(description, basestring): continue
# store discovered exercise
exercices.append(element)
return exercices
def _packages(pkg):
''' Discover all packages located in pkg. '''
packages = []
# search packages
for _, name, ispkg in pkgutil.iter_modules(pkg.__path__, pkg.__name__+'.'):
# skip modules
if not ispkg: continue
# import discovered package
package = __import__(name, fromlist=pkg.__name__)
# exercise packages must have a description property
if 'description' not in dir(package): continue
description = package.__dict__['description']
# description property must be a string
if not isinstance(description, basestring): continue
# valid exercise package
packages.append(package)
return packages
# Packages d'exercices
PACKAGES = _packages(ex)
LESFICHES = []
for pkg in PACKAGES:
pkg.EXERCICES = _exercices(pkg)
titles = [ex.description for ex in pkg.EXERCICES]
LESFICHES.append([pkg.description, '', titles])
ex.load()
for level, exercices in ex.levels.iteritems():
LESFICHES.append([level, '', exercices])
import os
import types
import pkgutil
levels = {}
class Exercise(object):
''' Base class for all exercise types. '''
description = u'Description'
levels = u'Academic level'
thumb = 'path/to/thumbnail.png'
def __str__(self):
return self.description
class TexExercise(Exercise):
''' Exercise with TeX support. '''
def tex_statement(self):
''' Return problem statement in TeX format. '''
raise NotImplementedError()
return ["\\exercice TODO"]
def tex_answer(self):
''' Return full answer in TeX format. '''
return ["\\exercice* TODO"]
class __LegacyExercise(TexExercise):
''' Base class for legacy format exercise proxies. '''
_id = 0
function = []
def __init__(self):
self.stat, self.ans = self.function[0]()
def tex_statement(self):
return self.stat
def tex_answer(self):
return self.ans
def __legacy(path, i, function):
''' Create a new class proxying for a legacy exercise 'function'. '''
__LegacyExercise._id += 1
# Create a proxy class inheriting from LegacyExercise for this function
return type('LegacyExercise%u' % __LegacyExercise._id,
(__LegacyExercise,),
dict(description=function.description,
levels=function.level,
thumb=os.path.join(path, 'img', 'ex-%02d.png' % i),
function=(function,),
)
)
def __isfunction(obj):
''' Is 'obj' a function? '''
return type(obj) is types.FunctionType
def __hasdescription(obj):
''' Has 'obj' a legit description? '''
if 'description' not in dir(obj): return False
description = obj.__dict__['description']
# description must be some kind of string (preferably unicode)
if not isinstance(description, basestring): return False
return True
def __isexercise(obj):
''' Is target object an exercise in legacy format? '''
return __isfunction(obj) and __hasdescription(obj)
def __levels(level):
''' Format academic level(s). '''
# level may be a string or a list (default)
if not isinstance(level, list): level = [level]
return level
def __import(name=__name__, parent=None):
''' Import 'name' from 'parent' package. '''
if not isinstance(name, basestring):
name = name.__name__
# parent is None: assume 'name' is a package name
if parent is None: parent = name
elif not isinstance(parent, basestring):
# assume 'parent' is a package instance
parent = parent.__name__
return __import__(name, fromlist=parent)
def _exercises(pkg):
''' List exercises in 'pkg' modules. '''
# level defaults to description, then unknown
if 'level' not in dir(pkg): pkg.level = u"Inconnu"
n = 0
for _, name, ispkg in pkgutil.iter_modules(pkg.__path__, pkg.__name__+'.'):
# skip packages
if ispkg: continue;
# import module
mod = __import(name, pkg)
if 'level' not in dir(mod): mod.level = pkg.level
for element in dir(mod):
element = mod.__dict__[element]
if not __isexercise(element): continue
# found an exercise: work out what level it is
element.level = __levels(element.level if 'level' in dir(element)
else mod.level)
yield __legacy(pkg.__path__[0], n, element)
n+=1
def _subpackages(pkg):
''' List 'pkg' sub-packages. '''
for _, name, ispkg in pkgutil.iter_modules(pkg.__path__, pkg.__name__+'.'):
# skip modules
if not ispkg: continue;
yield __import(name, pkg)
def load(pkg=None, recursive=True):
''' Discover exercises. '''
# target package defaults to this package (pyromaths.ex)
if pkg is None: pkg = __import()
# load package exercises
for ex in _exercises(pkg):
for lvl in ex.levels:
# new level? create its exercise list
if lvl not in levels.keys(): levels[lvl] = []
levels[lvl].append(ex)
if not recursive: return
# load sub-packages
for pk in _subpackages(pkg): load(pk)
......@@ -256,7 +256,7 @@ def exo_variation():
return exo,cor
exo_variation.description = u"Sens de variations"
exo_variation.level = u"1èreS, Term STG"
exo_variation.level = [u"1èreS", u"Term STG"]
def exo_variation_lim():
......
......@@ -23,7 +23,7 @@
from PyQt4 import QtGui, QtCore
import os, lxml, codecs, sys
from outils import System
from Values import HOME, CONFIGDIR, DATADIR, PACKAGES, LESFICHES, COPYRIGHTS, VERSION, ICONDIR
from Values import HOME, CONFIGDIR, DATADIR, LESFICHES, COPYRIGHTS, VERSION, ICONDIR
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
......@@ -89,8 +89,8 @@ class Ui_MainWindow(object):
#============================================================
self.tabs = []
for pkg_no in range(len(PACKAGES)):
self.tabs.append(Tab(self.tabWidget, pkg_no, self.setNbExos))
for level in LESFICHES:
self.tabs.append(Tab(self.tabWidget, level, self.setNbExos))
#============================================================
# Onglet options
......@@ -449,13 +449,14 @@ class Ui_MainWindow(object):
for i in range(len(self.liste_creation)):
niveau = self.liste_creation[i][0]
exo = self.liste_creation[i][1]
list.append("%se: %s" % (6-niveau, LESFICHES[niveau][2][exo]))
list.append(LESFICHES[niveau][2][exo])
self.List=QtGui.QListWidget()
for i in range(len(list)):
item = QtGui.QListWidgetItem(list[i])
item = QtGui.QListWidgetItem(list[i].description)
item.setFlags(QtCore.Qt.ItemIsEnabled |
QtCore.Qt.ItemIsSelectable |
QtCore.Qt.ItemIsDragEnabled)
item.exercice = list[i]
self.List.addItem(item)
bmono=True
for i in range(len(list)):
......@@ -651,14 +652,9 @@ def valide(list, LesFiches, parametres):
""" Permet de choisir les noms et emplacements des fichiers tex, les écrits
et lance la compilation LaTex"""
corrige = parametres['corrige']
l=[]
lesexos = []
for i in range(list.count()):
l.append(unicode(list.item(i).text()))
for text in l:
niveau = 6 - int(text[0])
pos = LesFiches[niveau][2].index(text[4:])
lesexos.append((niveau, pos))
lesexos.append(list.item(i).exercice())
#============================================================
# Choix des noms des fichiers exercices et corrigés
......@@ -695,11 +691,10 @@ def valide(list, LesFiches, parametres):
class Tab(QtGui.QWidget):
"""Gère les onglets permettant de sélectionner des exercices"""
def __init__(self, parent, pkg_no, onchange):
def __init__(self, parent, level, onchange):
QtGui.QWidget.__init__(self) # Initialise la super-classe
self.pkg = PACKAGES[pkg_no]
self.titre = self.pkg.description
self.exos = LESFICHES[pkg_no][2]
self.titre = level[0]
self.exos = level[2]
self.layout = QtGui.QGridLayout(self)
self.spinBox = []
# Crée les widgets des exercices
......@@ -732,13 +727,11 @@ class Tab(QtGui.QWidget):
img = QtGui.QLabel(self)
img.setText(r'<img src="%s"/>' %
os.path.join(DATADIR, 'images', 'whatsthis.png'))
img.setToolTip(r'<img src="%s"/>' %
os.path.join(self.pkg.__path__[0], 'img',
'ex-%02d.png' % i))
img.setToolTip(r'<img src="%s"/>' % self.exos[i].thumb)
layout.addWidget(img)
# Label
label = QtGui.QLabel(self)
label.setText(self.exos[i])
label.setText(self.exos[i].description)
layout.addWidget(label)
# Espacements
spacer = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
......
......@@ -26,7 +26,7 @@ from lxml import etree
from lxml import _elementpath as DONTUSE # Astuce pour inclure lxml dans Py2exe
from re import findall
from .TexFiles import mise_en_forme
from pyromaths.Values import HOME, VERSION, CONFIGDIR, PACKAGES
from pyromaths.Values import HOME, VERSION, CONFIGDIR
#==============================================================
......@@ -156,15 +156,11 @@ def creation(parametres):
copie_tronq_modele(f1, parametres, 'entete')
for exercice in parametres['liste_exos']:
pkg_no = exercice[0]
ex_no = exercice[1]
# get exercise's TeX code (question & answer)
enonce, correction = PACKAGES[pkg_no].EXERCICES[ex_no]()
# write to files
# write exercise's TeX code (question & answer) to files
f0.write("\n")
f0.writelines(line + "\n" for line in enonce)
f0.writelines(line + "\n" for line in exercice.tex_statement())
f1.write("\n")
f1.writelines(line + "\n" for line in correction)
f1.writelines(line + "\n" for line in exercice.tex_answer())
if parametres['creer_pdf']:
......
......@@ -74,8 +74,8 @@ elif (len(sys.argv) == 1):
parametres['fiche_cor'] = os.path.join(dt, 'exercices-corrige.tex')
lst = []
for n in range(len(LESFICHES)):
for i in range(len(LESFICHES[n][2])):
lst.append([n,i])
for exo in LESFICHES[n][2]:
lst.append(exo())
parametres['liste_exos'] = lst
creation(parametres)
nettoyage(dt)
......
......@@ -5,11 +5,11 @@ from os.path import dirname, normpath, join, abspath, realpath, split
_path = normpath(join(abspath(dirname(__file__)), "../src"))
sys.path[0] = realpath(_path)
from pyromaths import pyromaths
from pyromaths import pyromaths, ex
#datadir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
#sys.path.append(datadir)
from pyromaths.Values import PACKAGES, LESFICHES, data_dir, configdir
from pyromaths.Values import data_dir, configdir, LESFICHES
from pyromaths.outils.System import creation
from subprocess import call, Popen
......@@ -45,21 +45,30 @@ parametres = {
'openpdf': 0,
}
#for n in range(1):
#for i in range(1):
for n in range(len(PACKAGES)):
pkg = PACKAGES[n]
imgdir = join(pkg.__path__[0], "img")
for i in range(len(LESFICHES[n][2])):
lst = [[n, i]]
parametres['liste_exos'] = lst
creation(parametres)
call(["convert", "-density", "288", "/tmp/test.pdf", "-resize", "25%",
"-crop", "710x560+0+85", "-flatten", "-trim", "/tmp/ex-%02d.png" % i],
def __thumb(exercise, imgdir, i):
parametres['liste_exos'] = [exercise()]
creation(parametres)
call(["convert", "-density", "288", "/tmp/test.pdf", "-resize", "25%",
"-crop", "710x560+0+85", "-flatten", "-trim", "/tmp/ex-%02d.png" % i],
stdout=log)
call(["pngnq", "-f", "-s1", "-n32", "/tmp/ex-%02d.png" % i],
stdout=log)
call(["pngnq", "-f", "-s1", "-n32", "/tmp/ex-%02d.png" % i],
stdout=log)
shutil.copyfile( "/tmp/ex-%02d-nq8.png" % i, "%s/ex-%02d.png" % (imgdir, i))
Popen(args=["optipng", "-o7", "%s/ex-%02d.png" % (imgdir, i)])
shutil.copyfile( "/tmp/ex-%02d-nq8.png" % i, "%s/ex-%02d.png" % (imgdir, i))
Popen(args=["optipng", "-o7", "%s/ex-%02d.png" % (imgdir, i)])
def __thumbs(pkg):
imgdir = join(pkg.__path__[0], "img")
i = 0
for e in ex._exercises(pkg):
__thumb(e, imgdir, i)
i += 1
def thumbs(pkg=ex, recursive=True):
__thumbs(pkg)
if not recursive: return
for pk in ex._subpackages(pkg):
thumbs(pk)
thumbs()
log.close()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment