Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -712,12 +712,156 @@ iface = gr.Interface(
|
|
712 |
title="Análise de Boletim Escolar",
|
713 |
description="Faça upload do boletim em PDF para gerar um relatório com análises e visualizações.",
|
714 |
allow_flagging="never",
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
721 |
|
722 |
# Interface Gradio
|
723 |
iface = gr.Interface(
|
|
|
712 |
title="Análise de Boletim Escolar",
|
713 |
description="Faça upload do boletim em PDF para gerar um relatório com análises e visualizações.",
|
714 |
allow_flagging="never",
|
715 |
+
def extrair_dados_direto(conteudo):
|
716 |
+
"""Extrai dados diretamente do texto."""
|
717 |
+
linhas = conteudo.split('\n')
|
718 |
+
info_aluno = {}
|
719 |
+
dados_disciplinas = []
|
720 |
+
|
721 |
+
# Extrair informações do aluno
|
722 |
+
for i, linha in enumerate(linhas):
|
723 |
+
if 'Nome do Aluno:' in linha and i + 1 < len(linhas):
|
724 |
+
info_aluno['nome'] = linhas[i + 1].strip()
|
725 |
+
|
726 |
+
# Encontrar o início das disciplinas
|
727 |
+
inicio_disciplinas = None
|
728 |
+
for i, linha in enumerate(linhas):
|
729 |
+
if 'Disciplina' in linha and 'Bimestre' in linha:
|
730 |
+
inicio_disciplinas = i + 1
|
731 |
+
break
|
732 |
+
|
733 |
+
if inicio_disciplinas:
|
734 |
+
# Processar disciplinas até encontrar "Resultado Final" ou "Siglas"
|
735 |
+
for linha in linhas[inicio_disciplinas:]:
|
736 |
+
if 'Resultado Final' in linha or 'Siglas' in linha:
|
737 |
+
break
|
738 |
+
|
739 |
+
partes = linha.split()
|
740 |
+
if not partes or 'Disciplina' in linha:
|
741 |
+
continue
|
742 |
+
|
743 |
+
try:
|
744 |
+
disciplina = []
|
745 |
+
notas = []
|
746 |
+
freqs = []
|
747 |
+
current_value = ''
|
748 |
+
|
749 |
+
# Primeiro item é sempre o nome da disciplina
|
750 |
+
for parte in partes:
|
751 |
+
if parte.replace('.', '').replace('-', '').isdigit() or parte in ['ET', 'ES', 'EP']:
|
752 |
+
if current_value:
|
753 |
+
disciplina.append(current_value.strip())
|
754 |
+
current_value = ''
|
755 |
+
notas.append(parte)
|
756 |
+
elif '%' in parte:
|
757 |
+
freqs.append(parte.replace('%', ''))
|
758 |
+
else:
|
759 |
+
if current_value:
|
760 |
+
current_value += ' '
|
761 |
+
current_value += parte
|
762 |
+
|
763 |
+
if current_value:
|
764 |
+
disciplina.append(current_value.strip())
|
765 |
+
|
766 |
+
if disciplina:
|
767 |
+
nome_disciplina = ' '.join(disciplina)
|
768 |
+
dados_disciplinas.append({
|
769 |
+
'disciplina': nome_disciplina,
|
770 |
+
'notas': notas[:4], # Primeiros 4 valores são notas dos bimestres
|
771 |
+
'frequencias': freqs[:4], # 4 valores de frequência
|
772 |
+
'media_notas': sum([float(n) if n.replace('.', '').isdigit() else 0 for n in notas[:4]]) / len([n for n in notas[:4] if n.replace('.', '').isdigit() or n in ['ET', 'ES', 'EP']]) if any(n.replace('.', '').isdigit() or n in ['ET', 'ES', 'EP'] for n in notas[:4]) else 0,
|
773 |
+
'media_freq': sum([float(f) for f in freqs if f and f != '-']) / len([f for f in freqs if f and f != '-']) if freqs else 0,
|
774 |
+
'bimestres_cursados': [i+1 for i, (n, f) in enumerate(zip(notas[:4], freqs[:4])) if (n.replace('.', '').isdigit() or n in ['ET', 'ES', 'EP']) or (f and f != '-')]
|
775 |
+
})
|
776 |
+
|
777 |
+
except Exception as e:
|
778 |
+
print(f"Erro ao processar linha: {linha}")
|
779 |
+
print(f"Erro: {str(e)}")
|
780 |
+
continue
|
781 |
+
|
782 |
+
return info_aluno, dados_disciplinas
|
783 |
+
|
784 |
+
def processar_boletim(file):
|
785 |
+
"""Função principal que processa o boletim e gera o relatório."""
|
786 |
+
temp_dir = None
|
787 |
+
try:
|
788 |
+
print("Iniciando processamento do arquivo...")
|
789 |
+
|
790 |
+
if file is None:
|
791 |
+
return None, "Nenhum arquivo foi fornecido."
|
792 |
+
|
793 |
+
# Criar diretório temporário
|
794 |
+
temp_dir = tempfile.mkdtemp()
|
795 |
+
print(f"Diretório temporário criado: {temp_dir}")
|
796 |
+
|
797 |
+
# Tentar ler o conteúdo do arquivo
|
798 |
+
try:
|
799 |
+
if isinstance(file, bytes):
|
800 |
+
conteudo = file.decode('utf-8')
|
801 |
+
else:
|
802 |
+
conteudo = file.read().decode('utf-8')
|
803 |
+
|
804 |
+
# Extrair dados diretamente do texto
|
805 |
+
info_aluno, disciplinas_dados = extrair_dados_direto(conteudo)
|
806 |
+
|
807 |
+
if not disciplinas_dados:
|
808 |
+
return None, "Não foi possível extrair dados do arquivo."
|
809 |
+
|
810 |
+
# Separar disciplinas por categoria
|
811 |
+
categorias = separar_disciplinas_por_categoria(disciplinas_dados)
|
812 |
+
nivel = categorias['nivel']
|
813 |
+
nivel_texto = "Ensino Médio" if nivel == "medio" else "Ensino Fundamental"
|
814 |
+
|
815 |
+
# Gerar gráficos
|
816 |
+
print("Gerando gráficos...")
|
817 |
+
grafico_basica = plotar_evolucao_bimestres(
|
818 |
+
categorias['formacao_basica'],
|
819 |
+
temp_dir,
|
820 |
+
titulo=f"Evolução das Médias - Formação Geral Básica ({nivel_texto})",
|
821 |
+
nome_arquivo='evolucao_basica.png'
|
822 |
+
)
|
823 |
+
|
824 |
+
grafico_diversificada = plotar_evolucao_bimestres(
|
825 |
+
categorias['diversificada'],
|
826 |
+
temp_dir,
|
827 |
+
titulo=f"Evolução das Médias - Parte Diversificada ({nivel_texto})",
|
828 |
+
nome_arquivo='evolucao_diversificada.png'
|
829 |
+
)
|
830 |
+
|
831 |
+
grafico_medias = plotar_graficos_destacados(disciplinas_dados, temp_dir)
|
832 |
+
print("Gráficos gerados")
|
833 |
+
|
834 |
+
# Criar DataFrame simulado para manter compatibilidade
|
835 |
+
df = pd.DataFrame(disciplinas_dados)
|
836 |
+
df.attrs.update(info_aluno)
|
837 |
+
|
838 |
+
# Gerar PDF
|
839 |
+
print("Gerando relatório PDF...")
|
840 |
+
pdf_path = gerar_relatorio_pdf(df, disciplinas_dados, grafico_basica, grafico_diversificada, grafico_medias)
|
841 |
+
print("Relatório PDF gerado")
|
842 |
+
|
843 |
+
# Criar arquivo de retorno
|
844 |
+
output_file = tempfile.NamedTemporaryFile(delete=False, suffix='.pdf')
|
845 |
+
output_path = output_file.name
|
846 |
+
shutil.copy2(pdf_path, output_path)
|
847 |
+
|
848 |
+
return output_path, "Relatório gerado com sucesso!"
|
849 |
+
|
850 |
+
except Exception as e:
|
851 |
+
print(f"Erro no processamento dos dados: {str(e)}")
|
852 |
+
return None, f"Erro ao processar os dados: {str(e)}"
|
853 |
+
|
854 |
+
except Exception as e:
|
855 |
+
print(f"Erro durante o processamento: {str(e)}")
|
856 |
+
return None, f"Erro ao processar o arquivo: {str(e)}"
|
857 |
+
|
858 |
+
finally:
|
859 |
+
if temp_dir and os.path.exists(temp_dir):
|
860 |
+
try:
|
861 |
+
shutil.rmtree(temp_dir)
|
862 |
+
print("Arquivos temporários limpos")
|
863 |
+
except Exception as e:
|
864 |
+
print(f"Erro ao limpar arquivos temporários: {str(e)}")
|
865 |
|
866 |
# Interface Gradio
|
867 |
iface = gr.Interface(
|