diff --git a/Guia2/README.md b/Guia2/README.md new file mode 100644 index 0000000..56985d6 --- /dev/null +++ b/Guia2/README.md @@ -0,0 +1,155 @@ +# Guia 2 — Sistema de Folha de Pagamento (RH) + +## Contexto + +Você faz parte da equipe responsável por manter um módulo de **Folha de Pagamento** dentro de um sistema de **Recursos Humanos (RH)**. + +Esse módulo calcula informações básicas de funcionários de diferentes cargos, como: + +- nome +- matricula +- salario_base + +Atualmente o sistema possui uma hierarquia de classes para representar funcionários, mas carece implementar as subclasses de acordo com o diagrama UML abaixo: + + -------------------------------- + | Funcionario | + -------------------------------- + | - nome | + | - matricula | + | - salario_base | + -------------------------------- + | + dados_basicos() | + | + gerar_contracheque() | + | + calcular_salario_liquido() | + | # calcular_bonus() | + | # calcular_descontos() | + | # calcular_adicionais() | + -------------------------------- + ▲ + ----------------------------------------- + | | | + | | | + ----------------- ----------------- ----------------- + | Desenvolvedor | | Gerente | | Estagiari o | + ----------------- ----------------- ----------------- + | linguagem | | setor | | curso | + | senioridade | | qtd_equipe | | carga_horaria | + ----------------- ----------------- ----------------- + +Seu papel é implementar as subclasses passando nos testes propostos. + +--- + +## 1. Desenvolvedor + +### Atributos adicionais + +- `linguagem` +- `senioridade` + +### Regras + +#### `calcular_bonus()` + +O bônus depende da senioridade: + +| Senioridade | Bônus | +|-------------|----------------------| +| junior | 5% do salário base | +| pleno | 10% do salário base | +| senior | 15% do salário base | + +--- + +#### `calcular_descontos()` + +Desconto fixo de **8% do salário base**. + +--- + +#### `calcular_adicionais()` + +Adicional definido pela linguagem principal: + +| Linguagem | Adicional | +|----------------|-----------| +| Python | +500 | +| Java | +400 | +| JavaScript | +350 | +| Qualquer outra | +200 | + +--- + +## 2. Gerente + +### Atributos adicionais + +- `setor` +- `qtd_equipe` + +### Regras + +#### `calcular_bonus()` + +O bônus depende da quantidade de pessoas na equipe: + +| Tamanho da equipe | Bônus | +|-------------------|---------------------| +| até 5 | 10% do salário base | +| de 6 até 10 | 15% do salário base | +| acima de 10 | 20% do salário base | + +--- + +#### `calcular_descontos()` + +Desconto fixo de **12% do salário base**. + +--- + +#### `calcular_adicionais()` + +Adicional por responsabilidade: + +| Quantidade da equipe | Adicional | +|----------------------|-----------| +| equipe > 10 | +2000 | +| equipe > 5 | +1000 | +| caso contrário | +500 | + +--- + +## 3. Estagiario + +### Atributos adicionais + +- `curso` +- `carga_horaria` + +### Regras + +#### `calcular_bonus()` + +Bônus fixo de **3% do salário base**. + +--- + +#### `calcular_descontos()` + +Desconto fixo de **2% do salário base**. + +--- + +#### `calcular_adicionais()` + +Auxílio baseado na carga horária: + +| Carga horária | Adicional | +|---------------|-----------| +| até 20h | +150 | +| até 30h | +250 | +| acima de 30h | +350 | + +--- +995b5983a8b684cba7bbc7f802c760906f0d690c1e90bf440631cfe486082eb3 \ No newline at end of file diff --git a/Guia2/pytest.ini b/Guia2/pytest.ini new file mode 100644 index 0000000..97a0030 --- /dev/null +++ b/Guia2/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +pythonpath = src +testpaths = tests \ No newline at end of file diff --git a/Guia2/requirements.txt b/Guia2/requirements.txt new file mode 100644 index 0000000..e69de29 diff --git a/Guia2/run_tests.bat b/Guia2/run_tests.bat new file mode 100644 index 0000000..a2937ce --- /dev/null +++ b/Guia2/run_tests.bat @@ -0,0 +1,2 @@ +pytest -v +pause \ No newline at end of file diff --git a/Guia2/src/__init__.py b/Guia2/src/__init__.py new file mode 100644 index 0000000..5d96e84 --- /dev/null +++ b/Guia2/src/__init__.py @@ -0,0 +1 @@ +from folha_pagamento import Estagiario, Gerente, Desenvolvedor, Funcionario diff --git a/Guia2/src/__pycache__/__init__.cpython-312.pyc b/Guia2/src/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..73e61be Binary files /dev/null and b/Guia2/src/__pycache__/__init__.cpython-312.pyc differ diff --git a/Guia2/src/folha_pagamento/__init__.py b/Guia2/src/folha_pagamento/__init__.py new file mode 100644 index 0000000..63a2be0 --- /dev/null +++ b/Guia2/src/folha_pagamento/__init__.py @@ -0,0 +1,4 @@ +from .funcionario import Funcionario +from .estagiario import Estagiario +from .desenvolvedor import Desenvolvedor +from .gerente import Gerente diff --git a/Guia2/src/folha_pagamento/__pycache__/__init__.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..c9423a9 Binary files /dev/null and b/Guia2/src/folha_pagamento/__pycache__/__init__.cpython-312.pyc differ diff --git a/Guia2/src/folha_pagamento/__pycache__/desenvolvedor.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/desenvolvedor.cpython-312.pyc new file mode 100644 index 0000000..4184750 Binary files /dev/null and b/Guia2/src/folha_pagamento/__pycache__/desenvolvedor.cpython-312.pyc differ diff --git a/Guia2/src/folha_pagamento/__pycache__/estagiario.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/estagiario.cpython-312.pyc new file mode 100644 index 0000000..065df0d Binary files /dev/null and b/Guia2/src/folha_pagamento/__pycache__/estagiario.cpython-312.pyc differ diff --git a/Guia2/src/folha_pagamento/__pycache__/funcionario.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/funcionario.cpython-312.pyc new file mode 100644 index 0000000..a87ac56 Binary files /dev/null and b/Guia2/src/folha_pagamento/__pycache__/funcionario.cpython-312.pyc differ diff --git a/Guia2/src/folha_pagamento/__pycache__/gerente.cpython-312.pyc b/Guia2/src/folha_pagamento/__pycache__/gerente.cpython-312.pyc new file mode 100644 index 0000000..444c7e2 Binary files /dev/null and b/Guia2/src/folha_pagamento/__pycache__/gerente.cpython-312.pyc differ diff --git a/Guia2/src/folha_pagamento/desenvolvedor.py b/Guia2/src/folha_pagamento/desenvolvedor.py new file mode 100644 index 0000000..5c5d3c9 --- /dev/null +++ b/Guia2/src/folha_pagamento/desenvolvedor.py @@ -0,0 +1,6 @@ +from folha_pagamento.funcionario import Funcionario + +# Desenvolva a classe Desenvolvedor aqui. + +class Desenvolvedor: + pass \ No newline at end of file diff --git a/Guia2/src/folha_pagamento/estagiario.py b/Guia2/src/folha_pagamento/estagiario.py new file mode 100644 index 0000000..d50a433 --- /dev/null +++ b/Guia2/src/folha_pagamento/estagiario.py @@ -0,0 +1,6 @@ +from folha_pagamento.funcionario import Funcionario + +# Desenvolva a classe Estagiario aqui. + +class Estagiario: + pass \ No newline at end of file diff --git a/Guia2/src/folha_pagamento/funcionario.py b/Guia2/src/folha_pagamento/funcionario.py new file mode 100644 index 0000000..0f8dccc --- /dev/null +++ b/Guia2/src/folha_pagamento/funcionario.py @@ -0,0 +1,77 @@ +from abc import ABC, abstractmethod + +class Funcionario(ABC): + def __init__(self, nome: str, matricula: str, salario_base: float): + if not nome: + raise ValueError("Nome inválido.") + + if not matricula: + raise ValueError("Matrícula inválida.") + + if salario_base < 0: + raise ValueError("Salário não pode ser negativo.") + + self._nome = nome + self._matricula = matricula + self._salario_base = salario_base + + # --------------------------- + # Propriedades comuns + # --------------------------- + @property + def nome(self) -> str: + return self._nome + + @property + def matricula(self) -> str: + return self._matricula + + @property + def salario_base(self) -> float: + return self._salario_base + + # --------------------------- + # Métodos concretos + # --------------------------- + def dados_basicos(self) -> dict: + return { + "nome": self.nome, + "matricula": self.matricula, + "salario_base": self.salario_base, + "cargo": self.__class__.__name__ + } + + def calcular_salario_liquido(self) -> float: + return ( + self.salario_base + + self.calcular_bonus() + + self.calcular_adicionais() + - self.calcular_descontos() + ) + + def gerar_contracheque(self) -> dict: + return { + "nome": self.nome, + "matricula": self.matricula, + "cargo": self.__class__.__name__, + "salario_base": self.salario_base, + "bonus": self.calcular_bonus(), + "adicionais": self.calcular_adicionais(), + "descontos": self.calcular_descontos(), + "salario_liquido": self.calcular_salario_liquido() + } + + # --------------------------- + # Contrato abstrato + # --------------------------- + @abstractmethod + def calcular_bonus(self) -> float: + pass + + @abstractmethod + def calcular_descontos(self) -> float: + pass + + @abstractmethod + def calcular_adicionais(self) -> float: + pass \ No newline at end of file diff --git a/Guia2/src/folha_pagamento/gerente.py b/Guia2/src/folha_pagamento/gerente.py new file mode 100644 index 0000000..31819a1 --- /dev/null +++ b/Guia2/src/folha_pagamento/gerente.py @@ -0,0 +1,6 @@ +from folha_pagamento.funcionario import Funcionario + +# Desenvolva a classe Gerente aqui. + +class Gerente: + pass \ No newline at end of file diff --git a/Guia2/tests/__init__.py b/Guia2/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Guia2/tests/__pycache__/__init__.cpython-312.pyc b/Guia2/tests/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..65afc7b Binary files /dev/null and b/Guia2/tests/__pycache__/__init__.cpython-312.pyc differ diff --git a/Guia2/tests/__pycache__/test_desenvolvedor.cpython-312-pytest-8.3.5.pyc b/Guia2/tests/__pycache__/test_desenvolvedor.cpython-312-pytest-8.3.5.pyc new file mode 100644 index 0000000..e7c7fd2 Binary files /dev/null and b/Guia2/tests/__pycache__/test_desenvolvedor.cpython-312-pytest-8.3.5.pyc differ diff --git a/Guia2/tests/__pycache__/test_estagiario.cpython-312-pytest-8.3.5.pyc b/Guia2/tests/__pycache__/test_estagiario.cpython-312-pytest-8.3.5.pyc new file mode 100644 index 0000000..bdcfb1c Binary files /dev/null and b/Guia2/tests/__pycache__/test_estagiario.cpython-312-pytest-8.3.5.pyc differ diff --git a/Guia2/tests/__pycache__/test_gerente.cpython-312-pytest-8.3.5.pyc b/Guia2/tests/__pycache__/test_gerente.cpython-312-pytest-8.3.5.pyc new file mode 100644 index 0000000..42c8ece Binary files /dev/null and b/Guia2/tests/__pycache__/test_gerente.cpython-312-pytest-8.3.5.pyc differ diff --git a/Guia2/tests/integrity.py b/Guia2/tests/integrity.py new file mode 100644 index 0000000..6d3ebd9 --- /dev/null +++ b/Guia2/tests/integrity.py @@ -0,0 +1,32 @@ +from pathlib import Path +import hashlib + + +def gerar_hash_pasta(pasta=".", extensao=".py"): + arquivos = sorted( + [ + arquivo + for arquivo in Path(pasta).rglob(f"*{extensao}") + if arquivo.name != "integrity.py" + ] + ) + + print(arquivos) + + hash_global = hashlib.sha256() + + for arquivo in arquivos: + # inclui nome/caminho do arquivo no hash + hash_global.update(str(arquivo.relative_to(pasta)).encode()) + + # inclui conteúdo + with open(arquivo, "rb") as f: + while bloco := f.read(4096): + hash_global.update(bloco) + + return hash_global.hexdigest() + + +if __name__ == "__main__": + resultado = gerar_hash_pasta() + print(resultado) \ No newline at end of file diff --git a/Guia2/tests/test_desenvolvedor.py b/Guia2/tests/test_desenvolvedor.py new file mode 100644 index 0000000..0ee0137 --- /dev/null +++ b/Guia2/tests/test_desenvolvedor.py @@ -0,0 +1,44 @@ +import pytest +from src import Desenvolvedor + + +@pytest.fixture +def desenvolvedor(): + # Instância base com salário 5000, linguagem Python, senioridade pleno + return Desenvolvedor("Ana", "123", 5000.0, "Python", "pleno") + +# ---- Testes para calcular_bonus() ---- +@pytest.mark.parametrize("senioridade,percentual", [ + ("junior", 0.05), + ("pleno", 0.10), + ("senior", 0.15), +]) +def test_bonus_por_senioridade(desenvolvedor, senioridade, percentual): + desenvolvedor.senioridade = senioridade + esperado = percentual * desenvolvedor.salario_base + assert desenvolvedor.calcular_bonus() == esperado + +# ---- Teste para calcular_descontos() ---- +def test_desconto_fixo(desenvolvedor): + # 8% do salário base + assert desenvolvedor.calcular_descontos() == 0.08 * desenvolvedor.salario_base + +# ---- Testes para calcular_adicionais() ---- +@pytest.mark.parametrize("linguagem,adicional_esperado", [ + ("Python", 500), + ("Java", 400), + ("JavaScript", 350), + ("C++", 200), + ("Ruby", 200), +]) +def test_adicional_por_linguagem(desenvolvedor, linguagem, adicional_esperado): + desenvolvedor.linguagem = linguagem + assert desenvolvedor.calcular_adicionais() == adicional_esperado + +# ---- Teste integrado de salário líquido ---- +def test_salario_liquido_pleno_python(desenvolvedor): + desenvolvedor.senioridade = "pleno" + desenvolvedor.linguagem = "Python" + # salario_base (5000) + bonus(10%) + adicional(500) - desconto(8%) + esperado = 5000 + 500 + 500 - 400 # 5600 + assert desenvolvedor.calcular_salario_liquido() == esperado \ No newline at end of file diff --git a/Guia2/tests/test_estagiario.py b/Guia2/tests/test_estagiario.py new file mode 100644 index 0000000..e1007fe --- /dev/null +++ b/Guia2/tests/test_estagiario.py @@ -0,0 +1,38 @@ +import pytest +from src import Estagiario + + +@pytest.fixture +def estagiario(): + # Salário base 1500, carga horária 30h + return Estagiario("Carlos", "456", 1500.0, "Engenharia", 30) + +# ---- Teste do bônus fixo ---- +def test_bonus_fixo(estagiario): + # 3% do salário base + assert estagiario.calcular_bonus() == 0.03 * estagiario.salario_base + +# ---- Teste do desconto fixo ---- +def test_desconto_fixo(estagiario): + # 2% do salário base + assert estagiario.calcular_descontos() == 0.02 * estagiario.salario_base + +# ---- Testes de adicionais por carga horária ---- +@pytest.mark.parametrize("carga_horaria,adicional_esperado", [ + (20, 150), + (15, 150), # até 20h inclusive + (25, 250), + (30, 250), # até 30h inclusive + (35, 350), + (40, 350), +]) +def test_adicional_por_carga_horaria(estagiario, carga_horaria, adicional_esperado): + estagiario.carga_horaria = carga_horaria + assert estagiario.calcular_adicionais() == adicional_esperado + +# ---- Teste de salário líquido para carga de 30h ---- +def test_salario_liquido_30h(estagiario): + estagiario.carga_horaria = 30 + # 1500 + 45 (bônus) + 250 (adicional) - 30 (desconto) = 1765 + esperado = 1500 + 45 + 250 - 30 + assert estagiario.calcular_salario_liquido() == esperado \ No newline at end of file diff --git a/Guia2/tests/test_gerente.py b/Guia2/tests/test_gerente.py new file mode 100644 index 0000000..da59182 --- /dev/null +++ b/Guia2/tests/test_gerente.py @@ -0,0 +1,47 @@ +import pytest +from src import Gerente + + +@pytest.fixture +def gerente(): + # Salário base 8000, equipe = 5 (para teste básico) + return Gerente("Roberta", "789", 8000.0, "TI", 5) + +# ---- Testes de bônus por tamanho da equipe ---- +@pytest.mark.parametrize("qtd_equipe,percentual_bonus", [ + (3, 0.10), + (5, 0.10), + (6, 0.15), + (10, 0.15), + (11, 0.20), + (20, 0.20), +]) +def test_bonus_por_tamanho_equipe(gerente, qtd_equipe, percentual_bonus): + gerente.qtd_equipe = qtd_equipe + esperado = percentual_bonus * gerente.salario_base + assert gerente.calcular_bonus() == esperado + +# ---- Teste de desconto fixo ---- +def test_desconto_fixo(gerente): + # 12% do salário base + assert gerente.calcular_descontos() == 0.12 * gerente.salario_base + +# ---- Testes de adicional por tamanho da equipe ---- +@pytest.mark.parametrize("qtd_equipe,adicional_esperado", [ + (1, 500), + (5, 500), + (6, 1000), + (10, 1000), + (11, 2000), + (15, 2000), +]) +def test_adicional_por_tamanho_equipe(gerente, qtd_equipe, adicional_esperado): + gerente.qtd_equipe = qtd_equipe + assert gerente.calcular_adicionais() == adicional_esperado + +# ---- Teste integrado para equipe de 8 pessoas ---- +def test_salario_liquido_equipe_8(gerente): + gerente.qtd_equipe = 8 + # bonus 15% = 1200, adicional = 1000, desconto 12% = 960 + esperado = 8000 + 1200 + 1000 - 960 # 9240 + assert gerente.calcular_salario_liquido() == esperado \ No newline at end of file diff --git a/Guia3/.gitignore b/Guia3/.gitignore new file mode 100644 index 0000000..4b3bf0c --- /dev/null +++ b/Guia3/.gitignore @@ -0,0 +1,13 @@ +__pycache__/ +*.pyc +*.pyo +*.pyd +venv/ +.venv/ +.venv +env/ +.env +.pytest_cache/ +.pytest_cache +.coverage +htmlcov/ diff --git a/Guia3/README.md b/Guia3/README.md new file mode 100644 index 0000000..c6877eb --- /dev/null +++ b/Guia3/README.md @@ -0,0 +1,252 @@ +# Guia 3 — Sistema de Quiz + +## Contexto + +Você faz parte da equipe responsável por desenvolver um **Sistema de Quiz** educativo. + +O sistema deve permitir a criação de quizzes (questionários) com perguntas de múltipla escolha ou discursivas, validação de respostas e cálculo de pontuação. + +O projeto já possui a estrutura de pastas definidas. Sua missão é **implementar/completar** as classes seguindo o **diagrama UML** e as regras abaixo, passando em todos os testes. + +--- + +## Diagrama UML + +```mermaid +classDiagram + direction TB + + class Pergunta { + <> + -String texto + -String? explicacao_geral //Pode ser None + +validar_resposta(resposta) boolean + +get_explicacao() String + +get_tipo() String + } + + class PerguntaMultiplaEscolha { + -List~Alternativa~ alternativas + +validar_resposta(int indice) boolean + +get_alternativa_correta() Alternativa + } + + class PerguntaDiscursiva { + -String? resposta_esperada //Pode ser None + +validar_resposta(String texto) boolean + } + + class Alternativa { + +String texto + +boolean correta + +String? explicacao //Pode ser None + } + + class Resposta { + <> + -Pergunta pergunta + -boolean esta_correta + -float pontuacao_obtida + +calcular_pontuacao() float + } + + class RespostaObjetiva { + -int indice_escolhido + -Alternativa? alternativa_selecionada //Pode ser None + } + + class RespostaDiscursiva { + -String texto_resposta + } + + class Questionario { + -String titulo + -List~Pergunta~ perguntas + +adicionar_pergunta(Pergunta p) + +criar_attempt(String usuario) QuizAttempt + } + + class TentativaQuestionario { + -Questionario questionario + -String usuario + -DateTime? data_inicio //Pode ser None + -DateTime? data_fim //Pode ser None + -List~Resposta~ respostas + +registrar_resposta(int indice_pergunta, Object valor) + +finalizar() Tuple~float, String~ + +calcular_pontuacao() float + +is_finalizado() boolean + } + + %% Relacionamentos + Pergunta <|-- PerguntaMultiplaEscolha + Pergunta <|-- PerguntaDiscursiva + Resposta <|-- RespostaObjetiva + Resposta <|-- RespostaDiscursiva + + PerguntaMultiplaEscolha "1" *-- "2..*" Alternativa + Questionario "1" *-- "0..*" Pergunta + Questionario "1" --> "0..*" TentativaQuestionario + TentativaQuestionario "1" *-- "0..*" Resposta + Resposta "1" --> "1" Pergunta +``` + +--- + +## Descrição das Classes + +### Pergunta (Classe Abstrata) + +Classe base para todas as perguntas do sistema. + +Atributos: +- texto: String — Enunciado da pergunta. +- explicacao_geral: String? (opcional) — Texto explicativo mostrado após a correção. + +Métodos: +- validar_resposta(resposta) → boolean — Valida a resposta (implementado nas subclasses). +- get_explicacao() → String — Retorna a explicação geral. +- get_tipo() → String — Retorna o tipo ("multipla_escolha" ou "discursiva"). + +### PerguntaMultiplaEscolha + +Herda de Pergunta. Perguntas com alternativas. + +Atributos: +- alternativas: List[Alternativa] — Lista de alternativas. + +Métodos: +- validar_resposta(int indice) → boolean — Valida o índice escolhido. +- get_alternativa_correta() → Alternativa — Retorna a alternativa correta. + +### PerguntaDiscursiva + +Herda de Pergunta. Perguntas com resposta em texto livre. + +Atributos: +- resposta_esperada: String? (opcional) — Resposta considerada correta. +- case_sensitive: boolean — Diferencia maiúsculas/minúsculas. + +Métodos: +- validar_resposta(String texto) → boolean — Compara texto do usuário. + +### Alternativa + +Representa uma opção em perguntas de múltipla escolha. + +Atributos: +- texto: String — Texto da alternativa. +- correta: boolean — Indica se é correta. +- explicacao: String? (opcional) — Explicação da alternativa. + +### Resposta (Classe Abstrata) + +Classe base para respostas dadas pelo usuário. + +Atributos: +- pergunta: Pergunta — Pergunta respondida. +- esta_correta: boolean — Se a resposta está correta. +- pontuacao_obtida: float — Pontuação obtida. + +Métodos: +- calcular_pontuacao() → float — Calcula pontuação. + +### RespostaObjetiva + +Herda de Resposta. Para perguntas de múltipla escolha. + +Atributos: +- indice_escolhido: int — Índice escolhido. +- alternativa_selecionada: Alternativa? (opcional) + +### RespostaDiscursiva + +Herda de Resposta. Para perguntas discursivas. + +Atributos: +- texto_resposta: String — Texto digitado pelo usuário. + +### Quiz + +Modelo/template do quiz (criado uma vez). + +Atributos: +- titulo: String — Título do quiz. +- perguntas: List[Pergunta] — Lista de perguntas. + +Métodos: +- adicionar_pergunta(Pergunta p) +- criar_attempt(String usuario) → QuizAttempt + +### QuizAttempt + +Representa uma tentativa de responder o quiz. + +Atributos: +- quiz: Quiz — Quiz original. +- usuario: String — Usuário. +- data_inicio: DateTime? +- data_fim: DateTime? +- respostas: List[Resposta] + +Métodos: +- registrar_resposta(int indice_pergunta, Object valor) +- finalizar() → (float, String) +- calcular_pontuacao() → float +- is_finalizado() → boolean + +--- + +## Como prepara o ambiente e rodar os testes? + +#### 1. Criar ambiente virutal + +Na pasta do projeto ..\Guia3> executar o comando: + +```bash +python -m venv .venv +``` + +#### 2. Ativar Ambiente Virtual + +Isso garante que qualquer modificação precise ser feita, seja realizada em um Ambiente Virtual controlado e não produza conflitos entre pacotes de outros projetos. + +PowerShell do Windows: +```bash +.\.venv\Scripts\activate +``` +macOS / Linux: +```bash +source .venv/bin/activate +``` +#### 3. Instalar dependências + +Na pasta do projeto ..\Guia3> executar o comando: + +```bash +pip install -r requirements.txt +``` + +#### Rodar exemplo + +Na pasta do projeto ..\Guia3> executar o comando: + +```bash +python main.py +``` + +#### Rodar testes + +Na pasta do projeto ..\Guia3> executar o comando: + +bash +``` +pytest -v +``` + +ou + +bash +``` +python -m pytest -v +``` \ No newline at end of file diff --git a/Guia3/main.py b/Guia3/main.py new file mode 100644 index 0000000..e9e667d --- /dev/null +++ b/Guia3/main.py @@ -0,0 +1,8 @@ +from Guia3.src import * + +def main(): + pass + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Guia3/pytest.ini b/Guia3/pytest.ini new file mode 100644 index 0000000..97a0030 --- /dev/null +++ b/Guia3/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +pythonpath = src +testpaths = tests \ No newline at end of file diff --git a/Guia3/requirements.txt b/Guia3/requirements.txt new file mode 100644 index 0000000..b820918 --- /dev/null +++ b/Guia3/requirements.txt @@ -0,0 +1,2 @@ +pytest>=8.0.0 +pytest-cov>=4.0.0 diff --git a/Guia3/src/__init__.py b/Guia3/src/__init__.py new file mode 100644 index 0000000..9283af9 --- /dev/null +++ b/Guia3/src/__init__.py @@ -0,0 +1,9 @@ +from .alternativa import Alternativa +from .pergunta import Pergunta +from .perguntadiscursiva import PerguntaDiscursiva +from .perguntamultiplaescolha import PerguntaMultiplaEscolha +from .questionario import Questionario +from .resposta import Resposta +from .respostadiscursiva import RespostaDiscursiva +from .respostaobjetiva import RespostaObjetiva +from .tentativaquestionario import TentativaQuestionario \ No newline at end of file diff --git a/Guia3/src/alternativa.py b/Guia3/src/alternativa.py new file mode 100644 index 0000000..4dde61f --- /dev/null +++ b/Guia3/src/alternativa.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Alternativa: + pass \ No newline at end of file diff --git a/Guia3/src/pergunta.py b/Guia3/src/pergunta.py new file mode 100644 index 0000000..5b3763d --- /dev/null +++ b/Guia3/src/pergunta.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Pergunta: + pass \ No newline at end of file diff --git a/Guia3/src/perguntadiscursiva.py b/Guia3/src/perguntadiscursiva.py new file mode 100644 index 0000000..f4c26af --- /dev/null +++ b/Guia3/src/perguntadiscursiva.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class PerguntaDiscursiva: + pass \ No newline at end of file diff --git a/Guia3/src/perguntamultiplaescolha.py b/Guia3/src/perguntamultiplaescolha.py new file mode 100644 index 0000000..bcbe94d --- /dev/null +++ b/Guia3/src/perguntamultiplaescolha.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class PerguntaMultiplaEscolha: + pass \ No newline at end of file diff --git a/Guia3/src/questionario.py b/Guia3/src/questionario.py new file mode 100644 index 0000000..7525582 --- /dev/null +++ b/Guia3/src/questionario.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Questionario: + pass diff --git a/Guia3/src/resposta.py b/Guia3/src/resposta.py new file mode 100644 index 0000000..846d771 --- /dev/null +++ b/Guia3/src/resposta.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Resposta: + pass \ No newline at end of file diff --git a/Guia3/src/respostadiscursiva.py b/Guia3/src/respostadiscursiva.py new file mode 100644 index 0000000..4ea6dbb --- /dev/null +++ b/Guia3/src/respostadiscursiva.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class RespostaDiscursiva: + pass \ No newline at end of file diff --git a/Guia3/src/respostaobjetiva.py b/Guia3/src/respostaobjetiva.py new file mode 100644 index 0000000..72ed2d0 --- /dev/null +++ b/Guia3/src/respostaobjetiva.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class RespostaObjetiva: + pass \ No newline at end of file diff --git a/Guia3/src/tentativaquestionario.py b/Guia3/src/tentativaquestionario.py new file mode 100644 index 0000000..9947dd1 --- /dev/null +++ b/Guia3/src/tentativaquestionario.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class TentativaQuestionario: + pass \ No newline at end of file diff --git a/Guia3/tests/__init__.py b/Guia3/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Guia3/tests/test_alternativa.py b/Guia3/tests/test_alternativa.py new file mode 100644 index 0000000..41b5c6d --- /dev/null +++ b/Guia3/tests/test_alternativa.py @@ -0,0 +1,21 @@ +import pytest + +from src.alternativa import Alternativa + + +def test_criar_alternativa(): + alt = Alternativa( + texto="Python", + correta=True, + explicacao="Linguagem interpretada" + ) + + assert alt.texto == "Python" + assert alt.correta is True + assert alt.explicacao == "Linguagem interpretada" + + +def test_alternativa_sem_explicacao(): + alt = Alternativa("Java", False) + + assert alt.explicacao is None \ No newline at end of file diff --git a/Guia3/tests/test_pergunta.py b/Guia3/tests/test_pergunta.py new file mode 100644 index 0000000..160c4db --- /dev/null +++ b/Guia3/tests/test_pergunta.py @@ -0,0 +1,8 @@ +import pytest + +from src.pergunta import Pergunta + + +def test_nao_instanciar_pergunta_abstract(): + with pytest.raises(TypeError): + Pergunta("Pergunta abstrata") \ No newline at end of file diff --git a/Guia3/tests/test_perguntadiscursiva.py b/Guia3/tests/test_perguntadiscursiva.py new file mode 100644 index 0000000..04505a7 --- /dev/null +++ b/Guia3/tests/test_perguntadiscursiva.py @@ -0,0 +1,39 @@ +from src.perguntadiscursiva import PerguntaDiscursiva + + +def test_validar_resposta_correta(): + pergunta = PerguntaDiscursiva( + texto="O que é POO?", + resposta_esperada="Programação Orientada a Objetos" + ) + + resposta = "Programação Orientada a Objetos" + + assert pergunta.validar_resposta(resposta) is True + + +def test_validar_resposta_errada(): + pergunta = PerguntaDiscursiva( + texto="O que é POO?", + resposta_esperada="Programação Orientada a Objetos" + ) + + resposta = "Banco de dados" + + assert pergunta.validar_resposta(resposta) is False + + +def test_pergunta_sem_resposta_esperada(): + pergunta = PerguntaDiscursiva( + texto="Explique encapsulamento." + ) + + assert pergunta.resposta_esperada is None + + +def test_get_tipo(): + pergunta = PerguntaDiscursiva( + texto="Explique herança." + ) + + assert pergunta.get_tipo() == "discursiva" \ No newline at end of file diff --git a/Guia3/tests/test_perguntamultiplaescolha.py b/Guia3/tests/test_perguntamultiplaescolha.py new file mode 100644 index 0000000..45f3d32 --- /dev/null +++ b/Guia3/tests/test_perguntamultiplaescolha.py @@ -0,0 +1,51 @@ +from src.alternativa import Alternativa +from src.perguntamultiplaescolha import PerguntaMultiplaEscolha + + +def criar_pergunta(): + alternativas = [ + Alternativa("Java", False), + Alternativa("Python", True), + Alternativa("C", False), + ] + + return PerguntaMultiplaEscolha( + texto="Qual linguagem é interpretada?", + alternativas=alternativas, + explicacao_geral="Python normalmente é interpretada." + ) + + +def test_validar_resposta_correta(): + pergunta = criar_pergunta() + + assert pergunta.validar_resposta(1) is True + + +def test_validar_resposta_errada(): + pergunta = criar_pergunta() + + assert pergunta.validar_resposta(0) is False + + +def test_get_alternativa_correta(): + pergunta = criar_pergunta() + + correta = pergunta.get_alternativa_correta() + + assert correta.texto == "Python" + assert correta.correta is True + + +def test_get_tipo(): + pergunta = criar_pergunta() + + assert pergunta.get_tipo() == "multipla_escolha" + + +def test_get_explicacao(): + pergunta = criar_pergunta() + + assert pergunta.get_explicacao() == ( + "Python normalmente é interpretada." + ) \ No newline at end of file diff --git a/Guia3/tests/test_questionario.py b/Guia3/tests/test_questionario.py new file mode 100644 index 0000000..c592025 --- /dev/null +++ b/Guia3/tests/test_questionario.py @@ -0,0 +1,27 @@ +import pytest + +from src.questionario import Questionario +from src.perguntadiscursiva import PerguntaDiscursiva +from src.tentativaquestionario import TentativaQuestionario + + +def test_adicionar_pergunta(): + questionario = Questionario("Quiz POO") + + pergunta = PerguntaDiscursiva( + texto="O que é encapsulamento?" + ) + + questionario.adicionar_pergunta(pergunta) + + assert len(questionario.perguntas) == 1 + + +def test_criar_attempt(): + questionario = Questionario("Quiz Redes") + + tentativa = questionario.criar_attempt("valter") + + assert isinstance(tentativa, TentativaQuestionario) + assert tentativa.usuario == "valter" + diff --git a/Guia3/tests/test_resposta.py b/Guia3/tests/test_resposta.py new file mode 100644 index 0000000..fd9a6d6 --- /dev/null +++ b/Guia3/tests/test_resposta.py @@ -0,0 +1,8 @@ +import pytest + +from src.resposta import Resposta + + +def test_nao_instanciar_resposta_abstract(): + with pytest.raises(TypeError): + Resposta(None) \ No newline at end of file diff --git a/Guia3/tests/test_respostadiscursiva.py b/Guia3/tests/test_respostadiscursiva.py new file mode 100644 index 0000000..b1201d4 --- /dev/null +++ b/Guia3/tests/test_respostadiscursiva.py @@ -0,0 +1,42 @@ +from src.perguntadiscursiva import PerguntaDiscursiva +from src.respostadiscursiva import RespostaDiscursiva + + +def criar_pergunta(): + return PerguntaDiscursiva( + texto="O que significa CPU?", + resposta_esperada="Central Processing Unit" + ) + + +def test_resposta_discursiva_correta(): + pergunta = criar_pergunta() + + resposta = RespostaDiscursiva( + pergunta=pergunta, + texto_resposta="Central Processing Unit" + ) + + assert resposta.esta_correta is True + + +def test_resposta_discursiva_errada(): + pergunta = criar_pergunta() + + resposta = RespostaDiscursiva( + pergunta=pergunta, + texto_resposta="Memória RAM" + ) + + assert resposta.esta_correta is False + + +def test_calcular_pontuacao(): + pergunta = criar_pergunta() + + resposta = RespostaDiscursiva( + pergunta=pergunta, + texto_resposta="Central Processing Unit" + ) + + assert resposta.calcular_pontuacao() == 1.0 \ No newline at end of file diff --git a/Guia3/tests/test_respostaobjetiva.py b/Guia3/tests/test_respostaobjetiva.py new file mode 100644 index 0000000..e2a0739 --- /dev/null +++ b/Guia3/tests/test_respostaobjetiva.py @@ -0,0 +1,59 @@ +from src.alternativa import Alternativa +from src.perguntamultiplaescolha import PerguntaMultiplaEscolha +from src.respostaobjetiva import RespostaObjetiva + + +def criar_pergunta(): + alternativas = [ + Alternativa("HTTP", False), + Alternativa("TCP/IP", True), + ] + + return PerguntaMultiplaEscolha( + texto="Qual protocolo é base da internet?", + alternativas=alternativas + ) + + +def test_resposta_objetiva_correta(): + pergunta = criar_pergunta() + + resposta = RespostaObjetiva( + pergunta=pergunta, + indice_escolhido=1 + ) + + assert resposta.esta_correta is True + + +def test_resposta_objetiva_errada(): + pergunta = criar_pergunta() + + resposta = RespostaObjetiva( + pergunta=pergunta, + indice_escolhido=0 + ) + + assert resposta.esta_correta is False + + +def test_calcular_pontuacao_correta(): + pergunta = criar_pergunta() + + resposta = RespostaObjetiva( + pergunta=pergunta, + indice_escolhido=1 + ) + + assert resposta.calcular_pontuacao() == 1.0 + + +def test_calcular_pontuacao_errada(): + pergunta = criar_pergunta() + + resposta = RespostaObjetiva( + pergunta=pergunta, + indice_escolhido=0 + ) + + assert resposta.calcular_pontuacao() == 0.0 \ No newline at end of file diff --git a/Guia3/tests/test_tentativaquestionario.py b/Guia3/tests/test_tentativaquestionario.py new file mode 100644 index 0000000..e0f4ede --- /dev/null +++ b/Guia3/tests/test_tentativaquestionario.py @@ -0,0 +1,90 @@ +from src.alternativa import Alternativa +from src.perguntamultiplaescolha import PerguntaMultiplaEscolha +from src.perguntadiscursiva import PerguntaDiscursiva +from src.questionario import Questionario +from src.tentativaquestionario import TentativaQuestionario + + +def criar_questionario(): + q = Questionario("Quiz") + + p1 = PerguntaMultiplaEscolha( + texto="2 + 2?", + alternativas=[ + Alternativa("3", False), + Alternativa("4", True), + ] + ) + + p2 = PerguntaDiscursiva( + texto="Sigla CPU", + resposta_esperada="Central Processing Unit" + ) + + q.adicionar_pergunta(p1) + q.adicionar_pergunta(p2) + + return q + + +def test_registrar_resposta_objetiva(): + q = criar_questionario() + + tentativa = TentativaQuestionario( + questionario=q, + usuario="valter" + ) + + tentativa.registrar_resposta(0, 1) + + assert len(tentativa.respostas) == 1 + + +def test_registrar_resposta_discursiva(): + q = criar_questionario() + + tentativa = TentativaQuestionario( + questionario=q, + usuario="valter" + ) + + tentativa.registrar_resposta( + 1, + "Central Processing Unit" + ) + + assert len(tentativa.respostas) == 1 + + +def test_calcular_pontuacao(): + q = criar_questionario() + + tentativa = TentativaQuestionario( + questionario=q, + usuario="valter" + ) + + tentativa.registrar_resposta(0, 1) + tentativa.registrar_resposta( + 1, + "Central Processing Unit" + ) + + assert tentativa.calcular_pontuacao() == 2.0 + + +def test_finalizar(): + q = criar_questionario() + + tentativa = TentativaQuestionario( + questionario=q, + usuario="valter" + ) + + tentativa.registrar_resposta(0, 1) + + pontuacao, feedback = tentativa.finalizar() + + assert pontuacao >= 0 + assert isinstance(feedback, str) + assert tentativa.is_finalizado() is True \ No newline at end of file diff --git a/Guia4/.gitignore b/Guia4/.gitignore new file mode 100644 index 0000000..4b3bf0c --- /dev/null +++ b/Guia4/.gitignore @@ -0,0 +1,13 @@ +__pycache__/ +*.pyc +*.pyo +*.pyd +venv/ +.venv/ +.venv +env/ +.env +.pytest_cache/ +.pytest_cache +.coverage +htmlcov/ diff --git a/Guia4/README.md b/Guia4/README.md new file mode 100644 index 0000000..95cb04c --- /dev/null +++ b/Guia4/README.md @@ -0,0 +1,171 @@ +# Guia 4 — Serviço LLM + +## Contexto +Você faz parte da equipe responsável por desenvolver um **Sistema de Quiz** educativo. +O sistema deve permitir a criação de quizzes com perguntas de múltipla escolha ou **discursivas**, validação de respostas e cálculo de pontuação. + +Agora, **perguntas discursivas** deverão ser corrigidas por um serviço de LLM (Groq) via API. +Sua missão é implementar/completar as classes seguindo o **diagrama UML** complementar e as regras abaixo. + +--- + +## Diagrama UML + +### 1. Diagrama Principal (mantido exatamente como estava) + +```mermaid +classDiagram + direction TB + class Pergunta { + <> + -String texto + -String? explicacao_geral + +validar_resposta(resposta) boolean + +get_explicacao() String + +get_tipo() String + } + class PerguntaMultiplaEscolha { + -List~Alternativa~ alternativas + +validar_resposta(int indice) boolean + +get_alternativa_correta() Alternativa + } + class PerguntaDiscursiva { + -String? resposta_esperada + +validar_resposta(String texto) boolean + } + class Alternativa { + +String texto + +boolean correta + +String? explicacao + } + class Resposta { + <> + -Pergunta pergunta + -boolean esta_correta + -float pontuacao_obtida + +calcular_pontuacao() float + } + class RespostaObjetiva { + -int indice_escolhido + -Alternativa? alternativa_selecionada + } + class RespostaDiscursiva { + -String texto_resposta + } + class Questionario { + -String titulo + -List~Pergunta~ perguntas + +adicionar_pergunta(Pergunta p) + +criar_attempt(String usuario) QuizAttempt + } + class TentativaQuestionario { + -Questionario questionario + -String usuario + -DateTime? data_inicio + -DateTime? data_fim + -List~Resposta~ respostas + +registrar_resposta(int indice_pergunta, Object valor) + +finalizar() Tuple~float, String~ + +calcular_pontuacao() float + +is_finalizado() boolean + } + + %% Relacionamentos + Pergunta <|-- PerguntaMultiplaEscolha + Pergunta <|-- PerguntaDiscursiva + Resposta <|-- RespostaObjetiva + Resposta <|-- RespostaDiscursiva + + PerguntaMultiplaEscolha "1" *-- "2..*" Alternativa + Questionario "1" *-- "0..*" Pergunta + Questionario "1" --> "0..*" TentativaQuestionario + TentativaQuestionario "1" *-- "0..*" Resposta + Resposta "1" --> "1" Pergunta +``` + +### 2. Diagrama Complementar — Integração com LLM (Novo) + +```mermaid +classDiagram + direction TB + + class LLMService { + <> + -String api_key + -String model + -Groq_obj groq + +__init__(api_key: str, model: str = "llama3-70b-8192") + -_fazer_chamada_api(prompt: str) -> str + } + + class Correcao { + <> + +corrigir_discursiva(pergunta: PerguntaDiscursiva, resposta_aluno: str, service: LLMService = None) -> Dict + +criar_prompt_correcao(pergunta: PerguntaDiscursiva, resposta_aluno: str) -> str + } + + LLMService o-- Correcao : "é usado por" +``` + +--- + +## Nova Descrição das Classes + +### LLMService (Classe de Serviço) +Responsável pela **conexão direta** com o serviço Groq. + +**Responsabilidades:** +- Guardar a API Key (deve ser carregada via variável de ambiente `GROQ_API_KEY`) +- Realizar as chamadas HTTP para a API do Groq +- **Tratar todos os erros** (timeout, rate limit, autenticação, JSON inválido, etc.) internamente +- Montar o prompt adequado para correção de questões discursivas +- Retornar apenas o resultado limpo (nunca expor detalhes da API para o resto da aplicação) + +**Métodos principais:** +- `corrigir_resposta(pergunta: PerguntaDiscursiva, resposta_aluno: str) → Dict` + - Retorna dicionário com: `{"correta": bool, "pontuacao": float, "feedback": str, "explicacao": str}` + +### CorrecaoUtil (Classe Utilitária) +Classe de alto nível que a aplicação deve usar. + +**Responsabilidades:** +- Abstrair o uso do `LLMService` +- Criar o prompt de forma inteligente +- Fornecer interface simples e limpa para o resto do sistema +- Possibilitar uso de mock em testes + +**Método principal:** +- `corrigir_discursiva(...)` + +--- + +## Regras de Implementação Importantes + +1. **Não modificar** as classes existentes do diagrama principal. +2. A classe `PerguntaDiscursiva` **não deve** conhecer o `LLMService` diretamente. +3. Toda correção de discursiva deve passar pela `Correcao`. +4. O `LLMService` deve: + - Usar a biblioteca `groq` (ou `requests`) + - Tratar erros internamente + - Ter fallback ou mensagem clara em caso de falha na API +5. A API Key **nunca** deve ficar hard-coded. + +--- + +## Como preparar o ambiente + +```bash +# 1. Criar venv +python -m venv .venv + +# 2. Ativar +# Windows +.\.venv\Scripts\activate +# Linux/macOS +source .venv/bin/activate + +# 3. Instalar dependências +pip install -r requirements.txt +``` + +--- \ No newline at end of file diff --git a/Guia4/main.py b/Guia4/main.py new file mode 100644 index 0000000..e9e667d --- /dev/null +++ b/Guia4/main.py @@ -0,0 +1,8 @@ +from Guia3.src import * + +def main(): + pass + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Guia4/requirements.txt b/Guia4/requirements.txt new file mode 100644 index 0000000..a0ca34d --- /dev/null +++ b/Guia4/requirements.txt @@ -0,0 +1,4 @@ +pytest>=8.0.0 +pytest-cov>=4.0.0 +groq +python-dotenv \ No newline at end of file diff --git a/Guia4/src/__init__.py b/Guia4/src/__init__.py new file mode 100644 index 0000000..9283af9 --- /dev/null +++ b/Guia4/src/__init__.py @@ -0,0 +1,9 @@ +from .alternativa import Alternativa +from .pergunta import Pergunta +from .perguntadiscursiva import PerguntaDiscursiva +from .perguntamultiplaescolha import PerguntaMultiplaEscolha +from .questionario import Questionario +from .resposta import Resposta +from .respostadiscursiva import RespostaDiscursiva +from .respostaobjetiva import RespostaObjetiva +from .tentativaquestionario import TentativaQuestionario \ No newline at end of file diff --git a/Guia4/src/alternativa.py b/Guia4/src/alternativa.py new file mode 100644 index 0000000..4dde61f --- /dev/null +++ b/Guia4/src/alternativa.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Alternativa: + pass \ No newline at end of file diff --git a/Guia4/src/correcao.py b/Guia4/src/correcao.py new file mode 100644 index 0000000..bdf2fa4 --- /dev/null +++ b/Guia4/src/correcao.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Correcao: + pass \ No newline at end of file diff --git a/Guia4/src/llmservice.py b/Guia4/src/llmservice.py new file mode 100644 index 0000000..e6e91b5 --- /dev/null +++ b/Guia4/src/llmservice.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class LLMService: + pass \ No newline at end of file diff --git a/Guia4/src/pergunta.py b/Guia4/src/pergunta.py new file mode 100644 index 0000000..5b3763d --- /dev/null +++ b/Guia4/src/pergunta.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Pergunta: + pass \ No newline at end of file diff --git a/Guia4/src/perguntadiscursiva.py b/Guia4/src/perguntadiscursiva.py new file mode 100644 index 0000000..f4c26af --- /dev/null +++ b/Guia4/src/perguntadiscursiva.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class PerguntaDiscursiva: + pass \ No newline at end of file diff --git a/Guia4/src/perguntamultiplaescolha.py b/Guia4/src/perguntamultiplaescolha.py new file mode 100644 index 0000000..bcbe94d --- /dev/null +++ b/Guia4/src/perguntamultiplaescolha.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class PerguntaMultiplaEscolha: + pass \ No newline at end of file diff --git a/Guia4/src/questionario.py b/Guia4/src/questionario.py new file mode 100644 index 0000000..7525582 --- /dev/null +++ b/Guia4/src/questionario.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Questionario: + pass diff --git a/Guia4/src/resposta.py b/Guia4/src/resposta.py new file mode 100644 index 0000000..846d771 --- /dev/null +++ b/Guia4/src/resposta.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class Resposta: + pass \ No newline at end of file diff --git a/Guia4/src/respostadiscursiva.py b/Guia4/src/respostadiscursiva.py new file mode 100644 index 0000000..4ea6dbb --- /dev/null +++ b/Guia4/src/respostadiscursiva.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class RespostaDiscursiva: + pass \ No newline at end of file diff --git a/Guia4/src/respostaobjetiva.py b/Guia4/src/respostaobjetiva.py new file mode 100644 index 0000000..72ed2d0 --- /dev/null +++ b/Guia4/src/respostaobjetiva.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class RespostaObjetiva: + pass \ No newline at end of file diff --git a/Guia4/src/tentativaquestionario.py b/Guia4/src/tentativaquestionario.py new file mode 100644 index 0000000..9947dd1 --- /dev/null +++ b/Guia4/src/tentativaquestionario.py @@ -0,0 +1,4 @@ +from typing import List, Tuple, Dict + +class TentativaQuestionario: + pass \ No newline at end of file diff --git a/Guia4/tests/__init__.py b/Guia4/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Guia5/.gitignore b/Guia5/.gitignore new file mode 100644 index 0000000..4b3bf0c --- /dev/null +++ b/Guia5/.gitignore @@ -0,0 +1,13 @@ +__pycache__/ +*.pyc +*.pyo +*.pyd +venv/ +.venv/ +.venv +env/ +.env +.pytest_cache/ +.pytest_cache +.coverage +htmlcov/ diff --git a/Guia5/README.md b/Guia5/README.md new file mode 100644 index 0000000..7c18aef --- /dev/null +++ b/Guia5/README.md @@ -0,0 +1,149 @@ +# Guia 5 — Projeto de Sistema com Orientação a Objetos + +## Contexto + +Agora é sua vez de propor e implementar um **sistema completo** utilizando o paradigma de Orientação a Objetos em Python. + +O objetivo deste guia é consolidar os conceitos vistos no curso de POO: classes, objetos, construtores, métodos, encapsulamento, atributos de classe/métodos de classe, herança, polimorfismo, classes abstratas, interfaces (via ABC), composição, etc. + +**Exemplos de sistemas sugeridos** (escolha um ou crie o seu): +- Sistema de Banco (conta corrente, poupança, transferência, cliente) +- Sistema de Gerenciamento de Biblioteca +- Sistema de Loja/E-commerce simples (Produto, Carrinho, Cliente, Pedido) +- Sistema de Escola (Aluno, Professor, Disciplina, Turma) +- Sistema de Hospital (Paciente, Médico, Consulta, Exame) + +Toda o projeto deve estar explicado conceitualmente em um arquivo Guia5__README.md contendo o que se segue: + +--- + +## 1. Diagrama UML + +### Diagrama de Classes Principal + +Mantenha o diagrama **exatamente como está** (atualize apenas se necessário). + +```mermaid +classDiagram + class Cliente { + -nome: str + -cpf: str + +__init__(nome, cpf) + +__str__() str + } + class Conta { + <> + -numero: int + -saldo: float + +depositar(valor) + +sacar(valor) + +transferir(destino, valor) + } + class ContaCorrente { + -limite: float + } + class ContaPoupanca { + -taxa_rendimento: float + } + Cliente "1" --> "1..*" Conta : possui + Conta <|-- ContaCorrente + Conta <|-- ContaPoupanca +``` + +--- + +## Descreva as Classes (Exemplos) + +Cliente: Representa o titular da conta. +Conta (abstrata): Define o contrato comum (depósito, saque, transferência). +ContaCorrente: Herda de Conta, permite saldo negativo até o limite. +ContaPoupanca: Herda de Conta, aplica rendimento. + +--- + +## Use este esquema de pastas como Exemplo +```bash +meu-sistema-banco/ +├── src/ +│ ├── __init__.py +│ ├── cliente.py +│ ├── conta.py +│ ├── conta_corrente.py +│ └── conta_poupanca.py +├── tests/ +│ ├── __init__.py +│ ├── test_cliente.py +│ ├── test_conta_corrente.py +│ └── test_sistema_banco.py +├── requirements.txt +├── README.md +└── .gitignore +``` + +--- + +## Descreva como preparar o ambiente + +Siga rigorosamente uma sequência e descreva ela nesta seção para garantir reprodutibilidade. Exemplo: + + +### 1. Criar venv + +Na pasta do projeto ..\Guia5> executar o comando: + +```bash +python -m venv .venv +``` + +### 2. Ativar ambiente + +#### Windows + +Na pasta do projeto ..\Guia5> executar o comando: + +```bash +.\.venv\Scripts\activate +``` + +#### Linux/macOS + +Na pasta do projeto ..\Guia5> executar o comando: + +```bash +source .venv/bin/activate +``` + +### 3. Instalar dependências + +Na pasta do projeto ..\Guia5> executar o comando: + +```bash +pip install -r requirements.txt +``` + +### 4. Testes + +Na pasta do projeto ..\Guia5> executar o comando: + + +```bash +pytest -v +``` + +ou + +```bash +python -m pytest -v +``` + +### 5. Execução +Na pasta do projeto ..\Guia5> executar o comando: + +```bash +python main.py +``` + +Na tela que abrir você poderá interagir com o sistema da seguinte forma... (descreva funcionalidades, o que o usuário pode experimentar, etc.). + +--- + diff --git a/Guia5/main.py b/Guia5/main.py new file mode 100644 index 0000000..6222e1f --- /dev/null +++ b/Guia5/main.py @@ -0,0 +1,8 @@ +from Guia5.src import * + +def main(): + pass + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Guia5/requirements.txt b/Guia5/requirements.txt new file mode 100644 index 0000000..4616af2 --- /dev/null +++ b/Guia5/requirements.txt @@ -0,0 +1,3 @@ +pytest>=8.0.0 +pytest-cov>=4.0.0 +python-dotenv \ No newline at end of file diff --git a/Guia5/src/__init__.py b/Guia5/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Guia5/tests/__init__.py b/Guia5/tests/__init__.py new file mode 100644 index 0000000..e69de29