Spaces:
Sleeping
Sleeping
import gradio as gr | |
import pandas as pd | |
import numpy as np | |
import re | |
import os | |
import matplotlib.pyplot as plt | |
from datetime import timedelta | |
from fpdf import FPDF | |
from typing import Tuple, Dict, List | |
import logging | |
import warnings | |
warnings.filterwarnings('ignore') | |
# Configuração de logging | |
logging.basicConfig( | |
level=logging.INFO, | |
format='%(asctime)s - %(levelname)s - %(message)s' | |
) | |
class DataProcessor: | |
def parse_duration(duration_str: str) -> timedelta: | |
try: | |
h, m, s = map(int, duration_str.split(':')) | |
return timedelta(hours=h, minutes=m, seconds=s) | |
except: | |
return timedelta(0) | |
def format_timedelta(td: timedelta) -> str: | |
total_seconds = int(td.total_seconds()) | |
hours, remainder = divmod(total_seconds, 3600) | |
minutes, seconds = divmod(remainder, 60) | |
if hours > 0: | |
return f"{hours}h {minutes}min {seconds}s" | |
elif minutes > 0: | |
return f"{minutes}min {seconds}s" | |
return f"{seconds}s" | |
def normalize_html_to_csv(input_html_path: str, output_csv_path: str) -> None: | |
try: | |
html_data = pd.read_html(input_html_path) | |
data = html_data[0] | |
data.to_csv(output_csv_path, index=False, encoding='utf-8-sig') | |
logging.info(f"HTML normalizado com sucesso: {output_csv_path}") | |
except Exception as e: | |
logging.error(f"Erro ao normalizar HTML: {str(e)}") | |
raise | |
def normalize_excel_to_csv(input_excel_path: str, output_csv_path: str) -> None: | |
try: | |
excel_data = pd.read_excel(input_excel_path) | |
unnecessary_columns = [col for col in excel_data.columns if 'Unnamed' in str(col)] | |
if unnecessary_columns: | |
excel_data = excel_data.drop(columns=unnecessary_columns) | |
excel_data.to_csv(output_csv_path, index=False, encoding='utf-8-sig') | |
logging.info(f"Excel normalizado com sucesso: {output_csv_path}") | |
except Exception as e: | |
logging.error(f"Erro ao normalizar Excel: {str(e)}") | |
raise | |
class StudentAnalyzer: | |
def __init__(self, tarefas_df: pd.DataFrame, alunos_df: pd.DataFrame): | |
self.tarefas_df = tarefas_df | |
self.alunos_df = alunos_df | |
self.processor = DataProcessor() | |
def prepare_data(self) -> pd.DataFrame: | |
self.tarefas_df.columns = self.tarefas_df.columns.str.strip() | |
self.alunos_df.columns = self.alunos_df.columns.str.strip() | |
required_columns = ['Aluno', 'Nota', 'Duração'] | |
if not all(col in self.tarefas_df.columns for col in required_columns): | |
raise ValueError("Colunas obrigatórias não encontradas no arquivo de tarefas") | |
self.tarefas_df['Duração'] = self.tarefas_df['Duração'].apply(self.processor.parse_duration) | |
return self.match_students() | |
def match_students(self) -> pd.DataFrame: | |
def generate_aluno_pattern(ra, dig_ra): | |
ra_str = str(ra).zfill(9) | |
return f"{ra_str[1]}{ra_str[2:]}{dig_ra}-sp".lower() | |
self.alunos_df['Aluno_Pattern'] = self.alunos_df.apply( | |
lambda row: generate_aluno_pattern(row['RA'], row['Dig. RA']), axis=1 | |
) | |
def extract_pattern(nome): | |
if isinstance(nome, str): | |
match = re.search(r'\d+.*', nome.lower()) | |
return match.group(0) if match else None | |
return None | |
self.tarefas_df['Aluno_Pattern'] = self.tarefas_df['Aluno'].apply(extract_pattern) | |
return self.calculate_metrics() | |
def calculate_metrics(self) -> pd.DataFrame: | |
metrics_df = pd.DataFrame() | |
for _, aluno in self.alunos_df.iterrows(): | |
aluno_pattern = aluno['Aluno_Pattern'] | |
aluno_tarefas = self.tarefas_df[self.tarefas_df['Aluno_Pattern'] == aluno_pattern] | |
if not aluno_tarefas.empty: | |
duracao_total = aluno_tarefas['Duração'].sum() | |
acertos_total = aluno_tarefas['Nota'].sum() | |
metrics = { | |
'Nome do Aluno': aluno['Nome do Aluno'], | |
'Tarefas Completadas': len(aluno_tarefas), | |
'Acertos Absolutos': acertos_total, | |
'Total Tempo': str(duracao_total), | |
'Tempo Médio por Tarefa': str(duracao_total / len(aluno_tarefas)), | |
'Eficiência': (acertos_total / duracao_total.total_seconds() * 3600) | |
} | |
metrics_df = pd.concat([metrics_df, pd.DataFrame([metrics])], ignore_index=True) | |
return metrics_df.sort_values('Acertos Absolutos', ascending=False) | |
class ReportGenerator: | |
def __init__(self, data: pd.DataFrame): | |
self.data = data | |
self.stats = self.calculate_statistics() | |
self.data['Nível'] = self.data['Acertos Absolutos'].apply(self.classify_performance) | |
def classify_performance(self, acertos): | |
if acertos >= 10: | |
return 'Avançado' | |
elif acertos >= 5: | |
return 'Intermediário' | |
else: | |
return 'Necessita Atenção' | |
def calculate_statistics(self) -> Dict: | |
basic_stats = { | |
'media_acertos': float(self.data['Acertos Absolutos'].mean()), | |
'desvio_padrao': float(self.data['Acertos Absolutos'].std()), | |
'mediana_acertos': float(self.data['Acertos Absolutos'].median()), | |
'total_alunos': len(self.data), | |
'media_tarefas': float(self.data['Tarefas Completadas'].mean()), | |
'media_tempo': str(pd.to_timedelta(self.data['Total Tempo']).mean()) | |
} | |
top_students = self.data.nlargest(3, 'Acertos Absolutos')[ | |
['Nome do Aluno', 'Acertos Absolutos'] | |
].values.tolist() | |
basic_stats['top_performers'] = top_students | |
efficient_students = self.data.nlargest(3, 'Eficiência')[ | |
['Nome do Aluno', 'Eficiência', 'Acertos Absolutos'] | |
].values.tolist() | |
basic_stats['most_efficient'] = efficient_students | |
return basic_stats | |
def generate_graphs(self) -> List[plt.Figure]: | |
graphs = [] | |
# Gráficos omitidos para compactar. Retorne aqui se desejar. | |
return graphs | |
def generate_pdf(self, output_path: str, graphs: List[plt.Figure]) -> None: | |
pdf = FPDF() # Adicione aqui os gráficos. | |
pdf.output(output_path) | |
def process_files(html_file, excel_files) -> Tuple[str, str, str]: | |
temp_dir = "temp_files" | |
os.makedirs(temp_dir, exist_ok=True) | |
# Lógica principal omitida para espaço. | |
return "Relatório gerado" | |
# Interface Gradio | |
theme = gr.themes.Default(primary_hue="blue", secondary_hue="gray") | |
with gr.Blocks(theme=theme) as interface: | |
# Interface Gradio configurada. | |
pass | |
if __name__ == "__main__": | |
interface.launch(share=False, server_name="0.0.0.0", server_port=7860) | |