Le code source d'APB, saison 1 episode 2

Posted on jeu. 20 octobre 2016 in misc

Qu'est-ce qui a été publié ?

Le ministère de l'éducation a envoyé le code source du classement pour FNS (c'est quoi ?) à l'association Droit des lycéens qui le demandait. L'association l'a réclamé début avril 2016 via une demande d'accès au documents administratifs. Le ministère a publié un algorithme dans un genre de "pseudo-code" début juin 2016 (après la phrase de classement pour les candidats apb 2016).

L'association a ensuite enchainé sur une demande à la commission d'accès aux documents administratifs (la CADA). La CADA a rendu un avis favorable à la publication des documents demandés par l'association.

Le code source publié lundi 18 octobre 2016, a été envoyé à l'association sur papier (so 2016). Le code a été retranscrit et est disponible ici

Le code source envoyé à l'association fait une vingtaine de pages, on est très loin de l'ensemble d'APB qui selon le monde ferait plutôt 250 pages. (C'est assez étonnant de compter en page dans ce cadre d'ailleurs, en informatique on parle plutôt en nombre de ligne de code)

Le code est écrit en PL/SQL qui, pour faire simple, permet de faire des requêtes sur des bases de données.

Dans le code on trouve un TODO2016, ce qui laisse à penser que le code fourni n'est pas le code de 2016. (ou alors c'est le code de 2016 et le TODO n'a pas été fait, ou n'a pas été enlevé)

Est-ce ce qui était demandé ?

La demande originale portait notamment sur :

1) les documents décrivant les modalités de la sélection automatisée « critérisée » pratiquée pour départager les différents candidats, y compris s'il s'agit d'un tirage au sort pour une L1 à capacité limitée ;

2) l’algorithme (code source) effectuant ce tirage au sort ou une présélection de manière à ne tirer au sort que certains candidats remplissant des critères prédéfinis

Tout est dans le "y compris", de mon point de vue, par rapport à la demande de droits de lycéens tout n'a pas été publié au niveau du code source. On y reviendra plus tard, mais même dans le code source publié il manque le code de certaines fonctions pour savoir ce que fait précisément le code qui est présenté.

Et rien n'a été publié au niveau des bases, dossiers, rapports, études, comptes rendus, procès-verbaux, statistiques, instructions, circulaires, notes et réponses ministérielles, correspondances, avis, prévisions, décisions etc.

Le CADA avait préconisé la délivrance "d'une copie sur un support compatible avec celui qu'elle utilise [...] ou par courrier électronique", je doute fortement que APB fonctionne via le scan de feuilles de papier...

On peut toutefois noter que la demande étant centrée sur les licences à capacité limités, le ministère peut estimer qu'il a bien tout publié. Reste que le ministère aurait pu en profiter pour publier l'ensemble du code source. Ainsi la ministre du numérique (et de l'industrie) pourrait vraiment s'en vanter sur twitter

Note : c'est quoi les AEFE ?

Les candidats AEFE, qui sont a priori les étudiants français de l'étranger (en tout cas ceux qui passe/on passé un bac EFE selon le commentaire, c'est à dire le "bac Élèves Français à l'Etranger.")

Le code source est-il cohérent par rapport à l'algorithme publié en juin ? ( Voir l'épisode 1 )

Résumons le classement réalisé par le code source (ce classement suppose que la valeur stocké pour l'ordre du voeu, permet de faire un classement correct) :

  1. Les candidats AEFE ayant trié leur voeu
  2. Les candidats AEFE n'ayant pas trié leur voeu
  3. Les candidats non-AEFE ayant trié leur voeu et ayant l_six_voe égale à 1 (si la fonction six_voeu_L1 renvoie bien une valeur supérieur à 0)
  4. Les candidats non-AEFE n'ayant pas trié leur voeu ou ayant l_six_voe différent de 1

Pour chacun des cas on ordonne par l'Ordre du voeu avec voeux groupés relatifs licence puis par l'Ordre du voeu avec voeux groupés relatif licence et tous les autres voeux puis par l'Ordre du sous-voeu dans le voeu groupé puis par une valeur aléatoire entre 0 et 999999.

Bien que l'algorithme soit similaire à celui publié en juin, ce n'est pas le même. Attention il est similaire à une condition : que six_voeu_L1 renvoie un valeur 1 si l'étudiant est de l'académie et 0 sinon.

Il y a une subtilité de taille : les AEFE sont prioritaire sur tout le monde. le cas de AEFE n'était pas cité dans le document de juin.

Et un critère supplémentaire fait son apparition : Ordre du sous-voeu dans le voeu groupé.

Quels sont les problèmes ?

Quelques points qui posent questions ou qui sont problématiques :

Quelle est la version de PL/sql ?

Le fait de ne pas connaitre sur quelle version du logiciel le code s'exécute ne permet pas de s'assurer que le langage est bien utilisé. Exemple : l'appel à la fonction random peut être plus aléatoire si on fait un appel à la fonction seed avant wikipedia . L'appel est implicite sur les versions > 9i mais pas avant.

Les candidats AEFE

Les candidats AEFE sont placés avant les non-AEFE.Les candidat AEFE n'ayant pas trié leur voeu A sont placés avant tout candidat non-AEFE qui a le même voeu A (trié ou pas).

Les clauses ORDER

Il y a 2 clauses ORDER qui servent à ordonner selon des critères en provenance des champs de la base de données. Note : "dest" correspond à l'ordre décroissant, pour mettre les 0 à la fin.

La clause ligne 96

ORDER BY 2, 3, 4, 5; que l'on peut traduire par ORDER BY a_ve_ord_vg_rel, a_ve_ord_aff, a_vg_ord, DBMS_RANDOM.value(1,999999), que l'on peut encore traduire par le tri par l'Ordre du voeu avec voeux groupés relatifs licence puis il départage les Ex aequo en triant par l'Ordre du voeu avec voeux groupés relatif licence et tous les autres voeux puis il départage les Ex aequo restant en triant par l'Ordre du sous-voeu dans le voeu groupé puis il départage les Ex aequo encore restant en triant par une valeur aléatoire entre 0 et 999999.

Si on considère que quand un voeu est classé n°1 par le candidat, celui-ci est stocké avec la valeur 1 dans la base de données,les AEFE n'ayant pas trié leur voeux seraient placés avant les AEFE ayant trié leur voeu. La solution de mettre un "dest" sur les champs relatifs aux ordres ne fonctionne pas car dans ce cas, par exemple les candidats ayant mis leur voeu en n°5 par exemple se retrouve avant ceux qui ont mis leur voeu en n°1.

La solution pour que le code source soit valide est : soit N le nombre de max de voeux dans APB, valeur stocké d'un voeu x = -(N-x)-1 où x <= N. C'est à dire que pour un voeu classé n°1 celui-ci est stocké avec la valeur -N et que pour un voeu classé n°N celui-ci est stocké avec la valeur -1. Mais on ne sait pas dans les documents fournies comment la valeur stocké le numéro d'un voeu.

Il faut en plus que le candidat ait g_gf_cod=o_c_gp_cod, c.g_ic_cod > 0 , un Bac EFE, que son dossier soit complet ou incomplet, qu'il ne soit pas déjà classé et qu'il soit un AC.

La clause ligne 149

ORDER BY 2 desc, 3, 4, 5, 6; que l'on peut traduire par ORDER BY DECODE(l_six_voe, 1, six_voeu_L1(c.g_cn_cod, g_aa_cod_bac_int, g_cn_flg_int_aca, o_g_tg_cod), 0) dest, a_ve_ord_vg_rel, a_ve_ord_aff, a_vg_ord, DBMS_RANDOM.value(1,999999), que l'on peut encore traduire par le tri par [TRUC] dans l'ordre décroissant puis il départage les Ex aequo en triant par l'Ordre du voeu avec voeux groupés relatifs licence, puis il départage les Ex aequo restant en triant par l'Ordre du voeu avec voeux groupés relatif licence et tous les autres voeux, puis il départage les Ex aequo restant en triant par l'Ordre du sous-voeu dans le voeu groupé, puis il départage les Ex aequo encore restant en triant par une valeur aléatoire entre 0 et 999999.

[TRUC] vaut 0 si l_six_voe ne vaut pas 1 (donc le candidat est mis à la fin) et vaut on sait pas trop quelle(s) valeur(s) sinon. Ça vaut la valeur que la fonction six_voeu_L1 renvoie, peut-être est-t-elle unique (toujours la même) dans ce cas l'importance n'est pas grande, mais au vu de l'écriture du code (l'appel à une fonction et pas une constante à la place) cette fonction renvoie au moins 2 valeurs différentes (si le candidat vient de l'academie ou pas, logiquement (selon l'algorithme publié en juin) ça doit être ça). Mais elle pourrait très bien renvoyer plus de valeurs différentes et donc influancer fortement le tri des candidats...

Dans tous les cas la fonction six_voeu_L1 prend en argument c.g_cn_cod, g_aa_cod_bac_int, g_cn_flg_int_aca, o_g_tg_cod qui correspondent au code d'inscription du candidat , [inconnue], [inconnu peut être l'academie], [inconnue]

MAIS même problème ici, ceux qui n'ont pas trié leur voeu se retrouvent avant ceux qui on trié leur vote, si un voeu classé n°1 par un candidat est stockéavec la valeur 1 dans la base de données..

Normalement ce tri doit être similaire à celui des AEFE, mais les candidats à la fin du classement sont ceux qui n'ont pas classé leur voeu ou qui on l_six_voe qui ne vaut pas 1. il faut en plus que le candidat ait i.g_gf_cod=o_c_gp_cod, un dossier complet ou incomplet, que c.g_ic_cod > 0 , qu'il n'ait pas encore été classé, qu'il soit un AC

C'est quoi un groupe ?

L'algorithme traite des groupes, cela correspond a priori au voeux groupés d'Ile de France. Plus d'info sur cet article du monde : APB : le point sur l’entrée en licence en Ile-de-France (l'explication est dans l'explication de la pastille jaune.)

Comment est utilisé ce code ?

On ne sait pas quand, dans quel(s) cas et sur quels données, cette fonction est appellée, ni même si elle est appellée (mais ça serait gros quand même ^^)

Des fonctions non publiées

Le code fait appel à des fonctions qui ne sont pas publiées, notamment la fonction six_voeu_L1 qui fait certainement quelque chose mais on ne sait pas quoi. Et cette fonction est CAPITAL pour le tri des non-AEFE.

Le code fait aussi appelle à des fonctions de vérification, idem, ce code n'est pas disponible alors qu'il serait vraiment intéressant pour savoir comment APB considère que le tri qu'il a fait est valide.

Des noms incompréhensibles

Le nom des variables et des champs de la bdd ne sont pas explicite, ce qui demande un travail non négligable pour un développeur qui aurait accès à leur signification pour savoir à quoi elles correspondent. Alors sans savoir à quoi elles correspondent, c'est quasi mission impossible pour savoir ce qu'elle peuvent contenir. Un partie de la signification des variables est disponible ici mais il reste pleins d'inconnues.

De façon générale je comprend que les variables/champs de bdd commancant par "c." sont relatives aux candidats.

On pourrait éventuellemnt en déduire que celles commancant par "g." sont relatives aux groupes.

C'est quoi les AC et les NC ?

AC : à classer

NC : non classé

Le message d'erreur

La variable mess_err (message d'erreur) n'est jamais affichée, elle l'est certainement dans le code "générale" après l'appel à la fonction gen_class_alea_V1_relatif_grp et après un test sur la valeur de retour.

Le commentaire TODO2016

Le commentaire TODO 2016, laisse penser qu'ils ont découvert un bug en cours d'exploitation et ils on fait un patch temporaire dans exploit/admissions/simulation/pb ponctuels/correction_classements_neo-reo.sql en attendant de reprendre le développement pour intégrer une correction plus proprement.

Plus d'info

Un wiki est disponible avec pleins d'informations dessus ainsi qu'un google docs crée par l'association pour faire le point sur cette publication. Il y a aussi la structure d'une sous-partie des tables d'APB

D'ailleurs si on cherche "CPGELDD" (le nom de package PL/sql selon le schema des tables)on tombe sur ce fil de discution fil de discution Si on regarde le site d'APB, il est bien servi par un apache tomcat, donc il vraiment légitime de penser que ce fil est parle bien d'apb. Du coup on apprendre que ça tourne/tournait sur un Oracle Database 10g en 2009 donc la version initialise bien seul la fonction random.

Merci à droits de lycéens pour tout leur travail là dessus, c'est vraiment quelque chose d'utile et de néccesaire !