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 |
|