Signed-off-by: Cherif <cbalde@mysy-training.com>
master_Elyos_FI
Cherif 2025-06-30 21:18:01 +02:00
parent 191d205a75
commit 0fa22292ea
6 changed files with 65315 additions and 19 deletions

View File

@ -4,13 +4,13 @@
<option name="autoReloadType" value="SELECTIVE" />
</component>
<component name="ChangeListManager">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="qsd">
<list default="true" id="c6d0259a-16e1-410d-91a1-830590ee2a08" name="Changes" comment="qsdssdd">
<change afterPath="$PROJECT_DIR$/tools_cherif/barchart.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Log/log_file.log" beforeDir="false" afterPath="$PROJECT_DIR$/Log/log_file.log" afterDir="false" />
<change beforePath="$PROJECT_DIR$/Session_Formation.py" beforeDir="false" afterPath="$PROJECT_DIR$/Session_Formation.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/base_class_calcul_note.py" beforeDir="false" afterPath="$PROJECT_DIR$/base_class_calcul_note.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.py" beforeDir="false" afterPath="$PROJECT_DIR$/main.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/prj_common.py" beforeDir="false" afterPath="$PROJECT_DIR$/prj_common.py" afterDir="false" />
<change beforePath="$PROJECT_DIR$/tools_cherif/tools_cherif.py" beforeDir="false" afterPath="$PROJECT_DIR$/tools_cherif/tools_cherif.py" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -49,19 +49,20 @@
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">{
&quot;keyToString&quot;: {
&quot;Python.main.executor&quot;: &quot;Run&quot;,
&quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
&quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
&quot;git-widget-placeholder&quot;: &quot;master__Elyos__FI&quot;,
&quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
&quot;last_opened_file_path&quot;: &quot;C:/Users/Cherif/Documents/myclass.com/Siteweb/Elyos_Ftion_Initiale/Ela_back/Back_Office_FI&quot;,
&quot;settings.editor.selected.configurable&quot;: &quot;project.propVCSSupport.CommitDialog&quot;
<component name="PropertiesComponent"><![CDATA[{
"keyToString": {
"Python.main.executor": "Run",
"RunOnceActivity.OpenProjectViewOnStart": "true",
"RunOnceActivity.ShowReadmeOnStart": "true",
"git-widget-placeholder": "master__Elyos__FI",
"ignore.virus.scanning.warn.message": "true",
"last_opened_file_path": "C:/Users/Cherif/Documents/myclass.com/Siteweb/Elyos_Ftion_Initiale/Ela_back/Back_Office_FI/tools_cherif",
"settings.editor.selected.configurable": "project.propVCSSupport.CommitDialog"
}
}</component>
}]]></component>
<component name="RecentsManager">
<key name="CopyFile.RECENT_KEYS">
<recent name="C:\Users\Cherif\Documents\myclass.com\Siteweb\Elyos_Ftion_Initiale\Ela_back\Back_Office_FI\tools_cherif" />
<recent name="C:\Users\billa\Documents\myclass.com\Siteweb\Production\Ela_back\Back_Office\tools_cherif" />
<recent name="C:\Users\billa\Documents\myclass.com\Siteweb\Production\Ela_back\Back_Office" />
</key>
@ -452,7 +453,7 @@
<option name="project" value="LOCAL" />
<updated>1747251650255</updated>
</task>
<option name="localTasksCounter" value="482" />
<option name="localTasksCounter" value="483" />
<servers />
</component>
<component name="Vcs.Log.Tabs.Properties">
@ -494,7 +495,6 @@
</option>
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="06/05/2025 - 20h" />
<MESSAGE value="07/05/2025 - 20h" />
<MESSAGE value="08/05/2025 - 14h" />
<MESSAGE value="08/05/2025 - 19" />
@ -519,6 +519,7 @@
<MESSAGE value="ssqsdqsd" />
<MESSAGE value="25/06/2025 - 18h" />
<MESSAGE value="qsd" />
<option name="LAST_COMMIT_MESSAGE" value="qsd" />
<MESSAGE value="qsdssdd" />
<option name="LAST_COMMIT_MESSAGE" value="qsdssdd" />
</component>
</project>

File diff suppressed because one or more lines are too long

View File

@ -26,11 +26,13 @@ La collection : "note_evaluation_participant" :
- Elle contient les notes attribuées à un apprenant sur une evaluation.
- Elle contient les informations :evaluation_id, inscription_id, group_inscription_id, note (la note obtenue par l'apprenant)
"""
import base64
from zipfile import ZipFile
import bson
import pymongo
from flask import send_file
from matplotlib import pyplot as plt
from pandas.io.formats.style import jinja2
from pymongo import MongoClient
import json
@ -48,8 +50,7 @@ import sys, os
from pymongo import ReturnDocument
import GlobalVariable as MYSY_GV
from GlobalVariable import dbname
"""
Cette fonction permet d'appliquer la regle de calcul :
@ -2161,6 +2162,132 @@ def Cacul_UE_Note_Finale_Standard(diction):
upsert=False,
)
"""
Remplir la collection 'note_categorie_session_ue'
qui permet de connaitre le pourcentage de personnes
par eu et par note_categorie
"""
pipe_qry_nb_personne_par_ue = [
{'$match': {"partner_owner_recid": str(my_partner['recid']),
'class_id': str(diction['class_id']),
'session_id': str(diction['session_id'])
}},
{'$group': {
'_id': {
"session_id": "$session_id",
"ue_id": "$ue_id",
},
"count": {"$sum": 1}
}
},
]
for retval in MYSY_GV.dbname['session_formation_final_note_classement'].aggregate(pipe_qry_nb_personne_par_ue):
print(" ### retval pipe_qry_nb_personne_par_ue = ", retval)
pipe_qry = [
{'$match': {"partner_owner_recid": str(my_partner['recid']),
'class_id': str(diction['class_id']),
'session_id': str(diction['session_id'])
}},
{'$group': {
'_id': {
"session_id": "$session_id",
"ue_id": "$ue_id",
"note_categorie": "$note_categorie",
},
"count": {"$sum": 1}
}
},
]
"""
Initialisation de toutes les categorie de note à un pourcentage de '0'
"""
print(" ### tab_ue_ids = ", tab_ue_ids)
for local_ue in str(tab_ue_ids).split(","):
if( local_ue):
for val in MYSY_GV.dbname['note_categorie'].find({'valide':'1', 'locked':'0'}):
node_note_categorie_session_ue = {}
node_note_categorie_session_ue['partner_owner_recid'] = str(my_partner['recid'])
node_note_categorie_session_ue['valide'] = "1"
node_note_categorie_session_ue['locked'] = "0"
node_note_categorie_session_ue['date_creation'] = str(datetime.now())
node_note_categorie_session_ue['creation_by'] = str(my_partner['_id'])
node_note_categorie_session_ue['session_id'] = str(diction['session_id'])
node_note_categorie_session_ue['ue_id'] = str(local_ue)
node_note_categorie_session_ue['class_id'] = str(diction['class_id'])
node_note_categorie_session_ue['nb_personne'] = "0"
node_note_categorie_session_ue['note_categorie_code'] = val['code']
node_note_categorie_session_ue['pourcentage'] = "0"
print(" ### node_note_categorie_session_ue = ", node_note_categorie_session_ue)
data_key = {}
data_key['ue_id'] = str(local_ue)
data_key['class_id'] = str(diction['class_id'])
data_key['session_id'] = str(diction['session_id'])
data_key['note_categorie_code'] = val['code']
data_key['partner_owner_recid'] = str(my_partner['recid'])
ret_val = MYSY_GV.dbname['note_categorie_session_ue'].find_one_and_update(
data_key,
{"$set": node_note_categorie_session_ue},
upsert=True,
return_document=ReturnDocument.AFTER
)
tab_data = []
for retval in MYSY_GV.dbname['session_formation_final_note_classement'].aggregate(pipe_qry):
print(" ### retval ici pipe_qry = ", retval)
## Calcul du nombre total d'inscrit pour cette UE
total_personne = MYSY_GV.dbname['session_formation_final_note_classement'].count_documents({'partner_owner_recid':str(my_partner['recid']),
'session_id':str(retval['_id']['session_id']),
'ue_id':str(retval['_id']['ue_id'])})
print(" ### total_personne pour UE ("+str(str(retval['_id']['ue_id']))+") = ", total_personne)
node_note_categorie_session_ue = {}
node_note_categorie_session_ue['partner_owner_recid'] = str(my_partner['recid'])
node_note_categorie_session_ue['valide'] = "1"
node_note_categorie_session_ue['locked'] = "0"
node_note_categorie_session_ue['date_creation'] = str(datetime.now())
node_note_categorie_session_ue['creation_by'] = str(my_partner['_id'])
node_note_categorie_session_ue['session_id'] = retval['_id']['session_id']
node_note_categorie_session_ue['ue_id'] = retval['_id']['ue_id']
node_note_categorie_session_ue['class_id'] = str(diction['class_id'])
node_note_categorie_session_ue['nb_personne'] = str(retval['count'])
node_note_categorie_session_ue['note_categorie_code'] = retval['_id']['note_categorie']
pourcentage = ""
if( total_personne > 0):
pourcentage = round( float(str(retval['count'])) / float(total_personne) * 100, 2)
node_note_categorie_session_ue['pourcentage'] = str(pourcentage)
else:
node_note_categorie_session_ue['pourcentage'] = ""
data_key = {}
data_key['ue_id'] = retval['_id']['ue_id']
data_key['class_id'] = str(diction['class_id'])
data_key['session_id'] = retval['_id']['session_id']
data_key['note_categorie_code'] = retval['_id']['note_categorie']
data_key['partner_owner_recid'] = str(my_partner['recid'])
ret_val = MYSY_GV.dbname['note_categorie_session_ue'].find_one_and_update(
data_key,
{"$set": node_note_categorie_session_ue},
upsert=False,
return_document=ReturnDocument.AFTER
)
"""
Après avoir calculer et definit le rang par session, nous allons à présent faire le classement final pour toute la promo/session
@ -2802,6 +2929,7 @@ def Create_Bulletin_By_Inscrit_PDF(diction):
return local_status, my_partner
# 1 - Verifier que le modele de courrier est bien editable par individu
template_courrier_data = MYSY_GV.dbname['courrier_template'].find_one({'_id':ObjectId(str(diction['courrier_template_id'])),
'valide':'1',
@ -2840,6 +2968,8 @@ def Create_Bulletin_By_Inscrit_PDF(diction):
tab_apprenant.append(ObjectId(str(statgiaire_data['apprenant_id'])))
# Recuperer les notes des UE dans la collection 'session_formation_final_note_classement'
session_formation_final_note_classement_data = []
for note_classement_data in MYSY_GV.dbname['session_formation_final_note_classement'].find({'inscription_id': str(diction['inscription_id']),
@ -2854,6 +2984,48 @@ def Create_Bulletin_By_Inscrit_PDF(diction):
else:
local_node['ue_id_data'] = {}
"""
Creation de l'image Graphe de repartition
"""
graph_local_node = {}
graph_local_node['apprenant_categorie'] = local_node['note_categorie']
graph_local_node['categorie'] = "A,B,C,D,E"
tab_pourcentage = []
print(" ## qry = ", {'partner_owner_recid':str(my_partner['recid']),
'session_id': str(local_node['session_id']),
'ue_id': str(local_node['ue_id']),
})
for data in MYSY_GV.dbname['note_categorie_session_ue'].find({'partner_owner_recid':str(my_partner['recid']),
'session_id': str(local_node['session_id']),
'ue_id': str(local_node['ue_id']),
}).sort([("note_categorie_code", pymongo.ASCENDING), ]):
tab_pourcentage.append(str(data['pourcentage']))
print('### tab_pourcentage = ', tab_pourcentage)
final_tab_pourcentage = ",".join(tab_pourcentage)
graph_local_node['pourcentage'] = final_tab_pourcentage
print('### graph_local_node = ', graph_local_node)
local_graph_status, local_graph_retval = Create_Bar_Chart_And_Save_Ok(graph_local_node)
if( local_graph_status ):
print(" ### local_graph_retval = ", local_graph_retval)
filepath = str(local_graph_retval)
binary_fc = open(filepath, 'rb').read() # fc aka file_content
base64_utf8_str = base64.b64encode(binary_fc).decode('utf-8')
ext = filepath.split('.')[-1]
graphe = f'data:image/{ext};base64,{base64_utf8_str}'
local_node['graphe'] = graphe
else:
local_node['graphe'] = ""
session_formation_final_note_classement_data.append(local_node)
@ -2888,6 +3060,7 @@ def Create_Bulletin_By_Inscrit_PDF(diction):
convention_dictionnary_data['full_statgiaire_data'] = statgiaire_data
body = {
"params": convention_dictionnary_data,
}
@ -2926,3 +3099,90 @@ def Create_Bulletin_By_Inscrit_PDF(diction):
mycommon.myprint(str(inspect.stack()[0][3]) + " -" + str(e) + " - Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de créer le fichier pdf Create_Bulletin_By_Inscrit_PDF "
"""
Creation d'une graphique et enregistrement de l'image
"""
def Create_Bar_Chart_And_Save_Ok(diction):
try:
categorie = []
pourcentage = []
print(" ## diction['categorie'] = ", diction['categorie'])
categorie_split = str(diction['categorie']).split(',')
for val in categorie_split:
if( val):
print(" ### val = ",val)
categorie.append(str(val))
pourcentage_split = str(diction['pourcentage']).split(',')
for val in pourcentage_split:
if( val ):
val_float = mycommon.tryFloat(str(val))
pourcentage.append(val_float)
fig, ax = plt.subplots()
if ("apprenant_categorie" in diction.keys() and diction['apprenant_categorie']):
if (str(diction['apprenant_categorie']).lower() == "a"):
categorie = ['=A=', 'B', 'C', 'D', 'E']
elif (str(diction['apprenant_categorie']).lower() == "b"):
categorie = ['A', '=B=', 'C', 'D', 'E']
elif (str(diction['apprenant_categorie']).lower() == "c"):
categorie = ['A', 'B', '=C=', 'D', 'E']
elif (str(diction['apprenant_categorie']).lower() == "d"):
categorie = ['A', 'B', 'C', '=D=', 'E']
elif (str(diction['apprenant_categorie']).lower() == "e"):
categorie = ['A', 'B', 'C', 'D', '=E=']
bar_labels = ['red', 'blue', '_red', 'orange']
bar_colors = ['tab:green', 'tab:blue', 'tab:orange', 'tab:red' ]
rects = ax.bar(categorie, pourcentage, color=bar_colors)
#ax.set_ylabel('')
#ax.set_title('Fruit supply by kind and color')
#ax.legend(title='Fruit color')
"""ax.bar_label(rects, fontweight='bold',
color='midnightblue',
padding=4)"""
labels = ax.bar_label(ax.containers[0], color='black', fontsize=10)
print(ax.legend())
for label in labels:
label.set_ha('right')
print(" ### label.get_text() = ", label.get_text())
if label.get_text() == '40':
label.set_color('b')
label.set_text("Eleve")
label.set_fontstyle("oblique")
label.set_fontweight('bold')
#label.set_fontsize(20)
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-7:]
orig_file_name = "graph_" + str(ts) + ".png"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
plt.savefig(outputFilename)
return True, str(outputFilename)
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de Create_Bar_Chart_And_Save"

12
main.py
View File

@ -13335,6 +13335,18 @@ def ENT_Enable_Apprenant_Account():
return jsonify(status=status, message=retval)
"""
API de creation d'un graphique et sauvegade en PNG
"""
@app.route('/myclass/api/Create_Bar_Chart_And_Save/', methods=['POST','GET'])
@crossdomain(origin='*')
def Create_Bar_Chart_And_Save():
# On recupere le corps (payload) de la requete
payload = mycommon.strip_dictionary (request.form.to_dict())
print(" ### Create_Bar_Chart_And_Save payload = ",payload)
status, retval = tools_cherif.Create_Bar_Chart_And_Save(payload)
return jsonify(status=status, message=retval)
if __name__ == '__main__':
print(" debut api")

61
tools_cherif/barchart.py Normal file
View File

@ -0,0 +1,61 @@
"""
=============================
Grouped bar chart with labels
=============================
This example shows a how to create a grouped bar chart and how to annotate
bars with labels.
"""
# data from https://allisonhorst.github.io/palmerpenguins/
import matplotlib.pyplot as plt
import numpy as np
import GlobalVariable as MYSY_GV
species = ("Adelie", "Chinstrap", "Gentoo")
penguin_means = {
'Bill Depth': (18.35, 18.43, 14.98),
'Bill Length': (38.79, 48.83, 47.50),
'Flipper Length': (189.95, 195.82, 217.19),
}
x = np.arange(len(species)) # the label locations
width = 0.25 # the width of the bars
multiplier = 0
fig, ax = plt.subplots(layout='constrained')
for attribute, measurement in penguin_means.items():
offset = width * multiplier
rects = ax.bar(x + offset, measurement, width, label=attribute)
ax.bar_label(rects, padding=3)
multiplier += 1
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Length (mm)')
ax.set_title('Penguin attributes by species')
ax.set_xticks(x + width, species)
ax.legend(loc='upper left', ncols=3)
ax.set_ylim(0, 250)
img_name = str(MYSY_GV.TEMPORARY_DIRECTORY_V2)+"graph.png"
plt.savefig(img_name)
plt.show()
# %%
#
# .. admonition:: References
#
# The use of the following functions, methods, classes and modules is shown
# in this example:
#
# - `matplotlib.axes.Axes.bar` / `matplotlib.pyplot.bar`
# - `matplotlib.axes.Axes.bar_label` / `matplotlib.pyplot.bar_label`
#
# .. tags::
#
# component: label
# plot-type: bar
# level: beginner

View File

@ -24,7 +24,8 @@ import email_mgt as email
import urllib.request
from validate_email import validate_email
import jinja2
import matplotlib.pyplot as plt
import numpy as np
"""
Cette fonction monitore un siteweb.
@ -1828,3 +1829,158 @@ def Delete_Nicole_Account(diction):
print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de Delete_Nicole_Account"
"""
Creation d'une graphique et enregistrement de l'image
"""
def Create_Bar_Chart_And_Save_good(diction):
try:
categorie = []
pourcentage = []
print(" ## diction['categorie'] = ", diction['categorie'])
categorie_split = str(diction['categorie']).split(',')
for val in categorie_split:
if( val):
print(" ### val = ",val)
categorie.append(str(val))
pourcentage_split = str(diction['pourcentage']).split(',')
for val in pourcentage_split:
if( val ):
val_float = mycommon.tryFloat(str(val))
pourcentage.append(val_float)
fig, ax = plt.subplots()
if ("apprenant_categorie" in diction.keys() and diction['apprenant_categorie']):
if (str(diction['apprenant_categorie']).lower() == "a"):
categorie = ['=A=', 'B', 'C', 'D']
elif (str(diction['apprenant_categorie']).lower() == "b"):
categorie = ['A', '=B=', 'C', 'D']
elif (str(diction['apprenant_categorie']).lower() == "c"):
categorie = ['A', 'B', '=C=', 'D']
elif (str(diction['apprenant_categorie']).lower() == "d"):
categorie = ['A', 'B', 'C', '=D=']
bar_labels = ['red', 'blue', '_red', 'orange']
bar_colors = ['tab:green', 'tab:blue', 'tab:orange', 'tab:red' ]
rects = ax.bar(categorie, pourcentage, color=bar_colors)
#ax.set_ylabel('')
#ax.set_title('Fruit supply by kind and color')
#ax.legend(title='Fruit color')
"""ax.bar_label(rects, fontweight='bold',
color='midnightblue',
padding=4)"""
labels = ax.bar_label(ax.containers[0], color='black', fontsize=10)
print(ax.legend())
for label in labels:
label.set_ha('right')
print(" ### label.get_text() = ", label.get_text())
if label.get_text() == '40':
label.set_color('b')
label.set_text("Eleve")
label.set_fontstyle("oblique")
label.set_fontweight('bold')
#label.set_fontsize(20)
ts = datetime.now().timestamp()
ts = str(ts).replace(".", "").replace(",", "")[-7:]
orig_file_name = "graph_" + str(ts) + ".png"
outputFilename = str(MYSY_GV.TEMPORARY_DIRECTORY) + "/" + str(orig_file_name)
plt.savefig(outputFilename)
plt.show()
return True, "Graphe OK : "+str(outputFilename)
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de Create_Bar_Chart_And_Save"
def Create_Bar_Chart_And_Save_CB():
try:
species = ("Adelie", "Chinstrap", "Gentoo")
penguin_means = {
'Nb_Apprenants': (2, 18, 14, 5)
}
x = np.arange(len(species)) # the label locations
width = 0.25 # the width of the bars
multiplier = 0
fig, ax = plt.subplots(layout='constrained')
for attribute, measurement in penguin_means.items():
offset = width * multiplier
rects = ax.bar(x + offset, measurement, width, label=attribute)
ax.bar_label(rects, padding=3)
multiplier += 1
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Length (mm)')
ax.set_title('Positionnement Apprenant ')
ax.set_xticks(x + width, species)
ax.legend(loc='upper left', ncols=4)
ax.set_ylim(0, 250)
img_name = str(MYSY_GV.TEMPORARY_DIRECTORY_V2) + "graph.png"
plt.savefig(img_name)
plt.show()
return True, "Grpahe OK"
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de Create_Bar_Chart_And_Save"
def Create_Bar_Chart_And_Save(diction):
try:
pipe_qry = [
{'$match': {"partner_owner_recid":'43598820dd270936c3d2fd822717d0f18f194b1a1b894aaf89', 'class_id':'6655b721fd47c656dcaf8f05'}},
{'$group': {
'_id': {
"session_id": "$session_id",
"ue_id": "$ue_id",
"note_categorie": "$note_categorie",
},
"count": { "$sum": 1}
}
},
]
tab_data = []
for retval in MYSY_GV.dbname['session_formation_final_note_classement'].aggregate(pipe_qry):
print(" ### retval ici pipe_qry = ", retval)
return True, "Grpahe OK"
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
print(str(inspect.stack()[0][3]) + " -" + str(e) + " - ERRORRRR AT Line : " + str(exc_tb.tb_lineno))
return False, " Impossible de Create_Bar_Chart_And_Save"