Compare commits
4 Commits
a8b2ac455d
...
7553628306
Author | SHA1 | Date | |
---|---|---|---|
7553628306 | |||
effc049578 | |||
411f910ce6 | |||
00d81d694a |
23
recopytex/dashboard/common/formating.py
Normal file
23
recopytex/dashboard/common/formating.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
|
||||||
|
def highlight_scores(highlight_columns, score_color):
|
||||||
|
""" Cells style in a datatable for scores
|
||||||
|
|
||||||
|
:param highlight_columns: columns to highlight
|
||||||
|
:param value_color: dictionnary {"score": "color"}
|
||||||
|
|
||||||
|
"""
|
||||||
|
hight = []
|
||||||
|
for v, color in score_color.items():
|
||||||
|
if v:
|
||||||
|
hight += [
|
||||||
|
{
|
||||||
|
"if": {"filter_query": "{{{}}} = {}".format(col, v), "column_id": col},
|
||||||
|
"backgroundColor": color,
|
||||||
|
"color": "white",
|
||||||
|
}
|
||||||
|
for col in highlight_columns
|
||||||
|
]
|
||||||
|
return hight
|
@ -8,8 +8,16 @@ import dash_table
|
|||||||
import json
|
import json
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
from ...app import app
|
from recopytex.dashboard.app import app
|
||||||
from .models import get_tribes, get_exams, get_unstack_scores, get_students_from_exam
|
from recopytex.dashboard.common.formating import highlight_scores
|
||||||
|
|
||||||
|
from .models import (
|
||||||
|
get_tribes,
|
||||||
|
get_exams,
|
||||||
|
get_unstack_scores,
|
||||||
|
get_students_from_exam,
|
||||||
|
get_score_colors,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.callback(
|
@app.callback(
|
||||||
@ -57,11 +65,15 @@ def update_scores_store(exam):
|
|||||||
"score_rate",
|
"score_rate",
|
||||||
"is_leveled",
|
"is_leveled",
|
||||||
]
|
]
|
||||||
columns = fixed_columns + list(get_students_from_exam(exam))
|
|
||||||
|
students = list(get_students_from_exam(exam))
|
||||||
|
columns = fixed_columns + students
|
||||||
|
|
||||||
|
score_color = get_score_colors()
|
||||||
|
|
||||||
return [
|
return [
|
||||||
[{"id": c, "name": c} for c in columns],
|
[{"id": c, "name": c} for c in columns],
|
||||||
scores.to_dict("records"),
|
scores.to_dict("records"),
|
||||||
[],
|
highlight_scores(students, score_color),
|
||||||
{"headers": True, "data": len(fixed_columns)},
|
{"headers": True, "data": len(fixed_columns)},
|
||||||
]
|
]
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
|
|
||||||
from recopytex.database.filesystem.loader import CSVLoader
|
from recopytex.database.filesystem.loader import CSVLoader
|
||||||
from recopytex.lib.dataframe import column_values_to_column
|
from recopytex.datalib.dataframe import column_values_to_column
|
||||||
|
|
||||||
LOADER = CSVLoader("./test_config.yml")
|
LOADER = CSVLoader("./test_config.yml")
|
||||||
|
|
||||||
@ -22,9 +22,17 @@ def get_record_scores(exam):
|
|||||||
def get_unstack_scores(exam):
|
def get_unstack_scores(exam):
|
||||||
flat_scores = LOADER.get_exam_scores(exam)
|
flat_scores = LOADER.get_exam_scores(exam)
|
||||||
kept_columns = [col for col in LOADER.score_columns if col != "score"]
|
kept_columns = [col for col in LOADER.score_columns if col != "score"]
|
||||||
return column_values_to_column(flat_scores, "student_name", "score", kept_columns)
|
return column_values_to_column("student_name", "score", kept_columns, flat_scores)
|
||||||
|
|
||||||
|
|
||||||
def get_students_from_exam(exam):
|
def get_students_from_exam(exam):
|
||||||
flat_scores = LOADER.get_exam_scores(exam)
|
flat_scores = LOADER.get_exam_scores(exam)
|
||||||
return flat_scores["student_name"].unique()
|
return flat_scores["student_name"].unique()
|
||||||
|
|
||||||
|
|
||||||
|
def get_score_colors():
|
||||||
|
scores_config = LOADER.get_config()["valid_scores"]
|
||||||
|
score_color = {}
|
||||||
|
for key, score in scores_config.items():
|
||||||
|
score_color[score["value"]] = score["color"]
|
||||||
|
return score_color
|
||||||
|
@ -22,13 +22,27 @@ competences: # Competences
|
|||||||
abrv: Com
|
abrv: Com
|
||||||
|
|
||||||
valid_scores: #
|
valid_scores: #
|
||||||
BAD: 0 # Everything is bad
|
BAD: # Everything is bad
|
||||||
FEW: 1 # Few good things
|
value: 0
|
||||||
NEARLY: 2 # Nearly good but things are missing
|
color: "#E7472B"
|
||||||
GOOD: 3 # Everything is good
|
FEW: # Few good things
|
||||||
NOTFILLED: # The item is not scored yet
|
value: 1
|
||||||
NOANSWER: . # Student gives no answer (count as 0)
|
color: "#FF712B"
|
||||||
ABS: "a" # Student has absent (this score won't be impact the final mark)
|
NEARLY: # Nearly good but things are missing
|
||||||
|
value: 2
|
||||||
|
color: "#F2EC4C"
|
||||||
|
GOOD: # Everything is good
|
||||||
|
value: 3
|
||||||
|
color: "#68D42F"
|
||||||
|
NOTFILLED: # The item is not scored yet
|
||||||
|
value: ""
|
||||||
|
color: white
|
||||||
|
NOANSWER: # Student gives no answer (count as 0)
|
||||||
|
value: "."
|
||||||
|
color: black
|
||||||
|
ABS: # Student has absent (this score won't be impact the final mark)
|
||||||
|
value: a
|
||||||
|
color: lightgray
|
||||||
|
|
||||||
csv_fields: # dataframe_field: csv_field
|
csv_fields: # dataframe_field: csv_field
|
||||||
term: Trimestre
|
term: Trimestre
|
||||||
|
@ -31,10 +31,10 @@ class CSVLoader(Loader):
|
|||||||
:example:
|
:example:
|
||||||
>>> loader = CSVLoader()
|
>>> loader = CSVLoader()
|
||||||
>>> loader.get_config()
|
>>> loader.get_config()
|
||||||
{'source': './', 'competences': {'Chercher': {'name': 'Chercher', 'abrv': 'Cher'}, 'Représenter': {'name': 'Représenter', 'abrv': 'Rep'}, 'Modéliser': {'name': 'Modéliser', 'abrv': 'Mod'}, 'Raisonner': {'name': 'Raisonner', 'abrv': 'Rai'}, 'Calculer': {'name': 'Calculer', 'abrv': 'Cal'}, 'Communiquer': {'name': 'Communiquer', 'abrv': 'Com'}}, 'valid_scores': {'BAD': 0, 'FEW': 1, 'NEARLY': 2, 'GOOD': 3, 'NOTFILLED': None, 'NOANSWER': '.', 'ABS': 'a'}, 'csv_fields': {'term': 'Trimestre', 'exam': 'Nom', 'date': 'Date', 'exercise': 'Exercice', 'question': 'Question', 'competence': 'Competence', 'theme': 'Domaine', 'comment': 'Commentaire', 'score_rate': 'Bareme', 'is_leveled': 'Est_nivele'}, 'id_templates': {'exam': '{name}_{tribe}', 'question': '{exam_id}_{exercise}_{question}_{comment}'}}
|
{'source': './', 'competences': {'Chercher': {'name': 'Chercher', 'abrv': 'Cher'}, 'Représenter': {'name': 'Représenter', 'abrv': 'Rep'}, 'Modéliser': {'name': 'Modéliser', 'abrv': 'Mod'}, 'Raisonner': {'name': 'Raisonner', 'abrv': 'Rai'}, 'Calculer': {'name': 'Calculer', 'abrv': 'Cal'}, 'Communiquer': {'name': 'Communiquer', 'abrv': 'Com'}}, 'valid_scores': {'BAD': {'value': 0, 'color': '#E7472B'}, 'FEW': {'value': 1, 'color': '#FF712B'}, 'NEARLY': {'value': 2, 'color': '#F2EC4C'}, 'GOOD': {'value': 3, 'color': '#68D42F'}, 'NOTFILLED': {'value': '', 'color': 'white'}, 'NOANSWER': {'value': '.', 'color': 'black'}, 'ABS': {'value': 'a', 'color': 'lightgray'}}, 'csv_fields': {'term': 'Trimestre', 'exam': 'Nom', 'date': 'Date', 'exercise': 'Exercice', 'question': 'Question', 'competence': 'Competence', 'theme': 'Domaine', 'comment': 'Commentaire', 'score_rate': 'Bareme', 'is_leveled': 'Est_nivele'}, 'id_templates': {'exam': '{name}_{tribe}', 'question': '{exam_id}_{exercise}_{question}_{comment}'}}
|
||||||
>>> loader = CSVLoader("./test_config.yml")
|
>>> loader = CSVLoader("./test_config.yml")
|
||||||
>>> loader.get_config()
|
>>> loader.get_config()
|
||||||
{'source': './example', 'competences': {'Chercher': {'name': 'Chercher', 'abrv': 'Cher'}, 'Représenter': {'name': 'Représenter', 'abrv': 'Rep'}, 'Modéliser': {'name': 'Modéliser', 'abrv': 'Mod'}, 'Raisonner': {'name': 'Raisonner', 'abrv': 'Rai'}, 'Calculer': {'name': 'Calculer', 'abrv': 'Cal'}, 'Communiquer': {'name': 'Communiquer', 'abrv': 'Com'}}, 'valid_scores': {'BAD': 0, 'FEW': 1, 'NEARLY': 2, 'GOOD': 3, 'NOTFILLED': None, 'NOANSWER': '.', 'ABS': 'a'}, 'csv_fields': {'term': 'Trimestre', 'exam': 'Nom', 'date': 'Date', 'exercise': 'Exercice', 'question': 'Question', 'competence': 'Competence', 'theme': 'Domaine', 'comment': 'Commentaire', 'score_rate': 'Bareme', 'is_leveled': 'Est_nivele'}, 'id_templates': {'exam': '{name}_{tribe}', 'question': '{exam_id}_{exercise}_{question}_{comment}'}, 'output': './output', 'templates': 'templates/', 'tribes': {'Tribe1': {'name': 'Tribe1', 'type': 'Type1', 'students': 'tribe1.csv'}, 'Tribe2': {'name': 'Tribe2', 'students': 'tribe2.csv'}}}
|
{'source': './example', 'competences': {'Chercher': {'name': 'Chercher', 'abrv': 'Cher'}, 'Représenter': {'name': 'Représenter', 'abrv': 'Rep'}, 'Modéliser': {'name': 'Modéliser', 'abrv': 'Mod'}, 'Raisonner': {'name': 'Raisonner', 'abrv': 'Rai'}, 'Calculer': {'name': 'Calculer', 'abrv': 'Cal'}, 'Communiquer': {'name': 'Communiquer', 'abrv': 'Com'}}, 'valid_scores': {'BAD': {'value': 0, 'color': '#E7472B'}, 'FEW': {'value': 1, 'color': '#FF712B'}, 'NEARLY': {'value': 2, 'color': '#F2EC4C'}, 'GOOD': {'value': 3, 'color': '#68D42F'}, 'NOTFILLED': {'value': '', 'color': 'white'}, 'NOANSWER': {'value': '.', 'color': 'black'}, 'ABS': {'value': 'a', 'color': 'lightgray'}}, 'csv_fields': {'term': 'Trimestre', 'exam': 'Nom', 'date': 'Date', 'exercise': 'Exercice', 'question': 'Question', 'competence': 'Competence', 'theme': 'Domaine', 'comment': 'Commentaire', 'score_rate': 'Bareme', 'is_leveled': 'Est_nivele'}, 'id_templates': {'exam': '{name}_{tribe}', 'question': '{exam_id}_{exercise}_{question}_{comment}'}, 'output': './output', 'templates': 'templates/', 'tribes': {'Tribe1': {'name': 'Tribe1', 'type': 'Type1', 'students': 'tribe1.csv'}, 'Tribe2': {'name': 'Tribe2', 'students': 'tribe2.csv'}}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
CONFIG = DEFAULT_CONFIG
|
CONFIG = DEFAULT_CONFIG
|
||||||
|
21
recopytex/datalib/dataframe.py
Normal file
21
recopytex/datalib/dataframe.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# encoding: utf-8
|
||||||
|
|
||||||
|
|
||||||
|
def column_values_to_column(pivot_column, value_column, kept_columns, df):
|
||||||
|
"""Pivot_column's values go to column with value_column under it, keeping kept_columns
|
||||||
|
|
||||||
|
:param pivot_column: column name where value will become columns
|
||||||
|
:param value_column: column name where value will be under pivot_column
|
||||||
|
:param kept_columns: unchanged columns
|
||||||
|
:param df: DataFrame to work with
|
||||||
|
|
||||||
|
:return: Stack dataframe
|
||||||
|
|
||||||
|
"""
|
||||||
|
if pivot_column in kept_columns:
|
||||||
|
pivot_columns = kept_columns
|
||||||
|
else:
|
||||||
|
pivot_columns = kept_columns + [pivot_column]
|
||||||
|
|
||||||
|
return df.set_index(pivot_columns).unstack(pivot_column)[value_column].reset_index()
|
Loading…
Reference in New Issue
Block a user