Compare commits
6 Commits
a50901556e
...
9e0ea14d05
Author | SHA1 | Date | |
---|---|---|---|
9e0ea14d05 | |||
2031ade1ab | |||
6ed55c07d4 | |||
1d234ea5fc | |||
646314ad88 | |||
0739cfdae7 |
@ -15,10 +15,11 @@ layout = html.Div(
|
||||
],
|
||||
),
|
||||
html.Main(
|
||||
children=[
|
||||
html.Section(
|
||||
[
|
||||
children=[
|
||||
html.Div(
|
||||
[
|
||||
children=[
|
||||
"Classe: ",
|
||||
dcc.Dropdown(
|
||||
id="tribe",
|
||||
@ -31,45 +32,36 @@ layout = html.Div(
|
||||
],
|
||||
),
|
||||
html.Div(
|
||||
[
|
||||
children=[
|
||||
"Evaluation: ",
|
||||
dcc.Dropdown(id="exam_select"),
|
||||
],
|
||||
html.P(id="test"),
|
||||
),
|
||||
],
|
||||
id="select",
|
||||
id="selects",
|
||||
),
|
||||
html.Section(
|
||||
[
|
||||
children=[
|
||||
html.Div(
|
||||
dash_table.DataTable(
|
||||
id="final_score_table",
|
||||
columns=[
|
||||
{"id": "Eleve", "name": "Élève"},
|
||||
{"id": "Note", "name": "Note"},
|
||||
{"id": "Bareme", "name": "Barème"},
|
||||
],
|
||||
data=[],
|
||||
style_data_conditional=[
|
||||
{
|
||||
"if": {"row_index": "odd"},
|
||||
"backgroundColor": "rgb(248, 248, 248)",
|
||||
}
|
||||
],
|
||||
style_data={
|
||||
"width": "100px",
|
||||
"maxWidth": "100px",
|
||||
"minWidth": "100px",
|
||||
},
|
||||
),
|
||||
children=[],
|
||||
id="final_score_table_container",
|
||||
),
|
||||
],
|
||||
id="analysis",
|
||||
),
|
||||
html.Section(
|
||||
children=[
|
||||
dash_table.DataTable(
|
||||
id="scores_table",
|
||||
columns=[],
|
||||
style_data_conditional=[],
|
||||
fixed_columns={},
|
||||
editable=True,
|
||||
)
|
||||
],
|
||||
id="edit",
|
||||
),
|
||||
],
|
||||
),
|
||||
dcc.Store(id="scores"),
|
||||
],
|
||||
|
@ -1,11 +1,15 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from dash.dependencies import Input, Output
|
||||
from dash.dependencies import Input, Output, State
|
||||
import dash
|
||||
from dash.exceptions import PreventUpdate
|
||||
import dash_table
|
||||
import json
|
||||
import pandas as pd
|
||||
|
||||
from ...app import app
|
||||
from .models import get_tribes, get_exams
|
||||
from .models import get_tribes, get_exams, get_unstack_scores, get_students_from_exam
|
||||
|
||||
|
||||
@app.callback(
|
||||
@ -15,12 +19,11 @@ from .models import get_tribes, get_exams
|
||||
],
|
||||
[Input("tribe", "value")],
|
||||
)
|
||||
def update_csvs(value):
|
||||
if not value:
|
||||
def update_exams_choices(tribe):
|
||||
if not tribe:
|
||||
raise PreventUpdate
|
||||
exams = get_exams(value)
|
||||
exams = get_exams(tribe)
|
||||
exams.reset_index(inplace=True)
|
||||
print(exams.loc[0, "name"])
|
||||
if not exams.empty:
|
||||
return [
|
||||
{"label": e["name"], "value": e.to_json()} for i, e in exams.iterrows()
|
||||
@ -30,24 +33,35 @@ def update_csvs(value):
|
||||
|
||||
@app.callback(
|
||||
[
|
||||
dash.dependencies.Output("final_score", "data"),
|
||||
Output("scores_table", "columns"),
|
||||
Output("scores_table", "data"),
|
||||
Output("scores_table", "style_data_conditional"),
|
||||
Output("scores_table", "fixed_columns"),
|
||||
],
|
||||
[
|
||||
Input("exam_select", "value"),
|
||||
],
|
||||
[dash.dependencies.Input("scores_table", "data")],
|
||||
)
|
||||
def update_final_scores(data):
|
||||
if not data:
|
||||
raise PreventUpdate
|
||||
def update_scores_store(exam):
|
||||
ctx = dash.callback_context
|
||||
if not exam:
|
||||
return [[], [], [], {}]
|
||||
exam = pd.DataFrame.from_dict([json.loads(exam)])
|
||||
scores = get_unstack_scores(exam)
|
||||
fixed_columns = [
|
||||
"exercise",
|
||||
"question",
|
||||
"competence",
|
||||
"theme",
|
||||
"comment",
|
||||
"score_rate",
|
||||
"is_leveled",
|
||||
]
|
||||
columns = fixed_columns + list(get_students_from_exam(exam))
|
||||
|
||||
scores = pd.DataFrame.from_records(data)
|
||||
try:
|
||||
if scores.iloc[0]["Commentaire"] == "commentaire":
|
||||
scores.drop([0], inplace=True)
|
||||
except KeyError:
|
||||
pass
|
||||
scores = flat_df_students(scores).dropna(subset=["Score"])
|
||||
if scores.empty:
|
||||
return [{}]
|
||||
|
||||
scores = pp_q_scores(scores)
|
||||
assessment_scores = scores.groupby(["Eleve"]).agg({"Note": "sum", "Bareme": "sum"})
|
||||
return [assessment_scores.reset_index().to_dict("records")]
|
||||
return [
|
||||
[{"id": c, "name": c} for c in columns],
|
||||
scores.to_dict("records"),
|
||||
[],
|
||||
{"headers": True, "data": len(fixed_columns)},
|
||||
]
|
||||
|
@ -1,7 +1,8 @@
|
||||
#!/usr/bin/env python
|
||||
# encoding: utf-8
|
||||
|
||||
from ....database.filesystem.loader import CSVLoader
|
||||
from recopytex.database.filesystem.loader import CSVLoader
|
||||
from recopytex.lib.dataframe import column_values_to_column
|
||||
|
||||
LOADER = CSVLoader("./test_config.yml")
|
||||
|
||||
@ -13,3 +14,17 @@ def get_tribes():
|
||||
def get_exams(tribe):
|
||||
return LOADER.get_exams([tribe])
|
||||
|
||||
|
||||
def get_record_scores(exam):
|
||||
return LOADER.get_exam_scores(exam)
|
||||
|
||||
|
||||
def get_unstack_scores(exam):
|
||||
flat_scores = LOADER.get_exam_scores(exam)
|
||||
kept_columns = [col for col in LOADER.score_columns if col != "score"]
|
||||
return column_values_to_column(flat_scores, "student_name", "score", kept_columns)
|
||||
|
||||
|
||||
def get_students_from_exam(exam):
|
||||
flat_scores = LOADER.get_exam_scores(exam)
|
||||
return flat_scores["student_name"].unique()
|
||||
|
@ -43,6 +43,49 @@ class CSVLoader(Loader):
|
||||
""" Get config """
|
||||
return self._config
|
||||
|
||||
@property
|
||||
def exam_columns(self):
|
||||
return pd.Index(["name", "date", "term", "origin", "tribe", "id"])
|
||||
|
||||
@property
|
||||
def question_columns(self):
|
||||
return pd.Index(
|
||||
[
|
||||
"exercise",
|
||||
"question",
|
||||
"competence",
|
||||
"theme",
|
||||
"comment",
|
||||
"score_rate",
|
||||
"is_leveled",
|
||||
"origin",
|
||||
"exam_id",
|
||||
"id",
|
||||
]
|
||||
)
|
||||
|
||||
@property
|
||||
def score_columns(self):
|
||||
return pd.Index(
|
||||
[
|
||||
"term",
|
||||
"exam",
|
||||
"date",
|
||||
"exercise",
|
||||
"question",
|
||||
"competence",
|
||||
"theme",
|
||||
"comment",
|
||||
"score_rate",
|
||||
"is_leveled",
|
||||
"origin",
|
||||
"exam_id",
|
||||
"question_id",
|
||||
"student_name",
|
||||
"score",
|
||||
]
|
||||
)
|
||||
|
||||
def rename_columns(self, dataframe):
|
||||
"""Rename dataframe column to match with `csv_fields`
|
||||
|
||||
@ -84,8 +127,8 @@ class CSVLoader(Loader):
|
||||
:example:
|
||||
>>> loader = CSVLoader("./test_config.yml")
|
||||
>>> exams = loader.get_exams(["Tribe1"])
|
||||
>>> exams.columns
|
||||
Index(['name', 'date', 'term', 'origin', 'tribe', 'id'], dtype='object')
|
||||
>>> all(exams.columns == loader.exam_columns)
|
||||
True
|
||||
>>> exams
|
||||
name date term origin tribe id
|
||||
0 DS 12/01/2021 1 example/Tribe1/210112_DS.csv Tribe1 DS_Tribe1
|
||||
@ -118,10 +161,7 @@ class CSVLoader(Loader):
|
||||
:example:
|
||||
>>> loader = CSVLoader("./test_config.yml")
|
||||
>>> exams = loader.get_exams(["Tribe1"])
|
||||
>>> loader.get_exam_questions([exams.iloc[0]]).columns
|
||||
Index(['exercise', 'question', 'competence', 'theme', 'comment', 'score_rate',
|
||||
'is_leveled', 'origin', 'exam_id', 'id'],
|
||||
dtype='object')
|
||||
>>> all(loader.get_exam_questions([exams.iloc[0]]).columns == loader.score_columns)
|
||||
>>> questions = loader.get_exam_questions(exams)
|
||||
>>> questions.iloc[0]
|
||||
exercise Exercice 1
|
||||
@ -172,11 +212,8 @@ class CSVLoader(Loader):
|
||||
>>> exams = loader.get_exams(["Tribe1"])
|
||||
>>> questions = loader.get_exam_questions(exams)
|
||||
>>> scores = loader.get_questions_scores(questions)
|
||||
>>> scores.columns
|
||||
Index(['term', 'exam', 'date', 'exercise', 'question', 'competence', 'theme',
|
||||
'comment', 'score_rate', 'is_leveled', 'origin', 'exam_id',
|
||||
'question_id', 'student_name', 'score'],
|
||||
dtype='object')
|
||||
>>> all(scores.columns == loader.score_columns)
|
||||
True
|
||||
>>> scores["student_name"].unique()
|
||||
array(['Star Tice', 'Umberto Dingate', 'Starlin Crangle',
|
||||
'Humbert Bourcq', 'Gabriella Handyside', 'Stewart Eaves',
|
||||
@ -214,6 +251,24 @@ class CSVLoader(Loader):
|
||||
|
||||
return pd.concat(scores)
|
||||
|
||||
def get_exam_scores(self, exams=[]):
|
||||
"""Get scores for all question of the exam
|
||||
|
||||
:param exams: list or dataframe of exams metadatas (need origin field to find the csv)
|
||||
|
||||
:example:
|
||||
>>> loader = CSVLoader("./test_config.yml")
|
||||
>>> exams = loader.get_exams(["Tribe1"])
|
||||
>>> scores = loader.get_exam_scores(exams)
|
||||
>>> scores.columns
|
||||
Index(['term', 'exam', 'date', 'exercise', 'question', 'competence', 'theme',
|
||||
'comment', 'score_rate', 'is_leveled', 'origin', 'exam_id',
|
||||
'question_id', 'student_name', 'score'],
|
||||
dtype='object')
|
||||
"""
|
||||
questions = self.get_exam_questions(exams)
|
||||
return self.get_questions_scores(questions)
|
||||
|
||||
def get_students(self, tribes=[]):
|
||||
"""Get student list
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user