From b7f85f6f8d76577804b45fd9a277779685acabfc Mon Sep 17 00:00:00 2001 From: RaimundoValter Date: Thu, 21 May 2026 17:32:25 -0300 Subject: [PATCH 1/4] Guia 2 --- Guia2/README.md | 155 ++++++++++++++++++ Guia2/pytest.ini | 3 + Guia2/requirements.txt | 0 Guia2/run_tests.bat | 2 + Guia2/src/__init__.py | 1 + .../src/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 274 bytes Guia2/src/folha_pagamento/__init__.py | 4 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 358 bytes .../__pycache__/desenvolvedor.cpython-312.pyc | Bin 0 -> 419 bytes .../__pycache__/estagiario.cpython-312.pyc | Bin 0 -> 413 bytes .../__pycache__/funcionario.cpython-312.pyc | Bin 0 -> 3389 bytes .../__pycache__/gerente.cpython-312.pyc | Bin 0 -> 407 bytes Guia2/src/folha_pagamento/desenvolvedor.py | 6 + Guia2/src/folha_pagamento/estagiario.py | 6 + Guia2/src/folha_pagamento/funcionario.py | 77 +++++++++ Guia2/src/folha_pagamento/gerente.py | 6 + Guia2/tests/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 156 bytes ...desenvolvedor.cpython-312-pytest-8.3.5.pyc | Bin 0 -> 5824 bytes ...st_estagiario.cpython-312-pytest-8.3.5.pyc | Bin 0 -> 5706 bytes .../test_gerente.cpython-312-pytest-8.3.5.pyc | Bin 0 -> 5809 bytes Guia2/tests/integrity.py | 32 ++++ Guia2/tests/test_desenvolvedor.py | 44 +++++ Guia2/tests/test_estagiario.py | 38 +++++ Guia2/tests/test_gerente.py | 47 ++++++ 25 files changed, 421 insertions(+) create mode 100644 Guia2/README.md create mode 100644 Guia2/pytest.ini create mode 100644 Guia2/requirements.txt create mode 100644 Guia2/run_tests.bat create mode 100644 Guia2/src/__init__.py create mode 100644 Guia2/src/__pycache__/__init__.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__init__.py create mode 100644 Guia2/src/folha_pagamento/__pycache__/__init__.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/desenvolvedor.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/estagiario.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/funcionario.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/__pycache__/gerente.cpython-312.pyc create mode 100644 Guia2/src/folha_pagamento/desenvolvedor.py create mode 100644 Guia2/src/folha_pagamento/estagiario.py create mode 100644 Guia2/src/folha_pagamento/funcionario.py create mode 100644 Guia2/src/folha_pagamento/gerente.py create mode 100644 Guia2/tests/__init__.py create mode 100644 Guia2/tests/__pycache__/__init__.cpython-312.pyc create mode 100644 Guia2/tests/__pycache__/test_desenvolvedor.cpython-312-pytest-8.3.5.pyc create mode 100644 Guia2/tests/__pycache__/test_estagiario.cpython-312-pytest-8.3.5.pyc create mode 100644 Guia2/tests/__pycache__/test_gerente.cpython-312-pytest-8.3.5.pyc create mode 100644 Guia2/tests/integrity.py create mode 100644 Guia2/tests/test_desenvolvedor.py create mode 100644 Guia2/tests/test_estagiario.py create mode 100644 Guia2/tests/test_gerente.py 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 0000000000000000000000000000000000000000..73e61bee553995b8bd027336b80c464892268f93 GIT binary patch literal 274 zcmXwxJx&8L6ol>dhMz>MT!0H~LqP{ZH2kE9AT%^9OO};=BnJPiZ0|}r2@MzEEVNW^ zD5&U=(xu{Af|2HX^Q6(dSJjxHUf0v7TfATS`B(85wnrFVNK0C(iJ=WOMN=5oFjF=q zC7YsV-?>_sX?z``Tq)_5OZzkMU?ZgJ3If={=>b~j)8wYNOXX}X-PNNseRO&)MJHF% zVBdL$TfWQ~W$Yo|$QDU%-+e!o~`3lE*+vtG#)9{iFEp{$BR h9Cw@D!MSm5ui?T^aEYQr4nK@i`bp*=WbO~~{{@WEN-zKb literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c9423a903a7dca7b90ee06f3f9aa6224229a09cf GIT binary patch literal 358 zcmYjMyH3L}6t(lLQUYRULJVYKKuid+@TgcQ3rl3lvKluH*l}bhk-G2^Ed2()g+GWC z7A7{NZk@O;<#DBZea^AYx%O)uM+oX^w)5}|=es38XlRLxg|GpVvh@N>Nl$@Z6K W7sjWHG49bpkM?_X_=fiM7N}opPh`0O literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..4184750c23ee8739353eb22bf091220842d63946 GIT binary patch literal 419 zcmZ8dJx{|h5WP!MDgB6$SXo)Jbbt*Z77*Q97M948WyNj@Byn&)q^_v{p}zs~Q}_cY z5@KLtLu5eegq^ekagv|kv+tgL_w0EC(DAm|yM566yAiu^wxl`KWDOiR#*kou2o_9$ zTPxu9lhtJf*3$8NA4d3C4=>9!jAY7GB*QMDL)?mHq{$it1js?xqHopSg~&x($+!|+ zs;O_+E~P0;1f}(W(nRtyHhe_seaYhP<`EiWxtX4ykn3EioK!3>1kql1h0Ms+Y-Sc! zB9mlNM(l{>DkO6m-!Pi7g|<%%N%-HV$JtW#v}p^5|Lhn8`c&MHQTtST`OnG)6z^N-`DVIBjPI@f4hkNFVN7|`~bVbXleie literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..065df0dbcb89a046b855bcc4ae46a3e63fcf4c99 GIT binary patch literal 413 zcmZ8dJx{|h5WP!MDNP$8v9hvc=>Qu-EPQl8qAVmI$Vy;D`PSz&(e~U6RvJcQIN~Y#4IX# zA;`E&*d9?bB2$rGGg`2jE}xfz@ZWbw#a#Au#TE=v1{Uz*xY7)&JvX1*`B!5!{cBj- nn@rg^tThfaTe*i_A4k&H(#%3_YxuAc@fG&JT*Uq-XlOk@grQ}} literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..a87ac567fc05396055a7991980519217e7f7a3ed GIT binary patch literal 3389 zcmbsrO>Yxd@a>o5&vkHc8=E9{5}+}KfKs?rh|&T@&^A;JJQaZH#6^J zKHq*Hi-ifm!H?tDJ`WP|J5IVFbcpsLAXbS&6hC z<>vzmzrxQ7YCsWGZk|;FEBw>Wve`bD+vnj1Z7vVGK@T?s>%+hc!EOs*(jX zBWvrAz{YHO{cAnDs4HsLP-(WTF34u_raqbDt?);(R#DGUs#8mlY$t`KZ7;9GL_H}AOpRZ1$g%UnK$#7;RqvtQ`Ss1e^xcFoBCq@!%LU&lc>6==g(J) z@>JfSh5Wp(U6rLpc|k6zWmC`3ZwG90amflwQn6e#C8@gC6Uxah7f&@V0=i9piVysp z7}^+~tS63cM34R&AGD{(>xmN^(G#1ISJy^=i0rd@Z`Bj0H=?IElc~G>r{QLL9ENyv zICq!-F_><{Zo~>u)vVBR!3_{Fk+zc}4Fn_wxdx*jX2=s}I>*o`2%az$qh{d3EbRwu zd#&2LBoygu3?+7A~pjsXHE?Hydb@Zdr-HT>1c7bDG~Y-8w1ZRkid znOeQ_;7TKTxRyM;6%zWxEh2=%y>3Jo+HSlJ#0%VrIzH&W09D|F^SUpUN6V*yZNmqy z2E2eX#K~UX?kbj8kTq;=RGQPv6~h{E=dx0?8+*~P5-w9wje-tc#OQJBpsUkOG_81} z0!_5K-|OM$X&r_u8|MIlv!nfu=x{AM+!PZHakM6m*2VEHj*0ExM8?6Ic(5)`Yzb^E z*9wsMKtnuG6A#qI*S7k&*hGulH3C=J0R^1`3VI3!TdNa#!HIa-6X=i|Un}klV=m;`WFKxa)ZK|@ zkjf$&MKp%U*A}hBf=VIFFniz^>8g68qE<(|nb9jh4*M9N0O~0~Z{2yTv5}mpB`501 zL(TL^BRy41Pu0`Mp=ukcW3|+=dTOef8E<4x)-osSnNwSPLRhe&-3k^Cb<%|gVikT6 z?4o(nW0q}tHSM*-&2ZbjXJCCBixzAMMteI0NOn1h;(w^$g|>5d`piAcjoW!#_&TDV z#|@Y-eN+~7tC?NR+D@1EKxzA|>0H822`el~C0(g#(0r|^B;BaUn$wCc4t|dlZc zE2PCng+psIEds-1XZTiVJO<-t^kicF%H1<%y*P_*80m+g?9PI?wR>BQ$0Jpp?7?_^-Lwm61iej($3^A{N=c7OaI If}_3rzZ)*OL;wH) literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..444c7e28d7fdbdb5546407bbd4222630c1e9431c GIT binary patch literal 407 zcmZ8dJx{|h5WP!MHT{T?SXo)Jbbt*Z77$^gEG&^F%ZlALki@}BDs}IF=x;#$6#f8; z#Kgpg$bi%dJ86Z)Nq&CMzI*oFtLF_tM}Kkfu+;m95&Ljas#><@mi%BYdn!*Hsq9GGi*1QJ2sm?nE=zWCH?1)W+U zX~t4PX+5MgmApy}A5;2Nv820shQ^p}Z!XWseIZmqmMkd+xe~==DRXi+otj0J$R!D? zn4OS9MPw$E1*18eYx}H}WZpeG$ychU?OHITFtCO<$5m!T?Ya5c(LaO9?5|a2?=#iF ku(oid+15Spnz&G&mSzgYp@uIT5#QnT$3+}`gNC-|7wB_hPXGV_ literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..65afc7ba052841abcb210e076b4cc2512b3b915a GIT binary patch literal 156 zcmX@j%ge<81i23USs?l`h(HIQS%4zb87dhx8U0o=6fpsLpFwJVSvy7&-6@X`dxTLuH@qeV)apbnHw2>;9lJyg#itJiOilTA?8ASs@D6!(Ml$9wi zJG)dRg#_f*KyxXOo719)pePC(LJOnqAwBm}AcvBcY#9p_b0r~dL%$qkeyPR*|<0oxxSpwygg^tB3jgWt0MU+&i>^=qM4zY+O70HamuJV#n zkR`ID&ZH#Xqs?g0BNx+4nVF14Y;EzFa1>uHCRf%d>C4^%j2f)GoWTZ&n<0 zaMrgy-(xawC6_x;UJcszw9qzijf?VL0Qw&^(%Gt3e}-+ z?G)_Waj9dOmfc^rX~8b}6|-n4h8$>%73^F1#m}+an=oYB0%OAZpP(LSeE7l;D}SCS z;NC=uZryj`soo(~sY>#qk5uIKvi|G2mZiM^ZTT0Ik{aoqfz>DfX1-g$%U_=Ex-C+9oN zB`ZV8$}q2R-=oRO>mEX)TNH|?DtMV~mfiDw*`@i!oud6pcy+iz+|&(F>bi0ForXTVt>Wil*uZO%Y^cNU zkMr7QtZt!k4{v_J21Wz80`Bj=6Acq;(&&*o%s5(zUJI}X+&_C|{F-x*EJDNnQj>sX zlHf~Cwj@TqCPb{MRi&yjE~bE*DM7psB=3|j-r-~sPTc+iv_s}8I4Z$B)yEaGvdE$X zQR7#!CdRzje-k>!Bm+Xkmj98CNQeV$C2{T#u#*pI7tsl3{{P;2M0;SU)|8<~#j{G> znY0q5;I#f7^4i0o`eNaj3X&VGYH#J`Z8*2c{O)ots?>B+z`+h zn}>{Sa4ceOv?h86-JC`7DvE9t=TLkF#aB^$4aIp7f|5Ph08z#sGL9r+_&Nu6$jlry z(3mlt^D#HLr*^R!A&)Uaik0T)ofVgkf*;(t_g4_>L0r602@T>xh^K*u}hhab%6Ce&9PLvfLAO zYAov1!l*OtAC{PD@ir0HFzQTFQowQgIpHXN<4%H(=qidlj|q$T6i^J2Ddx5h?AUaF@D4zSEGXlsye}|?>no|T*$1ev6o}~~VJRv;C__1%! zJo|qv52-QyTSl+K7$lPSTM+Byad!{T3eSF>q2x)&`7kBSHS}CvodCJ14}ntGhwiU5 z^oea1KM%tOUW;Tyoj{tP#b&H-p>d8kKVSo+0bBw1_gA;G?D>9k#It5NLczpm?-ERk#sB8bU+ALTz^219i!y zHv=91HGuyCeCn*(ET3kfBf~JejTF;7wkme_pJl$e}RqpeM{O^hI_q7zr$oId?-Es3 wKFcc7$gU3B4r)(ZW$A|Wg#n{aiFOGFXfU8%maa*=9iZ-THJg$yOKiFS1}LSA7ytkO literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..bdcfb1cf5898e0a23351b53293c72bba75a5ca35 GIT binary patch literal 5706 zcmeHL(Qn(v8NVY>lq}hC;xw6)bg9~=h3U4c?Zio&+Nqtkt2cOQ*I^i77$X>ww&}>C zcBHe|l>lc=u|4)-XkLn;7`DQOfx?gZANDXQa^r%)unxl>i~@yQ@5xX5zB`hpQlmD4 z0O>;s@#FX1{l1UKlkUgg>F*sKSpvuEbmwe7MaX|Jhz^LwvAqVD+r%OkEs+T-uF9NR zR4AEa6DcZtv?M z;UW%;T8gDw%u20>bMQ-|YgYp8HItWIFHp}7o}U)T%Iy&-U!JzhGf>{#JPoZJYp#%O z1ngXX?c(IGJezxy*Uge|Prhz@*L=4!`Sx3H;c0NY;!eIf@0bIVzU}#*um*VHfD4s{ zAiEp#4k(Ia@_qzniTqC^?Z-cu`8f6Q_2ufFcbd78Ive3R=qtug13?>{;z|Dsb9S3l z$t*P7f7GZ#sxsIPNHk9s#e(|jH8ySD%I4r9`LlP_5t;d`_Zq4%xcLT z>03%wo1&JASyRd?3tO3wBNWH1_&r9EyhdZXPP}7@`t7YKjH+Zcd~TjZ9{Mh1nOZDS zbuTQ9s_uhR4v14D9NhW){p2hjY3d_w5x&t{+S06aHSJIlW&9)2+$QE`kCk7|M3tiJ z?}15f&>DqPfm4H1g_G4%3q;RcnZ9%S{V#uU=g+UM&>dxXSf`7%XL>3N=X5XoZs_EP z^XLskP2hx0eY#gDnx*1=$>hdWw>)e!$9#=!N+&LB3}~ zvf~<8P0!BObg}eSv_P#a^r0C*a}Lb~G%p3Lve4hR(`kCJ+p4sRnL zpg$R$O$O(a!OL=JVNOfZpzM-&>mO)|&UyH=&qoKxr5tpM2@v0wG3DHF`3umBT;}}) z%o6z`cWfhfrja{SXJcTSxo5#y#%S&2M*mo&e@w>U_M%${KrbN2HW+^HMJ+OnZG(;d z@uG~HyY4!o&&cMxA~W`v!{)ex9D%qARDi(<7c2CK_l}`)ksnAJzSAE_8YY3v?)A!v zUt|Y(Jv~B_e)q9Y-~9LDpI+si@F2j^Hy@CrE!!))W#4^BJk9Z~#Jka)z=36hu9$w~ zTk%ua|2P_ynOumsC(z5Ic@oW2Xr4xM2FzZp)g@RfDk_Pq53q+3pCGQDMy{vM#=$mo zz2GccVAdu!2FDwN<1z-ffNmWC1wf8(F#Oz$T4Wg81{+7>LP&GhT}O0}Y`!ZpV}IF_ zZfxZUq6#n=;bMis@ZK?0I#5s$*J8eC@@dnUaXISV=S|Bg!g~Z>Kekt~xoNq&rYoC| z!5nOU2nKxof$#z8<9D*TBYci80zN3)aiTYW0}2lCpeYHz0H%n_H9BI=UXV(bR*4by zp|0Iat*W4F)ks5vc4bvXDArUp<$aY#( zrOxY~6i{6eVs{~|FphGVA4P);0@dRAokIzo2x^lbhaRA*j+S*59F18kD(rX%Wh^}- z#>6k-jW42k2F{$3I8erZ;kWosEKR=AHwm4)#R|M>iOLK8spp7~2LLMT$d6bJtx*v@V

6G=KL4lB@x;D`T@x%+8>sj-_ARhySssHVVq3#!sV~P zy5qxWB$tSVA9TkIa$mgz(@0v<$m>|Sl|lFjwvB@EaN&fEAvbf~f-vs8r*XD#hW`Yh zPhrmAz$}r^pLkNx#21}UFO3PVC^T|~IvWDp%=Lj&&-JarHg0Hx;pelkK}NA{upwj$ zL^OBZbp#h=^Iee`CrAg%ufZNIOpDwk=pGvqJfR;6GSLoPNX6iUA@}SBN#&q_3f%r3 zcYN4?$4x;xY!mYxXfh>GJznGtCLl<|R@a~Bwwz_$@^X}q0h=@VwIB!Ef7sCb+*z~* z#fs_U_$Qedm6+_E%+Q=`&6n&;{B7vKf51Hae{xHul>Up5Tjaftf0C118c{NTIDPZ< z*NQ?%>9$Ig!&}1rCach&QnWv(TUkV%x_N4Yb~k8u{lqKZkn|;Go1_)>>%$7YOt+7K NyCvN$qr+k#{|B!WW?TRO literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..42c8ece72bf1eed6daec55129e5b0f65754100e6 GIT binary patch literal 5809 zcmd6rO>7)V6@aUMre{3uzc`R}5|Xud*Rgw@_%Dus7Hnt5;sAmyECD2AX=qQkz2nTd zXRF(bZDu3~g4pBUvLFr-0+h&?h|_X`11H3Rnb@(TmJlm(01F9u<2~iXdsSWCZD+!m zDAH1ze*LQIy;oK3uCHJD&rMBf0_FSPYgyb*5b}4dhyrz1_8-CR7O{vW<;jf1?s7rN z$`UE4GYN_JXfqo0$oXU;HItHvtu3|%{;`{-+$0-8eI^YyCt{s}x_I)*HcMR~R^pe^ zhRpjcEf%NAO5P+h&HqER6hv!?MN7w`wOBetYh9I$#$6oj>RriCUa_gYAl0CSDn87oFKF%Q$Kd^6q=gzfzgPZ!Lih7Ca(6@H_9nZ?x?=0tv z_W7bsv#{c2GoP7rmX=*ZGvr;I;6Hx;Gc3QGGGy8Sb=m>~`ZVmj$jTp~Zx>%HdW`pB z^uX^=*!LOiLy^UZqJ+=$Yw$?*V(Qq`Ck0a6DEPQ$maGmQ>Q_;qQn(^YTUz-BLVU3oDC_LW}NVtapj~ z*;xGM$UF~yM(Z_)aSM$MZ~PTqRKeQ~<)o!q$x<>Wv0BPIE}lVbE%?$LDy5VdSKNODh+2`#DqM-Own~f??BU1q#DpQO zeZ8xvxH@dO=^qA4$3zEeL!t?kplQHx`?6*}yPP*E-vsG$kC85SOmLSG!)2SxPuVVP z7t?a?s=iWO9Y8UJVi?89<7U%^o$Rr3#tau5#|+(1N88PBbWIo~=Vazg*Y=wa4(q2c z7guqYXH4oJ%Rpxy_dm@#g`!DqzY)4KbIZBBms@guE$@JZ>$hjzx1Hs@#Y{5`d1nsx z@{(Dw{f3Nd&I2im)Ng*BO)cjveThcCvU#b976}LK=|7$p_@?SM%!vXLvA+wX22To z5wP#cuQ>n6A~YN>WeJ!j3C@&dOJek^LB_ILQc5c0V*==z5afGba!+`{cZrZifsDoS!79rsPVg)6JuW#zXl~Eq5&x)%l}GABt;!tN$meRcJdMJLQ28N z|KBSQsShmGYO)kR#H_@gO^x*IsVtR%r7~O^Tnb!jIl;KP@Zs5?{Og+^{(g#Lb^(07 z@r-=6Y&YvHd5#+~wg*Fv0*+s0>jv9=r%t#^#Gg+HVWt8_tQogkfGm(S_n1if$B;O%Q6Jcoju22!YEB z*w6y5G1GV8=kZfa+6f@1t=T;m#0dbJZ?q5KxlaG*p zT~)oSqE3U{)Vo2sGYsNh_s-CCb!eK`LG4Ag0tUTcIlZIeZ(FqRYACDfG{O;0HY0Tl zt-E;hedZbJcZRtdN{cMVg8URyTKYPO+WBc8=kvk*v}Sf%R)E%u zAR`c2Ey;|-kc&bF8nLeyg(aXbW}x5`qpAA|WpYD|6mXV|on$S!4E0)P*|H3@kV9H1kiSWc7Ql_Vw18X> zXn{GO6r)ArQ>I0t4h6z}SjR4;ilsfb6@~d?U0Q^eKnpmd2Itj;m9iR2iGUW`k!hg` zN{D+v3(T*SvI==s`syxjo?JVm9D*C)eMWAG>?oguf9zOJlwQT*!47dxp+$R0i$kG~ zjEp2l2BsuWrv>hrfEMxN-=Q&s!(V2MeiiI7-Ew~oVx2rZd5RtWK5FR>PJF#py|+s(JIPZHjw`Q~BGRq7pB9=Wqil;a>EB3@6r@l~dtmV8tNv}Z% zCQ$BsAodhVlKw`>P4eTWzmgaBG$N;ddiKWIk7ZdJ*;k0%x`*0c8rx6bIK3maSEcsK y$&p7SIWF&$q^x}0sz?L-$3WXd?NOsFU6Gz}7z2mT3kO-63LH>NtI}(1rvCvcfpkFt literal 0 HcmV?d00001 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 From 45e2e7162b2f7dfa202e9f4547e370ad0b08cc73 Mon Sep 17 00:00:00 2001 From: RaimundoValter Date: Thu, 28 May 2026 15:51:05 -0300 Subject: [PATCH 2/4] Guia 3 --- Guia3/.gitignore | 13 + Guia3/README.md | 252 ++++++++++++++++++++ Guia3/main.py | 8 + Guia3/pytest.ini | 3 + Guia3/requirements.txt | 2 + Guia3/src/__init__.py | 9 + Guia3/src/alternativa.py | 4 + Guia3/src/pergunta.py | 4 + Guia3/src/perguntadiscursiva.py | 4 + Guia3/src/perguntamultiplaescolha.py | 4 + Guia3/src/questionario.py | 4 + Guia3/src/resposta.py | 4 + Guia3/src/respostadiscursiva.py | 4 + Guia3/src/respostaobjetiva.py | 4 + Guia3/src/tentativaquestionario.py | 4 + Guia3/tests/__init__.py | 0 Guia3/tests/test_alternativa.py | 21 ++ Guia3/tests/test_pergunta.py | 8 + Guia3/tests/test_perguntadiscursiva.py | 39 +++ Guia3/tests/test_perguntamultiplaescolha.py | 51 ++++ Guia3/tests/test_questionario.py | 27 +++ Guia3/tests/test_resposta.py | 8 + Guia3/tests/test_respostadiscursiva.py | 42 ++++ Guia3/tests/test_respostaobjetiva.py | 59 +++++ Guia3/tests/test_tentativaquestionario.py | 90 +++++++ 25 files changed, 668 insertions(+) create mode 100644 Guia3/.gitignore create mode 100644 Guia3/README.md create mode 100644 Guia3/main.py create mode 100644 Guia3/pytest.ini create mode 100644 Guia3/requirements.txt create mode 100644 Guia3/src/__init__.py create mode 100644 Guia3/src/alternativa.py create mode 100644 Guia3/src/pergunta.py create mode 100644 Guia3/src/perguntadiscursiva.py create mode 100644 Guia3/src/perguntamultiplaescolha.py create mode 100644 Guia3/src/questionario.py create mode 100644 Guia3/src/resposta.py create mode 100644 Guia3/src/respostadiscursiva.py create mode 100644 Guia3/src/respostaobjetiva.py create mode 100644 Guia3/src/tentativaquestionario.py create mode 100644 Guia3/tests/__init__.py create mode 100644 Guia3/tests/test_alternativa.py create mode 100644 Guia3/tests/test_pergunta.py create mode 100644 Guia3/tests/test_perguntadiscursiva.py create mode 100644 Guia3/tests/test_perguntamultiplaescolha.py create mode 100644 Guia3/tests/test_questionario.py create mode 100644 Guia3/tests/test_resposta.py create mode 100644 Guia3/tests/test_respostadiscursiva.py create mode 100644 Guia3/tests/test_respostaobjetiva.py create mode 100644 Guia3/tests/test_tentativaquestionario.py 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 From be8e7d2e5bacef3504f8ab5350580122632c6443 Mon Sep 17 00:00:00 2001 From: RaimundoValter Date: Fri, 12 Jun 2026 15:10:19 -0300 Subject: [PATCH 3/4] Guia 4 --- Guia4/.gitignore | 13 ++ Guia4/README.md | 173 +++++++++++++++++++++++++++ Guia4/main.py | 8 ++ Guia4/requirements.txt | 4 + Guia4/src/__init__.py | 9 ++ Guia4/src/alternativa.py | 4 + Guia4/src/correcao.py | 4 + Guia4/src/llmservice.py | 4 + Guia4/src/pergunta.py | 4 + Guia4/src/perguntadiscursiva.py | 4 + Guia4/src/perguntamultiplaescolha.py | 4 + Guia4/src/questionario.py | 4 + Guia4/src/resposta.py | 4 + Guia4/src/respostadiscursiva.py | 4 + Guia4/src/respostaobjetiva.py | 4 + Guia4/src/tentativaquestionario.py | 4 + Guia4/tests/__init__.py | 0 17 files changed, 251 insertions(+) create mode 100644 Guia4/.gitignore create mode 100644 Guia4/README.md create mode 100644 Guia4/main.py create mode 100644 Guia4/requirements.txt create mode 100644 Guia4/src/__init__.py create mode 100644 Guia4/src/alternativa.py create mode 100644 Guia4/src/correcao.py create mode 100644 Guia4/src/llmservice.py create mode 100644 Guia4/src/pergunta.py create mode 100644 Guia4/src/perguntadiscursiva.py create mode 100644 Guia4/src/perguntamultiplaescolha.py create mode 100644 Guia4/src/questionario.py create mode 100644 Guia4/src/resposta.py create mode 100644 Guia4/src/respostadiscursiva.py create mode 100644 Guia4/src/respostaobjetiva.py create mode 100644 Guia4/src/tentativaquestionario.py create mode 100644 Guia4/tests/__init__.py 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..ca95454 --- /dev/null +++ b/Guia4/README.md @@ -0,0 +1,173 @@ +# 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 + -String base_url + +__init__(api_key: str, model: str = "llama3-70b-8192") + +corrigir_resposta(pergunta: PerguntaDiscursiva, resposta_aluno: str) -> Dict + -_fazer_chamada_api(prompt: str) -> str + -_tratar_erro(e: Exception) -> None + } + + 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 From a3ae950ceb917ebef2ff52ea86e90002ad0de81c Mon Sep 17 00:00:00 2001 From: RaimundoValter Date: Sun, 14 Jun 2026 15:26:31 -0300 Subject: [PATCH 4/4] Guia 5 --- Guia4/README.md | 4 +- Guia5/.gitignore | 13 ++++ Guia5/README.md | 149 ++++++++++++++++++++++++++++++++++++++++ Guia5/main.py | 8 +++ Guia5/requirements.txt | 3 + Guia5/src/__init__.py | 0 Guia5/tests/__init__.py | 0 7 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 Guia5/.gitignore create mode 100644 Guia5/README.md create mode 100644 Guia5/main.py create mode 100644 Guia5/requirements.txt create mode 100644 Guia5/src/__init__.py create mode 100644 Guia5/tests/__init__.py diff --git a/Guia4/README.md b/Guia4/README.md index ca95454..95cb04c 100644 --- a/Guia4/README.md +++ b/Guia4/README.md @@ -93,11 +93,9 @@ classDiagram <> -String api_key -String model - -String base_url + -Groq_obj groq +__init__(api_key: str, model: str = "llama3-70b-8192") - +corrigir_resposta(pergunta: PerguntaDiscursiva, resposta_aluno: str) -> Dict -_fazer_chamada_api(prompt: str) -> str - -_tratar_erro(e: Exception) -> None } class Correcao { 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