diff --git a/models/report_correction_model/README.md b/models/report_correction_model/README.md
new file mode 100644
index 0000000..6fa58c1
--- /dev/null
+++ b/models/report_correction_model/README.md
@@ -0,0 +1,133 @@
+# Grading Automation Tools
+
+This project provides a set of Python scripts to automate and standardize the process of creating grading reports for student assignments. The solution is divided into two main tools:
+
+1. **Report Generator (`report_tool.py`)**: Creates a folder and file structure for grading in Markdown (`.md`) for each student from a customizable template.
+2. **PDF Converter (`convert_to_pdf.py`)**: Converts the finalized Markdown grading reports to PDF, preserving formatting, tables, and mathematical formulas in LaTeX.
+
+## ✨ Features
+
+ - **Batch Generation**: Create the grading structure for all students in a class at once.
+ - **Standardized Template**: Ensure consistency across all grades by using a template file (`template.md`).
+ - **Customizable**: Easily modify the `template.md` to adapt to different evaluation criteria.
+ - **High-Quality PDF Conversion**: Generate professional-looking PDFs by rendering Markdown with a style similar to GitHub.
+ - **LaTeX Support**: Write complex mathematical formulas in your reports using LaTeX syntax, which will be correctly rendered in the final PDF.
+
+## 📂 Expected Directory Structure
+
+For the scripts to work correctly, organize your folders as follows:
+
+```
+your_project/
+├── submissions/ <-- Folder with each student's directory
+│ ├── Example_1/
+│ ├── Example_2/
+│ └── Example_3/
+├── report_tool.py <-- Generator script
+├── convert_to_pdf.py <-- Converter script
+└── template.md <-- Report template
+```
+
+ - The main directory (e.g., `submissions/`) should contain a subfolder for each student. The name of the subfolder will be used as the student's name in the report.
+
+## 🚀 Installation and Setup
+
+### Prerequisites
+
+ - Python 3.7 or higher.
+
+### Installation Steps
+
+1. **Clone or download the files** to a directory on your computer.
+
+2. **Create a virtual environment (recommended)**:
+
+ ```bash
+ python -m venv venv
+ ```
+
+ - On Windows, activate with: `.\venv\Scripts\activate`
+ - On macOS/Linux, activate with: `source venv/bin/activate`
+
+3. **Install the necessary dependencies**:
+ The scripts use a few Python libraries to render Markdown and generate the PDF. Install them with the following command:
+
+ ```bash
+ pip install "markdown-it-py<3.0.0" "mdit-py-plugins" pyppeteer
+ ```
+
+ > **Note**: The first time the `convert_to_pdf.py` script is run, the `pyppeteer` library will automatically download a version of Chromium (a headless browser) to render the page. This may take a few minutes.
+
+## 📝 Workflow and Usage
+
+### Step 1: Generate the Grading Files
+
+Run the `report_tool.py` script to create the `.md` files for each student.
+
+**Basic Usage:**
+Provide the activity name as the main argument. The script will look for student folders in the current directory (`.`).
+
+```bash
+# Example for an activity named "Lab01"
+python report_tool.py Lab01
+```
+
+**Advanced Usage with Options:**
+You can specify the student directory, the grader's name, and the report title.
+
+```bash
+python report_tool.py "Lab02_Circuits" -o "./submissions" -g "Prof. Ada Lovelace" --activity-title "Laboratory 02 Report"
+```
+
+After running, the following structure will be created inside each student's folder:
+
+```
+submissions/
+└── John_Smith/
+ └── John_Smith_Lab01_correction/
+ ├── John_Smith_Lab01_correction.md <-- The report to be filled out
+ └── src/ <-- Optional folder for corrected code
+```
+
+### Step 2: Fill in the Reports
+
+Open each generated `.md` file and fill in the grades, comments, and feedback for each student.
+
+### Step 3: Convert the Reports to PDF
+
+Once the grades are finalized, run the `convert_to_pdf.py` script to generate the PDFs.
+
+**Usage:**
+Provide the directory where the `.md` reports are located. The script will recursively search for all `.md` files and convert them.
+
+```bash
+# Converts all reports inside the 'submissions' folder
+python convert_to_pdf.py ./submissions
+```
+
+The script will create a `.pdf` file with the same name and in the same location as the original `.md` file.
+
+## 🔧 Component Details
+
+### `report_tool.py`
+
+ - **Purpose**: To automate the creation of the grading structure.
+ - **Command-Line Arguments**:
+ - `activity_name` (required): A short name for the activity, used for naming files.
+ - `-o, --output-dir`: The directory where the student folders are located (default: `.`).
+ - `-g, --grader`: The name of the grader to be inserted into the report.
+ - `-t, --activity-title`: The full title of the activity for the header. If omitted, it uses `activity_name`.
+ - `--template`: The path to the template file (default: `template.md`).
+
+### `convert_to_pdf.py`
+
+ - **Purpose**: To convert Markdown files to PDF.
+ - **Technology**: Uses `pyppeteer` to control a headless browser that "prints" the HTML version of the Markdown to a PDF file.
+ - **Command-Line Arguments**:
+ - `base_dir` (optional): The base directory to recursively search for `.md` files (default: `.`).
+
+### `template.md`
+
+ - **Purpose**: To serve as a model for all grading reports.
+ - **Syntax**: Uses the `${variable}` syntax from Python's `string.Template` for fields that will be replaced by `report_tool.py`, such as `${student_name}`, `${activity_title}`, etc..
+ - **Customization**: Feel free to edit this file, changing the evaluation criteria, weights, text, and the calculation formula to meet your needs. Just keep the placeholders that the script uses.
diff --git a/models/report_correction_model/convert_to_pdf.py b/models/report_correction_model/convert_to_pdf.py
new file mode 100644
index 0000000..f40843b
--- /dev/null
+++ b/models/report_correction_model/convert_to_pdf.py
@@ -0,0 +1,150 @@
+import argparse
+import asyncio
+import sys
+from pathlib import Path
+
+from markdown_it import MarkdownIt
+from mdit_py_plugins.front_matter import front_matter_plugin
+from mdit_py_plugins.texmath import texmath_plugin
+
+from pyppeteer import launch
+
+# --- HTML TEMPLATE ---
+HTML_TEMPLATE = """
+
+
+
+
+ {title}
+
+
+
+
+
+ {content}
+
+
+"""
+
+# --- HELPER FUNCTION ---
+def log(msg: str, success: bool = True, indent: int = 0) -> None:
+ GREEN, RED, YELLOW, RESET = "\033[92m", "\033[91m", "\033[93m", "\033[0m"
+ prefix = f"{GREEN}✅{RESET}" if success else (f"{YELLOW}ℹ️{RESET}" if success is None else f"{RED}❌{RESET}")
+ print(f"{' ' * indent}{prefix} {msg}")
+
+# --- CORE LOGIC ---
+async def convert_file_to_pdf(md_path: Path, browser):
+ pdf_path = md_path.with_suffix(".pdf")
+ log(f"Processando '{md_path.name}'...", success=None, indent=1)
+
+ try:
+ # Plugin de matemática sem argumento extra
+ md_converter = (
+ MarkdownIt("gfm-like")
+ .use(front_matter_plugin)
+ .use(texmath_plugin) # ✅ sem argumento
+ )
+
+ markdown_text = md_path.read_text(encoding="utf-8")
+ html_content = md_converter.render(markdown_text)
+ final_html = HTML_TEMPLATE.format(title=md_path.stem, content=html_content)
+
+ page = await browser.newPage()
+ await page.setContent(final_html)
+ await page.pdf({
+ "path": str(pdf_path),
+ "format": "A4",
+ "printBackground": True,
+ "margin": {"top": "2.5cm", "right": "2.5cm", "bottom": "2.5cm", "left": "2.5cm"},
+ })
+ await page.close()
+
+ log(f"Convertido com sucesso para '{pdf_path.name}'", success=True, indent=2)
+ return True
+
+ except Exception as e:
+ log(f"Falha na conversão de '{md_path.name}'", success=False, indent=2)
+ log(f"Erro: {e}", success=False, indent=3)
+ return False
+
+async def main_converter(base_dir: Path):
+ print("\n" + "="*50)
+ print("🚀 Iniciando Conversão de Markdown para PDF")
+ print(f"📂 Diretório de Busca: {base_dir.resolve()}")
+ print("="*50 + "\n")
+
+ markdown_files = list(base_dir.rglob("*.md"))
+ if not markdown_files:
+ log("Nenhum arquivo Markdown (.md) foi encontrado para conversão.", success=None)
+ print("\n✨ Processo concluído!")
+ return
+
+ log(f"Encontrados {len(markdown_files)} arquivos Markdown para processar.")
+ log("Iniciando o navegador headless (pode demorar na primeira vez)...", success=None)
+
+ browser = None
+ try:
+ browser = await launch(headless=True, args=['--no-sandbox'])
+
+ success_count = 0
+ fail_count = 0
+
+ tasks = [convert_file_to_pdf(md_path, browser) for md_path in markdown_files]
+ results = await asyncio.gather(*tasks)
+
+ for result in results:
+ if result:
+ success_count += 1
+ else:
+ fail_count += 1
+
+ except Exception as e:
+ log("Ocorreu um erro ao iniciar o navegador ou processar os arquivos.", success=False)
+ log(f"Erro: {e}", success=False)
+
+ finally:
+ if browser:
+ await browser.close()
+ log("Navegador headless fechado.", success=None)
+
+ print("\n" + "="*50)
+ print("✨ Processo de conversão concluído!")
+ log(f"Sucessos: {success_count}", success=True)
+ log(f"Falhas: {fail_count}", success=False)
+ print("="*50)
+
+
+# --- SCRIPT ENTRY POINT ---
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(
+ description="Ferramenta para converter arquivos Markdown (.md) em PDF usando Pyppeteer.",
+ formatter_class=argparse.HelpFormatter
+ )
+ parser.add_argument(
+ "base_dir",
+ type=Path,
+ nargs='?',
+ default=Path("."),
+ help="Diretório base para buscar arquivos .md recursivamente. Padrão: diretório atual."
+ )
+ args = parser.parse_args()
+
+ if sys.platform == "win32":
+ asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+
+ asyncio.run(main_converter(args.base_dir))
diff --git a/models/report_correction_model/report_tool.py b/models/report_correction_model/report_tool.py
new file mode 100644
index 0000000..67b9f96
--- /dev/null
+++ b/models/report_correction_model/report_tool.py
@@ -0,0 +1,159 @@
+import argparse
+import sys
+import re
+from datetime import datetime
+from string import Template
+from pathlib import Path
+from typing import Set
+
+# --- CONSTANTS ---
+# Pastas a serem ignoradas durante a busca por diretórios de alunos.
+IGNORED_FOLDERS: Set[str] = {"__pycache__", ".git", ".idea", ".vscode"}
+
+
+# --- HELPER FUNCTIONS ---
+def safe_filename(name: str) -> str:
+ """Remove caracteres inválidos para criar um nome de arquivo seguro."""
+ # Remove qualquer caractere que não seja letra, número, sublinhado ou hífen.
+ return re.sub(r'[^\w-]', '_', name)
+
+
+def log(msg: str, success: bool = True) -> None:
+ """Imprime mensagens de log com formatação colorida (sucesso/erro)."""
+ # Códigos de escape ANSI para cores no terminal
+ GREEN = "\033[92m"
+ RED = "\033[91m"
+ RESET = "\033[0m"
+
+ prefix = f"{GREEN}✅{RESET}" if success else f"{RED}❌{RESET}"
+ print(f"{prefix} {msg}")
+
+
+def load_template(template_path: Path) -> Template:
+ """Carrega o conteúdo do arquivo de template especificado."""
+ try:
+ content = template_path.read_text(encoding="utf-8")
+ return Template(content)
+ except FileNotFoundError:
+ log(f"Arquivo de template não encontrado em: {template_path}", success=False)
+ sys.exit(1) # Encerra o script se o template não existir.
+ except IOError as e:
+ log(f"Erro ao ler o arquivo de template: {e}", success=False)
+ sys.exit(1)
+
+
+# --- CORE LOGIC ---
+def create_correction_files(args: argparse.Namespace) -> None:
+ """Função principal que itera sobre as pastas e cria os arquivos de correção."""
+ base_dir = args.output_dir.resolve() # .resolve() obtém o caminho absoluto
+ md_template = load_template(args.template)
+
+ print("\n" + "="*50)
+ print("🚀 Iniciando a Geração de Relatórios de Correção")
+ print(f"📂 Diretório Base: {base_dir}")
+ print(f"📄 Atividade: {args.activity_name}")
+ print(f"🧑🏫 Corretor: {args.grader}")
+ print("="*50 + "\n")
+
+ if not base_dir.is_dir():
+ log(f"O diretório base '{base_dir}' não existe ou não é um diretório.", success=False)
+ return
+
+ student_dirs_found = 0
+ for item in base_dir.iterdir():
+ # Pula arquivos e pastas ignoradas
+ if not item.is_dir() or item.name in IGNORED_FOLDERS:
+ continue
+
+ student_dirs_found += 1
+ student_name = item.name
+ safe_name = safe_filename(student_name)
+
+ base_name = f"{safe_name}_{args.activity_name}_correction"
+ correction_folder = item / base_name
+ md_file_path = correction_folder / f"{base_name}.md"
+ src_folder_path = correction_folder / "src"
+
+ try:
+ # Cria as pastas de correção e 'src' (exist_ok=True evita erro se já existirem)
+ src_folder_path.mkdir(parents=True, exist_ok=True)
+
+ # Preenche as variáveis do template
+ content_to_write = md_template.substitute(
+ activity_title=args.activity_title,
+ grader_name=args.grader,
+ student_name=student_name,
+ correction_date=datetime.now().strftime("%Y-%m-%d"),
+ final=args.default_grade,
+ )
+
+ # Escreve o arquivo Markdown
+ md_file_path.write_text(content_to_write, encoding="utf-8")
+ log(f"Estrutura de correção criada para '{student_name}' em: {correction_folder}")
+
+ except OSError as e:
+ log(f"Erro ao criar estrutura para '{student_name}': {e}", success=False)
+
+ if student_dirs_found == 0:
+ log("Nenhum diretório de aluno encontrado para processar.", success=False)
+
+ print("\n" + "="*50)
+ print("✨ Processo concluído!")
+ print("="*50)
+
+
+# --- SCRIPT ENTRY POINT ---
+def main():
+ """Analisa os argumentos da linha de comando e inicia o script."""
+ parser = argparse.ArgumentParser(
+ description="Ferramenta para criar estruturas de correção para atividades de alunos.",
+ formatter_class=argparse.HelpFormatter
+ )
+
+ parser.add_argument(
+ "activity_name",
+ type=str,
+ help="Nome ou número da atividade (ex: 'Exp01', 'Lab_AND_Gate'). Usado nos nomes dos arquivos."
+ )
+ parser.add_argument(
+ "-t", "--activity-title",
+ type=str,
+ help="Título completo da atividade para o cabeçalho do relatório. Se não for fornecido, usa o 'activity_name'.",
+ default=None
+ )
+ parser.add_argument(
+ "-o", "--output-dir",
+ type=Path,
+ default=Path("."),
+ help="Diretório base contendo as pastas dos alunos. Padrão: diretório atual."
+ )
+ parser.add_argument(
+ "-g", "--grader",
+ type=str,
+ default="Nome do Corretor",
+ help="Nome do corretor a ser inserido no relatório."
+ )
+ parser.add_argument(
+ "-d", "--default-grade",
+ type=str,
+ default="[INSERIR NOTA]",
+ help="Valor padrão para o campo da nota final."
+ )
+ parser.add_argument(
+ "--template",
+ type=Path,
+ default=Path("template.md"),
+ help="Caminho para o arquivo de template Markdown. Padrão: 'template.md' no mesmo diretório."
+ )
+
+ args = parser.parse_args()
+
+ # Se o título não for fornecido, usa o nome da atividade como padrão.
+ if args.activity_title is None:
+ args.activity_title = args.activity_name.replace('_', ' ').title()
+
+ create_correction_files(args)
+
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/models/report_correction_model/template.md b/models/report_correction_model/template.md
new file mode 100644
index 0000000..3ed86b4
--- /dev/null
+++ b/models/report_correction_model/template.md
@@ -0,0 +1,44 @@
+# Relatório de Correção: ${activity_title}
+
+| **Corretor:** | ${grader_name} |
+| :--- | :--- |
+| **Aluno(a):** | ${student_name} |
+| **Matrícula:** | [Inserir Matrícula] |
+| **Data da Correção:** | ${correction_date} |
+
+---
+
+## 📝 Resumo da Avaliação
+
+| Nota Final |
+| :---: |
+| **${final}** |
+
+### Comentários Gerais
+[Forneça um parágrafo de resumo aqui sobre os pontos fortes e as áreas para melhoria.]
+
+---
+
+## 📊 Detalhamento da Nota
+
+| Critério | Seção do Relatório | Peso | Nota (0-10) | Comentários Específicos |
+| :--- |:---|:---:|:---:|:---|
+| 📄 **Documentação** | Introdução, Teoria, Código, Análise e Conclusão | 10% | `[Nota Doc]` | [Feedback sobre a qualidade da escrita, clareza e formatação.] |
+| ⚙️ **Compilação** | Compilação | 20% | `[Nota Comp]` | [Feedback sobre a compilação do código, ausência de warnings, etc.] |
+| 🚀 **Simulação** | Simulação, Análise e Resultados | 70% | `[Nota Sim]` | [Feedback sobre a corretude da simulação, formas de onda e análise dos resultados.] |
+| 🕒 **Fator Pontualidade** | - | - | `[Fator Pontualidade]` | [Ex: 1.0 (dentro do prazo), 0.8 (atraso de 1 dia)] |
+
+### Fórmula de Cálculo
+
+A nota final é calculada usando a seguinte fórmula:
+
+$$
+\text{Nota}_{\text{final}} = \Big( (N_{Doc} \cdot 0.1) + (N_{Comp} \cdot 0.2) + (N_{Sim} \cdot 0.7) \Big) \cdot F_{\text{Pontualidade}}
+$$
+
+**Cálculo prático com suas notas:**
+
+`= ( ( [Nota Doc] * 0.1 ) + ( [Nota Comp] * 0.2 ) + ( [Nota Sim] * 0.7 ) ) * [Fator Pontualidade]`
+
+---
+**[Comentários finais ou de encerramento]**