Rozdíly

Zde můžete vidět rozdíly mezi vybranou verzí a aktuální verzí dané stránky.

Odkaz na výstup diff

public:pb161_fall14_cviko03_452036 [2018/02/24 19:10] (aktuální)
Řádek 1: Řádek 1:
 +====== Cvičení 03 ======
 +===== Úvod do cvičení =====
 +Na tomto a nasledujúcom cvičení budeme pracovať so zložitejšou hierarchiou objektov. Hierarchia bude v konečnom dôsledku predstavovať niečo ako jednoduchú textovú verziu hry [[http://​en.wikipedia.org/​wiki/​The_Sims|The Sims]]. Pravdepodobne si pri hraní textovej verzie neužijete toľko zábavy, ako v The Sims 4, ale snáď sa niečo nové naučíte :-). Pomerne veľká časť kódu (napr. textové menu, pomocné triedy, atď.) bude už pre vás pripravená , vašou úlohou bude len doplniť časti kódu podľa nižšie uvedených inštrukcií. Na tomto cvičení pripravíme časti hierarchie, ktoré využijeme v ďalšom cvičení. Stiahnite si [[https://​www.fi.muni.cz/​~xklucar/​_tmp/​pb161/​pb161-cv03.zip|archív]] s kostrou projektu.
  
 +<note important>​Poznámka pre testerov: vzhľadom k tomu, že študenti v tejto fáze semestra ešte neovládajú niektoré užitočné prvky jazyka C++ (napr. kontajnery, preťažovanie operátorov,​ dynamic_cast,​ atď.), sú niektoré časti hierarchie riešené možno nie úplne elegantne. Ak na niečo také narazíte a budete mať nejaký nápad, ako by sa to dalo vylepšiť, budem rád, ak mi ho napíšete.</​note>​
 +
 +===== Predstavenie hierarchie =====
 +V tomto odstavci si stručne zhrnieme, akú rolu zohrávajú jednotlivé triedy v našej hierarchii (niektoré časti hierarchie sa objavia až v nasledujúcom cvičení). Ďalšie informácie o hierarchii je možné získať z dokumentácie jednotlivých tried, metód a atribútov.
 +
 +Základom pre našu hru je susedstvo (''​class Neighborhood''​),​ v ktorom sa nachádzajú domy (''​class House''​). V domoch sa nachádzajú miestnosti (''​class Room''​) a bývajú tam simíci (''​class Sim''​),​ ktorí majú svoje potreby (''​class SimNeeds''​). Simík sa môže presúvať medzi jednotlivými miestnosťami;​ na jednoduché zapamätanie miestnosti, v ktorej sa simík nachádza, je možné použiť priloženú triedu (''​class SimRoomMap''​). V miestnosti sa nachádzajú rozličné predmety. Pre jednoduchosť uvážime len 3 druhy predmetov (posteľ -- ''​class Bed'',​ počítač -- ''​class Computer''​ a obraz -- ''​class Painting''​). Uvedené triedy majú spoločného abstraktného predka -- ''​class HouseholdItem''​. Táto trieda obsahuje dva atribúty typu ''​bool''​ -- ''​isInteractive''​ a ''​isDecorative''​. Prvý z nich je nastavený na ''​true'',​ ak ide o predmet, s ktorým môže simík interagovať. Druhý je nastavený na ''​true'',​ ak ide o predmet, ktorý má dekoratívny účel -- "​skrášľuje"​ miestnosť (predmet môže byť interaktívny aj dekoratívny zároveň). ​
 +
 +Triedy ''​House'',​ ''​Room'',​ ''​Sim''​ a ''​HouseholdItem''​ sú potomkami abstraktnej triedy ''​IObject''​. Vďaka tomu si môžete pomocou triedy ''​ListOfObjects''​ pamätať zoznamy domov, miestností,​ simíkov a predmetov, do ktorých môžete jednoducho pridávať nové prvky a odoberať existujúce.
 +
 +<note tip>Ak to uznáte za vhodné, môžete si do ľubovoľnej triedy hierarchie pridať pomocné metódy a atribúty.</​note>​
 + 
 +===== První úkol - SimNeeds =====
 +Trieda ''​SimNeeds''​ slúži na reprezentáciu potrieb simíka. Okrem toho ju využívame ako návratový typ v metóde ''​HouseholdItem::​interact'',​ kde slúži na reprezentáciu hodnôt, o ktoré sa zmenia potreby simíka po interakcii s objektom. Trieda obsahuje tri atribúty typu ''​int''​ -- ''​fun'',​ ''​energy''​ a ''​roomBeauty''​ na reprezentáciu príslušných potrieb simíka a getter a setter pre každú z nich. Okrem toho obsahuje trieda boolovský atribút ''​enforceLimits''​ (a príslušný getter). Ak je tento atribút nastavený na ''​true'',​ je nutné zabezpečiť,​ aby sa hodnoty všetkých potrieb simíka nachádzali medzi 0 až 10 vrátane (ak je limit prekročený,​ použije sa okrajová hodnota). Ak je ''​enforceLimits''​ nastavené na ''​false'',​ hodnoty celočíselných atribútov nie sú nijakým spôsobom obmedzované.
 +
 +Okrem toho trieda obsahuje dva konštruktory (viď priložený kód) a implementácie operátorov ''​+''​ a ''​+=''​. Sčítanie dvoch tried typu SimNeeds prebieha tak, že sa sčítajú hodnoty príslušných atribútov. Výsledná trieda má ''​enforceLmits''​ nastavený na ''​true'',​ práve ak ho na ''​true''​ mala nastavená **aspoň jedna** zo sčítavaných tried.
 +
 +==== Zadání úkolu ====
 +V súboroch ''​simneeds.cpp''​ a ''​simneeds.h''​ je pre vás pripravená implementácia uvedenej triedy. V implementácii v súbore ''​simneeds.cpp''​ sa však zámerne nachádzajú 3 drobné chyby. Chyby by ste pravdepodobne odhalili aj prečítaním kódu, vašou úlohou je však napísať jednoduché unit testy, ktoré chyby odhalia. ​
 +
 +  * Pomocou frameworku catch vytvorte jednoduché unit testy pre túto triedu. (Môžete sa inšpirovať testami, ktoré boli dodané k prvým dvom cvičeniam.)
 +  * Vaše unit testy umiestnite do súboru ''​simneeds_tests.cpp''​ a spustite ich (cieľ simneeds_tests). Ak máte testy napísané rozumne, niektoré by mali zlyhať.
 +  * Opravte 3 chyby v implementácii (stačia drobné zmeny, nie je nutné celý kód prepisovať).
 +  * Spustite znova unit testy, tentokrát by mali prejsť.
 +
 +<note tip>​Cieľom je si písanie unit testov na cvičení vyskúšať,​ aby ste ich mohli používať pre kontrolu vlastného kódu napr. pri práci na domácich úlohách. Ak sa vám pomocou unit testov nedarí objaviť chyby, môžete nahliadnuť do priloženého vzorového riešenia. </​note>​
 +
 +===== Druhý úkol - hierarchia pre predmety v domácnosti =====
 +Vašou úlohou bude doplniť v súboroch ''​objects.cpp''​ a ''​objects.h''​ časti hierarchie pre reprezentáciu predmetov, ktoré sa môžu nachádzať v miestnostiach pre simíkov.
 +
 +==== Zadání úkolu ====
 +  * Definujte abstraktnú triedu ''​IObject''​ s čiste virtuálnou metódou ''​string getId() const''​. ''​id''​ je reťazec, ktorý bude užívateľovi slúžiť pre jednoduchšiu identifikáciu objektov.
 +  * Nezabudnite,​ že do triedy ''​IObject''​ je nutné pridať ešte jednu metódu (niektorí potomkovia ''​IObject''​ budú v ďalšom cvičení dynamicky alokovať pamäť, ktorú budú potom potrebovať uvoľniť).
 +
 +Trieda ''​HouseholdItem''​ je už pre vás pripravená,​ význam metódy ''​getListOfInteractions()''​ zatiaľ nemusíte riešiť. Implementujte nasledujúcich potomkov triedy ''​HouseholdItem''​ a prekryte uvedené metódy.
 +
 +=== class  Painting ===
 +  * Trieda, ktorá predstavuje obraz. Ide o dekoratívny predmet.
 +  * Trieda bude obsahovať konštruktor ''​Painting(string id, unsigned price)''​. ''​price''​ predstavuje cenu obrazu.
 +  * ''​getBeauty''​ vráti stotinu ceny obrazu (celočíselné delenie)
 +  * ''​getId''​ vráti ''​id''​ zadané v konštruktore
 +  * Zvyšné metódy implementovať nemusíte (použije sa zdedená verzia)
 +
 +=== class Bed ===
 +  * Trieda, ktorá predstavuje posteľ. Ide o predmet, s ktorým simík môže interagovať a zároveň má aj dekoratívny účel.
 +  * Trieda bude obsahovať konštruktor s jedným parametrom ''​string id''​. Tento reťazec bude vracať metóda ''​getId''​.
 +  * ''​getBeauty''​ vráti 2
 +  * ''​interact''​ vo všetkých prípadoch vráti inštanciu ''​SimNeeds'',​ kde ''​roomBeauty''​ bude ''​0''​ a ''​enforceLimits''​ bude ''​false''​. Ak je parametrom metódy reťazec ''​Sleep'',​ ''​energy''​ bude 10 a ''​fun''​ bude -3, ak je parametrom reťazec ''​Relax'',​ ''​energy''​ bude 2 a ''​fun''​ bude -3.  Ináč bude ''​energy''​ aj ''​fun''​ rovné 0.
 +  * Metódu ''​getListOfInteractions''​ zatiaľ implementovať nemusíte (použije sa zdedená verzia).
 +
 +=== class Computer ===
 +  * Trieda predstavujúca počítač. Ide o predmet, s ktorým môže simík interagovať. Počítač môže byť zapnutý alebo vypnutý.
 +  * Trieda bude obsahovať konštruktor s jedným parametrom ''​string id''​. Tento reťazec bude vracať metóda ''​getId''​. Po vytvorení je počítať vypnutý.
 +  * Metódu ''​getListOfInteractions''​ zatiaľ implementovať nemusíte (použije sa zdedená verzia).
 +
 +Metóda ''​interact''​ bude pracovať nasledovne: ​
 +  * Ak je počítač vypnutý a parametrom metódy je reťazec ''​Turn on'',​ počítač sa zapne. Ak bol zadaný iný parameter, nestane sa nič. 
 +  * Ak bol počítač zapnutý, sú tri možné hodnoty parametra metódy: ''​Turn off''​ -- počítač sa vypne, ''​Play games''​ -- vráti inštanciu SimNeeds s ''​energy=-1''​ a ''​fun=5''​ a ''​Visit social network''​ -- vráti inštanciu SimNeeds s ''​energy=-1''​ a ''​fun=allVisits-myVisits''​ kde ''​allVisits''​ je počet návštev sociálnej siete zo všetkých počítačov (použite statický atribút) a ''​myVisits''​ je počet návštev sociálnej siete z príslušného počítača.
 +  * V uvedených prípadoch bude vždy vo vrátenej inštancii ''​SimNeeds''​ použité ''​roomBeauty = 0''​ a ''​enforceLimist=false''​. V prípadoch, ktoré vyššie nie sú zmienené, budú vo vrátenej inštancii všetky atribúty nastavené na 0.
 +
 +<note important>​Otestujte si vašu implementáciu pomocou testov priložených v súbore ''​objects_tests.cpp''​ (cieľ object_tests). Testy tentokrát nie sú až také dôkladné, môžete si ich ale sami vhodne rozšíriť. </​note>​
 +
 +
 +===== Třetí úkol - class Sim =====
 +Trieda predstavuje simíka, ktorý bude interagovať s predmetmi. Simík má svoje meno, vek, pohlavie (''​enum Gender''​) a potreby (limitované na hodnoty od 0 do 10). Trieda je potomkom ''​IObject'',​ aby bolo možné využiť ''​ListOfObjects''​ na vytváranie zoznamu simíkov v dome.
 +
 +==== Zadání úkolu ====
 +V súboroch ''​sim.h''​ a ''​sim.cpp''​ implementujte triedu Sim:
 +  * Trieda bude potomkom ''​IObject''​. ​
 +  * Konštruktor ''​Sim(string name, unsigned age, Gender gender)''​ vytvorí simíka so zadaným menom, vekom a pohlavím. U potrieb simíka bude ''​energy''​ a ''​fun''​ nastavené na 5, ''​roomBeauty''​ na 0.
 +  * ''​getId()''​ vráti meno simíka
 +  * Konštantná metóda ''​getNeeds()''​ vráti aktuálne potreby simíka vo forme konštantnej referencie na príslušný atribút typu ''​SimNeeds''​.
 +  * Metóda ''​void setRoomBeauty(int)''​ nastaví v potrebách simíka krásu miestnosti na hodnotu zadanú ako parameter
 +  * Metóda ''​useObject(HouseholdItem* o, string interaction)''​ bude pracovať nasledovne: ak ''​*o''​ nie je interaktívny (atribút ''​isInteractive''​),​ metóda neurobí nič. V opačnom prípade zavolá metódu ''​interact''​ u objektu, na ktorý ukazuje ''​o''​. Výsledok volania (návratová hodnota ''​interact''​) sa pripočíta k aktuálnym potrebám simíka. Ak ide o neplnoletého simíka, návratová hodnota sa pripočíta dvakrát (tzn. neplnoletému simíkovi sa menia potreby dvakrát rýchlejšie). (Pozor, to neznamená, že neplnoletý simík s predmetom interaguje dvakrát!)
 +
 +<note important>​Unit testy sú k dispozícii v súbore ''​sim_tests.cpp''​ (cieľ sim_tests). Môžete si ich ďalej rozšíriť.</​note>​
 +
 +<note important>​Pozrite si súbor ''​listofobjects_demo.cpp''​ (cieľ listofobjects_demo),​ ktorý demonštruje použitie triedy ''​ListOfObjects''​ -- túto triedu budete používať v ďalšom cvičení.</​note>​
 +
 +===== Bonus =====
 +Pomocou nástroja ''​gcov'',​ ktorý je súčasťou ''​gcc/​g++'',​ môžete jednoduchým spôsobom zistiť, aké percento kódu vaše unit testy pokrývajú. Vo všeobecnosti platí, že čím väčšie pokrytie, tým lepšie, je potrebné však vziať do úvahy aj ďalšie faktory -- prečítajte si k tejto téme krátky príbeh: http://​stackoverflow.com/​a/​90021
 +
 +Základné použitie ''​gcov''​ (bližšie info v dokumentácii):​
 +  - Skompilujte vašu binárku pomocou ''​g++''​ s použitím dodatočných prepínačov ''​-fprofile-arcs -ftest-coverage''​.
 +  - Spustite binárku. ​
 +  - Zavolajte ''​gcov -b -r subor.cpp''​ kde ''​subor.cpp''​ je súbor s kódom, v ktorom chcete overiť pokrytie testami.
 +
 +Ak by sme teda chceli overiť, ako dobre pokrývajú kód v súbore ''​simneeds.cpp''​ testy zo súboru ''​simneeds_tests.cpp'',​ použili by sme nasledujúce príkazy:
 +  - ''​g++ -Wall -Wextra -fprofile-arcs -ftest-coverage simneeds.cpp simneeds_tests.cpp -o simneeds''​
 +  - ''​./​simneeds''​
 +  - ''​gcov -b -r simneeds.cpp''​
 +===== Vzorové řešení =====
 +[[https://​www.fi.muni.cz/​~xklucar/​_tmp/​pb161/​pb161-cv03-solution.zip|Vzorové riešenie]]
 +
 +--- //Cvičenie pripravil Marek Klučár. Ak v zadaní, pripravenom kóde alebo vzorovom riešení objavíte nejaké nedostatky/​chyby,​ píšte prosím na <​klucar@mail.muni.cz>//​
QR Code
QR Code public:pb161_fall14_cviko03_452036 (generated for current page)