# Obsolète, non disponible en ScoDoc 9

<img src="/img/alert.png" style="vertical-align: bottom; margin:0 0 0 0;"
alt="/!\" /> **Les formules utilisateurs, disponibles à titre expérimental en
ScoDoc version 7,
posaient maints problèmes de performance et de maintenance, et ne sont plus
utilisées en ScoDoc 9.** <img src="/img/alert.png" style="vertical-align: bottom; margin:0 0 0 0;" alt="/!\" />

## Formules utilisateurs pour le calcul des moyennes

Dans certains cas (assez rares), on veut calculer la note d'un module autrement
qu'avec une simple moyenne des notes pondérée par les coefficients des
évaluations. Par exemple, on veut parfois prendre la meilleure note de deux
évaluations. On peut alors définir une formule ad-hoc pour le calcul de la
moyenne du module.

Les formules sont aussi utilisable pour calculer la moyenne d'une Unité d'Enseignement (UE).

<img src="/img/alert.png" style="vertical-align: bottom; margin:0 0 0 0;"
alt="/!\" /> Attention: l'utilisation de formules ralenti considérablement les
traitements, et devrait être réservé à des cas exceptionnels.

### Détails

Le problème est compliqué par le fait que les notes à traitées ne sont pas
toujours des nombres: absences, notes en attentes ou manquantes...

La formule reçoit donc:

* Un tableau (vecteur) de notes (noté "notes"), de taille fixe et égale au
  nombre d'évaluations définies. Dans ce tableau, les notes "manquantes" ou
  "neutralisée" sont remplacées par des zéros. Les valeurs sont toujours entre 0
  et 20. Toutes les évaluations sont présentes, même celle des évaluation
  incomplètes (mais leurs notes sont mises à zéro, même celles des étudiants qui
  ont une note note).

* Un tableau des coefficients de chaque évaluation, dans lequel les valeurs
  correspondants aux notes "manquantes" sont nulles.

Dans ces tableaux, les évaluations sont ordonnées en fonction de leur place sur
le tableau de bord du module: l'ordre des évaluation (par défaut par date) peut
être modifié par l'utilisateur en utilisant les flèches.

Ainsi, si on a pour un étudiant deux évaluations de coefficients 2 et 3 avec les
notes (12/20 et 16/20), on aura:

```py
notes = [ 12., 20. ]
coefs = [ 2., 3. ]
```

Quelques fonctions sont définies:
`abs, cmp, dot, len, map, max, min, pow, reduce, round, sum, ifelse`.

Exemples:

* Le max de deux évaluations: `max( notes[0], notes[1] )` (*voir une meilleure approche plus bas*)
* La moyenne classique: `dot( notes, coefs ) / sum(coefs)` (la fonction dot est le produit scalaire habituel)
* Ajouter 1 à la moyenne: `ifelse(moy_is_valid, min(moy_val + 1, 20), moy)`
 * `ifelse(condition, valeur_si_vrai, valeur_si_faux)`
 * on utilise `min` car le résultat ne doit en aucun cas dépasser 20
 * pour le calcul, on utilise la variable `moy_val` (un nombre)
 * si la moyenne n'est pas valide, on renvoie la valeur `moy` (ce qui permet de garder le bon code)
* Le max de deux évaluations, en résistant aux notes manquantes: `ifelse(moy_is_valid, max(notes[0], notes[1]), moy)`

Autres variables définies dans les formules:

* moy : la valeur de la moyenne calculée classiquement (somme pondérée) <img src="/img/alert.png" style="vertical-align: bottom; margin:0 0 0 0;" alt="/!\" /> *attention, ce n'est pas forcément un nombre !*
* moy_val: la valeur de la moyenne (moy) (toujours un nombre, valant 0 si moyenne invalide)
* moy_is_valid: vrai si la moyenne (moy) est valide (numérique). Par exemple, si absence EXCusée, la moyenne n'est pas valide.
* cmask : un vecteur de 0/1, 0 si l'évaluation correspondante n'a pas de note, 1 sinon.
* nbabs : nombre d'absences de l'étudiant dans le semestre (en demi-journées)
* nbabs_just: nombre d'absences *justifiées* de l'étudiant dans le semestre (en demi-journées)
* nbabs_nojust : nombre d'absences *non justifiées* de l'étudiant dans le semestre (en demi-journées)


Attention: pour les conditions, on utilisera la fonction `ifelse`: comme pour
tout appel de fonction python, les arguments cette dernière sont évalués avant
l'appel, ce qui implique que les deux branches (vraie et faux) sont toujours
évaluées. Ce détail est important si l'une d'entre elle déclenche une exception!

### Calcul des moyennes d'UE

Dans les formules de calcul des moyennes d'UE, on peut utiliser soit le vecteur
de notes soit avec des indices numériques (comme ci-dessus, les moyennes de
modules étant accessibles dans l'ordre sous lequel elle apparaissent dans les
bulletins de notes), soit en utilisant le code du module.

Ainsi, la moyenne du module `BD1` serait aussi accessible comme la variable `notes['BD1']`.

Exemple: dans une UE, on veut ajouter la note du module SPORT (qui aurait été
défini avec un coefficient nul dans le programme), on écrira:

```py
ifelse(moy_is_valid, min(moy_val+notes['SPORT'], 20), moy)
```

### Traitement des erreurs

La formule doit ramener une valeur numérique entre 0 et 20, sans quoi ScoDoc
considère la note erronée et la remplace par le code 'ERR' (qui se voit dans le
tableau récapitulatif des notes et sur les bulletins). Idem pour tout autre
erreur de calcul pouvant se produire. Si vous voyez des 'ERR', corrigez votre
formule ! (message d'erreur affiché sur le tableau de bord du semestre)

## Exemples de formules de calcul utiles

### Exemple (contribué par Cédric C., IUT de Bordeaux)

*J'ai réussi à faire mon calcul de moyenne pour une évaluation ayant pour calcul :* `moyenne(DS5, TD4, moyenne(TP1,TP2,TP3))`

*Si cela vous intéresse, voici le détail :*

```
Moyenne des [TPs](TPs.md)
(notes[1]*coefs[1]+notes[2]*coefs[2]+notes[3]*coefs[3])/(coefs[1]+coefs[2]+coefs[3])

Somme des coefficients des [TPs](TPs.md) jamais nulle (avec prise en compte d’une excuse globale)
ifelse(max(max(cmask[1],cmask[2]),cmask[3]), coefs[1]+coefs[2]+coefs[3],1)

Moyenne globale
(notes[5]*coefs[5]+notes[4]*coefs[4]+TP)/(coefs[5]+coefs[4]+CTP)

Calcul du Coefficient de la moyenne TP pour moyenne globale
 max(max(cmask[1],cmask[2]),cmask[3])

Il ne faut pas que le dénominateur puisse être nul donc on prend
max(coefs[5]+coefs[4]+CTP,1)

Test global pour excuse
Ifelse(max(max(max(max(cmask[1], cmask[2]), cmask[3]), cmask[4]), cmask[5]),moncalcul,moy)

Soit la formule finale de moyenne de production
ifelse(max(max(max(max(cmask[1], cmask[2]), cmask[3]), cmask[4]), cmask[5]), ((notes[5]*coefs[5]+notes[4]*coefs[4]+ (notes[1]*coefs[1]+notes[2]*coefs[2]+notes[3]*coefs[3])/( ifelse(max(max(cmask[1],cmask[2]),cmask[3]), coefs[1]+coefs[2]+coefs[3],1)
)))/max(coefs[5]+coefs[4]+max(max(cmask[1],cmask[2]),cmask[3]),1) ,moy)
```