histlearn commited on
Commit
4a797d4
·
verified ·
1 Parent(s): 1f36773

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -39
app.py CHANGED
@@ -406,32 +406,26 @@ class ReportGenerator:
406
  """Cria o gráfico de relação entre tarefas e acertos com visualização otimizada."""
407
  plt.figure(figsize=(15, 10))
408
  ax = plt.gca()
409
-
410
  # Configuração inicial
411
  plt.grid(True, alpha=0.2, linestyle='--')
412
  ax.set_facecolor('#f8f9fa')
413
-
414
  def calculate_distance(p1, p2):
415
  return np.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
416
 
417
- def create_smooth_connection(start, end, offset=0.5):
418
- """Cria uma conexão suave entre dois pontos."""
419
- mid_x = (start[0] + end[0]) / 2 + offset
420
- return f'M{start[0]},{start[1]} ' \
421
- f'C{mid_x},{start[1]} {mid_x},{end[1]} {end[0]},{end[1]}'
422
-
423
  # Estruturas para armazenamento
424
  points_by_level = {level: [] for level in self.colors.keys()}
425
  used_positions = []
426
-
427
  # Coletar e plotar pontos
428
  for nivel, color in self.colors.items():
429
  mask = self.data['Nível'] == nivel
430
  tarefas = self.data[mask]['Tarefas Completadas']
431
  acertos = self.data[mask]['Acertos Absolutos']
432
-
433
- scatter = plt.scatter(tarefas, acertos, c=color, label=nivel, alpha=0.7, s=100)
434
-
435
  for t, a, nome in zip(tarefas, acertos, self.data[mask]['Nome do Aluno']):
436
  points_by_level[nivel].append((t, a, nome))
437
 
@@ -466,39 +460,31 @@ class ReportGenerator:
466
  for (x, y), group in point_groups.items():
467
  if len(group) == 1:
468
  label = group[0][2].split()[0]
469
- offset = 0
470
  else:
471
  label = f"{len(group)} alunos com\n{group[0][0]:.0f} tarefas:\n" + \
472
  "\n".join(sorted(p[2].split()[0] for p in group))
473
- offset = len(group) * 0.2
474
 
475
  # Encontrar posição livre para o label
476
- label_pos = None
477
  radius = 2.0 + len(group) * 0.5
478
- angle_step = 2 * np.pi / 16
479
 
480
- for r in np.arange(radius, radius * 3, radius):
481
- if label_pos:
 
 
 
 
 
 
 
482
  break
483
- for angle in np.arange(0, 2 * np.pi, angle_step):
484
- test_x = x + r * np.cos(angle)
485
- test_y = y + r * np.sin(angle)
486
-
487
- # Verificar se posição está livre
488
- if not any(calculate_distance((test_x, test_y), pos) < 2.0
489
- for pos in used_positions):
490
- label_pos = (test_x, test_y)
491
- used_positions.append(label_pos)
492
- break
493
-
494
- if not label_pos:
495
- label_pos = (x + radius, y + radius)
496
 
497
- # Criar anotação
498
  plt.annotate(
499
  label,
500
  (x, y),
501
- xytext=label_pos,
502
  textcoords='data',
503
  bbox=dict(
504
  facecolor='white',
@@ -510,7 +496,7 @@ class ReportGenerator:
510
  fontsize=9,
511
  arrowprops=dict(
512
  arrowstyle='-|>',
513
- connectionstyle=f'path,{create_smooth_connection((x,y), label_pos, offset)}',
514
  color='gray',
515
  alpha=0.6,
516
  mutation_scale=15
@@ -521,10 +507,10 @@ class ReportGenerator:
521
  plt.title('Relação entre Tarefas Completadas e Acertos', pad=20, fontsize=14)
522
  plt.xlabel('Número de Tarefas Completadas', fontsize=12)
523
  plt.ylabel('Número de Acertos', fontsize=12)
524
-
525
  # Forçar ticks inteiros no eixo x
526
  ax.xaxis.set_major_locator(MaxNLocator(integer=True))
527
-
528
  # Ajustar limites
529
  plt.xlim(
530
  self.data['Tarefas Completadas'].min() - 1,
@@ -534,8 +520,8 @@ class ReportGenerator:
534
  max(0, self.data['Acertos Absolutos'].min() - 1),
535
  self.data['Acertos Absolutos'].max() + 2
536
  )
537
-
538
- # Legenda com todos os elementos
539
  handles, labels = plt.gca().get_legend_handles_labels()
540
  by_label = dict(zip(labels, handles))
541
  plt.legend(
@@ -547,7 +533,7 @@ class ReportGenerator:
547
  frameon=True,
548
  fancybox=True
549
  )
550
-
551
  plt.tight_layout()
552
  return plt.gcf()
553
 
 
406
  """Cria o gráfico de relação entre tarefas e acertos com visualização otimizada."""
407
  plt.figure(figsize=(15, 10))
408
  ax = plt.gca()
409
+
410
  # Configuração inicial
411
  plt.grid(True, alpha=0.2, linestyle='--')
412
  ax.set_facecolor('#f8f9fa')
413
+
414
  def calculate_distance(p1, p2):
415
  return np.sqrt((p1[0] - p2[0])**2 + (p1[1] - p2[1])**2)
416
 
 
 
 
 
 
 
417
  # Estruturas para armazenamento
418
  points_by_level = {level: [] for level in self.colors.keys()}
419
  used_positions = []
420
+
421
  # Coletar e plotar pontos
422
  for nivel, color in self.colors.items():
423
  mask = self.data['Nível'] == nivel
424
  tarefas = self.data[mask]['Tarefas Completadas']
425
  acertos = self.data[mask]['Acertos Absolutos']
426
+
427
+ plt.scatter(tarefas, acertos, c=color, label=nivel, alpha=0.7, s=100)
428
+
429
  for t, a, nome in zip(tarefas, acertos, self.data[mask]['Nome do Aluno']):
430
  points_by_level[nivel].append((t, a, nome))
431
 
 
460
  for (x, y), group in point_groups.items():
461
  if len(group) == 1:
462
  label = group[0][2].split()[0]
 
463
  else:
464
  label = f"{len(group)} alunos com\n{group[0][0]:.0f} tarefas:\n" + \
465
  "\n".join(sorted(p[2].split()[0] for p in group))
 
466
 
467
  # Encontrar posição livre para o label
 
468
  radius = 2.0 + len(group) * 0.5
469
+ angle = np.random.uniform(0, 2 * np.pi)
470
 
471
+ # Tentar diferentes posições até encontrar uma livre
472
+ for r in np.arange(radius, radius * 3, radius/2):
473
+ label_x = x + r * np.cos(angle)
474
+ label_y = y + r * np.sin(angle)
475
+
476
+ # Verificar se posição está livre
477
+ if not any(calculate_distance((label_x, label_y), pos) < 2.0
478
+ for pos in used_positions):
479
+ used_positions.append((label_x, label_y))
480
  break
481
+ angle += np.pi/4
 
 
 
 
 
 
 
 
 
 
 
 
482
 
483
+ # Criar anotação com estilo de conexão padrão
484
  plt.annotate(
485
  label,
486
  (x, y),
487
+ xytext=(label_x, label_y),
488
  textcoords='data',
489
  bbox=dict(
490
  facecolor='white',
 
496
  fontsize=9,
497
  arrowprops=dict(
498
  arrowstyle='-|>',
499
+ connectionstyle='arc3,rad=0.2', # Estilo de conexão padrão
500
  color='gray',
501
  alpha=0.6,
502
  mutation_scale=15
 
507
  plt.title('Relação entre Tarefas Completadas e Acertos', pad=20, fontsize=14)
508
  plt.xlabel('Número de Tarefas Completadas', fontsize=12)
509
  plt.ylabel('Número de Acertos', fontsize=12)
510
+
511
  # Forçar ticks inteiros no eixo x
512
  ax.xaxis.set_major_locator(MaxNLocator(integer=True))
513
+
514
  # Ajustar limites
515
  plt.xlim(
516
  self.data['Tarefas Completadas'].min() - 1,
 
520
  max(0, self.data['Acertos Absolutos'].min() - 1),
521
  self.data['Acertos Absolutos'].max() + 2
522
  )
523
+
524
+ # Legenda
525
  handles, labels = plt.gca().get_legend_handles_labels()
526
  by_label = dict(zip(labels, handles))
527
  plt.legend(
 
533
  frameon=True,
534
  fancybox=True
535
  )
536
+
537
  plt.tight_layout()
538
  return plt.gcf()
539