David Madore's WebLog: Copies, tableurs, mails, et autres crottes de ragondin

Index of all entries / Index de toutes les entréesXML (RSS 1.0) • Recent comments / Commentaires récents

↓Entry #2495 [older| permalink|newer] / ↓Entrée #2495 [précédente| permalien|suivante] ↓

(vendredi)

Copies, tableurs, mails, et autres crottes de ragondin

J'avais raconté l'an dernier comment je corrige des copies, et ce n'est pas un hasard si je reviens sur un sujet proche à peu près un an plus tard.

En gros, ma méthode est la suivante : ouvrir un tableur avec une ligne par copie (= par élève, λ), une colonne par question du contrôle (i) ; et remplir chaque case avec un nombre réel xλ,i entre 0 (question complètement fausse ou non traitée) et 1 (question traitée de façon parfaitement satisfaisante). Puis décider d'un barème, c'est-à-dire un poids pi pour chaque question : a priori la note (Nλ de la copie λ) est la somme des xλ,j pondérée par les pj, c'est-à-dire Nλ := ∑j(pj·xλ,j) ; sauf qu'en fait, j'ai envie de pouvoir ajuster plus commodément le coefficient multiplicatif : donc au lieu que pi soit directement le nombre de points sur lequel est notée la question i, ça va être un poids relatif, je choisis un total Nmax sur lequel est noté le contrôle, et j'applique la formule Nλ := Nmax·∑j(pj·xλ,j)/∑j(pj). Traditionnellement, en France, les notes sont exprimées sur 20, mais Nmax peut prendre une autre valeur, par exemple quand le sujet était trop long et qu'on n'exige pas de tout traiter pour obtenir la note maximale, je mettrai Nmax à 21, 22 ou plus. Le fait de choisir indépendamment Nmax et les pj signifie que je peux ajuster librement le poids relatif des questions (typiquement pj vaudra 1 pour une question « normale », 0.5 pour une question simple et facile, 1.5 pour une question plus complexe, 2 pour une question particulièrement longue et discriminante… si le poids devient plus grand que ça, je vais généralement subdiviser la question en plusieurs sous-questions) sans avoir à me préoccuper d'arriver au bon total : la question i sera notée, au final, sur Nmax·pi/∑j(pj), et tant pis si je me retrouve avec un exercice noté sur, disons, 7.737 et deux sur 6.632.

L'avantage de ce système est que je n'ai pas le carcan d'une granularité du point, demi-point ou quart de point. Pour chaque question je me fais un sous-barème mental (du genre : ici, une réponse correcte mais non justifiée vaudra 0.6, c'est-à-dire 60% de la valeur de la question ; dans tel ou tel raisonnement, une bonne idée qui n'aboutit pas peut valoir 0.2, ou 0.4, ou selon ce que j'estime qu'il vaut). Au final, mes notes sont des rationnels essentiellement arbitraires que j'arrondis à 0.1 point par excès avant de les envoyer à l'administration.

Tout cela est assez facile à faire avec LibreOffice : disons que j'inscris les notes xλ,i entre 0 et 1 dans les lignes 2 à 32, colonnes D à R d'un tableur (la ligne 1 contient les intitulés des colonnes, les colonnes A à C me servant typiquement à entrer le nom et prénom, et un 1 si l'élève était effectivement présent) ; je mets le barème pj dans la ligne 34 (cellules D34 à R34), la note maximal théorique Nmax dans la case S33, et la note dans la ligne λ de la colonne S sera calculée par la formule =SUMPRODUCT($Dλ:$Rλ,$D$34:$R$34)/SUM($D$34:$R$34)*$S$33 (copiée-collée dans toutes cellules S2 à S32).

Je n'aime pas la manière dont les tableurs incitent à faire travailler avec des numéros de ligne et des lettres de colonne explicites, et obligent à tout stocker dans des cellules d'une structure 2d, on se croirait à l'époque du BASIC où il fallait numéroter les lignes de programme. Il est vrai qu'il y a des moyens d'éviter ça au moins partiellement (on peut donner des noms symboliques à des cellules ou groupes de cellules) et j'avoue que je n'ai pas fait l'effort d'apprendre à m'en servir. Mais ce que je déteste particulièrement avec les tableurs, en fait, c'est surtout la manière dont on se retrouve à reproduire les formules à coup de copier-coller, parfois on cible mal le copier-coller (on sélectionne une ligne de moins en haut ou en bas, ou pas le bon ensemble de feuilles) et du coup la formule d'une cellule n'est pas changée avec toutes les autres et il y a un risque important de ne pas s'en apercevoir parce que toute la colonne est censée être uniforme. Et je déteste aussi le fait qu'on doive marquer tout ce qui est « absolu » par un $ alors que, dans ce que je manipule, il y a typiquement beaucoup plus de références lignes et colonnes absolues que relatives.

Ce que j'ai décrit, là, c'est la manière dont j'utilise un tableur quand je suis tout seul (je pourrais tout aussi bien utiliser un format de données personnel, mais ça n'aurait pas grand intérêt puisque, justement, dans ce cadre-là, les tableurs ne sont pas encore trop pénibles). Là où les choses deviennent plus lourdingues, c'est quand je dois coordonner plusieurs correcteurs, ce qui est cas pour un cours dont j'avais signalé le poly ici. Je crée un tableau avec une feuille par correcteur selon le modèle décrit ci-dessus, et chacun remplit les xλ,i (entre 0 et 1) pour ses copies. Déjà c'est plus pénible, parce que la gestion des feuilles, elle n'est pas aussi commode que celle des lignes et des colonnes (qui est déjà perfectible) : plus d'une fois je me suis retrouvé à faire accidentellement des modifications sur toutes les feuilles à la fois alors que je voulais les faire sur une seule, ou le contraire.

Certains de mes collègues utilisent un tableur Microsoft (je suppose que c'est Excel), donc je dois prier pour que l'import sous LibreOffice fonctionne correctement : pour juste des nombres, ça marche, mais pour les formules, je suis déjà plus méfiant. Par ailleurs, les cases d'un tableur viennent aussi avec des réglages de polices, tailles, couleurs et autres bizarreries que je ne comprends pas bien, qu'il me faut ensuite expurger (ou penser à demander de ne pas recopier). Voilà autre chose que je déteste : le mélange complètement bizarre entre le fond (les quantités dans le tableau) et la forme (la manière dont elles peuvent être formatées : dans certains cas, ça peut avoir un sens de considérer que ça fait partie du fond, mais, justement, le tableur ne semble pas permettre de distinguer ça proprement).

Un cas montrant à quel point tout ça est dangereux. Un de mes collègues m'a rendu un tableau dont les moyennes étaient particulièrement basses, et j'ai remarqué que les nombres étaient alignés bizarrement. En regardant de plus près, j'ai compris que les nombres comme 0.7 étaient considérés comme du texte (comme la chaîne de caractère 0.7) et pas comme des nombres (le réel 7/10), et comptaient comme zéro dans toutes les formules ; et ceci s'appliquait à tout nombre non-entier : autrement dit, le tableur avait effectivement transformé en zéro toutes les notes strictement comprises entre 0 et 1 mises par mon collègue à une question ! Des élèves auraient pu être lourdement pénalisés par une misfeature logicielle stupide.

Je suppose que la raison est qu'à un moment ou un autre, LibreOffice a décidé qu'il était en français et que le séparateur décimal en français est la virgule et pas le point.

Je digresse pour ranter à ce sujet. La seule convention qui fait sens est de considérer que la virgule ET le point sont tous les deux des séparateurs décimaux valables, quelle que soit la langue : c'est la position normalisée par la 22e Convention Générale des Poids et Mesures (résolution 10) et par le standard ISO 31-0 (après amendement 2) ; et c'est surtout la seule position conforme au principe de Postel. (Pour des raisons analogues, le séparateur de milliers doit être soit absent soit une espace insécable fine, mais en aucun cas une virgule ni autre chose.) Personnellement, j'ai pris l'habitude de systématiquement utiliser le point dans un contexte informatique (parce que la plupart des langages informatiques l'exigent et que ça simplifie le copier-coller), et la virgule quand j'écris à la main (parce qu'elle est plus visible que le point), et ce, que j'écrive en anglais ou en français. (De toute façon, je suis, par principe, favorable à adopter des conventions d'écriture et de typographie orthogonales aux langues dans lesquelles on écrit, mais j'ai déjà dit tout ça. Je ne sais pas pourquoi les gens ont tellement de mal à concevoir que « les deux sont permis » est la meilleure réponse possible à un grand nombre de choix de ce genre.) Toujours est-il que le programmeur qui a fait en sorte qu'un 0.7 tapé dans un tableau, fût-il en français, soit interprété comme une chaîne de caractères et pas comme le nombre réel 7/10, mérite une énorme paire de baffes. (Et méritent aussi une énorme paire de baffes ceux qui ont pondu le système de locales et qui n'ont prévu qu'un séparateur décimal et pas de mécanisme pour dire l'affichage utilisera tel séparateur, mais, en lecture, tel autre séparateur sera également accepté alors que c'est justement ce qu'imposent les standards !)

De toute façon, la gestion des nombres par LibreOffice a l'air tellement cassée et incohérente que je renonce à y comprendre quoi que ce soit. On m'a fait remarquer, par exemple, que suite à une opération de recherche-remplacement, LibreOffice réinterprète les chaînes comme des nombres si ce sont des nombres valables et que la case a effectivement été remplacée. Par exemple, si je rentre 0.7 comme chaîne de caractères (cela se fait en tapant '0.7) et que je fais une opération de recherche-remplacement globale de la chaîne 0.7 en 0.5, alors la case se transforme en nombre 0.5, bien que j'aie fait un remplacement sur des chaînes. (C'est complètement incohérent vu que, si je fais une opération de recherche-remplacement globale de la chaîne 0.7 en 0.7, évidemment, rien ne change.) C'est vraiment abominable, ça veut dire qu'il y a parfois du typage, mais parfois pas, et ce, de façon juste incohérente. Je n'ai pas cherché à comprendre plus loin.

Mais revenons à la notation de copies. Mes collègues se sont plaints, par le passé, que noter chaque question sur 1 (c'est-à-dire utiliser des réels entre 0 et 1) n'est pas très commode, parce que taper 0.25 en notant sur 1 est moins pratique que taper 1 en notant sur 4. J'ai donc ajouté une ligne à mes tableaux, disons la ligne 33, qui permet de spécifier sur combien on a noté la colonne (de façon complètement indépendante de son poids), et les nombres dans le tableau sont divisés par la ligne en question avant toute autre opération. La formule calculant la note devient alors un chouïa plus compliquée : =SUMPRODUCT(($Dλ:$Rλ)/($D$33:$R$33),$D$34:$R$34)/SUM($D$34:$R$34)*$S$33 c'est-à-dire Nλ := Nmax·∑j(pj·(xλ,j/xmax,j))/∑j(pj) en écrivant xmax,j pour le nombre sur lequel la question j a été notée. J'avoue au passage que je ne comprends pas bien les subtilités des fonctions de tableau de LibreOffice : par exemple, =SUM(Z1:Z42) somme les cellules Z1 à Z42 (disons que celles-ci contiennent des nombres), ce qui fait exactement comme =SUMPRODUCT(Z1:Z42) ; mais si on veut calculer, disons, la somme des sinus des valeurs en question, alors =SUM(SIN(Z1:Z42)) ne fonctionne pas (il renvoie #VALUE!) tandis que =SUMPRODUCT(SIN(Z1:Z42)) fonctionne : c'est probablement lié au fait que SUMPRODUCT est une fonction de tableu alors que SUM est… euh, je ne sais pas, autre chose. C'est probablement expliqué quelque part, mais en tout cas, c'est excessivement byzantin.

Bon, et quand on a plusieurs correcteurs, on peut avoir envie d'harmoniser les notes selon le principe que les correcteurs ne notent pas toujours aussi généreusement. La fonction d'harmonisation que j'ai envie de prendre est la fonction x ↦ xγ, appliquée à la note de chaque question (entre 0 et 1, donc), avec γ un réel strictement positif (et plutôt proche de 1) choisi d'autant plus grand que le correcteur est généreux, ou d'autant plus petit qu'il est sévère : l'idée est que tout le monde sera d'accord pour dire qu'une question totalement fausse vaut 0 et qu'une question parfaite vaut 1, les divergences viennent surtout des cas où on décide de mettre une partie des points. Donc l'idée serait d'appliquer cette fonction, qui fixe 0 et 1, aux notes de toutes les questions mises par un correcteur. (D'autres fonctions seraient possibles, mais celle-ci a le mérite d'être simple et standard.) Idéalement, ce qu'il faudrait faire, c'est répartir les copies aléatoirement entre les correcteurs, pour pouvoir faire l'hypothèse que chaque tas est de même niveau, puis appliquer la fonction à la note de chaque question avec un γ choisi, correcteur par correcteur, pour que les notes soient de niveaux égaux (niveau mesuré par la moyenne, ou la médiane, ou quelque chose comme ça — peut-être la moyenne des n/2 notes médianes, histoire de faire un compromis entre les deux et écarter les queues de distribution sans trop faire d'hypothèse sur le centre). Mais sans aller jusqu'à un tel niveau de précision, appliquer un γ un peu au-dessus de 1 pour un correcteur qui a tendance à être trop généreux avec les points partiels, et un peu en-dessous de 1 pour un correcteur qui a tendance à être trop sévère avec eux, permet d'harmoniser un peu. (D'où l'intérêt, aussi, d'insister pour que les correcteurs mettent effectivement des fractions de points quand il y a quelques idées de juste : ce sera toujours ajustable derrière, tandis que des 0 et des 1 ne le sont pas trop.) À ce stade-là, les notes ne sont même plus des rationnels (ce sont des algébriques parce que je prends des γ rationnels, mais bon, on s'en fout, on ne va pas faire des calculs exacts dessus).

Ma formule de calcul de note devient encore un peu plus compliquée : mathématiquement, c'est Nλ := Nmax·∑j(pj·(xλ,j/xmax,j)γ)/∑j(pj), je vous la refais en MathML juste pour le plaisir d'écrire du MathML et de rappeler que Firefox est meilleur que Chrome,

Nλ Nmax j pj xλj xmax γ j pj

et dans LibreOffice, cela devient =SUMPRODUCT(POWER(($Dλ:$Rλ)/($D$33:$R$33),$A$36),$D$34:$R$34)/SUM($D$34:$R$34)*$S$33 si j'ai mis le γ affecté au correcteur dans la cellule A36 de sa feuille à lui. Ah oui, et il faut sans doute mettre un CEILING(,0.1) si on veut arrondir tout ça. Voire ajouter des tests pour certaines notes particulières provoquant des effets de seuil (par exemple, en première année à Télécom, il y a un seuil à 6/20, donc il vaut mieux éviter une note comme 5.9). Ça commence à devenir vraiment fastidieux !

Difficulté suivante : communiquer les notes aux élèves. Bien sûr, mon école a une infrastructure prévue pour saisir les notes — mais il s'agit uniquement de la note finale du module. Si je veux communiquer aux élèves des notes intermédiaires, ou un décompte exercice par exercice, c'est à moi de me démerder. Et l'école ne veut pas non plus (ce qui est raisonnable) qu'on envoie à tout le monde un grand tableau avec les notes de tout le monde. La solution semble donc d'envoyer 150 mails individuels, et pour ça il est évident que je vais automatiser le processus. (Bien sûr, une meilleure solution aurait été que l'école s'arrange d'emblée pour que chaque élève se génère une paire publique/privée de clés cryptographiques et publie les clés publiques de tous les élèves : comme ça, j'aurais pu publier en une seule fois les informations pour chaque élève chiffrées de manière à ce qu'il soit le seul à pouvoir les déchiffrer. Mais ce n'est pas le cas, et par ailleurs je n'assure plus de cours de crypto, donc oublions.)

Or scripter l'envoi de mails est étonnamment difficile. Sous Unix, on peut bien invoquer /usr/lib/sendmail directement, mais encore faut-il que l'agent mail de la machine en question soit correctement configuré pour faire ce qu'il faut, ce qui est loin d'être évident ; et même si ça marche, il ne va pas s'occuper des choses pénibles adjacentes à l'envoi, comme l'encodage MIME et autres petites merdes de ce genre. Il y a toutes sortes de programmes comme mail et mailx qui sont censés être scriptables (même mutt, qui est mon agent utilisateur normal pour tout mon mail non-professionnel), mais, bien sûr, il n'y en a pas deux qui se comportent de la même manière (et plein de programmes différents peuvent se cacher sous le nom de mail, c'est une horreur). Le mieux que j'aie trouvé était, finalement, le programme s-nail. J'ai quand même passé beaucoup de temps à trouver quelles options lui donner pour qu'il arrive à parler au serveur de mon école (du genre : set smtp-use-starttls, set ssl-verify=ignore, set smtp-auth=login, set smtp-auth-user=mylogin@telecom-paristech.fr, set smtp-auth-password=mypassword et set smtp=smtp://z.mines-telecom.fr) et qu'il ne commette pas de crime de lèse-Unicode (set encoding=8bit et set sendcharsets=utf-8). Ensuite, il n'y a « plus qu'à » exporter le fichier des notes en CSV, et écrire un script Perl qui envoie les mails (je suppose, bien sûr, que j'aurais aussi pu trouver un module Perl qui fait le boulot d'envoyer les mails ; sauf qu'en fait j'aurais certainement trouvé douze modules différents, certains obsolètes, le rapport entre lesquels n'est pas clair, et dont les noms n'indiquent pas clairement ce qu'ils font). Et puis, bien sûr, personne n'a l'air de bien savoir combien de mails j'ai le droit d'envoyer par unité de temps.

Je ne peux que méditer les mots immortels du grand David M.*x : le chemin de l'enfer est pavé de petites crottes de ragondin.

↑Entry #2495 [older| permalink|newer] / ↑Entrée #2495 [précédente| permalien|suivante] ↑

Recent entries / Entrées récentesIndex of all entries / Index de toutes les entrées