Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -116,39 +116,40 @@ class StudentAnalyzer:
|
|
116 |
return self.calculate_metrics()
|
117 |
|
118 |
def calculate_metrics(self) -> pd.DataFrame:
|
119 |
-
"""Calcula métricas de desempenho dos alunos,
|
120 |
try:
|
121 |
metrics_df = pd.DataFrame()
|
122 |
|
123 |
# Agrupar por Aluno_Pattern para eliminar duplicatas
|
124 |
grouped_tasks = self.tarefas_df.groupby('Aluno_Pattern').agg({
|
125 |
-
'Aluno': 'first',
|
126 |
-
'Duração': 'sum',
|
127 |
-
'Nota': 'sum',
|
128 |
}).reset_index()
|
129 |
|
130 |
-
# Contar número de tarefas únicas por aluno
|
131 |
task_counts = self.tarefas_df.groupby('Aluno_Pattern').size().reset_index(name='total_tarefas')
|
132 |
grouped_tasks = grouped_tasks.merge(task_counts, on='Aluno_Pattern', how='left')
|
133 |
|
134 |
-
|
135 |
-
processed_patterns = set() # Conjunto para controlar padrões já processados
|
136 |
|
137 |
for _, aluno in self.alunos_df.iterrows():
|
138 |
aluno_pattern = aluno['Aluno_Pattern']
|
139 |
|
140 |
-
# Evitar duplicatas do mesmo padrão
|
141 |
if aluno_pattern not in processed_patterns:
|
142 |
aluno_data = grouped_tasks[grouped_tasks['Aluno_Pattern'] == aluno_pattern]
|
143 |
|
144 |
if not aluno_data.empty:
|
|
|
|
|
|
|
|
|
|
|
145 |
metrics = {
|
146 |
'Nome do Aluno': aluno['Nome do Aluno'],
|
147 |
'Tarefas Completadas': aluno_data['total_tarefas'].iloc[0],
|
148 |
'Acertos Absolutos': aluno_data['Nota'].iloc[0],
|
149 |
-
'Total Tempo':
|
150 |
-
'Tempo Médio por Tarefa':
|
151 |
-
if aluno_data['total_tarefas'].iloc[0] > 0 else timedelta(0))
|
152 |
}
|
153 |
metrics_df = pd.concat([metrics_df, pd.DataFrame([metrics])], ignore_index=True)
|
154 |
processed_patterns.add(aluno_pattern)
|
@@ -160,6 +161,28 @@ class StudentAnalyzer:
|
|
160 |
logging.error(f"Erro ao calcular métricas: {str(e)}")
|
161 |
raise
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
class ReportGenerator:
|
164 |
"""Classe responsável pela geração de relatórios e visualizações."""
|
165 |
|
@@ -832,21 +855,19 @@ def process_files(html_file, excel_files) -> Tuple[str, str, str]:
|
|
832 |
alunos_df = pd.read_csv(alunos_csv_path)
|
833 |
analyzer = StudentAnalyzer(tarefas_df, alunos_df)
|
834 |
results_df = analyzer.prepare_data()
|
835 |
-
|
836 |
-
|
837 |
-
graphs = report_generator.generate_graphs()
|
838 |
-
|
839 |
-
# Salvar outputs
|
840 |
output_html = os.path.join(temp_dir, "relatorio.html")
|
841 |
output_pdf = os.path.join(temp_dir, "relatorio.pdf")
|
842 |
-
|
|
|
|
|
|
|
|
|
|
|
843 |
report_generator.generate_pdf(output_pdf, graphs)
|
844 |
-
|
845 |
-
return
|
846 |
-
|
847 |
-
except Exception as e:
|
848 |
-
logging.error(f"Erro no processamento: {str(e)}")
|
849 |
-
raise
|
850 |
|
851 |
def create_interface():
|
852 |
"""Cria a interface Gradio."""
|
|
|
116 |
return self.calculate_metrics()
|
117 |
|
118 |
def calculate_metrics(self) -> pd.DataFrame:
|
119 |
+
"""Calcula métricas de desempenho dos alunos, com formatação de tempo melhorada."""
|
120 |
try:
|
121 |
metrics_df = pd.DataFrame()
|
122 |
|
123 |
# Agrupar por Aluno_Pattern para eliminar duplicatas
|
124 |
grouped_tasks = self.tarefas_df.groupby('Aluno_Pattern').agg({
|
125 |
+
'Aluno': 'first',
|
126 |
+
'Duração': 'sum',
|
127 |
+
'Nota': 'sum',
|
128 |
}).reset_index()
|
129 |
|
|
|
130 |
task_counts = self.tarefas_df.groupby('Aluno_Pattern').size().reset_index(name='total_tarefas')
|
131 |
grouped_tasks = grouped_tasks.merge(task_counts, on='Aluno_Pattern', how='left')
|
132 |
|
133 |
+
processed_patterns = set()
|
|
|
134 |
|
135 |
for _, aluno in self.alunos_df.iterrows():
|
136 |
aluno_pattern = aluno['Aluno_Pattern']
|
137 |
|
|
|
138 |
if aluno_pattern not in processed_patterns:
|
139 |
aluno_data = grouped_tasks[grouped_tasks['Aluno_Pattern'] == aluno_pattern]
|
140 |
|
141 |
if not aluno_data.empty:
|
142 |
+
total_tempo = aluno_data['Duração'].iloc[0]
|
143 |
+
tempo_medio = (total_tempo / aluno_data['total_tarefas'].iloc[0]
|
144 |
+
if aluno_data['total_tarefas'].iloc[0] > 0
|
145 |
+
else timedelta(0))
|
146 |
+
|
147 |
metrics = {
|
148 |
'Nome do Aluno': aluno['Nome do Aluno'],
|
149 |
'Tarefas Completadas': aluno_data['total_tarefas'].iloc[0],
|
150 |
'Acertos Absolutos': aluno_data['Nota'].iloc[0],
|
151 |
+
'Total Tempo': DataProcessor.format_timedelta(total_tempo),
|
152 |
+
'Tempo Médio por Tarefa': DataProcessor.format_timedelta(tempo_medio)
|
|
|
153 |
}
|
154 |
metrics_df = pd.concat([metrics_df, pd.DataFrame([metrics])], ignore_index=True)
|
155 |
processed_patterns.add(aluno_pattern)
|
|
|
161 |
logging.error(f"Erro ao calcular métricas: {str(e)}")
|
162 |
raise
|
163 |
|
164 |
+
def generate_html(self, df: pd.DataFrame) -> str:
|
165 |
+
"""Gera HTML com formatação personalizada."""
|
166 |
+
# Fazer uma cópia para não modificar o DataFrame original
|
167 |
+
df_display = df.copy()
|
168 |
+
|
169 |
+
# Definir formatação personalizada
|
170 |
+
formatters = {
|
171 |
+
'Tarefas Completadas': lambda x: f"{x:d}",
|
172 |
+
'Acertos Absolutos': lambda x: f"{x:.0f}",
|
173 |
+
}
|
174 |
+
|
175 |
+
# Gerar HTML com formatação personalizada
|
176 |
+
html = df_display.to_html(
|
177 |
+
index=False,
|
178 |
+
formatters=formatters,
|
179 |
+
escape=False,
|
180 |
+
classes='dataframe',
|
181 |
+
border=1
|
182 |
+
)
|
183 |
+
|
184 |
+
return html
|
185 |
+
|
186 |
class ReportGenerator:
|
187 |
"""Classe responsável pela geração de relatórios e visualizações."""
|
188 |
|
|
|
855 |
alunos_df = pd.read_csv(alunos_csv_path)
|
856 |
analyzer = StudentAnalyzer(tarefas_df, alunos_df)
|
857 |
results_df = analyzer.prepare_data()
|
858 |
+
|
859 |
+
# Salvar outputs com formatação melhorada
|
|
|
|
|
|
|
860 |
output_html = os.path.join(temp_dir, "relatorio.html")
|
861 |
output_pdf = os.path.join(temp_dir, "relatorio.pdf")
|
862 |
+
|
863 |
+
html_content = analyzer.generate_html(results_df)
|
864 |
+
with open(output_html, 'w', encoding='utf-8') as f:
|
865 |
+
f.write(html_content)
|
866 |
+
|
867 |
+
report_generator = ReportGenerator(results_df)
|
868 |
report_generator.generate_pdf(output_pdf, graphs)
|
869 |
+
|
870 |
+
return html_content, output_html, output_pdf
|
|
|
|
|
|
|
|
|
871 |
|
872 |
def create_interface():
|
873 |
"""Cria a interface Gradio."""
|