Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -99,22 +99,21 @@ class StudentAnalyzer:
|
|
| 99 |
|
| 100 |
def calculate_metrics(self) -> pd.DataFrame:
|
| 101 |
metrics_df = pd.DataFrame()
|
| 102 |
-
|
| 103 |
for _, aluno in self.alunos_df.iterrows():
|
| 104 |
aluno_pattern = aluno['Aluno_Pattern']
|
| 105 |
aluno_tarefas = self.tarefas_df[self.tarefas_df['Aluno_Pattern'] == aluno_pattern]
|
| 106 |
-
|
| 107 |
if not aluno_tarefas.empty:
|
| 108 |
duracao_total = aluno_tarefas['Duração'].sum()
|
| 109 |
acertos_total = aluno_tarefas['Nota'].sum()
|
| 110 |
-
|
| 111 |
metrics = {
|
| 112 |
'Nome do Aluno': aluno['Nome do Aluno'],
|
| 113 |
'Tarefas Completadas': len(aluno_tarefas),
|
| 114 |
'Acertos Absolutos': acertos_total,
|
| 115 |
'Total Tempo': str(duracao_total),
|
| 116 |
-
'Tempo Médio por Tarefa': str(duracao_total / len(aluno_tarefas))
|
| 117 |
-
'Eficiência': (acertos_total / duracao_total.total_seconds() * 3600)
|
| 118 |
}
|
| 119 |
metrics_df = pd.concat([metrics_df, pd.DataFrame([metrics])], ignore_index=True)
|
| 120 |
|
|
@@ -159,16 +158,12 @@ class ReportGenerator:
|
|
| 159 |
def generate_graphs(self) -> List[plt.Figure]:
|
| 160 |
graphs = []
|
| 161 |
|
| 162 |
-
# Configurações globais
|
| 163 |
-
plt.rcParams['figure.figsize'] = [
|
| 164 |
-
plt.rcParams['axes.grid'] = True
|
| 165 |
-
plt.rcParams['grid.alpha'] = 0.3
|
| 166 |
plt.rcParams['font.size'] = 10
|
| 167 |
plt.rcParams['axes.titlesize'] = 12
|
| 168 |
-
plt.rcParams['axes.titlepad'] = 20
|
| 169 |
-
plt.rcParams['axes.labelpad'] = 10
|
| 170 |
|
| 171 |
-
# 1. Distribuição por nível
|
| 172 |
plt.figure()
|
| 173 |
nivel_counts = self.data['Nível'].value_counts()
|
| 174 |
colors = {'Avançado': '#2ecc71', 'Intermediário': '#f1c40f', 'Necessita Atenção': '#e74c3c'}
|
|
@@ -185,44 +180,61 @@ class ReportGenerator:
|
|
| 185 |
graphs.append(plt.gcf())
|
| 186 |
plt.close()
|
| 187 |
|
| 188 |
-
# 2.
|
| 189 |
-
plt.figure()
|
| 190 |
-
|
| 191 |
-
bars = plt.barh(
|
| 192 |
-
color='#3498db')
|
| 193 |
|
| 194 |
-
plt.
|
|
|
|
| 195 |
plt.xlabel('Número de Acertos')
|
| 196 |
|
| 197 |
for i, bar in enumerate(bars):
|
| 198 |
-
plt.text(bar.get_width(),
|
| 199 |
-
f' {bar.get_width():.0f}',
|
| 200 |
va='center')
|
| 201 |
|
| 202 |
plt.tight_layout()
|
| 203 |
graphs.append(plt.gcf())
|
| 204 |
plt.close()
|
| 205 |
|
| 206 |
-
# 3. Relação tempo x acertos
|
| 207 |
-
plt.figure()
|
| 208 |
for nivel in colors:
|
| 209 |
mask = self.data['Nível'] == nivel
|
| 210 |
tempo = pd.to_timedelta(self.data[mask]['Total Tempo']).dt.total_seconds() / 60
|
|
|
|
| 211 |
plt.scatter(tempo, self.data[mask]['Acertos Absolutos'],
|
| 212 |
c=colors[nivel], label=nivel, alpha=0.6, s=100)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 213 |
|
| 214 |
plt.title('Relação entre Tempo e Acertos por Nível')
|
| 215 |
plt.xlabel('Tempo Total (minutos)')
|
| 216 |
plt.ylabel('Número de Acertos')
|
| 217 |
plt.legend()
|
|
|
|
| 218 |
graphs.append(plt.gcf())
|
| 219 |
plt.close()
|
| 220 |
|
| 221 |
-
# 4. Relação Tarefas x Acertos com linha de tendência
|
| 222 |
-
plt.figure()
|
| 223 |
plt.scatter(self.data['Tarefas Completadas'], self.data['Acertos Absolutos'],
|
| 224 |
color='#3498db', alpha=0.6, s=100)
|
| 225 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
z = np.polyfit(self.data['Tarefas Completadas'], self.data['Acertos Absolutos'], 1)
|
| 227 |
p = np.poly1d(z)
|
| 228 |
x_range = np.linspace(self.data['Tarefas Completadas'].min(),
|
|
@@ -233,6 +245,7 @@ class ReportGenerator:
|
|
| 233 |
plt.xlabel('Número de Tarefas Completadas')
|
| 234 |
plt.ylabel('Número de Acertos')
|
| 235 |
plt.legend()
|
|
|
|
| 236 |
graphs.append(plt.gcf())
|
| 237 |
plt.close()
|
| 238 |
|
|
|
|
| 99 |
|
| 100 |
def calculate_metrics(self) -> pd.DataFrame:
|
| 101 |
metrics_df = pd.DataFrame()
|
| 102 |
+
|
| 103 |
for _, aluno in self.alunos_df.iterrows():
|
| 104 |
aluno_pattern = aluno['Aluno_Pattern']
|
| 105 |
aluno_tarefas = self.tarefas_df[self.tarefas_df['Aluno_Pattern'] == aluno_pattern]
|
| 106 |
+
|
| 107 |
if not aluno_tarefas.empty:
|
| 108 |
duracao_total = aluno_tarefas['Duração'].sum()
|
| 109 |
acertos_total = aluno_tarefas['Nota'].sum()
|
| 110 |
+
|
| 111 |
metrics = {
|
| 112 |
'Nome do Aluno': aluno['Nome do Aluno'],
|
| 113 |
'Tarefas Completadas': len(aluno_tarefas),
|
| 114 |
'Acertos Absolutos': acertos_total,
|
| 115 |
'Total Tempo': str(duracao_total),
|
| 116 |
+
'Tempo Médio por Tarefa': str(duracao_total / len(aluno_tarefas))
|
|
|
|
| 117 |
}
|
| 118 |
metrics_df = pd.concat([metrics_df, pd.DataFrame([metrics])], ignore_index=True)
|
| 119 |
|
|
|
|
| 158 |
def generate_graphs(self) -> List[plt.Figure]:
|
| 159 |
graphs = []
|
| 160 |
|
| 161 |
+
# Configurações globais
|
| 162 |
+
plt.rcParams['figure.figsize'] = [15, 10] # Aumentado para acomodar rótulos
|
|
|
|
|
|
|
| 163 |
plt.rcParams['font.size'] = 10
|
| 164 |
plt.rcParams['axes.titlesize'] = 12
|
|
|
|
|
|
|
| 165 |
|
| 166 |
+
# 1. Distribuição por nível (mantido como está)
|
| 167 |
plt.figure()
|
| 168 |
nivel_counts = self.data['Nível'].value_counts()
|
| 169 |
colors = {'Avançado': '#2ecc71', 'Intermediário': '#f1c40f', 'Necessita Atenção': '#e74c3c'}
|
|
|
|
| 180 |
graphs.append(plt.gcf())
|
| 181 |
plt.close()
|
| 182 |
|
| 183 |
+
# 2. Todos os alunos por acertos
|
| 184 |
+
plt.figure(figsize=(15, 12))
|
| 185 |
+
students_data = self.data.sort_values('Acertos Absolutos', ascending=True)
|
| 186 |
+
bars = plt.barh(range(len(students_data)), students_data['Acertos Absolutos'])
|
|
|
|
| 187 |
|
| 188 |
+
plt.yticks(range(len(students_data)), students_data['Nome do Aluno'], fontsize=8)
|
| 189 |
+
plt.title('Ranking Completo - Acertos Absolutos')
|
| 190 |
plt.xlabel('Número de Acertos')
|
| 191 |
|
| 192 |
for i, bar in enumerate(bars):
|
| 193 |
+
plt.text(bar.get_width(), i, f' {bar.get_width():.0f}',
|
|
|
|
| 194 |
va='center')
|
| 195 |
|
| 196 |
plt.tight_layout()
|
| 197 |
graphs.append(plt.gcf())
|
| 198 |
plt.close()
|
| 199 |
|
| 200 |
+
# 3. Relação tempo x acertos com rótulos
|
| 201 |
+
plt.figure(figsize=(15, 10))
|
| 202 |
for nivel in colors:
|
| 203 |
mask = self.data['Nível'] == nivel
|
| 204 |
tempo = pd.to_timedelta(self.data[mask]['Total Tempo']).dt.total_seconds() / 60
|
| 205 |
+
|
| 206 |
plt.scatter(tempo, self.data[mask]['Acertos Absolutos'],
|
| 207 |
c=colors[nivel], label=nivel, alpha=0.6, s=100)
|
| 208 |
+
|
| 209 |
+
# Adicionar rótulos para cada ponto
|
| 210 |
+
for i, (x, y, nome) in enumerate(zip(tempo,
|
| 211 |
+
self.data[mask]['Acertos Absolutos'],
|
| 212 |
+
self.data[mask]['Nome do Aluno'])):
|
| 213 |
+
plt.annotate(nome, (x, y), xytext=(0, -10),
|
| 214 |
+
textcoords='offset points', ha='center',
|
| 215 |
+
va='top', rotation=45, fontsize=8)
|
| 216 |
|
| 217 |
plt.title('Relação entre Tempo e Acertos por Nível')
|
| 218 |
plt.xlabel('Tempo Total (minutos)')
|
| 219 |
plt.ylabel('Número de Acertos')
|
| 220 |
plt.legend()
|
| 221 |
+
plt.tight_layout()
|
| 222 |
graphs.append(plt.gcf())
|
| 223 |
plt.close()
|
| 224 |
|
| 225 |
+
# 4. Relação Tarefas x Acertos com rótulos e linha de tendência
|
| 226 |
+
plt.figure(figsize=(15, 10))
|
| 227 |
plt.scatter(self.data['Tarefas Completadas'], self.data['Acertos Absolutos'],
|
| 228 |
color='#3498db', alpha=0.6, s=100)
|
| 229 |
|
| 230 |
+
# Adicionar rótulos para cada ponto
|
| 231 |
+
for i, row in self.data.iterrows():
|
| 232 |
+
plt.annotate(row['Nome do Aluno'],
|
| 233 |
+
(row['Tarefas Completadas'], row['Acertos Absolutos']),
|
| 234 |
+
xytext=(0, -10), textcoords='offset points',
|
| 235 |
+
ha='center', va='top', rotation=45, fontsize=8)
|
| 236 |
+
|
| 237 |
+
# Linha de tendência
|
| 238 |
z = np.polyfit(self.data['Tarefas Completadas'], self.data['Acertos Absolutos'], 1)
|
| 239 |
p = np.poly1d(z)
|
| 240 |
x_range = np.linspace(self.data['Tarefas Completadas'].min(),
|
|
|
|
| 245 |
plt.xlabel('Número de Tarefas Completadas')
|
| 246 |
plt.ylabel('Número de Acertos')
|
| 247 |
plt.legend()
|
| 248 |
+
plt.tight_layout()
|
| 249 |
graphs.append(plt.gcf())
|
| 250 |
plt.close()
|
| 251 |
|