2021-12-06 14:04:03 +01:00
# -*- mode: python -*-
2020-09-26 16:19:37 +02:00
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
2022-01-01 14:49:42 +01:00
# Copyright (c) 1999 - 2022 Emmanuel Viennet. All rights reserved.
2020-09-26 16:19:37 +02:00
#
# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
""" Liste des notes d ' une évaluation
"""
2021-08-01 10:16:16 +02:00
import flask
2021-09-18 10:10:02 +02:00
from flask import url_for , g , request
2021-07-11 17:37:12 +02:00
2021-08-29 19:57:32 +02:00
from app import log
2022-02-13 23:53:11 +01:00
from app import models
2022-01-25 10:45:13 +01:00
from app . comp import res_sem
2021-11-22 00:31:53 +01:00
from app . comp import moy_mod
2022-01-25 10:45:13 +01:00
from app . comp . moy_mod import ModuleImplResults
from app . comp . res_common import NotesTableCompat
2022-02-13 23:53:11 +01:00
from app . models import FormSemestre
from app . models . evaluations import Evaluation
from app . models . moduleimpls import ModuleImpl
import app . scodoc . sco_utils as scu
import app . scodoc . notesdb as ndb
2021-06-19 23:21:37 +02:00
from app . scodoc . TrivialFormulator import TrivialFormulator
2021-07-19 19:53:01 +02:00
from app . scodoc import sco_cache
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_edit_module
from app . scodoc import sco_evaluations
2021-11-12 22:17:46 +01:00
from app . scodoc import sco_evaluation_db
2021-06-19 23:21:37 +02:00
from app . scodoc import sco_formsemestre
from app . scodoc import sco_groups
from app . scodoc import sco_moduleimpl
from app . scodoc import sco_preferences
from app . scodoc import sco_etud
2021-09-13 19:36:53 +02:00
from app . scodoc import sco_users
2021-08-21 17:07:44 +02:00
import sco_version
2021-06-19 23:21:37 +02:00
from app . scodoc . gen_tables import GenTable
from app . scodoc . htmlutils import histogram_notes
2020-09-26 16:19:37 +02:00
2021-12-18 12:16:49 +01:00
def do_evaluation_listenotes (
evaluation_id = None , moduleimpl_id = None , format = " html "
2021-12-20 20:38:21 +01:00
) - > tuple [ str , str ] :
2020-09-26 16:19:37 +02:00
"""
2021-12-18 12:16:49 +01:00
Affichage des notes d ' une évaluation (si evaluation_id)
ou de toutes les évaluations d ' un module (si moduleimpl_id)
2020-09-26 16:19:37 +02:00
"""
mode = None
2021-12-18 12:16:49 +01:00
if moduleimpl_id :
2020-09-26 16:19:37 +02:00
mode = " module "
2021-11-12 22:17:46 +01:00
evals = sco_evaluation_db . do_evaluation_list ( { " moduleimpl_id " : moduleimpl_id } )
2021-12-18 12:16:49 +01:00
elif evaluation_id :
mode = " eval "
evals = sco_evaluation_db . do_evaluation_list ( { " evaluation_id " : evaluation_id } )
else :
2020-09-26 16:19:37 +02:00
raise ValueError ( " missing argument: evaluation or module " )
if not evals :
2021-12-20 20:38:21 +01:00
return " <p>Aucune évaluation !</p> " , f " ScoDoc "
2020-09-26 16:19:37 +02:00
E = evals [ 0 ] # il y a au moins une evaluation
2021-12-18 12:16:49 +01:00
modimpl = ModuleImpl . query . get ( E [ " moduleimpl_id " ] )
2020-09-26 16:19:37 +02:00
# description de l'evaluation
if mode == " eval " :
2021-09-05 12:30:11 +02:00
H = [ sco_evaluations . evaluation_describe ( evaluation_id = evaluation_id ) ]
2021-12-18 12:16:49 +01:00
page_title = f " Notes { E [ ' description ' ] or modimpl . module . code } "
2020-09-26 16:19:37 +02:00
else :
H = [ ]
2021-12-18 12:16:49 +01:00
page_title = f " Notes { modimpl . module . code } "
2020-09-26 16:19:37 +02:00
# groupes
groups = sco_groups . do_evaluation_listegroupes (
2021-08-19 10:28:35 +02:00
E [ " evaluation_id " ] , include_default = True
2020-09-26 16:19:37 +02:00
)
grlabs = [ g [ " group_name " ] or " tous " for g in groups ] # legendes des boutons
2021-08-15 09:55:35 +02:00
grnams = [ str ( g [ " group_id " ] ) for g in groups ] # noms des checkbox
2020-09-26 16:19:37 +02:00
if len ( evals ) > 1 :
descr = [
( " moduleimpl_id " , { " default " : E [ " moduleimpl_id " ] , " input_type " : " hidden " } )
]
else :
descr = [
( " evaluation_id " , { " default " : E [ " evaluation_id " ] , " input_type " : " hidden " } )
]
if len ( grnams ) > 1 :
descr + = [
(
" s " ,
{
" input_type " : " separator " ,
" title " : " <b>Choix du ou des groupes d ' étudiants:</b> " ,
} ,
) ,
(
" group_ids " ,
{
" input_type " : " checkbox " ,
" title " : " " ,
" allowed_values " : grnams ,
" labels " : grlabs ,
" attributes " : ( ' onclick= " document.tf.submit(); " ' , ) ,
} ,
) ,
]
else :
if grnams :
def_nam = grnams [ 0 ]
else :
def_nam = " "
descr + = [
(
" group_ids " ,
{ " input_type " : " hidden " , " type " : " list " , " default " : [ def_nam ] } ,
)
]
descr + = [
(
" anonymous_listing " ,
{
" input_type " : " checkbox " ,
" title " : " " ,
" allowed_values " : ( " yes " , ) ,
" labels " : ( ' listing " anonyme " ' , ) ,
" attributes " : ( ' onclick= " document.tf.submit(); " ' , ) ,
" template " : ' <tr><td class= " tf-fieldlabel " > %(label)s </td><td class= " tf-field " > %(elem)s ' ,
} ,
) ,
2020-10-06 12:13:04 +02:00
(
" note_sur_20 " ,
{
" input_type " : " checkbox " ,
" title " : " " ,
" allowed_values " : ( " yes " , ) ,
" labels " : ( " notes sur 20 " , ) ,
" attributes " : ( ' onclick= " document.tf.submit(); " ' , ) ,
" template " : " %(elem)s " ,
} ,
) ,
2020-09-26 16:19:37 +02:00
(
" hide_groups " ,
{
" input_type " : " checkbox " ,
" title " : " " ,
" allowed_values " : ( " yes " , ) ,
" labels " : ( " masquer les groupes " , ) ,
" attributes " : ( ' onclick= " document.tf.submit(); " ' , ) ,
" template " : " %(elem)s " ,
} ,
) ,
(
2020-10-06 12:13:04 +02:00
" with_emails " ,
2020-09-26 16:19:37 +02:00
{
" input_type " : " checkbox " ,
" title " : " " ,
" allowed_values " : ( " yes " , ) ,
2020-10-06 12:13:04 +02:00
" labels " : ( " montrer les e-mails " , ) ,
2020-09-26 16:19:37 +02:00
" attributes " : ( ' onclick= " document.tf.submit(); " ' , ) ,
" template " : " %(elem)s </td></tr> " ,
} ,
) ,
]
tf = TrivialFormulator (
2021-09-18 10:10:02 +02:00
request . base_url ,
2021-09-27 16:42:14 +02:00
scu . get_request_args ( ) ,
2020-09-26 16:19:37 +02:00
descr ,
cancelbutton = None ,
submitbutton = None ,
bottom_buttons = False ,
method = " GET " ,
cssclass = " noprint " ,
name = " tf " ,
is_submitted = True , # toujours "soumis" (démarre avec liste complète)
)
if tf [ 0 ] == 0 :
2021-12-18 12:16:49 +01:00
return " \n " . join ( H ) + " \n " + tf [ 1 ] , page_title
2020-09-26 16:19:37 +02:00
elif tf [ 0 ] == - 1 :
2021-12-20 20:38:21 +01:00
return (
flask . redirect (
" %s /Notes/moduleimpl_status?moduleimpl_id= %s "
% ( scu . ScoURL ( ) , E [ " moduleimpl_id " ] )
) ,
" " ,
2020-09-26 16:19:37 +02:00
)
else :
anonymous_listing = tf [ 2 ] [ " anonymous_listing " ]
note_sur_20 = tf [ 2 ] [ " note_sur_20 " ]
hide_groups = tf [ 2 ] [ " hide_groups " ]
2020-10-06 12:13:04 +02:00
with_emails = tf [ 2 ] [ " with_emails " ]
2022-01-14 11:18:31 +01:00
group_ids = [ x for x in tf [ 2 ] [ " group_ids " ] if x != " " ]
2021-12-18 12:16:49 +01:00
return (
_make_table_notes (
tf [ 1 ] ,
evals ,
format = format ,
note_sur_20 = note_sur_20 ,
anonymous_listing = anonymous_listing ,
2022-01-14 11:18:31 +01:00
group_ids = group_ids ,
2021-12-18 12:16:49 +01:00
hide_groups = hide_groups ,
with_emails = with_emails ,
mode = mode ,
) ,
page_title ,
2020-09-26 16:19:37 +02:00
)
def _make_table_notes (
html_form ,
evals ,
format = " " ,
note_sur_20 = False ,
anonymous_listing = False ,
hide_groups = False ,
2020-10-06 12:13:04 +02:00
with_emails = False ,
2020-09-26 16:19:37 +02:00
group_ids = [ ] ,
2021-11-22 00:31:53 +01:00
mode = " module " , # "eval" or "module"
2020-09-26 16:19:37 +02:00
) :
2021-11-20 17:21:51 +01:00
""" Table liste notes (une seule évaluation ou toutes celles d ' un module) """
2021-11-22 00:31:53 +01:00
# Code à ré-écrire !
2020-09-26 16:19:37 +02:00
if not evals :
return " <p>Aucune évaluation !</p> "
E = evals [ 0 ]
moduleimpl_id = E [ " moduleimpl_id " ]
2021-12-08 23:43:07 +01:00
modimpl_o = sco_moduleimpl . moduleimpl_list ( moduleimpl_id = moduleimpl_id ) [ 0 ]
module = models . Module . query . get ( modimpl_o [ " module_id " ] )
2021-11-22 00:31:53 +01:00
is_apc = module . formation . get_parcours ( ) . APC_SAE
if is_apc :
2021-12-08 23:43:07 +01:00
modimpl = ModuleImpl . query . get ( moduleimpl_id )
is_conforme = modimpl . check_apc_conformity ( )
2021-12-26 19:15:47 +01:00
evals_poids , ues = moy_mod . load_evaluations_poids ( moduleimpl_id )
2021-11-28 16:31:33 +01:00
if not ues :
is_apc = False
2021-11-22 00:31:53 +01:00
else :
evals_poids , ues = None , None
2021-12-08 23:43:07 +01:00
is_conforme = True
sem = sco_formsemestre . get_formsemestre ( modimpl_o [ " formsemestre_id " ] )
2020-09-26 16:19:37 +02:00
# (debug) check that all evals are in same module:
for e in evals :
if e [ " moduleimpl_id " ] != moduleimpl_id :
raise ValueError ( " invalid evaluations list " )
if format == " xls " :
keep_numeric = True # pas de conversion des notes en strings
else :
keep_numeric = False
# Si pas de groupe, affiche tout
if not group_ids :
2021-12-08 23:43:07 +01:00
group_ids = [ sco_groups . get_default_group ( modimpl_o [ " formsemestre_id " ] ) ]
2021-08-19 10:28:35 +02:00
groups = sco_groups . listgroups ( group_ids )
2020-09-26 16:19:37 +02:00
gr_title = sco_groups . listgroups_abbrev ( groups )
gr_title_filename = sco_groups . listgroups_filename ( groups )
if anonymous_listing :
columns_ids = [ " code " ] # cols in table
else :
if format == " xls " or format == " xml " :
columns_ids = [ " nom " , " prenom " ]
else :
columns_ids = [ " nomprenom " ]
if not hide_groups :
columns_ids . append ( " group " )
titles = {
" code " : " Code " ,
" group " : " Groupe " ,
" nom " : " Nom " ,
" prenom " : " Prénom " ,
" nomprenom " : " Nom " ,
" expl_key " : " Rem. " ,
2020-12-02 01:00:23 +01:00
" email " : " e-mail " ,
" emailperso " : " e-mail perso " ,
2021-12-06 14:04:03 +01:00
" signatures " : " Signatures " ,
2020-09-26 16:19:37 +02:00
}
rows = [ ]
2021-11-22 00:31:53 +01:00
class KeyManager ( dict ) : # comment : key (pour regrouper les comments a la fin)
2020-09-26 16:19:37 +02:00
def __init__ ( self ) :
self . lastkey = 1
def nextkey ( self ) :
r = self . lastkey
self . lastkey + = 1
# self.lastkey = chr(ord(self.lastkey)+1)
return str ( r )
2021-11-22 00:31:53 +01:00
key_mgr = KeyManager ( )
# code pour listings anonyme, à la place du nom
if sco_preferences . get_preference ( " anonymous_lst_code " ) == " INE " :
anonymous_lst_key = " code_ine "
elif sco_preferences . get_preference ( " anonymous_lst_code " ) == " NIP " :
anonymous_lst_key = " code_nip "
else :
anonymous_lst_key = " etudid "
etudid_etats = sco_groups . do_evaluation_listeetuds_groups (
2022-01-16 23:47:52 +01:00
E [ " evaluation_id " ] , groups , include_demdef = True
2021-11-22 00:31:53 +01:00
)
2021-11-20 17:21:51 +01:00
for etudid , etat in etudid_etats :
2020-09-26 16:19:37 +02:00
css_row_class = None
# infos identite etudiant
2021-08-22 13:24:36 +02:00
etud = sco_etud . get_etud_info ( etudid = etudid , filled = True ) [ 0 ]
2020-09-26 16:19:37 +02:00
2021-11-20 17:21:51 +01:00
if etat == " I " : # si inscrit, indique groupe
2021-08-19 10:28:35 +02:00
groups = sco_groups . get_etud_groups ( etudid , sem )
2020-09-26 16:19:37 +02:00
grc = sco_groups . listgroups_abbrev ( groups )
else :
2021-11-20 17:21:51 +01:00
if etat == " D " :
2020-09-26 16:19:37 +02:00
grc = " DEM " # attention: ce code est re-ecrit plus bas, ne pas le changer (?)
css_row_class = " etuddem "
else :
2021-11-20 17:21:51 +01:00
grc = etat
2020-09-26 16:19:37 +02:00
2021-11-22 00:31:53 +01:00
code = etud . get ( anonymous_lst_key )
2020-09-26 16:19:37 +02:00
if not code : # laisser le code vide n'aurait aucun sens, prenons l'etudid
code = etudid
rows . append (
{
2021-10-04 22:05:05 +02:00
" code " : str ( code ) , # INE, NIP ou etudid
2020-09-26 16:19:37 +02:00
" _code_td_attrs " : ' style= " padding-left: 1em; padding-right: 2em; " ' ,
" etudid " : etudid ,
2021-08-21 00:24:51 +02:00
" nom " : etud [ " nom " ] . upper ( ) ,
2021-05-11 11:48:32 +02:00
" _nomprenom_target " : " formsemestre_bulletinetud?formsemestre_id= %s &etudid= %s "
2021-12-08 23:43:07 +01:00
% ( modimpl_o [ " formsemestre_id " ] , etudid ) ,
2020-09-26 16:19:37 +02:00
" _nomprenom_td_attrs " : ' id= " %s " class= " etudinfo " ' % ( etud [ " etudid " ] ) ,
2021-08-21 00:24:51 +02:00
" prenom " : etud [ " prenom " ] . lower ( ) . capitalize ( ) ,
2020-09-26 16:19:37 +02:00
" nomprenom " : etud [ " nomprenom " ] ,
" group " : grc ,
2020-12-02 01:00:23 +01:00
" email " : etud [ " email " ] ,
" emailperso " : etud [ " emailperso " ] ,
2020-09-26 16:19:37 +02:00
" _css_row_class " : css_row_class or " " ,
}
)
# Lignes en tête:
2021-11-22 00:31:53 +01:00
row_coefs = {
2020-09-26 16:19:37 +02:00
" nom " : " " ,
" prenom " : " " ,
" nomprenom " : " " ,
" group " : " " ,
" code " : " " ,
" _css_row_class " : " sorttop fontitalic " ,
" _table_part " : " head " ,
}
2021-11-22 00:31:53 +01:00
row_poids = {
" nom " : " " ,
" prenom " : " " ,
" nomprenom " : " " ,
" group " : " " ,
" code " : " " ,
" _css_row_class " : " sorttop poids " ,
" _table_part " : " head " ,
}
row_note_max = {
2020-09-26 16:19:37 +02:00
" nom " : " " ,
" prenom " : " " ,
" nomprenom " : " " ,
" group " : " " ,
" code " : " " ,
" _css_row_class " : " sorttop fontitalic " ,
" _table_part " : " head " ,
}
2021-11-22 00:31:53 +01:00
row_moys = {
2020-09-26 16:19:37 +02:00
" _css_row_class " : " moyenne sortbottom " ,
" _table_part " : " foot " ,
#'_nomprenom_td_attrs' : 'colspan="2" ',
" nomprenom " : " Moyenne (sans les absents) : " ,
" comment " : " " ,
}
# Ajoute les notes de chaque évaluation:
for e in evals :
2021-07-29 10:19:00 +02:00
e [ " eval_state " ] = sco_evaluations . do_evaluation_etat ( e [ " evaluation_id " ] )
2020-09-26 16:19:37 +02:00
notes , nb_abs , nb_att = _add_eval_columns (
e ,
2021-11-22 00:31:53 +01:00
evals_poids ,
ues ,
2020-09-26 16:19:37 +02:00
rows ,
titles ,
2021-11-22 00:31:53 +01:00
row_coefs ,
row_poids ,
row_note_max ,
row_moys ,
is_apc ,
key_mgr ,
2020-09-26 16:19:37 +02:00
note_sur_20 ,
keep_numeric ,
2021-12-19 11:08:03 +01:00
format = format ,
2020-09-26 16:19:37 +02:00
)
columns_ids . append ( e [ " evaluation_id " ] )
#
if anonymous_listing :
2021-10-04 22:30:57 +02:00
rows . sort ( key = lambda x : x [ " code " ] or " " )
2020-09-26 16:19:37 +02:00
else :
2021-10-04 22:05:05 +02:00
rows . sort (
key = lambda x : ( x [ " nom " ] or " " , x [ " prenom " ] or " " )
) # sort by nom, prenom
2020-09-26 16:19:37 +02:00
2021-11-22 00:31:53 +01:00
# Si module, ajoute la (les) "moyenne(s) du module:
if mode == " module " :
if len ( evals ) > 1 :
2021-12-19 11:08:03 +01:00
# Moyenne de l'étudiant dans le module
2021-11-22 00:31:53 +01:00
# Affichée même en APC à titre indicatif
_add_moymod_column (
sem [ " formsemestre_id " ] ,
moduleimpl_id ,
rows ,
columns_ids ,
titles ,
row_coefs ,
row_poids ,
row_note_max ,
row_moys ,
is_apc ,
keep_numeric ,
)
if is_apc :
# Ajoute une colonne par UE
_add_apc_columns (
2022-01-25 10:45:13 +01:00
modimpl ,
2021-11-22 00:31:53 +01:00
evals_poids ,
ues ,
rows ,
columns_ids ,
titles ,
2021-12-08 23:43:07 +01:00
is_conforme ,
2021-11-22 00:31:53 +01:00
row_coefs ,
row_poids ,
row_note_max ,
row_moys ,
keep_numeric ,
)
2020-09-26 16:19:37 +02:00
2020-10-06 12:13:04 +02:00
# Ajoute colonnes emails tout à droite:
if with_emails :
2020-12-02 01:00:23 +01:00
columns_ids + = [ " email " , " emailperso " ]
2020-10-06 12:13:04 +02:00
# Ajoute lignes en tête et moyennes
2021-12-06 23:15:55 +01:00
if len ( evals ) > 0 and format != " bordereau " :
2021-11-22 00:31:53 +01:00
rows_head = [ row_coefs ]
if is_apc :
rows_head . append ( row_poids )
rows_head . append ( row_note_max )
rows = rows_head + rows
rows . append ( row_moys )
2020-09-26 16:19:37 +02:00
# ajout liens HTMl vers affichage une evaluation:
if format == " html " and len ( evals ) > 1 :
rlinks = { " _table_part " : " head " }
for e in evals :
rlinks [ e [ " evaluation_id " ] ] = " afficher "
rlinks [
2021-08-15 09:55:35 +02:00
" _ " + str ( e [ " evaluation_id " ] ) + " _help "
2020-09-26 16:19:37 +02:00
] = " afficher seulement les notes de cette évaluation "
2021-08-15 09:55:35 +02:00
rlinks [ " _ " + str ( e [ " evaluation_id " ] ) + " _target " ] = url_for (
" notes.evaluation_listenotes " ,
scodoc_dept = g . scodoc_dept ,
evaluation_id = e [ " evaluation_id " ] ,
2020-09-26 16:19:37 +02:00
)
2021-08-15 09:55:35 +02:00
rlinks [ " _ " + str ( e [ " evaluation_id " ] ) + " _td_attrs " ] = ' class= " tdlink " '
2020-09-26 16:19:37 +02:00
rows . append ( rlinks )
if len ( evals ) == 1 : # colonne "Rem." seulement si une eval
if format == " html " : # pas d'indication d'origine en pdf (pour affichage)
columns_ids . append ( " expl_key " )
elif format == " xls " or format == " xml " :
columns_ids . append ( " comment " )
2021-12-06 14:04:03 +01:00
elif format == " bordereau " :
columns_ids . append ( " signatures " )
2020-09-26 16:19:37 +02:00
# titres divers:
2021-08-11 14:00:39 +02:00
gl = " " . join ( [ " &group_ids % 3Alist= " + str ( g ) for g in group_ids ] )
2020-09-26 16:19:37 +02:00
if note_sur_20 :
2021-05-11 11:48:32 +02:00
gl = " ¬e_sur_20 % 3Alist=yes " + gl
2020-09-26 16:19:37 +02:00
if anonymous_listing :
2021-05-11 11:48:32 +02:00
gl = " &anonymous_listing % 3Alist=yes " + gl
2020-09-26 16:19:37 +02:00
if hide_groups :
2021-05-11 11:48:32 +02:00
gl = " &hide_groups % 3Alist=yes " + gl
2020-10-06 12:13:04 +02:00
if with_emails :
2021-05-11 11:48:32 +02:00
gl = " &with_emails % 3Alist=yes " + gl
2020-09-26 16:19:37 +02:00
if len ( evals ) == 1 :
2021-11-22 00:31:53 +01:00
evalname = " %s - %s " % ( module . code , ndb . DateDMYtoISO ( E [ " jour " ] ) )
2021-11-20 17:21:51 +01:00
hh = " %s , %s ( %d étudiants) " % ( E [ " description " ] , gr_title , len ( etudid_etats ) )
2021-02-04 20:02:44 +01:00
filename = scu . make_filename ( " notes_ %s _ %s " % ( evalname , gr_title_filename ) )
2021-12-06 14:04:03 +01:00
2021-12-06 23:15:55 +01:00
if format == " bordereau " :
hh = " %d étudiants " % ( len ( etudid_etats ) )
2021-12-06 14:04:03 +01:00
hh + = " %d absent " % ( nb_abs )
if nb_abs > 1 :
hh + = " s "
2021-12-06 23:15:55 +01:00
hh + = " , %d en attente. " % ( nb_att )
pdf_title = " <br/> BORDEREAU DE SIGNATURES "
pdf_title + = " <br/><br/> %(titre)s " % sem
pdf_title + = " <br/>( %(mois_debut)s - %(mois_fin)s ) " % sem
pdf_title + = " semestre %s %s " % (
sem [ " semestre_id " ] ,
sem . get ( " modalite " , " " ) ,
)
pdf_title + = f " <br/>Notes du module { module . code } - { module . titre } "
pdf_title + = " <br/>Evaluation : %(description)s " % e
if len ( e [ " jour " ] ) > 0 :
2021-12-06 14:04:03 +01:00
pdf_title + = " ( %(jour)s ) " % e
2021-12-06 23:15:55 +01:00
pdf_title + = " (noté sur %(note_max)s )<br/><br/> " % e
2021-12-03 21:17:30 +01:00
else :
2021-12-06 23:15:55 +01:00
hh = " %s , %s ( %d étudiants) " % (
E [ " description " ] ,
gr_title ,
len ( etudid_etats ) ,
)
if len ( e [ " jour " ] ) > 0 :
2021-12-06 14:04:03 +01:00
pdf_title = " %(description)s ( %(jour)s ) " % e
else :
pdf_title = " %(description)s " % e
caption = hh
2020-09-26 16:19:37 +02:00
html_title = " "
base_url = " evaluation_listenotes?evaluation_id= %s " % E [ " evaluation_id " ] + gl
html_next_section = (
' <div class= " notes_evaluation_stats " > %d absents, %d en attente.</div> '
% ( nb_abs , nb_att )
)
else :
2021-11-22 00:31:53 +01:00
filename = scu . make_filename ( " notes_ %s _ %s " % ( module . code , gr_title_filename ) )
title = f " Notes { module . type_name ( ) } { module . code } { module . titre } "
2020-09-26 16:19:37 +02:00
title + = " semestre %(titremois)s " % sem
if gr_title and gr_title != " tous " :
title + = " %s " % gr_title
caption = title
html_next_section = " "
2021-12-06 14:04:03 +01:00
if format == " pdf " or format == " bordereau " :
2020-09-26 16:19:37 +02:00
caption = " " # same as pdf_title
pdf_title = title
2021-11-22 00:31:53 +01:00
html_title = f """ <h2 class= " formsemestre " >Notes { module . type_name ( ) } <a href= " {
url_for ( " notes.moduleimpl_status " ,
scodoc_dept = g . scodoc_dept , moduleimpl_id = moduleimpl_id )
} " > {module.code} {module.titre} </a></h2>
"""
2021-12-08 23:43:07 +01:00
if not is_conforme :
html_title + = (
""" <div class= " warning " >Poids des évaluations non conformes !</div> """
)
2020-09-26 16:19:37 +02:00
base_url = " evaluation_listenotes?moduleimpl_id= %s " % moduleimpl_id + gl
# display
tab = GenTable (
titles = titles ,
columns_ids = columns_ids ,
rows = rows ,
html_sortable = True ,
base_url = base_url ,
filename = filename ,
2021-08-21 17:07:44 +02:00
origin = " Généré par %s le " % sco_version . SCONAME
+ scu . timedate_human_repr ( )
+ " " ,
2020-09-26 16:19:37 +02:00
caption = caption ,
html_next_section = html_next_section ,
page_title = " Notes de " + sem [ " titremois " ] ,
html_title = html_title ,
pdf_title = pdf_title ,
html_class = " table_leftalign notes_evaluation " ,
2021-12-08 23:43:07 +01:00
preferences = sco_preferences . SemPreferences ( modimpl_o [ " formsemestre_id " ] ) ,
2020-09-26 16:19:37 +02:00
# html_generate_cells=False # la derniere ligne (moyennes) est incomplete
)
2021-12-06 14:04:03 +01:00
if format == " bordereau " :
format = " pdf "
2021-09-16 00:15:10 +02:00
t = tab . make_page ( format = format , with_html_headers = False )
2020-09-26 16:19:37 +02:00
if format != " html " :
return t
if len ( evals ) > 1 :
all_complete = True
for e in evals :
if not e [ " eval_state " ] [ " evalcomplete " ] :
all_complete = False
if all_complete :
eval_info = ' <span class= " eval_info eval_complete " >Evaluations prises en compte dans les moyennes</span> '
else :
eval_info = ' <span class= " eval_info help " >Les évaluations en vert et orange sont prises en compte dans les moyennes. Celles en rouge n \' ont pas toutes leurs notes.</span> '
return html_form + eval_info + t + " <p></p> "
else :
# Une seule evaluation: ajoute histogramme
histo = histogram_notes ( notes )
# 2 colonnes: histo, comments
C = [
2021-12-06 23:15:55 +01:00
f ' <br><a class= " stdlink " href= " { base_url } &format=bordereau " >Bordereau de Signatures (version PDF)</a> ' ,
2020-09-26 16:19:37 +02:00
" <table><tr><td><div><h4>Répartition des notes:</h4> "
+ histo
+ " </div></td> \n " ,
' <td style= " padding-left: 50px; vertical-align: top; " ><p> ' ,
]
2021-11-22 00:31:53 +01:00
commentkeys = list ( key_mgr . items ( ) ) # [ (comment, key), ... ]
2021-07-09 23:19:30 +02:00
commentkeys . sort ( key = lambda x : int ( x [ 1 ] ) )
2020-09-26 16:19:37 +02:00
for ( comment , key ) in commentkeys :
C . append (
' <span class= " colcomment " >( %s )</span> <em> %s </em><br/> ' % ( key , comment )
)
if commentkeys :
C . append (
' <span><a class=stdlink " href= " evaluation_list_operations?evaluation_id= %s " >Gérer les opérations</a></span><br/> '
% E [ " evaluation_id " ]
)
eval_info = " xxx "
if E [ " eval_state " ] [ " evalcomplete " ] :
eval_info = ' <span class= " eval_info eval_complete " >Evaluation prise en compte dans les moyennes</span> '
elif E [ " eval_state " ] [ " evalattente " ] :
eval_info = ' <span class= " eval_info eval_attente " >Il y a des notes en attente (les autres sont prises en compte)</span> '
else :
eval_info = ' <span class= " eval_info eval_incomplete " >Notes incomplètes, évaluation non prise en compte dans les moyennes</span> '
return (
2021-09-05 12:30:11 +02:00
sco_evaluations . evaluation_describe ( evaluation_id = E [ " evaluation_id " ] )
2020-09-26 16:19:37 +02:00
+ eval_info
+ html_form
+ t
+ " \n " . join ( C )
)
def _add_eval_columns (
2021-11-22 00:31:53 +01:00
e ,
evals_poids ,
ues ,
rows ,
titles ,
row_coefs ,
row_poids ,
row_note_max ,
row_moys ,
is_apc ,
K ,
note_sur_20 ,
keep_numeric ,
2021-12-19 11:08:03 +01:00
format = " html " ,
2020-09-26 16:19:37 +02:00
) :
""" Add eval e """
nb_notes = 0
nb_abs = 0
nb_att = 0
sum_notes = 0
notes = [ ] # liste des notes numeriques, pour calcul histogramme uniquement
evaluation_id = e [ " evaluation_id " ]
2021-12-19 11:08:03 +01:00
e_o = Evaluation . query . get ( evaluation_id ) # XXX en attendant ré-écriture
2022-01-17 00:18:08 +01:00
notes_db = sco_evaluation_db . do_evaluation_get_all_notes ( evaluation_id )
2020-09-26 16:19:37 +02:00
for row in rows :
etudid = row [ " etudid " ]
2022-01-17 00:18:08 +01:00
if etudid in notes_db :
val = notes_db [ etudid ] [ " value " ]
2020-09-26 16:19:37 +02:00
if val is None :
nb_abs + = 1
2021-02-04 20:02:44 +01:00
if val == scu . NOTES_ATTENTE :
2020-09-26 16:19:37 +02:00
nb_att + = 1
# calcul moyenne SANS LES ABSENTS
2021-02-04 20:02:44 +01:00
if val != None and val != scu . NOTES_NEUTRALISE and val != scu . NOTES_ATTENTE :
2020-09-26 16:19:37 +02:00
if e [ " note_max " ] > 0 :
valsur20 = val * 20.0 / e [ " note_max " ] # remet sur 20
else :
valsur20 = 0
notes . append ( valsur20 ) # toujours sur 20 pour l'histogramme
if note_sur_20 :
val = valsur20 # affichage notes / 20 demandé
nb_notes = nb_notes + 1
sum_notes + = val
2021-02-04 20:02:44 +01:00
val_fmt = scu . fmt_note ( val , keep_numeric = keep_numeric )
2022-01-17 00:18:08 +01:00
comment = notes_db [ etudid ] [ " comment " ]
2020-09-26 16:19:37 +02:00
if comment is None :
comment = " "
explanation = " %s ( %s ) %s " % (
2022-01-17 00:18:08 +01:00
notes_db [ etudid ] [ " date " ] . strftime ( " %d / % m/ % y % Hh % M " ) ,
sco_users . user_info ( notes_db [ etudid ] [ " uid " ] ) [ " nomcomplet " ] ,
2020-09-26 16:19:37 +02:00
comment ,
)
else :
explanation = " "
val_fmt = " "
val = None
if val is None :
2021-08-11 14:00:39 +02:00
row [ " _ " + str ( evaluation_id ) + " _td_attrs " ] = ' class= " etudabs " '
2020-09-26 16:19:37 +02:00
if not row . get ( " _css_row_class " , " " ) :
row [ " _css_row_class " ] = " etudabs "
# regroupe les commentaires
if explanation :
2021-07-09 17:47:06 +02:00
if explanation in K :
2020-09-26 16:19:37 +02:00
expl_key = " ( %s ) " % K [ explanation ]
else :
K [ explanation ] = K . nextkey ( )
expl_key = " ( %s ) " % K [ explanation ]
else :
expl_key = " "
row . update (
{
evaluation_id : val_fmt ,
2021-08-11 14:00:39 +02:00
" _ " + str ( evaluation_id ) + " _help " : explanation ,
2020-09-26 16:19:37 +02:00
# si plusieurs evals seront ecrasés et non affichés:
" comment " : explanation ,
" expl_key " : expl_key ,
" _expl_key_help " : explanation ,
}
)
2021-11-22 00:31:53 +01:00
row_coefs [ evaluation_id ] = " coef. %s " % e [ " coefficient " ]
if is_apc :
2021-12-19 11:08:03 +01:00
if format == " html " :
row_poids [ evaluation_id ] = _mini_table_eval_ue_poids (
evaluation_id , evals_poids , ues
)
else :
row_poids [ evaluation_id ] = e_o . get_ue_poids_str ( )
2020-09-26 16:19:37 +02:00
if note_sur_20 :
2021-02-05 18:21:34 +01:00
nmax = 20.0
2020-09-26 16:19:37 +02:00
else :
2021-02-05 18:21:34 +01:00
nmax = e [ " note_max " ]
2020-09-26 16:19:37 +02:00
if keep_numeric :
2021-11-22 00:31:53 +01:00
row_note_max [ evaluation_id ] = nmax
2020-09-26 16:19:37 +02:00
else :
2021-11-22 00:31:53 +01:00
row_note_max [ evaluation_id ] = " / %s " % nmax
2020-09-26 16:19:37 +02:00
if nb_notes > 0 :
2021-12-12 08:40:25 +01:00
row_moys [ evaluation_id ] = scu . fmt_note (
sum_notes / nb_notes , keep_numeric = keep_numeric
)
2021-11-22 00:31:53 +01:00
row_moys [
2021-08-11 14:00:39 +02:00
" _ " + str ( evaluation_id ) + " _help "
] = " moyenne sur %d notes ( %s le %s ) " % (
2020-09-26 16:19:37 +02:00
nb_notes ,
e [ " description " ] ,
e [ " jour " ] ,
)
else :
2021-11-22 00:31:53 +01:00
row_moys [ evaluation_id ] = " "
2020-09-26 16:19:37 +02:00
2021-12-03 21:17:30 +01:00
if len ( e [ " jour " ] ) > 0 :
titles [ evaluation_id ] = " %(description)s ( %(jour)s ) " % e
else :
titles [ evaluation_id ] = " %(description)s " % e
2020-09-26 16:19:37 +02:00
if e [ " eval_state " ] [ " evalcomplete " ] :
2021-08-11 14:00:39 +02:00
titles [ " _ " + str ( evaluation_id ) + " _td_attrs " ] = ' class= " eval_complete " '
2020-09-26 16:19:37 +02:00
elif e [ " eval_state " ] [ " evalattente " ] :
2021-08-11 14:00:39 +02:00
titles [ " _ " + str ( evaluation_id ) + " _td_attrs " ] = ' class= " eval_attente " '
2020-09-26 16:19:37 +02:00
else :
2021-08-11 14:00:39 +02:00
titles [ " _ " + str ( evaluation_id ) + " _td_attrs " ] = ' class= " eval_incomplete " '
2020-09-26 16:19:37 +02:00
return notes , nb_abs , nb_att # pour histogramme
2021-11-22 00:31:53 +01:00
def _mini_table_eval_ue_poids ( evaluation_id , evals_poids , ues ) :
" contenu de la cellule: poids "
return (
""" <table class= " eval_poids " title= " poids vers les UE " ><tr><td> """
+ " </td><td> " . join ( [ f " { ue . acronyme } " for ue in ues ] )
+ " </td></tr> "
+ " <tr><td> "
+ " </td><td> " . join ( [ f " { evals_poids [ ue . id ] [ evaluation_id ] } " for ue in ues ] )
+ " </td></tr></table> "
)
2020-09-26 16:19:37 +02:00
def _add_moymod_column (
formsemestre_id ,
2021-11-22 00:31:53 +01:00
moduleimpl_id ,
2020-09-26 16:19:37 +02:00
rows ,
2021-11-22 00:31:53 +01:00
columns_ids ,
2020-09-26 16:19:37 +02:00
titles ,
2021-11-22 00:31:53 +01:00
row_coefs ,
row_poids ,
row_note_max ,
row_moys ,
is_apc ,
2020-09-26 16:19:37 +02:00
keep_numeric ,
) :
2020-12-02 01:00:23 +01:00
""" Ajoute la colonne moymod à rows """
2020-09-26 16:19:37 +02:00
col_id = " moymod "
2022-02-13 23:53:11 +01:00
formsemestre = FormSemestre . query . get_or_404 ( formsemestre_id )
nt : NotesTableCompat = res_sem . load_formsemestre_results ( formsemestre )
2020-09-26 16:19:37 +02:00
nb_notes = 0
sum_notes = 0
notes = [ ] # liste des notes numeriques, pour calcul histogramme uniquement
for row in rows :
etudid = row [ " etudid " ]
2021-11-22 00:31:53 +01:00
val = nt . get_etud_mod_moy ( moduleimpl_id , etudid ) # note sur 20, ou 'NA','NI'
2021-02-04 20:02:44 +01:00
row [ col_id ] = scu . fmt_note ( val , keep_numeric = keep_numeric )
2020-09-26 16:19:37 +02:00
row [ " _ " + col_id + " _td_attrs " ] = ' class= " moyenne " '
2021-07-12 23:34:18 +02:00
if not isinstance ( val , str ) :
2020-09-26 16:19:37 +02:00
notes . append ( val )
nb_notes = nb_notes + 1
sum_notes + = val
2021-11-22 00:31:53 +01:00
row_coefs [ col_id ] = " (avec abs) "
if is_apc :
row_poids [ col_id ] = " à titre indicatif "
2020-09-26 16:19:37 +02:00
if keep_numeric :
2021-11-22 00:31:53 +01:00
row_note_max [ col_id ] = 20.0
2020-09-26 16:19:37 +02:00
else :
2021-11-22 00:31:53 +01:00
row_note_max [ col_id ] = " / 20 "
2020-09-26 16:19:37 +02:00
titles [ col_id ] = " Moyenne module "
2021-11-22 00:31:53 +01:00
columns_ids . append ( col_id )
2020-09-26 16:19:37 +02:00
if nb_notes > 0 :
2021-11-22 00:31:53 +01:00
row_moys [ col_id ] = " %.3g " % ( sum_notes / nb_notes )
row_moys [ " _ " + col_id + " _help " ] = " moyenne des moyennes "
2020-09-26 16:19:37 +02:00
else :
2021-11-22 00:31:53 +01:00
row_moys [ col_id ] = " "
def _add_apc_columns (
2022-01-25 10:45:13 +01:00
modimpl ,
2021-11-22 00:31:53 +01:00
evals_poids ,
ues ,
rows ,
columns_ids ,
titles ,
2021-12-08 23:43:07 +01:00
is_conforme : bool ,
2021-11-22 00:31:53 +01:00
row_coefs ,
row_poids ,
row_note_max ,
row_moys ,
keep_numeric ,
) :
""" Ajoute les colonnes moyennes vers les UE """
# On raccorde ici les nouveaux calculs de notes (BUT 2021)
# sur l'ancien code ScoDoc
# => On recharge tout dans les nouveaux modèles
# rows est une liste de dict avec une clé "etudid"
# on va y ajouter une clé par UE du semestre
2022-02-06 16:09:17 +01:00
nt : NotesTableCompat = res_sem . load_formsemestre_results ( modimpl . formsemestre )
2022-01-25 10:45:13 +01:00
modimpl_results : ModuleImplResults = nt . modimpls_results [ modimpl . id ]
# XXX A ENLEVER TODO
# modimpl = ModuleImpl.query.get(moduleimpl_id)
# evals_notes, evaluations, evaluations_completes = moy_mod.df_load_modimpl_notes(
# moduleimpl_id
# )
# etuds_moy_module = moy_mod.compute_module_moy(
# evals_notes, evals_poids, evaluations, evaluations_completes
# )
2021-12-08 23:43:07 +01:00
if is_conforme :
# valeur des moyennes vers les UEs:
for row in rows :
for ue in ues :
2022-01-25 10:45:13 +01:00
moy_ue = modimpl_results . etuds_moy_module [ ue . id ] . get ( row [ " etudid " ] , " ? " )
2021-12-08 23:43:07 +01:00
row [ f " moy_ue_ { ue . id } " ] = scu . fmt_note ( moy_ue , keep_numeric = keep_numeric )
row [ f " _moy_ue_ { ue . id } _class " ] = " moy_ue "
# Nom et coefs des UE (lignes titres):
ue_coefs = modimpl . module . ue_coefs
if is_conforme :
coef_class = " coef_mod_ue "
else :
coef_class = " coef_mod_ue_non_conforme "
2021-11-22 00:31:53 +01:00
for ue in ues :
col_id = f " moy_ue_ { ue . id } "
titles [ col_id ] = ue . acronyme
columns_ids . append ( col_id )
2021-12-08 22:33:32 +01:00
coefs = [ uc for uc in ue_coefs if uc . ue_id == ue . id ]
if coefs :
row_coefs [ f " moy_ue_ { ue . id } " ] = coefs [ 0 ] . coef
2021-12-08 23:43:07 +01:00
row_coefs [ f " _moy_ue_ { ue . id } _td_attrs " ] = f ' class= " { coef_class } " '