Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -73,9 +73,7 @@ class PDFReport(FPDF):
|
|
73 |
|
74 |
# Função de extração de tabelas do PDF
|
75 |
def extrair_tabelas_pdf(pdf_path: str) -> pd.DataFrame:
|
76 |
-
"""Extrai tabelas do PDF usando stream para o nome e lattice para notas."""
|
77 |
try:
|
78 |
-
# Extrair nome do aluno usando stream
|
79 |
tables_header = camelot.read_pdf(
|
80 |
pdf_path,
|
81 |
pages='1',
|
@@ -84,8 +82,6 @@ def extrair_tabelas_pdf(pdf_path: str) -> pd.DataFrame:
|
|
84 |
)
|
85 |
|
86 |
info_aluno = {}
|
87 |
-
|
88 |
-
# Procurar nome do aluno
|
89 |
for table in tables_header:
|
90 |
df = table.df
|
91 |
for i in range(len(df)):
|
@@ -103,14 +99,12 @@ def extrair_tabelas_pdf(pdf_path: str) -> pd.DataFrame:
|
|
103 |
except:
|
104 |
continue
|
105 |
|
106 |
-
# Extrair tabela de notas usando lattice
|
107 |
tables_notas = camelot.read_pdf(
|
108 |
pdf_path,
|
109 |
pages='all',
|
110 |
flavor='lattice'
|
111 |
)
|
112 |
|
113 |
-
# Encontrar tabela de notas
|
114 |
df_notas = None
|
115 |
max_rows = 0
|
116 |
|
@@ -131,7 +125,6 @@ def extrair_tabelas_pdf(pdf_path: str) -> pd.DataFrame:
|
|
131 |
if df_notas is None:
|
132 |
raise ValueError("Tabela de notas não encontrada")
|
133 |
|
134 |
-
# Adicionar informações do aluno ao DataFrame
|
135 |
df_notas.attrs['nome'] = info_aluno.get('nome', 'Nome não encontrado')
|
136 |
|
137 |
return df_notas
|
@@ -140,6 +133,90 @@ def extrair_tabelas_pdf(pdf_path: str) -> pd.DataFrame:
|
|
140 |
logger.error(f"Erro na extração das tabelas: {str(e)}")
|
141 |
raise
|
142 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
# Funções de plotagem
|
144 |
def plotar_evolucao_bimestres(disciplinas_dados: List[Dict], temp_dir: str,
|
145 |
titulo: Optional[str] = None,
|
|
|
73 |
|
74 |
# Função de extração de tabelas do PDF
|
75 |
def extrair_tabelas_pdf(pdf_path: str) -> pd.DataFrame:
|
|
|
76 |
try:
|
|
|
77 |
tables_header = camelot.read_pdf(
|
78 |
pdf_path,
|
79 |
pages='1',
|
|
|
82 |
)
|
83 |
|
84 |
info_aluno = {}
|
|
|
|
|
85 |
for table in tables_header:
|
86 |
df = table.df
|
87 |
for i in range(len(df)):
|
|
|
99 |
except:
|
100 |
continue
|
101 |
|
|
|
102 |
tables_notas = camelot.read_pdf(
|
103 |
pdf_path,
|
104 |
pages='all',
|
105 |
flavor='lattice'
|
106 |
)
|
107 |
|
|
|
108 |
df_notas = None
|
109 |
max_rows = 0
|
110 |
|
|
|
125 |
if df_notas is None:
|
126 |
raise ValueError("Tabela de notas não encontrada")
|
127 |
|
|
|
128 |
df_notas.attrs['nome'] = info_aluno.get('nome', 'Nome não encontrado')
|
129 |
|
130 |
return df_notas
|
|
|
133 |
logger.error(f"Erro na extração das tabelas: {str(e)}")
|
134 |
raise
|
135 |
|
136 |
+
# Função para identificar disciplinas válidas
|
137 |
+
def obter_disciplinas_validas(df: pd.DataFrame) -> List[Dict]:
|
138 |
+
colunas_notas = ['Nota B1', 'Nota B2', 'Nota B3', 'Nota B4']
|
139 |
+
colunas_freq = ['%Freq B1', '%Freq B2', '%Freq B3', '%Freq B4']
|
140 |
+
|
141 |
+
disciplinas_dados = []
|
142 |
+
|
143 |
+
for _, row in df.iterrows():
|
144 |
+
disciplina = row['Disciplina']
|
145 |
+
if pd.isna(disciplina) or disciplina == '':
|
146 |
+
continue
|
147 |
+
|
148 |
+
notas = []
|
149 |
+
freqs = []
|
150 |
+
bimestres_cursados = []
|
151 |
+
|
152 |
+
for i, (col_nota, col_freq) in enumerate(zip(colunas_notas, colunas_freq), 1):
|
153 |
+
nota = converter_nota(row[col_nota])
|
154 |
+
freq = row[col_freq] if col_freq in row else None
|
155 |
+
|
156 |
+
if nota is not None or (freq and freq != '-'):
|
157 |
+
bimestres_cursados.append(i)
|
158 |
+
notas.append(nota if nota is not None else 0)
|
159 |
+
freqs.append(freq)
|
160 |
+
else:
|
161 |
+
notas.append(None)
|
162 |
+
freqs.append(None)
|
163 |
+
|
164 |
+
if bimestres_cursados:
|
165 |
+
media_notas = calcular_media_bimestres(notas)
|
166 |
+
media_freq = calcular_frequencia_media(freqs)
|
167 |
+
|
168 |
+
disciplinas_dados.append({
|
169 |
+
'disciplina': disciplina,
|
170 |
+
'notas': notas,
|
171 |
+
'frequencias': freqs,
|
172 |
+
'media_notas': media_notas,
|
173 |
+
'media_freq': media_freq,
|
174 |
+
'bimestres_cursados': bimestres_cursados
|
175 |
+
})
|
176 |
+
|
177 |
+
return disciplinas_dados
|
178 |
+
|
179 |
+
# Função de conversão de nota
|
180 |
+
def converter_nota(valor) -> Optional[float]:
|
181 |
+
if pd.isna(valor) or valor == '-' or valor == 'N' or valor == '' or valor == 'None':
|
182 |
+
return None
|
183 |
+
|
184 |
+
if isinstance(valor, str):
|
185 |
+
valor_limpo = valor.strip().upper()
|
186 |
+
if valor_limpo in CONCEITOS_VALIDOS:
|
187 |
+
conceitos_map = {'ET': 10, 'ES': 8, 'EP': 6}
|
188 |
+
return conceitos_map.get(valor_limpo)
|
189 |
+
|
190 |
+
try:
|
191 |
+
return float(valor_limpo.replace(',', '.'))
|
192 |
+
except:
|
193 |
+
return None
|
194 |
+
|
195 |
+
if isinstance(valor, (int, float)):
|
196 |
+
return float(valor)
|
197 |
+
|
198 |
+
return None
|
199 |
+
|
200 |
+
# Funções de cálculo de médias e frequências
|
201 |
+
def calcular_media_bimestres(notas: List[float]) -> float:
|
202 |
+
notas_validas = [nota for nota in notas if nota is not None]
|
203 |
+
return sum(notas_validas) / len(notas_validas) if notas_validas else 0
|
204 |
+
|
205 |
+
def calcular_frequencia_media(frequencias: List[str]) -> float:
|
206 |
+
freq_validas = []
|
207 |
+
for freq in frequencias:
|
208 |
+
try:
|
209 |
+
if isinstance(freq, str):
|
210 |
+
freq = freq.strip().replace('%', '').replace(',', '.')
|
211 |
+
if freq and freq != '-':
|
212 |
+
valor = float(freq)
|
213 |
+
if valor > 0:
|
214 |
+
freq_validas.append(valor)
|
215 |
+
except:
|
216 |
+
continue
|
217 |
+
|
218 |
+
return sum(freq_validas) / len(freq_validas) if freq_validas else 0
|
219 |
+
|
220 |
# Funções de plotagem
|
221 |
def plotar_evolucao_bimestres(disciplinas_dados: List[Dict], temp_dir: str,
|
222 |
titulo: Optional[str] = None,
|