356 lines
11 KiB
Python
356 lines
11 KiB
Python
#!/usr/bin/env python
|
|
# encoding: utf-8
|
|
|
|
import dash
|
|
import dash_html_components as html
|
|
import dash_core_components as dcc
|
|
import dash_table
|
|
import plotly.graph_objects as go
|
|
from datetime import date, datetime
|
|
import uuid
|
|
import pandas as pd
|
|
import yaml
|
|
|
|
from ...scripts.getconfig import config
|
|
from ...config import NO_ST_COLUMNS
|
|
from ..app import app
|
|
from ...scripts.exam import Exam
|
|
|
|
QUESTION_COLUMNS = [
|
|
{"id": "id", "name": "Question"},
|
|
{
|
|
"id": "competence",
|
|
"name": "Competence",
|
|
"presentation": "dropdown",
|
|
},
|
|
{"id": "theme", "name": "Domaine"},
|
|
{"id": "comment", "name": "Commentaire"},
|
|
{"id": "score_rate", "name": "Bareme"},
|
|
{"id": "is_leveled", "name": "Est_nivele"},
|
|
]
|
|
|
|
|
|
def get_current_year_limit():
|
|
today = date.today()
|
|
if today.month > 8:
|
|
return {
|
|
"min_date_allowed": date(today.year, 9, 1),
|
|
"max_date_allowed": date(today.year + 1, 7, 15),
|
|
"initial_visible_month": today,
|
|
}
|
|
|
|
return {
|
|
"min_date_allowed": date(today.year - 1, 9, 1),
|
|
"max_date_allowed": date(today.year, 7, 15),
|
|
"initial_visible_month": today,
|
|
}
|
|
|
|
|
|
layout = html.Div(
|
|
[
|
|
html.Header(
|
|
children=[
|
|
html.H1("Création d'une évaluation"),
|
|
html.P("Pas encore de sauvegarde", id="is-saved"),
|
|
html.Button("Enregistrer dans csv", id="save-csv"),
|
|
],
|
|
),
|
|
html.Main(
|
|
children=[
|
|
html.Section(
|
|
children=[
|
|
html.Form(
|
|
id="new-exam",
|
|
children=[
|
|
html.Label(
|
|
children=[
|
|
"Classe",
|
|
dcc.Dropdown(
|
|
id="tribe",
|
|
options=[
|
|
{"label": t["name"], "value": t["name"]}
|
|
for t in config["tribes"]
|
|
],
|
|
value=config["tribes"][0]["name"],
|
|
),
|
|
]
|
|
),
|
|
html.Label(
|
|
children=[
|
|
"Nom de l'évaluation",
|
|
dcc.Input(
|
|
id="exam_name",
|
|
type="text",
|
|
placeholder="Nom de l'évaluation",
|
|
),
|
|
]
|
|
),
|
|
html.Label(
|
|
children=[
|
|
"Date",
|
|
dcc.DatePickerSingle(
|
|
id="date",
|
|
date=date.today(),
|
|
**get_current_year_limit(),
|
|
),
|
|
]
|
|
),
|
|
html.Label(
|
|
children=[
|
|
"Trimestre",
|
|
dcc.Dropdown(
|
|
id="term",
|
|
options=[
|
|
{"label": i + 1, "value": i + 1}
|
|
for i in range(3)
|
|
],
|
|
value=1,
|
|
),
|
|
]
|
|
),
|
|
],
|
|
),
|
|
],
|
|
id="form",
|
|
),
|
|
html.Section(
|
|
children=[
|
|
html.Div(
|
|
id="exercises",
|
|
children=[],
|
|
),
|
|
html.Button(
|
|
"Ajouter un exercice",
|
|
id="add-exercise",
|
|
className="add-exercise",
|
|
),
|
|
html.Div(
|
|
id="summary",
|
|
),
|
|
],
|
|
id="exercises",
|
|
),
|
|
html.Section(
|
|
children=[
|
|
html.Div(
|
|
id="score_rate",
|
|
),
|
|
html.Div(
|
|
id="exercises-viz",
|
|
),
|
|
html.Div(
|
|
id="competences-viz",
|
|
),
|
|
html.Div(
|
|
id="themes-viz",
|
|
),
|
|
],
|
|
id="visualisation",
|
|
),
|
|
]
|
|
),
|
|
dcc.Store(id="exam_store"),
|
|
]
|
|
)
|
|
|
|
|
|
@app.callback(
|
|
dash.dependencies.Output("exercises", "children"),
|
|
dash.dependencies.Input("add-exercise", "n_clicks"),
|
|
dash.dependencies.State("exercises", "children"),
|
|
)
|
|
def add_exercise(n_clicks, children):
|
|
if n_clicks is None:
|
|
return children
|
|
element_table = pd.DataFrame(columns=[c["id"] for c in QUESTION_COLUMNS])
|
|
element_table = element_table.append(
|
|
pd.Series(
|
|
data={
|
|
"id": 1,
|
|
"competence": "Rechercher",
|
|
"theme": "",
|
|
"comment": "",
|
|
"score_rate": 1,
|
|
"is_leveled": 1,
|
|
},
|
|
name=0,
|
|
)
|
|
)
|
|
new_exercise = html.Div(
|
|
children=[
|
|
html.Div(
|
|
children=[
|
|
dcc.Input(
|
|
id={"type": "exercice", "index": str(n_clicks)},
|
|
type="text",
|
|
value=f"Exercice {len(children)+1}",
|
|
placeholder="Nom de l'exercice",
|
|
className="exercise-name",
|
|
),
|
|
html.Button(
|
|
"X",
|
|
id={"type": "rm_exercice", "index": str(n_clicks)},
|
|
className="delete-exercise",
|
|
),
|
|
],
|
|
className="exercise-head",
|
|
),
|
|
dash_table.DataTable(
|
|
id={"type": "elements", "index": str(n_clicks)},
|
|
columns=QUESTION_COLUMNS,
|
|
data=element_table.to_dict("records"),
|
|
editable=True,
|
|
row_deletable=True,
|
|
dropdown={
|
|
"competence": {
|
|
"options": [
|
|
{"label": i, "value": i} for i in config["competences"]
|
|
]
|
|
},
|
|
},
|
|
style_cell={
|
|
"whiteSpace": "normal",
|
|
"height": "auto",
|
|
},
|
|
),
|
|
html.Button(
|
|
"Ajouter un élément de notation",
|
|
id={"type": "add-element", "index": str(n_clicks)},
|
|
className="add-element",
|
|
),
|
|
],
|
|
className="exercise",
|
|
id=f"exercise-{n_clicks}",
|
|
)
|
|
children.append(new_exercise)
|
|
return children
|
|
|
|
|
|
@app.callback(
|
|
dash.dependencies.Output(
|
|
{"type": "elements", "index": dash.dependencies.MATCH}, "data"
|
|
),
|
|
dash.dependencies.Input(
|
|
{"type": "add-element", "index": dash.dependencies.MATCH}, "n_clicks"
|
|
),
|
|
[
|
|
dash.dependencies.State(
|
|
{"type": "elements", "index": dash.dependencies.MATCH}, "data"
|
|
),
|
|
],
|
|
prevent_initial_call=True,
|
|
)
|
|
def add_element(n_clicks, elements):
|
|
if n_clicks is None or n_clicks < len(elements):
|
|
return elements
|
|
|
|
df = pd.DataFrame.from_records(elements)
|
|
df = df.append(
|
|
pd.Series(
|
|
data={
|
|
"id": len(df) + 1,
|
|
"competence": "",
|
|
"theme": "",
|
|
"comment": "",
|
|
"score_rate": 1,
|
|
"is_leveled": 1,
|
|
},
|
|
name=n_clicks,
|
|
)
|
|
)
|
|
return df.to_dict("records")
|
|
|
|
|
|
def exam_generalities(tribe, exam_name, date, term, exercices=[], elements=[]):
|
|
return [
|
|
html.H1(f"{exam_name} pour les {tribe}"),
|
|
html.P(f"Fait le {date} (Trimestre {term})"),
|
|
]
|
|
|
|
|
|
def exercise_summary(identifier, name, elements=[]):
|
|
df = pd.DataFrame.from_records(elements)
|
|
return html.Div(
|
|
[
|
|
html.H2(name),
|
|
dash_table.DataTable(
|
|
columns=[{"id": c, "name": c} for c in df], data=elements
|
|
),
|
|
]
|
|
)
|
|
|
|
|
|
@app.callback(
|
|
dash.dependencies.Output("exam_store", "data"),
|
|
[
|
|
dash.dependencies.Input("tribe", "value"),
|
|
dash.dependencies.Input("exam_name", "value"),
|
|
dash.dependencies.Input("date", "date"),
|
|
dash.dependencies.Input("term", "value"),
|
|
dash.dependencies.Input(
|
|
{"type": "exercice", "index": dash.dependencies.ALL}, "value"
|
|
),
|
|
dash.dependencies.Input(
|
|
{"type": "elements", "index": dash.dependencies.ALL}, "data"
|
|
),
|
|
],
|
|
dash.dependencies.State({"type": "elements", "index": dash.dependencies.ALL}, "id"),
|
|
)
|
|
def store_exam(tribe, exam_name, date, term, exercices, elements, elements_id):
|
|
exam = Exam(exam_name, tribe, date, term)
|
|
for (i, name) in enumerate(exercices):
|
|
ex_elements_id = [el for el in elements_id if el["index"] == str(i + 1)][0]
|
|
index = elements_id.index(ex_elements_id)
|
|
ex_elements = elements[index]
|
|
exam.add_exercise(name, ex_elements)
|
|
|
|
return exam.to_dict()
|
|
|
|
|
|
@app.callback(
|
|
dash.dependencies.Output("score_rate", "children"),
|
|
dash.dependencies.Input("exam_store", "data"),
|
|
prevent_initial_call=True,
|
|
)
|
|
def score_rate(data):
|
|
exam = Exam(**data)
|
|
return [html.P(f"Barème /{exam.score_rate}")]
|
|
|
|
|
|
@app.callback(
|
|
dash.dependencies.Output("competences-viz", "figure"),
|
|
dash.dependencies.Input("exam_store", "data"),
|
|
prevent_initial_call=True,
|
|
)
|
|
def competences_viz(data):
|
|
exam = Exam(**data)
|
|
return [html.P(str(exam.competences_rate))]
|
|
|
|
|
|
@app.callback(
|
|
dash.dependencies.Output("themes-viz", "children"),
|
|
dash.dependencies.Input("exam_store", "data"),
|
|
prevent_initial_call=True,
|
|
)
|
|
def themes_viz(data):
|
|
exam = Exam(**data)
|
|
themes_rate = exam.themes_rate
|
|
fig = go.Figure()
|
|
if themes_rate:
|
|
fig.add_trace(go.Pie(labels=list(themes_rate.keys()), values=list(themes_rate.values())))
|
|
return [dcc.Graph(figure=fig)]
|
|
return []
|
|
|
|
|
|
@app.callback(
|
|
dash.dependencies.Output("is-saved", "children"),
|
|
dash.dependencies.Input("save-csv", "n_clicks"),
|
|
dash.dependencies.State("exam_store", "data"),
|
|
prevent_initial_call=True,
|
|
)
|
|
def save_to_csv(n_clicks, data):
|
|
exam = Exam(**data)
|
|
csv = exam.path(".csv")
|
|
exam.write_csv()
|
|
return [f"Dernière sauvegarde {datetime.today()} dans {csv}"]
|