<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>RoboProjekt</title><link href="https://roboprojekt.pyladies.cz/" rel="alternate"></link><link href="https://roboprojekt.pyladies.cz/feed.xml" rel="self"></link><id>https://roboprojekt.pyladies.cz/</id><updated>2019-11-26T18:00:00+01:00</updated><entry><title>Poslední sraz</title><link href="https://roboprojekt.pyladies.cz/posledni-sraz" rel="alternate"></link><published>2019-11-26T18:00:00+01:00</published><updated>2019-11-26T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-11-26:/posledni-sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Dnes se scházíme naposled. 
Čeká nás finální opravování zásadních chyb, které mohou ovlivnit aktuální hratelnost hry, chceme doladit nějaké drobnosti a především otestovat hru v maximálním možném počtu hráčů.
Od minulého setkání prošla hra většími proměnami z hlediska grafiky a podařilo se vyřešit téměř všechno, co jsme si vytyčily pro …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Dnes se scházíme naposled. 
Čeká nás finální opravování zásadních chyb, které mohou ovlivnit aktuální hratelnost hry, chceme doladit nějaké drobnosti a především otestovat hru v maximálním možném počtu hráčů.
Od minulého setkání prošla hra většími proměnami z hlediska grafiky a podařilo se vyřešit téměř všechno, co jsme si vytyčily pro úspěšné ukonční projektu.&lt;/p&gt;
&lt;p&gt;Na začátku jsme ještě doplnily poslední důležitou věc, možnost nastavení nižšího počtu hráčů i v mapách pro více hráčů a pak už nic nebránilo testování hry.&lt;/p&gt;
&lt;p&gt;Aby nás bylo co nejvíce, pozvaly jsme si i posilu a tak nás i dohromady s Petrem bylo sedm.
V této sestavě jsme vyzkoušeli dvě mapy.
První byla v takto velkém počtu hráčů téměř nehratelná, ale byla to velká zábava (a velká řež).&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/screenshot_hard.png" target="_blank" title="screenshot_hard"&gt;&lt;img alt="screenshot_hard" src="https://roboprojekt.pyladies.cz/images/thumbnails/screenshot_hard.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Taková mapa by byla obtížná i v menším počtu hráčů, ale v sedmi lidech na ní bylo prakticky nemožné vyhrát.
Přibližně po hodině hraní jsme vzdali pokusy dostat se dál než na čtvrtou vlajku a zvolili jednodušší mapu.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/screenshot_mid.png" target="_blank" title="screenshot_mid"&gt;&lt;img alt="screenshot_mid" src="https://roboprojekt.pyladies.cz/images/thumbnails/screenshot_mid.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Ta už nám umožnila otestovat i výhru :)&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/screenshot_mid_win.png" target="_blank" title="screenshot_mid_win"&gt;&lt;img alt="screenshot_mid_win" src="https://roboprojekt.pyladies.cz/images/thumbnails/screenshot_mid_win.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Z testování vyplynulo ještě několik drobností.
Líbilo by se nám, kdyby bylo na mapě patrné, kde má který robot aktuální startovací políčko. 
Může se nám také stát, že když se má robot znovu objevit na svém aktuálním startovacím políčku a stojí na něm v tu chvíli jiný robot, stojí pak na sobě a překrývají se.
To by se dít nemělo a je třeba to vyřešit.
Testovací hry také ukázaly, že nám chybí větší množství jednodušších, lépe hratelných map.
Uvidíme, kolik z toho se nám podaří do čtvrtka vyřešit.&lt;/p&gt;
&lt;h3&gt;Co bude dál?&lt;/h3&gt;
&lt;p&gt;Přestože bude projektový kurz ve čtvrtek oficiálně ukončený, neznamená to, že na projektu nebudeme dál pracovat.
Je to něco, s čím žijeme více než rok, věřím tedy, že některé z nás určitě budou chtít kód dále vylepšovat.
Velkým krokem ale bude to, že ho veřejně představíme komunitě. 
Dá se tedy čekat, že se do vývoje zapojí i další lidé a Roboprojekt si tedy bude více žít vlastním životem.&lt;/p&gt;
&lt;h3&gt;Poděkování na závěr&lt;/h3&gt;
&lt;p&gt;Roboprojekt byl experimentální kurz.
Nikdo z nás na začátku netušil, kam se to celé vyvine a co nás všechno čeká.
Ráda bych poděkovala Petrovi, že se rozhodl takový kurz vést, že to s námi vydržel tak dlouho, za to, kolik nás toho naučil a jakou s námi měl trpělivost.
Poděkování patří také společnosti &lt;a href="https://www.kinali.cz/cs/"&gt;Kinali&lt;/a&gt;, která nám dovolila využívat tak dlouho jejich meetingovou místnost.
A v neposlední řadě všem, co se na Roboprojektu podíleli, že dali vzniknout fantastické hře, kterou si už každý může zkusit zahrát!&lt;/p&gt;
&lt;p&gt;Chcete si hru zahrát nebo se zapojit? Roboprojekt najdete &lt;a href="https://github.com/PyLadiesCZ/roboprojekt"&gt;na GitHubu&lt;/a&gt;!&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Předposlední sraz - Finishujeme!</title><link href="https://roboprojekt.pyladies.cz/predposledni-sraz" rel="alternate"></link><published>2019-11-19T18:00:00+01:00</published><updated>2019-11-19T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-11-19:/predposledni-sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Původně byl náš projektový kurz zamýšlený jako semestrální. 
Ukázalo se, že to bude mnohem víc práce, než jsme si dovedly představit, takže se scházíme už déle než rok. 
Abychom stanovily nějaký konec, dohodly jsem se, že Roboprojekt uzavřeme během listopadu. 
Čekala nás tedy dvě poslední setkání na doladění a učesání …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Původně byl náš projektový kurz zamýšlený jako semestrální. 
Ukázalo se, že to bude mnohem víc práce, než jsme si dovedly představit, takže se scházíme už déle než rok. 
Abychom stanovily nějaký konec, dohodly jsem se, že Roboprojekt uzavřeme během listopadu. 
Čekala nás tedy dvě poslední setkání na doladění a učesání aktuálního stavu.&lt;/p&gt;
&lt;p&gt;Při procházení posledních úprav jsme narazily na kus kódu, jehož zápisu většina z nás nerozuměla. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Petr nám vysvětlil, že jde o specifický druh operátoru.
Operátory můžeme dělit podle počtu operandů, se kterými pracují. 
Běžne se i v kódu setkáváme s operátory &lt;strong&gt;unární&lt;/strong&gt;, například &lt;code&gt;-1&lt;/code&gt;, a &lt;strong&gt;binární&lt;/strong&gt; (&lt;code&gt;1 + 1&lt;/code&gt;, &lt;code&gt;3 % 6&lt;/code&gt;, nebo &lt;code&gt;True or False&lt;/code&gt;). 
Zde se jedná o &lt;strong&gt;ternární operátor&lt;/strong&gt;, takovým se v Pythonu říká také podmíněné výrazy, &lt;strong&gt;conditional expressions&lt;/strong&gt;. 
V podstatě umožňují napsat podmínkovou if-else část kódu pouze na jeden řádek. 
Vysvětleno například &lt;a href="https://www.geeksforgeeks.org/ternary-operator-in-python/"&gt;zde&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;V našem případě jde tedy jen o jiný zápis&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Dobrá praxe ve sdílených projektech nicméně je používat zápis, který je srozumitelný většině. 
Přestože jsme se tedy naučily něco nového, bylo by lepší použít druhou, běžnější variantu.&lt;/p&gt;
&lt;h3&gt;Věci k dořešení do budoucna&lt;/h3&gt;
&lt;p&gt;Sepsaly jsme do projektu několik věcí, které ještě nejsou v ideálním stavu, i bez nich je ale možné vypustit projekt do světa.
Mezi takové patří složka s mapami, které jsou již vytvořené.
Aktuálně jsou všechny ve stejném adresáři a je v nich trochu nepořádek.
Stálo by za to mapy rozdělit do smysluplných celků, dát stranou testovací mapy a vlastně celkově mapy udělat hezčí, což vyžaduje nějakou práci s grafikou stávajícíh obrázků.&lt;/p&gt;
&lt;p&gt;Dalším bodem k řešení je odpojování a opětovné připojování klientů do hry. 
V nyní navrženém řešení to nefunguje optimálně. 
Když se klient odpojí a znovu připojí v aktuálně běžícím kole, může si znovu vybírat karty, i když už předtím potvrdil výběr. &lt;/p&gt;
&lt;p&gt;V budoucnu by také bylo dobré, aby se na serveru dalo hrát více her. 
Variant je více, neklademe si ale ambice toto vyřešit do příštího, posledního setkání. &lt;/p&gt;
&lt;h3&gt;Game Log&lt;/h3&gt;
&lt;p&gt;Když jsme poprvé hru spustily tak, že se dala hrát, shodly jsme se, že by bylo fajn, aby byl na herní ploše znatelný průběh jednotlivých fází herního kola.
Zatím se vše vyhodnocovalo zaráz a byl viditelný vždy jen konečný stav.
Dohodly jsme se, že vytvoříme &lt;strong&gt;game log&lt;/strong&gt;, což bude soupis jednotlivých kroků tak, jak se mají dít postupně v herním kole. 
Potřebujeme ho, abychom byly schopny "animovat" pohyb na herní ploše, aby bylo viditelné, kam se roboti točí, hýbají apod.&lt;/p&gt;
&lt;p&gt;Podstatou řešení, které jsme dokončily za pomoci Petra na dnešním srazu, je to, že změny stavu hry vytvoří zmiňovaný game log, který budou dostávat višchni klienti. 
Nebudou pokaždé dostávat celý log znovu, ale vždy jen tu část, která ještě nebyla poslaná. 
Část logu, kterou dostanou, se pak bude krok po kroku zpracovávat, provádět a vykreslovat, čímž dojde k postupné "animaci" na herní ploše.
Dokončení game logu nám zabralo skoro celý zbytech schůzky, ale nakonec bylo dosaženo vítězství! :)&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/screenshot_win.png" target="_blank" title="screenshot_win"&gt;&lt;img alt="screenshot_win" src="https://roboprojekt.pyladies.cz/images/thumbnails/screenshot_win.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;h3&gt;Jak celý projekt uzavřeme?&lt;/h3&gt;
&lt;p&gt;Dohodly jsme se, že poslední schůzku budeme mít příští týden, a doladíme na ní věci nezbytné k tomu, aby byl projekt uveřejnitelný. 
Jako oficiální závěr pak bude mít na listopadovém brněnském &lt;a href="https://pyvo.cz/brno-pyvo/"&gt;Pyvu&lt;/a&gt; Karolina krátkou přednášku o Roboprojektu z technického pohledu, o jeho budoucnosti a o tom, jak se do něj může kdokoliv zapojit. &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Hrajeme!</title><link href="https://roboprojekt.pyladies.cz/herni-sraz" rel="alternate"></link><published>2019-09-10T18:00:00+02:00</published><updated>2019-09-10T18:00:00+02:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-09-10:/herni-sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Dnes jsme se sešly bez Petra, ale s návodem, jak spustit hru skutečně jako multiplayer!
Podařilo se nám po drobných počátečních klopýtnutích úspěšně překonat nástrahy firewallu a jiných překážek ve spojení počítačů a hru skutečně spustit!
A nejen spustit, ale i dohrát do fáze, kdy jedna z nás vyhrála.&lt;/p&gt;
&lt;p&gt;Aktuálně …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Dnes jsme se sešly bez Petra, ale s návodem, jak spustit hru skutečně jako multiplayer!
Podařilo se nám po drobných počátečních klopýtnutích úspěšně překonat nástrahy firewallu a jiných překážek ve spojení počítačů a hru skutečně spustit!
A nejen spustit, ale i dohrát do fáze, kdy jedna z nás vyhrála.&lt;/p&gt;
&lt;p&gt;Aktuálně je hra nastavená tak, že i po vítězství jednoho z hráčů pokračuje dál.
Většina věcí funguje dle našich představ, krom několika drobností, které budeme ještě upravovat.
Hrály jsme celkem asi hodinu, než jsme narazily na chybu, kvůli které hra spadla.
Zbytek setkání jsme tedy věnovaly tomu, abychom zjistily, co je špatně a jak to opravit :) 
Zkoumáním chybové hlášky jsme došly k tomu, že si naše hra neumí poradit s tím, když robot umře během provádění příkazu jednoho registru. 
Například má jít o tři políčka rovně, ale hned na prvním je díra - po prvním kroku tedy umře, ale hra nyní počítá s tím, že musí pohyb dokončit a chce robota přesunout na další koordináty, které se ale v okamžiku smrti nastaví na &lt;code&gt;None&lt;/code&gt;. 
Alespoň se tak domníváme. 
Bohužel se nám nyní vykresluje naráz výsledek provedení všech tahů herního kola a nemáme ještě zpracovaný log, špatně se nám tedy zpětně rekonstruují pohyby robotů.
Budeme ale pracovat s touto teorií a uvidíme :)&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/game_screenshot.png" target="_blank" title="herni_screenshot"&gt;&lt;img alt="herni_screenshot" src="https://roboprojekt.pyladies.cz/images/thumbnails/game_screenshot.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Než jsme setkání rozpustily, otevřely jsme téma, v jaké fázi budeme s výsledkem RoboProjektu spokojeny. 
Každá z nás to má trošku jinak, budeme se nad tím tedy ještě muset zamyslet a vytyčit nějakou konkrétní uspokojivou podobu hry, abychom byly schopny někdy vůbec dosáhnout cíle :) &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Hlavní téma - síť</title><link href="https://roboprojekt.pyladies.cz/hlavni-tema-sit" rel="alternate"></link><published>2019-07-16T15:32:00+02:00</published><updated>2019-07-17T15:32:00+02:00</updated><author><name>Karolina Surma</name></author><id>tag:roboprojekt.pyladies.cz,2019-07-16:/hlavni-tema-sit</id><summary type="html">&lt;div&gt;&lt;h2&gt;Tip na Markdown&lt;/h2&gt;
&lt;p&gt;Sraz začal výjimečně připomínkou k formátování zpráv na blogu.
Máme tendenci psát dlouhé odstavce, se kterými si git a GitHub neví dobře rady.
Když něco v textu, který se táhne na několik řádků, změníme, GitHub už neoznačí konkrétní změnu, ale pro jistotu podsvítí celý ten řádek. 
Je …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;h2&gt;Tip na Markdown&lt;/h2&gt;
&lt;p&gt;Sraz začal výjimečně připomínkou k formátování zpráv na blogu.
Máme tendenci psát dlouhé odstavce, se kterými si git a GitHub neví dobře rady.
Když něco v textu, který se táhne na několik řádků, změníme, GitHub už neoznačí konkrétní změnu, ale pro jistotu podsvítí celý ten řádek. 
Je proto lepší texty psát tak, ze každá věta bude na jednom řádku. 
Čtenář blogu si toho nevšimne, protože na stránkách se vše poskládá dobře, a my máme nástroj, jak kontrolovat i drobné změny textu.&lt;/p&gt;
&lt;h2&gt;Úprava interface: nechceme pořád posílat zprávy serveru&lt;/h2&gt;
&lt;p&gt;Máme s interface problém: pořád posílá serveru zprávy. 
I když hráč potvrdí svůj výběr, při každém zmáčknutí jakékoli klávesy posílá serveru zprávu se svým stavem. 
To se nám nelíbí a chceme to změnit. 
Zde ale přichází na řadu aspekt, o němž jsme doposud vůbec neuvažovaly, a to bezpečnost síťové komunikace.
U komunikace server - klient chceme, aby server byl náš zdroj pravdy a byl ten prvek, který "šéfuje" všechno, co se k němu dostane. 
Můžeme si představit, že se k našemu pythonnímu serveru někdo bude chtít napsat jiného klienta (třeba v jiném programovacím jazyce, např. webového v JavaScriptu nebo ovladače robotů z 3D tiskárny).
Kdyby k tomu někdo napsal falešného klienta, který umí vyměnit karty za jiné, pozměnit nějaké atributy hry, nebo poslat přímo škodlivé zprávy, náš server musí vědět, že na takovou zprávu nemá reagovat. 
Pokud zpráva od klienta nebude dávat smysl, je lepší ji ošetřit na straně serveru. 
Takže náš problém není ve skutečnosti, že chceme přestat posílat zprávy z klienta, ale v tom, že server už nemá v jisté chvíli zprávy přijímat. 
Vycházíme z předpokladu, že klient nám může poslat cokoliv. 
Jakmile klient pošle informaci, že potvrdil výběr, ignorujeme další zprávy.&lt;/p&gt;
&lt;h2&gt;Jak zahrát hru?&lt;/h2&gt;
&lt;p&gt;Zprovozňujeme hru podle nástřelu serveru, který jsme společně vypracovaly minule. 
S každým novým krokem vidíme, co všechno ještě není dotažené, a snažíme se to propojit. 
Úpravy kódu potřebné pro to, aby každý robot hrál své karty a interface se pročistil po každém kole, trvaly téměř celý dnešní sraz.
Už opět vidíme, proč je dobré si namyslet algoritmus dopředu.
Potýkáme se čím dál víc s tím, že je náš kód už hodně složitý, měly bychom se proto zamyslet, jak ho zjednodušit a zdokumentovat. &lt;/p&gt;
&lt;h2&gt;Projekte, spusť se sám&lt;/h2&gt;
&lt;p&gt;Během analýzy, jak spustit funkční hru, jsme téměř hodinu spouštěly: v jednom terminálu server, ve druhém receiver (obecenstvo), ve třetím interface, ve čtvrtém druhý interface (simulace hry dvou hráčů). 
Je to úmorné, pokud to člověk musí dělat pořád dokola. 
A jako všechno, i to lze trochu usnadnit. Klienty můžeme přepsat do importovatelné podoby. 
Importovatelná podoba je taková, která nevyvolává vedlejší efekty. Pythonní soubory se čtou řádek po řádku a příkazy provádí i při importu do jiného modulu. 
Je proto zvykem ty příkazy, které vyvolávají vedlejší efekty, jako u nás spuštění webové aplikace nebo &lt;code&gt;ensure_future&lt;/code&gt; od &lt;em&gt;asyncio&lt;/em&gt;, zařádit do funkce &lt;code&gt;main()&lt;/code&gt;. 
Pak s kouzelným řádkem &lt;code&gt;if __name__ == "__main__":&lt;/code&gt; můžeme modul bez potíží naimportovat do spouštěcího skriptu.&lt;/p&gt;
&lt;p&gt;Náš spouštěcí modul bude mít tedy naimportované moduly: &lt;code&gt;client_receiver&lt;/code&gt;, &lt;code&gt;client_interface&lt;/code&gt; a spustíme jejich &lt;code&gt;.main()&lt;/code&gt; tolikrát, kolik chceme jednotlivých instancí. 
U nás je to jednou receiver a dvakrát interface.
Aby se nám vykreslila okénka, naimportujeme k tomu Pyglet a spustíme pygletí aplikaci.&lt;/p&gt;
&lt;p&gt;Co takto nejde ještě spustit, je server. 
Musely bychom se podívat do dokumentace &lt;em&gt;aiohttp&lt;/em&gt; nebo zamyslet nad vlákny, abychom ho zprovoznily.
Zatím to tak necháme - redukce 4 terminálů do 2 je pořád pěkná časová úspora :).&lt;/p&gt;
&lt;h2&gt;Vytvoření třídy &lt;code&gt;Server()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Minule jsme předělaly naše &lt;a href="https://roboprojekt.pyladies.cz/vyvijime-rozhrani"&gt;klienty na třídy&lt;/a&gt;, jejichž instance vytváříme pro spuštění hry.
Chtěly jsme podobně přepsat server, který je momentálně shlukem neprovázaných funkcí.
Zde jsme narazily na problém s dekorátorem &lt;code&gt;@routes.get&lt;/code&gt;, který po přepsání serveru přestal fungovat.
Je to kus kódu, který zajišťuje, že se každý druh klienta připojí k metodě, která mu poskytne to, co potřebuje k vykreslení své části hry. 
Každá "routa" má tedy nadefinovaný řetězec, kterým se obě strany propojí.
Python nejprve čte "recept" na vytvoření třídy &lt;code&gt;Server&lt;/code&gt; a až potom vytváří jeho konkrétní instanci. 
Při čtení receptu ještě ale žádné &lt;code&gt;routes&lt;/code&gt; nejsou (neexistuje konkrétní instance), a tak nám při použití &lt;code&gt;@routes.get&lt;/code&gt; Python vynadá a nepovolí server pustit.&lt;/p&gt;
&lt;p&gt;Musíme ten kus kódu tedy rozepsat. 
Podíváme se na dokumentaci k &lt;code&gt;aiohttp.web.Application().add_routes()&lt;/code&gt;.
Podle kapitoly &lt;a href="https://docs.aiohttp.org/en/latest/web_quickstart.html#resources-and-routes"&gt;Resources and Routes&lt;/a&gt; předěláme naše &lt;em&gt;routy&lt;/em&gt; přímo do aplikace mimo samotnou třídu &lt;code&gt;Server&lt;/code&gt;. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;add_routes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/receiver/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;receiver&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/interface/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Pokračujeme se síťovou komunikací</title><link href="https://roboprojekt.pyladies.cz/pokracujeme-se-sitovou-komunikaci" rel="alternate"></link><published>2019-07-02T22:28:00+02:00</published><updated>2019-07-02T22:28:00+02:00</updated><author><name>Karolina Surma</name></author><id>tag:roboprojekt.pyladies.cz,2019-07-02:/pokracujeme-se-sitovou-komunikaci</id><summary type="html">&lt;div&gt;&lt;p&gt;Po dvoutýdenní pauze jsme se opět sešly nad komunikací server-klient. Krok po kroku připisujeme nové funkcionality. Náš server už umí poslat klientovi jemu přiřazeného robota a karty, ze kterých si klient vybírá 5 pro odehrání herního kola. Chybí nám odhazovací balíček: pokud serveru dojdou karty na rozdání dalšímu robotovi, měl …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Po dvoutýdenní pauze jsme se opět sešly nad komunikací server-klient. Krok po kroku připisujeme nové funkcionality. Náš server už umí poslat klientovi jemu přiřazeného robota a karty, ze kterých si klient vybírá 5 pro odehrání herního kola. Chybí nám odhazovací balíček: pokud serveru dojdou karty na rozdání dalšímu robotovi, měl by vzít všechny doposud odhozené karty a vytvořit z nich nový herní balíček. &lt;/p&gt;
&lt;h2&gt;Interface&lt;/h2&gt;
&lt;p&gt;Změnilo se pozadí - ve spodní části interface se nyní vykresluje tolik okének pozadí robotů, kolik bude na mapě hráčů. Ještě řešíme vykreslení avatarů samotných robotů, což určitě budeme mít před dalším srazem hotové.
Klient také posílá serveru vybrané karty s informací, že skončil výběr, a zprávu, jestli hraje toto kolo (power down). Server tyto informace umí dekódovat a přeložit na příslušné atributy stavu hry.
V dalších krocích naučíme klienta číst zprávu o stavu svého robota ze stavu hry (nyní klientovi posíláme separovaná data, aby si sám vytvořil robota).&lt;/p&gt;
&lt;h2&gt;Jména a indikátory&lt;/h2&gt;
&lt;p&gt;Přejmenovaly jsme roboty. Doposud nesli jména osob, které je nakreslily v Inkscape během prvních týdnů projektu. Nyní mají opravdu kybernetická pojmenování. A zde nás, po přejmenování desítek souborů a spoustě změn v kódu, zastavil Petr. Je totiž rozdíl mezi jménem - tím, které ukazujeme hráči navenek, hezky zformátovaným, s velkými písmeny atd., a indikátorem, s nímž pracujeme uvnitř svého programu a nepropagujeme dál k uživateli. Indikátory není vhodné měnit, jsou zapletené do funkcí programů a každá jejich změna vyžaduje řetězec dalších. Naopak jména jsou čistě jen na nás - herní logika je znát nemusí, patři pouze frontendu. Je to vhodné jak pro vlastní formátovaní jmen, tak pro např. jazykové mutace. A jak dát takové jméno robotovi? Pokud má náš robot poznávací indikátor &lt;em&gt;franta&lt;/em&gt;, ale přejeme si ho zobrazovat pod jménem &lt;em&gt;Roy Batty&lt;/em&gt;, můžeme vytvořit soubor &lt;code&gt;yaml&lt;/code&gt; s název rovným indikátoru, a do těla napsat &lt;code&gt;name: Roy Batty&lt;/code&gt;. Python v našem frontendu si jméno jednoduše přečte a vykreslí. &lt;/p&gt;
&lt;h2&gt;Alternativní pohled na server&lt;/h2&gt;
&lt;p&gt;Petr se před několika srazy zmínil, že on by svůj server navrhl jinak. Abychom si ale užily proces vymyšlení serveru a přidávání nových funkcí, hned nám neřekl, jak by tyto otázky řešil on. Jelikož jsme už poměrně daleko v implementaci (konec se blíží!), dnes jsme se dozvěděly, jak bychom to mohly řešit jinak.
Pro komunikaci server - klient používáme asynchronní knihovnu AsyncIO. Ta v sobě obsahuje třídu &lt;a href="https://docs.python.org/3/library/asyncio-queue.html"&gt;Queue&lt;/a&gt;. Asynchronní fronta je z jedné strany otevřená pro vstup, z druhé strany pro výstup, což bychom mohly využít v situaci, když čekáme na informace od klientů. Server v podání Petra by měl zvlášť herní logiku a zvlášť síťovou komunikaci. Pokaždé, když by od klienta přišla nová zpráva na server (např. vybrané karty hráče), přidala by se do fronty, která by &lt;em&gt;se pošťouchla&lt;/em&gt;, že může zpracovat další kus dat. Až by z fronty vypadly vybrané karty posledního hráče, provedl by se další kus herní logiky (např. herní kolo - efekty karet a políček). &lt;/p&gt;
&lt;h2&gt;Spojování slovníku&lt;/h2&gt;
&lt;p&gt;Nová vlastnost Pythonu - spojování slovníků. 
Když máme dva slovníky:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;barvy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"zelena"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cervena"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;tvary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"kruh"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"circle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ctverec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"square"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;můžeme je postaru spojit dohromady tak, že vytvoříme nový slovník a následně ho aktualizujeme o dva slovníky:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;cze_eng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;cze_eng&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;barvy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;cze_eng&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tvary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;cze_eng&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"zelena"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cervena"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"kruh"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"circle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ctverec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"square"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Nově to lze udělat rychlé a jednoduše:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;cze_eng&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;barvy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;tvary&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;cze_eng&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"zelena"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"green"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"cervena"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"kruh"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"circle"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"ctverec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"square"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Vyvíjíme rozhraní</title><link href="https://roboprojekt.pyladies.cz/vyvijime-rozhrani" rel="alternate"></link><published>2019-06-18T16:36:00+02:00</published><updated>2019-06-18T16:36:00+02:00</updated><author><name>Karolina Surma</name></author><id>tag:roboprojekt.pyladies.cz,2019-06-18:/vyvijime-rozhrani</id><summary type="html">&lt;div&gt;&lt;p&gt;Naše srazy postupně získaly stálý rámec, kdy si řekneme: 
- co nového se událo na projektu za poslední období, 
- vysvětlíme případné nesrovnalosti v otevřených PR, 
- a naplánujeme, na čem budeme pracovat dál.&lt;/p&gt;
&lt;p&gt;Jelikož už méně přednáškujeme a jsme víc soustředěné na konkrétní problémy, vyplácí se nám práce s pracovním dokumentem s …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Naše srazy postupně získaly stálý rámec, kdy si řekneme: 
- co nového se událo na projektu za poslední období, 
- vysvětlíme případné nesrovnalosti v otevřených PR, 
- a naplánujeme, na čem budeme pracovat dál.&lt;/p&gt;
&lt;p&gt;Jelikož už méně přednáškujeme a jsme víc soustředěné na konkrétní problémy, vyplácí se nám práce s pracovním dokumentem s agendou, kam vkládáme vše, co nás během týdne napadne a co chceme probrat s expertem.&lt;/p&gt;
&lt;h2&gt;Server&lt;/h2&gt;
&lt;p&gt;Tento týden je naše hlavní starost komunikace server - klient.
Minule jsme si sepsaly průvodní dokument k serveru: jak chceme, aby logicky fungoval. 
Nad tímto dokumentem jsme měly doma zaiterovat a zkusit ho přepsat do Pythonu. 
Objevily jsme spoustu dotazů a opřipomínkovaly původní dokument s cílem pochopit, jak náš server bude fungovat v detailech. Už víckrát jsme totiž zjistily, že nemá smysl sedat ke kódu, dokud nevíme, &lt;strong&gt;co&lt;/strong&gt; chceme napsat :).
Server obecně funguje tak, že: 
1) něco pošle připojenému klientovi (&lt;em&gt;stav hry, robota, karty&lt;/em&gt;), 
2) čeká na data od všech klientů (&lt;em&gt;vybrané karty&lt;/em&gt;), 
3) něco pošle všem klientům (aktualizovaný &lt;em&gt;stav hry&lt;/em&gt;).&lt;/p&gt;
&lt;p&gt;Náš návrh ještě není ideální: máme naplánované odeslání karet každému robotovi na začátku, čekání na data a aktualizaci stavu. Nikde ale neposíláme všem klientům nové karty, z nichž můžou vybírat. Doplnily jsme tedy návrh algoritmu. &lt;/p&gt;
&lt;p&gt;Dozvěděly jsme se taky, že máme v kódu chybu, o níž nevíme. 
Jedná se o čas, který potřebuje server na zpracování karet. Může se stát, že serveru dojde interní časovač, ale ještě než o tom dá vědět klientům, dostane další zprávu s aktualizovanými kartami. Protože časové okénko na výběr už je zavřené, karty se přiřadí až k dalšímu kolu. Abychom tomu zamezily, je dobré přidat do zpráv s kartami číslo herního kola. Tím si zajistíme korektní přiřazení všech zpráv.&lt;/p&gt;
&lt;h2&gt;Kolik stavů potřebujeme? A co patří k Interface?&lt;/h2&gt;
&lt;p&gt;Nyní vytváříme stav hry a stav rozhraní. Stav hry drží informace o mapě a robotech, zatímco stav rozhraní patří konkrétnímu hráči a ukazuje detaily jeho robota + mini obrázky ostatních hráčů. 
Řešily jsme, zda klientovi, který se zabývá vykreslením rozhraní, máme posílat i celkový stav hry. Shodly jsme se, že ano, jelikož data o všech robotech musíme "vyzobat" a aktualizovat ze stavu hry.&lt;/p&gt;
&lt;p&gt;U stavu rozhraní máme další zajímavou věc: obsah jeho atributů totiž proudí mezi serverem a klientem: informaci o zvolených kartách, stavu &lt;code&gt;power_down&lt;/code&gt; a ukončení výběru posílá hráč serveru. Data o robotovi a karty, ze kterých si může hráč vybrat, posílá hráči server.
Je důležité proto odesílané zprávy pečlivě naplánovat a vždy důkladně promýšlet, která data posíláme a která přijímáme.&lt;/p&gt;
&lt;p&gt;Když se podíváme na stávající rozhraní, vykreslujeme ho hned s příkladovým (&lt;em&gt;fake&lt;/em&gt;) robotem a kartami. 
Může se však stát, že chceme vykreslit interface, ale ještě neznáme svého robota ani nemáme karty. Interface se proto musí umět vykreslit i v případě, že tyto údaje nejsou k dispozici.&lt;/p&gt;
&lt;p&gt;Co víc, máme v souboru s rozhraním i nějaké zavolané funkce: vytváří se v něm balíček karet, karty se rozdají a vykreslí, a vytvoří i instance třídy samotného interface. Tyto exekuce v souboru s logikou chování nechceme, dělá to kód netestovatelný a začíná se nám to přít s kódem, který postupně připisujeme serveru. Logika vytváření karet, které nepatří k logice klienta, taky nepatří tomuto souboru, měla by se přenést pod stav hry.&lt;/p&gt;
&lt;h2&gt;Klient Interface&lt;/h2&gt;
&lt;p&gt;Jelikož náš klient obsahuje v sobě už dost kódu a začaly jsme využívat globální proměnné, aby vše fungovalo, jak si představujeme, bylo nám doporučeno překlopit stávající proceduru na třídu. Globální proměnné tak překlopíme do atributů třídy, se kterými pak můžeme jednodušeji pracovat. U takového "roztřídění" kódu je velice podstatné rozmyslet si, které atributy patří nové vytvořené třídě (&lt;code&gt;self.window&lt;/code&gt;, &lt;code&gt;self.state&lt;/code&gt;) a které jsou dané zvenčí (v našem případě: &lt;code&gt;text&lt;/code&gt; ve smyslu vstupu z klávesnice). Pak zbývá rozchodit volání metod (spousta zapomenutých &lt;code&gt;self&lt;/code&gt; po cestě, které mají za výsledek &lt;code&gt;NameError&lt;/code&gt;).&lt;/p&gt;
&lt;h2&gt;Kam patří robotí program?&lt;/h2&gt;
&lt;p&gt;Petr podotkl, že seznam karet, které má robot na ruce, možná vůbec robotovi nepatří. Provedení efektů karet a políček (funkce &lt;code&gt;apply_all_effects&lt;/code&gt;) by měla dostat jako argumenty roboty a říct, co s nimi má udělat. &lt;code&gt;Program&lt;/code&gt; má totiž smysl tehdy, když se provádí, samotný není vlastnost robota. 
Zatím tuto změnu zavádět nebudeme, ale je dobré si na ní pamatovat do budoucna, až budeme mít chuť něco refaktorovat :)&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Co dělá server: zprávy, context manager a jak porovnávat hodnoty v Pythonu</title><link href="https://roboprojekt.pyladies.cz/co-dela-server-zpravy-context-manager-a-jak-porovnavat-hodnoty-v-pythonu" rel="alternate"></link><published>2019-06-11T18:00:00+02:00</published><updated>2019-06-11T20:00:00+02:00</updated><author><name>Karolina Surma</name></author><id>tag:roboprojekt.pyladies.cz,2019-06-11:/co-dela-server-zpravy-context-manager-a-jak-porovnavat-hodnoty-v-pythonu</id><summary type="html">&lt;div&gt;&lt;h2&gt;is vs ==&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;==&lt;/code&gt; je porovnání, které ověří hodnotu objektů, které jsou porovnávány.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;U každého datového typu můžeme upravit chování porovnávání přepsáním speciální metody &lt;code&gt;__eq__&lt;/code&gt;. Psaly jsme o tom post &lt;a href="https://roboprojekt.pyladies.cz/dvacaty-sraz-testy"&gt;zde&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;is&lt;/code&gt; vyhodnotí, jestli je to tentýž, stejný objekt.
Příklad níže se vyhodnotí …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;h2&gt;is vs ==&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;==&lt;/code&gt; je porovnání, které ověří hodnotu objektů, které jsou porovnávány.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;U každého datového typu můžeme upravit chování porovnávání přepsáním speciální metody &lt;code&gt;__eq__&lt;/code&gt;. Psaly jsme o tom post &lt;a href="https://roboprojekt.pyladies.cz/dvacaty-sraz-testy"&gt;zde&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;A &lt;code&gt;is&lt;/code&gt; vyhodnotí, jestli je to tentýž, stejný objekt.
Příklad níže se vyhodnotí jako nepravda, protože dva prázdné seznamy jsou dva různé objekty.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="go"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Dva prázdné seznamy se sice rovnají, pokud je vyhodnotíme pomocí &lt;code&gt;==&lt;/code&gt;, ale v budoucnosti tomu tak nemusí být:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="go"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Zatímco &lt;code&gt;is&lt;/code&gt; kontroluje, že je to úplně přesně to samé. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="go"&gt;False&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
&lt;span class="go"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;U posledního příkladu vzniká problém, protože u celých čísel se Python chová trochu nestandardně: nezáleží mu, jestli jde o tentýž objekt, nebo jiný objekt s hodnotou čísla 1.
Navíc malá a velká čísla se chovají trochu jinak:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="go"&gt;True&lt;/span&gt;

&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="go"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;U některých objektů proto &lt;code&gt;is&lt;/code&gt; může být zrádné. U &lt;code&gt;True&lt;/code&gt;, &lt;code&gt;False&lt;/code&gt; a &lt;code&gt;None&lt;/code&gt; tento problém není, protože nemůžeme vytvořit další objekt "True", vždy se jedná o stejnou instanci logické hodnoty.
Když chceme vyhodnotit &lt;em&gt;bool&lt;/em&gt; proměnnou jako podmínku, neměly bychom ale používat ani &lt;code&gt;==&lt;/code&gt;, ani &lt;code&gt;is&lt;/code&gt; - správný způsob, jak takovou podmínku napsat, je:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hodnota&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# místo "if hodnota is True"&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Ha!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;hodnota&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# místo "if hodnota is False"&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Nene!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;U &lt;code&gt;None&lt;/code&gt; je situace trochu jiná, zde opravdu chceme zjišťovat, jestli hodnotou atributu je &lt;code&gt;None&lt;/code&gt;, nebo ne, takže:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hodnota&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Jsem prázdný"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;hodnota&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Nejsem prázdný"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;is&lt;/code&gt; je trochu rychlejší a vyhodnocení podmínky tak trvá o něco méně, než v případě tradičního porovnávání.
Jako zajímavost jsme se dozvěděly, že o &lt;code&gt;is&lt;/code&gt; a &lt;code&gt;==&lt;/code&gt; se točí v pythonním světě diskuze.
Není to totiž triviální a začátečníci mívají problém s uchopením, kdy používat který způsob.&lt;/p&gt;
&lt;h2&gt;Třídy, víc tříd!&lt;/h2&gt;
&lt;p&gt;Naši klienti používají čím dál víc globálních proměnných. Některé věci, jako např. pygletí okno s hracím rozhraním, nastavujeme na začátku na &lt;code&gt;None&lt;/code&gt; a plníme je postupně díky zprávám od serveru.
Už bychom se měly zamyslet, jak klienty přepsat na třídy, kde tyto globální proměnné převedeme na atributy třídy, které budou k dispozici pro všechny metody. 
Na názorné ukázce jsme se přesvědčily, že přepsání není hodně složité: atributy se přenesou do metody &lt;code&gt;__init__&lt;/code&gt;, jako &lt;em&gt;self.atributy&lt;/em&gt;, metodám dáme &lt;code&gt;self&lt;/code&gt; jako první argument a předěláme bývalé globální proměnné v jejich tělech. 
Další výhoda třídy oproti kódu, který doposud máme, je jednoduchost importování. 
Můžeme takovou třídu &lt;code&gt;Interface()&lt;/code&gt; naimportovat do jiného programu, např. nové hry, a budeme mít přístup ke všem jejím metodám pomocí jednoho řádku kódu: &lt;code&gt;from interface import Interface&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Dva klienti - jeden server&lt;/h2&gt;
&lt;p&gt;V další části srazu jsme se podívali na &lt;em&gt;draft Pull Requestu&lt;/em&gt;. 
Během našeho psaní Roboprojektu Github přišel se zajímavou funkcí - nyní při vytváření PR můžu vybrat, jestli chci zpřístupnit svůj PR pro začlenění (považuji ho za finální), nebo na něm chci ještě pracovat (a merge není povolen).&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/draft.JPG" target="_blank" title="draft"&gt;&lt;img alt="draft" src="./images/draft.JPG" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Potřebujeme donutit náš server, aby mluvil i s klientem, který vykresluje hrací plochu, i s hráčem. 
Každému posílá společný stav hry, ale hráči pošle dodatečně informace o jeho robotovi a karty. 
Hráč serveru navíc odpovídá zprávami s obsahem karet nebo o tom, zda hraje další kolo.
Potřebujeme tedy rozlišit, aby server posílal každému jen informace, které mu patří. 
No a jak se klienti při připojení "představí"? Vyřešily jsme to pomocí &lt;code&gt;route&lt;/code&gt; dekorátoru, který určuje, na jaké adrese spolu budou server s klientem komunikovat. 
Doposud jsme tam měly: &lt;code&gt;routes.get("/ws/")&lt;/code&gt; a jednu funkci, která komunikovala s klienty. Nově rozlišujeme:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@routes.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/interface/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@routes.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/receiver/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Které dekorují zvláštní funkce: jednu pro plochu, druhou pro hráče.
Každý klient má povolenou jednu - svou - cestu. &lt;/p&gt;
&lt;p&gt;Je to sice čisté řešení, každý komunikuje se serverem na &lt;em&gt;svém&lt;/em&gt; kanálu, ale začal se nám opakovat kód: server musí v obou případech navázat spojení s klientem, přidat ho do seznamu klientů, a na konci bezpečně spojení ukončit vč. odstranění ze seznamu klientů. 
Chceme tak ošetřit začátek a konec funkce, zatímco vnitřek je jiný.&lt;/p&gt;
&lt;p&gt;Na pomoc nám přijde &lt;em&gt;context manager&lt;/em&gt;.&lt;/p&gt;
&lt;h2&gt;contextlib.contextmanager&lt;/h2&gt;
&lt;p&gt;Můžeme použit dekorátor z knihovny &lt;code&gt;contextlib&lt;/code&gt;.
Když nějaké funkci dáme dekorátor &lt;code&gt;contextmanager&lt;/code&gt;, taková funkce se může použít s příkazem &lt;code&gt;with&lt;/code&gt;. Příkaz &lt;code&gt;with&lt;/code&gt; už známe například z &lt;a href="https://naucse.python.cz/course/pyladies/beginners/files/"&gt;operací na souborech&lt;/a&gt;. 
Když otevřeme soubor s &lt;code&gt;with&lt;/code&gt;, zajistíme si, že se v každém případě hezky uzavře, i kdyby náš program spadl v půlce běhu kvůli nějaké chybě. 
Python nám umožňuje vytvářet vlastní context managery, kterým řekneme, co se má udělat před nějakým kouskem kódu a co po jeho doběhnutí.
Můžeme je vytvořit několika způsoby. První je vytvořit třídu, která má dvě metody:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Kontext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"začátek"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"NĚCO"&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"konec"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Kontext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;začátek&lt;/span&gt;
&lt;span class="go"&gt;NĚCO&lt;/span&gt;
&lt;span class="go"&gt;konec&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Na začátku se provede metoda &lt;code&gt;__enter__&lt;/code&gt;, a na konci &lt;code&gt;with&lt;/code&gt; bloku se provede &lt;code&gt;__exit__&lt;/code&gt;.
Důležité je, že i když uděláme chybu uprostřed své funkce, konec se vždy zavolá a vyčistí po nás prostředí. 
Další věc, kterou umí dělat context manager, je to, že dokáže naši chybu chytit a předat ji nám na další zpracování.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Kontext&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__enter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"začátek"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;"NĚCO"&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__exit__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"konec"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;Kontext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;výsledek bude: &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;začátek&lt;/span&gt;
&lt;span class="n"&gt;NĚCO&lt;/span&gt;
&lt;span class="n"&gt;konec&lt;/span&gt; &lt;span class="n"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Toto např. dělá &lt;code&gt;with pytest.raises&lt;/code&gt;, o němž jsme se učily &lt;a href="https://naucse.python.cz/course/pyladies/beginners/testing/"&gt;v začátečnickém kurzu&lt;/a&gt; - podívá se, jestli chyba, která vznikla, je chyba, kterou očekáváme. Pokud ano - test prochází, pokud ne - Pytest vyvolá vlastní chybu a řekne nám o tom.&lt;/p&gt;
&lt;p&gt;Problém tohoto přístupu je, že je... dlouhý. Zde přichází na pomoc Pythonní &lt;code&gt;yield&lt;/code&gt;. 
Můžeme si napsat jednodušší context manager, který udělá totéž jako naše třída výše.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;contextlib&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="nd"&gt;@contextlib.contextmanager&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;kontext_funkce&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"začátek"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;"NĚCO"&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"konec"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;kontext_funkce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Dekorátor je tak chytrý kus kódu, udělá všechny ty kroky za nás.
Zajímavé cvičení by bylo napsat tento dekorátor od začátku, my se ale spokojíme s tím, že už někdo napsal dekorátor připravený k využití.
Dokonce můžeme vylepšit náš context manager a přidat odchycení své chyby:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;contextlib&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="nd"&gt;@contextlib.contextmanager&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;kontext_funkce&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"zacatek"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="s2"&gt;"NĚCO"&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;        &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"oops"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"konec"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;kontext_funkce&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;neco&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;... &lt;/span&gt;    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="go"&gt;zacatek&lt;/span&gt;
&lt;span class="go"&gt;NĚCO&lt;/span&gt;
&lt;span class="go"&gt;oops&lt;/span&gt;
&lt;span class="go"&gt;konec&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Takový kontext využijeme pro náš server. Protože tvoříme hru s využitím asynchronní knihovny &lt;code&gt;asyncio&lt;/code&gt;, náš dekorátor bude patřičně jiný: &lt;code&gt;@contextlib.asynccontextmanager&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Zprávy server - klient&lt;/h2&gt;
&lt;p&gt;Zatím posíláme klientům zprávy jako stringy, kde prvních pár znaků je vždy stejných, např. "Robot: Bot123". Tyto zprávy máme překlopit na JSON, protože:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;jednoduše jdou překládat na pythonní slovníky&lt;/li&gt;
&lt;li&gt;nemusíme je následně složitě parsovat (kdokoli se pokoušel parsovat textové zprávy, ten ví, jak to bolí)
Druhy zpráv můžeme od sebe oddělit tak, že vždy nastavíme na začátku stejný klíč, např "kind"="state", nebo "kind=robot" a podle toho naučit klienta na zprávy reagovat.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Finální struktura serveru&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Polovinu srazu nám zabrala analýza návrhu fungování serveru. V rámci analýzy jsme se shodly na třech prvcích, ke kterým musí patřit veškerá funkčnost tohoto nástroje:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Server dělá něco pro klienta, který se k němu právě připojil (pošle mu robota, první stav hry, první karty etc.)&lt;/li&gt;
&lt;li&gt;Server dostává zprávy od klienta a nějak s nimi nakládá (vybrané karty, nehraju dál, etc.)&lt;/li&gt;
&lt;li&gt;Server posílá aktualizovaný stav hry všem připojeným klientům.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Na tomto základě postavíme celý náš server.&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Vylepšování klientů, propojení Pygletu a asyncio</title><link href="https://roboprojekt.pyladies.cz/dvacaty-sesty-sraz" rel="alternate"></link><published>2019-05-21T18:00:00+02:00</published><updated>2019-05-21T18:00:00+02:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-05-21:/dvacaty-sesty-sraz</id><summary type="html">&lt;div&gt;&lt;h2&gt;&lt;strong&gt;init&lt;/strong&gt;.py&lt;/h2&gt;
&lt;p&gt;Při zpracovávání testovacího frameworku jsme narazily na problém, kdy chceme spouštět testy z hlavního adresáře RoboProjektu, ale soubory s testy máme přesunuty do podsložky &lt;code&gt;tests&lt;/code&gt;. 
Po přesunutí do této složky začal pytest při spouštění testů hlásit chybu, kterou vyřešilo přidání prázdného souboru &lt;code&gt;__init__.py&lt;/code&gt;. 
Zajímala nás tedy magie …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;h2&gt;&lt;strong&gt;init&lt;/strong&gt;.py&lt;/h2&gt;
&lt;p&gt;Při zpracovávání testovacího frameworku jsme narazily na problém, kdy chceme spouštět testy z hlavního adresáře RoboProjektu, ale soubory s testy máme přesunuty do podsložky &lt;code&gt;tests&lt;/code&gt;. 
Po přesunutí do této složky začal pytest při spouštění testů hlásit chybu, kterou vyřešilo přidání prázdného souboru &lt;code&gt;__init__.py&lt;/code&gt;. 
Zajímala nás tedy magie za tím.
Petr nám vysvětlil, že tento soubor udělá z daného adresáře pythonní modul. 
Když používáme testy ze stejného adresáře, ze kterého je voláme, není tento soubor potřeba, protože dosáhneme na jednotlivé soubory, které importujeme jako moduly. &lt;/p&gt;
&lt;h2&gt;@classmethod&lt;/h2&gt;
&lt;p&gt;Při předělávání hry do podoby server - klient potřebujeme na straně klienta "dekódovat" data zaslaná serverem v podobě JSON souboru a vytvořit z nich stav hry, se kterým budeme moci dál pracovat. 
Proto jsme vytvořily funkci &lt;code&gt;state_from_dict&lt;/code&gt;, která umí vše potřebné vyextrahovat a vytvořit objekt třídy &lt;code&gt;State&lt;/code&gt;. 
Takové funkci se říká &lt;em&gt;factory&lt;/em&gt;, protože vytváří nové objekty. 
Je to alternativa metody &lt;code&gt;__init__&lt;/code&gt;, jen vytváří objekt z jiných vstupů. 
Funkce stála mimo danou třídu, což je malinko nepřehledné. 
Petr nám proto ukázal, jak z ní udělat metodu dané třídy. 
Problematické je zde &lt;code&gt;self&lt;/code&gt;, které daná funkce nemůže brát jako argument, protože ještě žádné &lt;code&gt;self&lt;/code&gt; neexistuje.
Problém řeší použití třídní metody s dekorátorem &lt;code&gt;@classmethod&lt;/code&gt;, která místo &lt;code&gt;self&lt;/code&gt; bere jako argument &lt;code&gt;cls&lt;/code&gt;, tedy třídu. 
Je to metoda, která neumí pracovat na nějaké instanci dané třídy, ale pracuje přímo se třídou.
Používá se často právě v případech, kdy existuje více možností, jak vytvořit objekt nějaké třídy. &lt;/p&gt;
&lt;h2&gt;Propojení Pygletu a asynchronních funkcí&lt;/h2&gt;
&lt;p&gt;Pyglet nepodporuje asynchronní programování, proto pro náš projekt potřebujeme zjistit, jak spojit tyto dvě věci dohromady. 
Obě spouštěcí funkce, &lt;code&gt;pyglet.app.run()&lt;/code&gt; i &lt;code&gt;asyncio.run()&lt;/code&gt; spouští nějaké smyčky událostí zahrnující reakci na nějaký vstup.
Koncept asynchronního programování je poměrně starý a dřívě existovala řada knihoven, které pracovaly se zpracováváním více úloh a čekáním na komunikaci po internetu a které mezi sebou nebyly kompatibilní, každá používala svoji konkrétní smyčku událostí. 
Aby se do budoucna předešlo problémům, ustanovila se právě knihovna asyncio a stala se obecně používanou. 
Jakákoliv knihovna, která chce komunikovat po internetu a umí zpracovávat asyncio smyčku, se dá použít s jakoukoliv jinou knihovnou, která umí asyncio. 
Bohužel Pyglet mezi tyto knihovny zatím nepatří a asyncio neumí. 
Čeho můžeme využít - asyncio čeká na nějakou událost a když ji zpracuje o chviličku později, nic zásadního se nestane. 
Můžeme tedy říct Pygletu, aby např.třicetkrát za vteřinu spustil kousek asyncio smyčky.
Pyglet tedy bude řídit to, kdy mohou běžet asynchronní operace. 
Pro tuto implementaci bude potřeba použít něco trochu složitějšího než &lt;code&gt;asyncio.run()&lt;/code&gt;, konkrétně pracovat s celými smyčkami událostí, které je třeba naplánovat a spustit. 
Smyčku nadefinujeme pomocí &lt;code&gt;loop&lt;/code&gt;, kde využijeme funkce &lt;code&gt;run_until_complete&lt;/code&gt;, která zajistí, aby se smyčka událostí běžela, dokud neskončí úkol nadefinovaný jako argument této funkce. 
Takto nadefinovaný úkol se naplánuje na poslední místo za všechny úkoly, které už čekají na zpracování. 
Pro naplánování spuštění klienta pak použijeme funkci &lt;code&gt;ensure_future()&lt;/code&gt;, kde se jako argument zadá funkce, kterou takto chceme spustit.
Více o použitých funkcích najdeme v dokumentaci k asyncio o &lt;a href="https://docs.python.org/3/library/asyncio-eventloop.html"&gt;smyčkách&lt;/a&gt; a &lt;a href="https://docs.python.org/3/library/asyncio-future.html"&gt;funkci &lt;code&gt;ensure_future&lt;/code&gt;&lt;/a&gt;. 
Kód pak může vypadat například takto:&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/loops.jpg" target="_blank" title="loops"&gt;&lt;img alt="loops" src="./images/loops.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Dvacátý pátý sraz - po delší době</title><link href="https://roboprojekt.pyladies.cz/dvacaty-paty-sraz-po-delsi-dobe" rel="alternate"></link><published>2019-05-14T18:00:00+02:00</published><updated>2019-05-14T18:00:00+02:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-05-14:/dvacaty-paty-sraz-po-delsi-dobe</id><summary type="html">&lt;div&gt;&lt;p&gt;Dnešní sraz proběhl po delší pauze, kdy Petr nebyl v Brně, ale v kódu jsme se hodně posunuly.
Setkání jsme tedy začly shrnutím, co hra nyní umí. Součástí backendu je teď důležitá a komplexní funkce &lt;code&gt;apply_all_effects&lt;/code&gt;, která zařídí, že proběhne herní kolo. Tedy střídavě se v daném pořadí provedou všechny …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Dnešní sraz proběhl po delší pauze, kdy Petr nebyl v Brně, ale v kódu jsme se hodně posunuly.
Setkání jsme tedy začly shrnutím, co hra nyní umí. Součástí backendu je teď důležitá a komplexní funkce &lt;code&gt;apply_all_effects&lt;/code&gt;, která zařídí, že proběhne herní kolo. Tedy střídavě se v daném pořadí provedou všechny naplánované akce z registru robota (efekty karet) a efekty políček. 
Při optimalizaci jejího kódu jsme narazily na dvě věci. První z nich je vyvolání vyjímky. Je třeba si vždy dobře rozmyslet, jakou vyjímku vyvoláváme a na jakém místě. Specifikace by měla být co nejpřesnější, aby se nám nestalo, že vyjímka bude odchytávat jiné chyby nebo chyby vzniklé na jiném místě, než to, které chceme ošetřit. 
Druhá připomínka se nám v kódu stále vrací, a to je pojmenovávání funkcí. Je to dobrá praxe, kterou bychom si měly vštípit a držet se jí, protože výrazně zlepšuje přehlednost kódu. Pokud pojmenováváme nějakou funkci, jméno by mělo odpovídat tomu, co daná funkce dělá. Například máme-li funkci &lt;code&gt;sort_robots_by_cards_priority&lt;/code&gt;, lze očekávat, že vezme nějaký seznam robotů a seřadí jej dle daného parametru. V našem případě ale funkce vytvářela nový seznam a teprve ten řadila, jméno tedy není zcela příhodné.
Karolina v mezičase výrazně pokročila s testovacím frameworkem, který nyní umí načíst příkazy ze všech adresářů, zpracovávat různé podmínky a po provedení příkazů zkontrolovat novou polohu a směr robota a porovnat je s konečnými políčky. 
Katka také rozpracovala jedno z vylepšení, které se s námi táhne již delší dobu, a to je načítání obrázků ve frontendu. Poměrně velká výpočetní náročnost hry byla dána tím, že jsme obrázky ve frontendu načítaly pořád dokola, přestože to není potřeba, stačilo by je načíst jen jednou. Nejobtížnějsí částí se nakonec ukázalo rozhodnout, jaké zvolíme názvy políček, jejichž obrázky se načítají, aby byly dostatečně výstižné, takže i zde jsme se dostaly zpět k pravidlu správného pojmenovávání. &lt;/p&gt;
&lt;h3&gt;Lambda&lt;/h3&gt;
&lt;p&gt;V agendě na dnešní setkání se objevil dotaz k jedné z částí kódu, které psala Karolina a kde vytváří seznam startovních políček robotů. Funkce obsahuje zápis &lt;code&gt;OrderedDict(sorted(robot_tiles.items(), key=lambda stn: stn[0]))&lt;/code&gt;.
O &lt;code&gt;OrderedDict&lt;/code&gt; jsme se bavily na jednom z &lt;a href="https://roboprojekt.pyladies.cz/dvacaty_treti_sraz"&gt;březnových srazů&lt;/a&gt;. Nevěděly jsme ale, co v tomto kódu znamená &lt;code&gt;lambda&lt;/code&gt;. 
Jde o způsob, jak definovat funkci na jeden řádek, respektive jako výraz.
V podstatě tedy zápis&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;OrderedDict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;robot_tiles&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
        &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;stn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;       
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;bude dělat to stejné, jako kód níže, kde si nadefinujeme pomocnou funkci sort_key:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;sort_key&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stn&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;stn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;OrderedDict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;robot_tiles&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; 
        &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sort_key&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;   
&lt;/code&gt;&lt;/pre&gt;


&lt;h3&gt;Sorted&lt;/h3&gt;
&lt;p&gt;Další nejasností v zápisu výše pro nás bylo &lt;code&gt;sorted&lt;/code&gt;. Známe funkci &lt;code&gt;sort&lt;/code&gt;, která umí řadit prvky v seznamu. Funkce &lt;code&gt;sorted&lt;/code&gt; umí z daných hodnot seznam vytvořit (převést jakékoliv zadané hodnoty na seznam), seřadit a vrátit seřazený. Více o této funkci můžeme najít v &lt;a href="https://docs.python.org/3/howto/sorting.html"&gt;Sorting HOW TO&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Co musíme udělat, aby hra konečně fungovala jako hra?&lt;/h3&gt;
&lt;p&gt;Karolina položila důležitou otázku. Co je třeba udělat, aby hra byla hratelná. Tedy jaké úkoly máme pro příští týdny. 
Hlavní je nyní kompletně hru předělat do podoby server - klient. V současné chvíli máme jednoduchý prototyp serveru, který po připojení klienta umí poslat soubor. 
Máme jednoduchého klienta, který se umí k serveru připojit a přijmout soubor. Jedná se zatím o jednoduchý soubor ve formátu JSON. Tento typ klienta, který dostává popis stavu hry, by jej měl dokázat převést do grafické podoby. Tedy zobrazit aktuální stav hry na základě dat dodaných serverem. Dnes jsme se tedy zaměřily na tento úkol. Soubor, který nyní server odesílá, obsahuje dohromady informace o herním plánu a robotech. Pro vykreslení je potřebujeme rozdělit a získat tak podklady pro vytvoření &lt;code&gt;board&lt;/code&gt; a &lt;code&gt;robots&lt;/code&gt;. 
Pro vytvoření &lt;code&gt;board&lt;/code&gt; již máme funkci napsanou. Abychom ji ale mohly využít i v modelu server - klient, je třeba ji trošku upravit, aby odpovídala vstupním datům, která bude posílat server. 
Dostaly jsme se zde do situace, kdy tedy potřebujeme jednu z původních funkci rozdělit na dvě, abychom mohly použít jen její část, ale nechceme tím rozbít existující testy a zbytek kódu. Petr nám tedy poradil jednoduchý způsob.
Najdeme si místo, kde chceme funkci rozdělit, a určíme tak, kterou část má dělat nová funkce. Naše nová funkce pak dostane jako parametr vše, co dělá první část kódu. A v první části kódu pak novou funkci zavoláme. Přidáme tedy v podstatě jen dva řádky kódu (viz ilustrační obrázek) a původní funkce tedy dělá to, co předtím, nová funkce se ale dá bez problémů použít samostatně zvlášť. &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="rozdeleni" src="./images/rozdeleni_fce.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;h3&gt;Logika server - klient&lt;/h3&gt;
&lt;p&gt;Potřebovaly jsme si trošku ujasnit, jak přesně bude fungovat, když hru přepíšeme tak, aby běžela na serveru a hráči se k ní připojovali přes klienty.
Server zpracovává samotnou logiku hry a drží všechny informace o ní, posílá je přihlášeným klientům a také zpracovává informace, které od nich dostane. Klienty budeme mít dvou typů. První bude čistě zobrazovací, prozatím mu říkáme &lt;code&gt;receiver&lt;/code&gt;. Jeho úkolem bude pouze vykreslovat aktuální stav hry, tedy herní plochu a roboty. Druhý, o něco složitější klient, bude pro ty, kteří chtějí hru hrát, a poběží na něm náš současný interface. Říkáme mu &lt;code&gt;sender&lt;/code&gt;, protože prostřednictvím tohoto klienta budou hráči dostávat od serveru karty, programovat roboty a odesílat data zpět na server. Zobrazení herní plochy a robotího interface budou tedy dva nezávislé programy. &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Dvacátý třetí sraz - Opakování a první krůčky se serverem</title><link href="https://roboprojekt.pyladies.cz/dvacaty_treti_sraz" rel="alternate"></link><published>2019-03-26T18:00:00+01:00</published><updated>2019-03-26T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-03-26:/dvacaty_treti_sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;V rámci retrospektivy, co se událo za poslední týden, jsme narazily na několik nejasností v rámci tříd. V našem projektu hrají třídy podstatnou roli, umožňují nám celý kód výrazně zjednodušit, zpřehlednit a zefektivnit. Proto jsme se rozhodly pro malé opakování, abychom si osvěžily informace ze &lt;a href="https://naucse.python.cz/2019/brno-jaro-2019-pondeli/beginners/class/"&gt;začátečnického kurzu&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Při vytváření tříd …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;V rámci retrospektivy, co se událo za poslední týden, jsme narazily na několik nejasností v rámci tříd. V našem projektu hrají třídy podstatnou roli, umožňují nám celý kód výrazně zjednodušit, zpřehlednit a zefektivnit. Proto jsme se rozhodly pro malé opakování, abychom si osvěžily informace ze &lt;a href="https://naucse.python.cz/2019/brno-jaro-2019-pondeli/beginners/class/"&gt;začátečnického kurzu&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Při vytváření tříd je neopomenutelným parametrem jejích atributů a metod &lt;code&gt;self&lt;/code&gt;, které vyjadřuje konkrétní objekt dané třídy. Při volání metody na konkrétní objekt pak metoda místo &lt;code&gt;self&lt;/code&gt; dostává objekt, na kterém je metoda volána.&lt;/p&gt;
&lt;p&gt;Konkrétním objektům třídy můžeme definovat atributy i bez toho, aby byly "vynucené" metodou &lt;code&gt;__init__&lt;/code&gt;, která říká, jaké atributy musí mít všechny objekty dané třídy a které je třeba nadefinovat již při vytváření objektu. &lt;/p&gt;
&lt;p&gt;Stejně jako u jiných částí kódu, i u metod třídy je dobré se dívat, zda něco zbytečně neduplikujeme. Z hlediska fází hry nebo pojmenování nějaké metody může dávat smysl mít části rozdělené a metody pak volat podle názvu v té fázi hry, kde se lépe hodí, pokud však mají většinu obsahu shodnou, je dobré se zamyslet nad tím, zda by nebylo lépe kód sjednotit pod jednu metodu, která bude obecněji uplatnitelná. Příkladem z našeho kódu budiž metody &lt;code&gt;Walk&lt;/code&gt; a &lt;code&gt;Move&lt;/code&gt;, které obě patří třídě &lt;code&gt;Robot&lt;/code&gt;. Jednu používáme, pokud se robot pohybuje na základě programu, který mu zadáme pomocí karet, druhou pak, pokud robotem hýbe nějaká jiná vnější příčina. Každá sice dělá něco jiného a používá se v jiné situaci, ale vnitřek se liší pouze tím, že v druhém případě se metoda neprovede, pokud na políčku, na které by se měl robot posunout, již nějaký robot stojí. (Dle pravidel při tomto pohybu nemá robot dostatečnou sílu na to pohnout jiným robotem a odsunout jej.) Pokud tedy ošetříme tuto část, můžeme nechat plný kód pouze v jedné z metod a v druhé ji pak pouze zavolat se správnými argumenty.
Případně je ještě možné společnou část kódu vydělit do pomocné funkce (označujeme s &lt;code&gt;_&lt;/code&gt; na začátku názvu funkce) a tu pak použít v obou původních funkcích.&lt;/p&gt;
&lt;h3&gt;OrderedDict&lt;/h3&gt;
&lt;p&gt;Doposud jsme v kódu pracovaly se seznamem startovních políček bez jakýchkoliv dalších detailů. Pro hru ale potřebujeme krom polohy startovních políček ještě několik doplňujícíh informací, například kterým směrem jsou orientována, a také potřebujeme, aby záznamy zůstávaly ve stejném pořadí. Karolina se rozhodla předělat seznam na slovník, kde klíčem bude číslo políčka a hodnotami budou směr a souřadnice. Starší verze Pythonu ale náhodně mění pořadí položek ve slovníku, bylo tedy třeba použít knihovnu &lt;code&gt;Collections&lt;/code&gt; a z ní třídu &lt;a href="https://docs.python.org/3/library/collections.html#collections.OrderedDict"&gt;OrderedDict&lt;/a&gt;, která starším verzím Pythonu přidává schopnost držet záznamy ve slovníku v takovém pořadí, v jakém jsou do něj vkládány. Od Pythonu 3.7 výše je tato vlastnost slovníků přímo zaintegrovaná do Pythonu. &lt;/p&gt;
&lt;h3&gt;Tvoříme server!&lt;/h3&gt;
&lt;p&gt;Před dvěma týdny jsme místo klasického setkání měly delší workshop zaměřený na &lt;a href="https://roboprojekt.pyladies.cz/dvacaty-prvni-sraz-workshop"&gt;asynchronní programování a síťovou komunikaci&lt;/a&gt;. Dnes jsme poprvé podrobněji rozebraly, k čemu nově nabyté informace využijeme v našem projektu. Cílem je, aby hra byla hratelná i jinak, než že si ji člověk spustí na svém počítači, v ideálním případě bude běžet někde na serveru a budou se k ní připojovat jednotliví hráči. Potřebujeme tedy vytvořit server, který bude znát stav hry, bude s ním umět pracovat, posílat ho připojeným klientům a zpracovávat změny. V rozdělení, jaké máme teď, budeme pracovat se dvěma typy klientů, první bude pouze pro zobrazení herní plochy, kterou si může zobrazit kdokoliv, aniž by nutně musel hru přímo hrát (na obrázku jako Obecenstvo), druhý pak bude samotné ovládání hry pro hráče (na obrázku jako Interface) - tento klient, když se připojí k serveru, dostane informaci, za jakého robota hraje, bude vybírat karty a odesílat je zpět na server apod. &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/server_klient.jpg" target="_blank" title="rozhrani"&gt;&lt;img alt="rozhrani" src="https://roboprojekt.pyladies.cz/images/thumbnails/server_klient.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Na začátek ale nebudeme řešit síťovou komunikaci tak, jak je popsána výše. Potřebujeme začít s něčím jednodušším a můžeme se vydat dvěma cestami.
První možnost je vytvořit jednoduchý prototyp "serveru" s využitím printu a inputu, který bude umět vypsat zprávu s mapou a zprávu se stavem hry a bude se umět zeptat na vybrané karty. Až budeme tohle mít hotové, můžeme navrhnout klienta pro "obecenstvo", který se bude umět zeptat na stav hry a pak ho vypsat, a klienta pro herní "interface", který se bude umět zeptat na jméno robota a vypsat vybrané karty. Tak si navrhneme logiku, na které bude založená budoucí komunikace, a můžeme ji dále rozpracovávat. 
Druhá možnost je začít od vytovření komunikačního kanálu a navrhnout za využití AsyncIO jednoduchý chatovací prográmek, ke kterému se bude dát připojit a který bude umět přijímat zprávy a posílat je dál všem připojeným klientům. Toto je cesta, kterou jsme se rozhodly vydat, protože můžeme rovnou využít informace a materiály z proběhlého workshopu. Začneme jednoduše vytvořením dvou testovacích klientů, jeden bude pouze přijímat informace ze serveru a druhý je bude serveru pouze odesílat. Co se týče serveru, je třeba zařídit, aby rozesílal informace všem připojeným klientům a aby uměl reagovat na zprávy. &lt;/p&gt;
&lt;p&gt;Potřebovaly jsme si ujasnit, jaké je propojení našeho stávajícího kódu a přechodu na mód server-klient. Nyní je náš stav hry, se kterým by měl později operovart server, vytvářen modulem &lt;code&gt;game.py&lt;/code&gt;. Můžeme tedy obsah tohoto modulu přenést do našeho serveru. Ten si pak bude vytářet stav hry, pamatovat si ho, pracovat s ním (upravovat na základě vstupů od klientů) a informace o něm rozesílat klientům. 
Server a klienti by si měli umět posílat informace v nějakém smysluplném datovém formátu. Protože už umíme obstojně pracovat s formátem JSON, využijeme ho i tady. Bude tedy potřeba vymyslet, jak vše, co obsahuje stav hry, převést na slovník - každý jednotlivý aspekt stavu hry by se měl umět popsat. Server z něj pak vytovří JSON, který bude posílat dál. &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Dvacátý druhý sraz - Mravenčí práce s kódem</title><link href="https://roboprojekt.pyladies.cz/dvacaty-druhy-sraz" rel="alternate"></link><published>2019-03-20T18:00:00+01:00</published><updated>2019-03-20T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-03-20:/dvacaty-druhy-sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Na začátku srazu jsme opět řešily, co se událo od posledně. 
Náš kód se hodně rozrostl a je čím dál složitější a propletenější. Při úpravách kódu se může snadno stát, že optimalizací chování nějaké části rozbijeme část jinou. 
Například dnes jsme se dostaly do situace, kdy jednoduchá úprava toho, jakým …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Na začátku srazu jsme opět řešily, co se událo od posledně. 
Náš kód se hodně rozrostl a je čím dál složitější a propletenější. Při úpravách kódu se může snadno stát, že optimalizací chování nějaké části rozbijeme část jinou. 
Například dnes jsme se dostaly do situace, kdy jednoduchá úprava toho, jakým způsobem říkáme robotovi, kam se má ve fázi pohybu dál posunout, najednou generuje chybu na úplně jiném místě. Ukázalo se, že úpravou metody, která řeší pohyb robotů po herním plánu, jsme se dostaly do situace, kdy není ošetřeno, co se stane, pokud během jakéhokoliv pohybu robot spadne do díry nebo se ocitne jiným způsobem mimo herní plochu. Aktuální kód operuje s koordináty všech robotů, které se však dané situaci mění na &lt;code&gt;None&lt;/code&gt; - tato hodnota pak nelze rozdělit na čísla, se kterými by se dalo dále počítat. Jako v podobných situacích podrobný rozbor chyby přímo nabízí řešení - potřebujeme se dostat do situace, aby se pohyb robota ukončil, pokud se během pohybu ocitne mimo herní plochu. 
Právě vzhledem ke zvyšující se složitosti kódu a obtížnějších částí hry, které ještě nemáme zpracované, se potřebujeme naučit, jak si práci co nejvíce zjednodušit. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Návrh a analýza algoritmů&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Poměrně komplexní část hry, která je ještě před námi, jsou pohyblivé pásy, které mají mnoho různých atributů a mohou ovlivňovat robota několika různými způsoby. V případě takovýchto složitějších problémů přichází ke slovu &lt;strong&gt;návrh algoritmů&lt;/strong&gt;, kdy víme, čeho chceme dosáhnout, ale je třeba to přesně napsat. Je tedy dobré rozepsat si vše do postupných kroků, kde ošetříme všechny možné varianty toho, pokud se robot ocitne na pohyblivém pásu. Jak by měly jednotlivé kroky vypadat a jak na sebe budou navazovat.&lt;/p&gt;
&lt;figure&gt;&lt;iframe width="640" height="360" src="https://www.youtube.com/embed/cDA3_5982h8" frameborder="0" autoplay encrypted-media picture-in-picture allowfullscreen&gt;&lt;/iframe&gt;

&lt;/figure&gt;&lt;p&gt;Jak je vidět na příkladu z videa, je to spousta mravenčí práce, protože je potřeba vše opravdu rozebrat do nejmenších detailů a co nejpodrobnějších kroků pokrývajících všechny možnosti. 
S tím pak souvisí &lt;strong&gt;analýza algoritmů&lt;/strong&gt;, při které si postupně probereme celý postup krok po kroku a podíváme se, jestli někdy skončí. To nám pomůže odhalit situace, které nejsou správně ošetřeny a mohly by generovat problém. Pak se můžeme vrátit zpět k návrhu a dle nalezených problematických částí jej upravit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Řídit Roboprojekt jako projekt&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Zatím jsme v rámci práce na Roboprojektu celkem hojně využívaly na GitHubu &lt;code&gt;Issues&lt;/code&gt;, u kterých je ale třeba si je rozkliknout a přečíst komentáře, aby člověk zjistil v jakém jsou stavu. To není úplně optimální, zvláště při našem počtu otevřených Issues. GitHub ale nabízí také možnost vytvořit &lt;code&gt;Project&lt;/code&gt; a v něm udělat &lt;a href="https://kanbanize.com/kanban-resources/getting-started/what-is-kanban-board/"&gt;Kanban board&lt;/a&gt;, kde bude přímo vidět, v jakém stavu je která Issue a jaký je progres. &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Dvacátý první sraz - AsyncIO a WebSockets</title><link href="https://roboprojekt.pyladies.cz/dvacaty-prvni-sraz-workshop" rel="alternate"></link><published>2019-03-12T17:00:00+01:00</published><updated>2019-03-12T17:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-03-12:/dvacaty-prvni-sraz-workshop</id><summary type="html">&lt;div&gt;&lt;p&gt;Dnešní sraz byl malinko nestandardní. Protože jsme se v projektu posunuly do fáze, kdy už by bylo dobré začít pracovat na spojení jednotlivých částí naší hry dohromady a zařídit, aby mezi sebou komunikovaly, rozhod se Petr udělat pro nás workshop zaměřený na &lt;strong&gt;asynchronní programování&lt;/strong&gt; a &lt;strong&gt;WebSockets&lt;/strong&gt;. Protože jsou to témata …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Dnešní sraz byl malinko nestandardní. Protože jsme se v projektu posunuly do fáze, kdy už by bylo dobré začít pracovat na spojení jednotlivých částí naší hry dohromady a zařídit, aby mezi sebou komunikovaly, rozhod se Petr udělat pro nás workshop zaměřený na &lt;strong&gt;asynchronní programování&lt;/strong&gt; a &lt;strong&gt;WebSockets&lt;/strong&gt;. Protože jsou to témata, která nemusí být zajímavá jen pro nás z RoboProjektu, otevřel workshop i pro další zájemce a sešli jsme se všichni tentokrát v Red Hatu, abychom měli dostatek místa. &lt;/p&gt;
&lt;p&gt;V rámci čtyřhodinového setkání jsme si nejprve vysvětlili a na jednoduchém příkladu ukázali, co to znamená asynchronní programování a k čemu je dobré. Podívali jsme se blíže na knihovnu &lt;a href="https://docs.python.org/3/library/asyncio.html"&gt;AsyncIO&lt;/a&gt;, která umožňuje napsat kód tak, aby počítač dělal více věcí zároveň, respektive zařídit, aby během toho, kdy u jednoho úkolu počítač na něco čeká, pracoval na něčem jiném. Vysvětlili jsme si základní principy, jak s touto knihovnou pracovat, a zkusili i nějaké malé praktické ukázky. 
Pro ty, koho by téma zajímalo hlouběji, k AsyncIO jsou dostupné podrobně zpracované materiály na stránkách &lt;a href="https://naucse.python.cz/lessons/intro/async/"&gt;Nauč se Python&lt;/a&gt;. 
Petr také bude mít na letošním &lt;a href="https://cz.pycon.org/2019/"&gt;PyCon CZ&lt;/a&gt; přednášku o tom, jak vypadá AsyncIO uvnitř, jak uvnitř funguje. &lt;/p&gt;
&lt;p&gt;V druhé části workshopu jsme se zaměřili na WebSockets, což je protokol, který umožňuje  nepřetržitou obousměrnou komunikaci mezi serverem a klientem na portu HTTP. Použili jsme knihovnu &lt;a href="https://aiohttp.readthedocs.io/en/stable/"&gt;aiohttp&lt;/a&gt;, která umí pracovat s HTTP a WebSockets v rámci asynchronního paradigmatu, kterému jsme se věnovali v předchozí části. Pomocí této knihovny jsme si vytvořili jednoduchý server a klienta a nastavili mezi nimi vzájemnou komunikaci. Podklady k této části workshopu jsou dostupné na &lt;a href="https://github.com/encukou/ws-chat"&gt;GithHubu&lt;/a&gt; a v dokumentaci aiohttp najdeme i jednoduché návody na to, jak vytvořit &lt;a href="https://docs.aiohttp.org/en/v3.0.1/web.html"&gt;server&lt;/a&gt; i &lt;a href="https://docs.aiohttp.org/en/v3.0.1/client.html#aiohttp-client"&gt;klienta&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Záznam celého workshopu najdete zde:
&lt;figure&gt;&lt;iframe width="640" height="360" src="https://www.youtube.com/embed/0EdYPukCQHg" frameborder="0" autoplay encrypted-media picture-in-picture allowfullscreen&gt;&lt;/iframe&gt;&lt;/figure&gt;&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Dvacátý sraz - Testy</title><link href="https://roboprojekt.pyladies.cz/dvacaty-sraz-testy" rel="alternate"></link><published>2019-03-05T18:00:00+01:00</published><updated>2019-03-05T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-03-05:/dvacaty-sraz-testy</id><summary type="html">&lt;div&gt;&lt;p&gt;Na předchozích setkáních jsme se věnovaly podrobnému procházení kódu, který jsme doposud daly dohromady. Další velká část, jejíž rozbor nás ještě čeká, jsou testy. Už na minulém srazu jsme je malinko nakously, dnes jsme se ale na oblast testů zaměřily podrobněji.&lt;/p&gt;
&lt;h3&gt;Trochu jiné porovnávání&lt;/h3&gt;
&lt;p&gt;V našem projektu v rámci tvorby …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Na předchozích setkáních jsme se věnovaly podrobnému procházení kódu, který jsme doposud daly dohromady. Další velká část, jejíž rozbor nás ještě čeká, jsou testy. Už na minulém srazu jsme je malinko nakously, dnes jsme se ale na oblast testů zaměřily podrobněji.&lt;/p&gt;
&lt;h3&gt;Trochu jiné porovnávání&lt;/h3&gt;
&lt;p&gt;V našem projektu v rámci tvorby testovacího frameworku budeme potřebovat porovnávat dva stavy hry. Z úplných začátků PyLadies známe &lt;a href="https://naucse.python.cz/course/pyladies/beginners/comparisons/"&gt;porovnávání&lt;/a&gt;, jsme schopny pomocí porovnávacího operátoru &lt;code&gt;==&lt;/code&gt; říci, zda se nějaké hodnoty rovnají nebo nerovnají. Výstupem je boolean hodnota &lt;code&gt;True&lt;/code&gt; v případě rovnosti a &lt;code&gt;False&lt;/code&gt; v případě nerovnosti. Pokud však potřebujeme porovnat například různé objekty stejné třídy, které v základním nastavení porovnávání budou vždy různé, potřebujeme operátor &lt;code&gt;==&lt;/code&gt; předefinovat. Třeba v následujícím kódu řekneme, že všechny objekty třídy A jsou si rovny:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__eq__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Pokud nadefinujeme &lt;code&gt;__eq__&lt;/code&gt;, automaticky se předefinuje i porovnávací operátor &lt;code&gt;__ne__&lt;/code&gt;, tedy &lt;code&gt;!=&lt;/code&gt;. Pokud bychom chtěly předefinovat i další porovnávací operátory, zde jsou jednotlivé zkratky:&lt;br&gt;
&lt;code&gt;__lt__&lt;/code&gt; je označení pro &lt;code&gt;&amp;lt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;__gt__&lt;/code&gt; pro  &lt;code&gt;&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;code&gt;__le__&lt;/code&gt; pro  &lt;code&gt;&amp;lt;=&lt;/code&gt;&lt;br&gt;
&lt;code&gt;__ge__&lt;/code&gt; pro  &lt;code&gt;&amp;gt;=&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;Odbočka - isinstance a issubclass&lt;/h3&gt;
&lt;p&gt;Při nastavení porovnávání v příkladu výše jsme v kódu použily &lt;code&gt;isinstance&lt;/code&gt;. Protože potřebuji zjistit, zda se rovnají objekty dané třídy, není nejvhodnějším řešením jednoduše porovnat typy objektů pomocí &lt;code&gt;type&lt;/code&gt;. Může se stát, že budu porovnávat objekty jedné třídy s jinou, která z té první dědí. Pak by porovnání &lt;code&gt;type&lt;/code&gt; mělo za výsledek &lt;code&gt;False&lt;/code&gt;, protože se skutečně jedná o jiné třídy. &lt;code&gt;isinstance&lt;/code&gt; je ale schopno zjistit, zda se jedná o objekt dané třídy, i když se jedná o podtřídu. Použití &lt;code&gt;isinstance&lt;/code&gt; je ale často pouze zkratkou, která ukazuje, že program není úplně dobře navržen a dal by se napsat lépe.
Podobnou funkcí je &lt;code&gt;issubclass&lt;/code&gt;, která přímo zjišťuje, zda je daná třída podtřídou druhé třídy. &lt;/p&gt;
&lt;h3&gt;Nedostatky v našem kódu&lt;/h3&gt;
&lt;p&gt;Ne všechny nedostatky a připomínky jsou specifické pro testy, přestože jsme na ně narazily při procházení testovacích modulů. Některé se dají aplikovat plošně na psaní kódu a vedou k jeho lepší čitelnosti a srozumitelnosti. &lt;/p&gt;
&lt;h4&gt;Názvy proměnných&lt;/h4&gt;
&lt;p&gt;První z této skupiny jsou názvy proměnných. Vytváříme-li nějakou proměnnou, která se bude používat v celém modulu, je dobré je pojmenovat dostatečně specificky tak, aby z ní bylo jasné, co skutečně obsahuje, ideálně včetně datového typu. Příklad z našeho kódu - na začátku jednoho z testovacích modulů vytváříme seznam cest k mapám, který byl pojmenován &lt;code&gt;maps&lt;/code&gt;. Neobsahuje ale mapy, pouze cesty k nim. Název je tedy poměrně matoucí, mohly bychom spíše čekat, že seznam bude obsahovat například JSONy map. Mnohem lepší název je tedy &lt;code&gt;all_map_paths&lt;/code&gt;, který jasně říká, co od proměnné můžeme čekat.
Další problém s názvem proměnné jsme odhalily o kus dál. Všimly jsme si, že editor nám v kódu zabarvuje proměnnou &lt;code&gt;type&lt;/code&gt; (viz obrázek). &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/type.png" target="_blank" title="type"&gt;&lt;img alt="type" src="https://roboprojekt.pyladies.cz/images/thumbnails/type.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Nejedná se o klíčové slovo, můžeme ho použít jako název proměnné, ale je to již (podobně jako &lt;code&gt;print&lt;/code&gt;) nadefinovaná funkce, kteráJaké testy by měly v projektu ještě být vrací typ objektu. Krom toho je to také třída. Například &lt;code&gt;int&lt;/code&gt; je objekt třídy &lt;code&gt;type&lt;/code&gt;. My ale &lt;code&gt;type&lt;/code&gt; v našem kódu používáme ve vztahu k vlastnostem políček na mapě. To ale není vhodné, od &lt;code&gt;type&lt;/code&gt; jsou podobně jako od &lt;code&gt;print&lt;/code&gt; očekávány nějaké konkrétní výstupy, není tedy dobře tyto věci předefinovávat. Pokud chceme použít nějaké generické jméno, které by již mohlo mít nějakou hodnotu nebo funkci, je lépe toto jméno více specifikovat.&lt;/p&gt;
&lt;h4&gt;Komentáře a dokumentační řetězce&lt;/h4&gt;
&lt;p&gt;Při procházení jednoho z testovacích modulů se ukázalo, že neumíme správně pracovat s komentáři a dokumentačními řetězci. Narazily jsme například v těle kódu na komentář, který hovoří o celém souboru. Takový text je ale poměrně důležitý, říká, k čemu soubor slouží. Měl tedy být dokumentačním řetězcem celého modulu a měl by být umístěn hned na začátku celého souboru (ještě před importy).&lt;br&gt;
Důležité je také rozlišovat mezi dokumentačními řetězci a komentáři. Dokumentační řetězec popisuje chování modulu, funkce nebo třídy a je umístěn na začátku té části kódu, ke které se vztahuje. Dokumentační řetězce slouží člověku, který danou věc používá, aby věděl, k čemu slouží.
Oproti tomu komentáře slouží těm, kteří čtou kód a potřebují zjistit, jak funguje. Vysvětlují například různé proměnné, použití konkrétních věcí v kódu apod.&lt;br&gt;
Důležité také je dokumentační řetězce i komentáře &lt;strong&gt;aktualizovat&lt;/strong&gt;. S kódem pracujeme pořád, vylepšujeme ho a měníme. Na komentáře ale často zapomínáme. Může se tak stát, že v komentáři nebo dokumentačním řetězci narazíme na něco, co již dávno v kódu nepoužíváme. Pro člověka, který kód vidí poprvé nebo jej nezná tak dobře jako autor, může být taková věc hodně matoucí. Proto je potřeba při změnách kódu myslet i na úpravy doprovodných textů, aby dávaly smysl.&lt;/p&gt;
&lt;h4&gt;Zbytečné testy?&lt;/h4&gt;
&lt;p&gt;Občas jsme narazily i na testy, které nemají pro kód žádnou přidanou hodnotu. Je dobré si u každého testu říct, co přináší, zda to, co testují, je skutečně potřeba testovat apod. Pokud nedokážeme najít nic, čím by takový test mohl být užitečný, že to je jen test pro test, můžeme ho s čistým svědomím smazat. &lt;br&gt;
Podobně je na tom i testování pomocných funkcí. Někdy může být dobré otestovat pomocnou funkci, na druhou stranu pokud zjistíme, že ji už nepotřebujeme, nestačí smazat pouze tuto pomocnou funkci, musíme také myslet na to, že je třeba smazat i její test. &lt;br&gt;
Podobné testy mohou být i relikty z dřívějších fází vývoje, kdy byl stav kódu takový, že daná funkce byla důležitá, potřebovala otestovat a dávalo to smysl. Pokud se ve vývoji posuneme dále a test už se může zdát nadbytečný, protože netestuje nic důležitého, stále může mít v kódu svoje místo. Takovým testům se říká &lt;strong&gt;regresní&lt;/strong&gt; testy a jejich úkolem je testovat, že se daná funkce nezmění. &lt;/p&gt;
&lt;h4&gt;Odbočka - Malá zákeřnost Pythonu 3&lt;/h4&gt;
&lt;p&gt;V naší sadě testů se objevoval jeden, který měl zajímavý výstup. Vždy prošel, pokud se spouštěl v Pythonu 3.6, a vždy spadl, pokud se spouštěl v nižší verzi.&lt;br&gt;
V kódu hodně pracujeme se slovníky. V předchozích verzích Pythonu 3 neměly slovníky dané pořadí, vypisovaly se různě. Slovník sám si nepamatoval, v jakém pořadí se do něj vkládaly prvky, na pořadí, v jakém se vypíší, se tedy nedalo spoléhat. Fungovalo ale velmi rychle vyhledávání podle klíče. V Pythonu 2 se sice slovníky vypisovaly vždy stejně, ale zabíraly více paměti a vyhledávání v nich bylo pomalejší. Od verze Pythonu 3.6 jsou slovníky opět seřazené, protože někdo vymyslel, jak to udělat, aby byly stále rychlé, spotřebovávaly méně paměti, ale zároveň zůstaly stejně seřazené. Náš problém tedy spočíval právě v tom, že daný test počítal s konkrétním seřazením slovníku, v Pythonu 3.5 tedy občas padal.&lt;/p&gt;
&lt;h3&gt;Testujeme vše, co je třeba?&lt;/h3&gt;
&lt;p&gt;U testů obecně je dobré se zaměřit nejen na to, jaké testy máme a v jakém jsou stavu, ale také na to, jaké testy ještě nemáme a měly bychom mít. Absenci testů jednoduše nepoznáme. Je třeba si celý kód projít, zaměřit se na všechny důležité funkce v něm a podívat se, zda jsou (dostatečně) otestované.&lt;br&gt;
Pokud bychom testy nepsaly, kód pravděpodobně bude fungovat dál, mohou se však do něj nepozorovaně vkrádat drobné chyby, které by nám mohly jednoho dne přerůst přes hlavu. Testy je tedy určitě dobré nepodceňovat. &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Devatenáctý sraz - Tipy na vylepšení</title><link href="https://roboprojekt.pyladies.cz/devatenacty-sraz-tipy" rel="alternate"></link><published>2019-02-26T18:00:00+01:00</published><updated>2019-02-26T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-02-26:/devatenacty-sraz-tipy</id><summary type="html">&lt;div&gt;&lt;h3&gt;Testy, co nemají procházet&lt;/h3&gt;
&lt;p&gt;Při psaní testů mohou nastat situace, kdy potřebujeme ošetřit, že nějaký konkrétní test neprochází. Pro různé situace jsou vhodná různá řešení.&lt;/p&gt;
&lt;h5&gt;@pytest.mark.xfail&lt;/h5&gt;
&lt;p&gt;Tímto dekorátorem označujeme test, který zatím neprochází, ale počítáme s tím, že v budoucnu by procházet měl. Buď testuje kód, který ještě …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;h3&gt;Testy, co nemají procházet&lt;/h3&gt;
&lt;p&gt;Při psaní testů mohou nastat situace, kdy potřebujeme ošetřit, že nějaký konkrétní test neprochází. Pro různé situace jsou vhodná různá řešení.&lt;/p&gt;
&lt;h5&gt;@pytest.mark.xfail&lt;/h5&gt;
&lt;p&gt;Tímto dekorátorem označujeme test, který zatím neprochází, ale počítáme s tím, že v budoucnu by procházet měl. Buď testuje kód, který ještě nebyl napsaný, nebo který ještě nefunguje, jak má. Lze mu přidat parametr &lt;code&gt;strict=True&lt;/code&gt;, čímž zařídíme, že jakmile test začne procházet, celkově testy neprojdou a upozorní nás to tak na nutnost dekorátor umazat.&lt;/p&gt;
&lt;h5&gt;@pytest.mark.skip&lt;/h5&gt;
&lt;p&gt;Používáme v situaci, kdy ani nepočítáme s tím, že by test procházel. Při spouštění testů se takto označený test vždy přeskočí. Je možné přidat tomuto dekorátoru parametr &lt;code&gt;reason&lt;/code&gt;, který pak v test reportu vypíše, proč byl test přeskočen.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@pytest.mark.skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"no way of currently testing this"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;h5&gt;@pytest.mark.skipif&lt;/h5&gt;
&lt;p&gt;Tento dekorátor se používá pro případ, kdy se test přeskočí jen v určité situaci, za určitých podmínek. Například v konkrétním operačním systému nebo konkrétní verzi pythonu. Je třeba danou podmínku vydefinovat přímo za dekorátor, například takto:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@pytest.mark.skipif&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version_info&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="n"&gt;reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"requires python3.6 or higher"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Při každém spouštění testů se zkontroluje u tohoto testu podmínka. Test se přeskočí, budou-li testy spouštěny v nižší verzi pythonu než 3.6. 
U použití tohoto dekorátoru je narozdíl od jednoduchého &lt;code&gt;skip&lt;/code&gt; vždy při definování podmínky nutné zadat parametr &lt;code&gt;reason&lt;/code&gt;, aby při výpisu výsledku testů byl jasný důvod, proč se test přeskočil.&lt;/p&gt;
&lt;p&gt;Více k tomuto tématu najdeme v dokumentaci &lt;a href="https://docs.pytest.org/en/latest/skipping.html"&gt;pytestu&lt;/a&gt;, odkud pochází i ukázky kódu výše.&lt;/p&gt;
&lt;h3&gt;Nástroje na kontrolu stylu - ano či ne?&lt;/h3&gt;
&lt;p&gt;V agendě pro dnešní setkání se také objevil dotaz, zda používáme nějaký nástroj na kontrolu stylu psaní kódu. V našem týmu je to v podstatě půl na půl. Některé z nás absolvovaly začátečnický kurz PyLadies dříve, než se v materiálech jako doporučovaný editor pro Win a Mac objevil Atom. Nyní je součástí materiálů pro samostudium jeho &lt;a href="https://naucse.python.cz/course/pyladies/beginners/install-editor/atom/"&gt;instalace&lt;/a&gt; a příprava, kdy se mimo jiné instaluje &lt;a href="http://flake8.pycqa.org/en/latest/"&gt;flake8&lt;/a&gt;, nástroj, který hlídá konzistentní styl psaní kódu v pythonu na základě &lt;a href="https://www.python.org/dev/peps/pep-0008/"&gt;PEP 8&lt;/a&gt;. Flake8 v editoru barevně vyznačuje například příliš dlouhé řádky, mezery navíc, nadbytečné importy nebo třeba nepoužívané metody. Výsledkem by měl být lépe čitelný kód. 
Jestli podobné nástroje používat nebo ne je sporné. Nelze se na ně plně spoléhat, protože kontrolují jen věci, které jdou odhalit automaticky, a také ne vždy se jedná o chybný styl - někdy můžete například specifické formátování dělat záměrně, protože může dávat větší smysl a být čitelnější a přehlednější, než přesné následování pravidel PEP 8. Na druhou stranu třeba pro nováčky pracující ve větším týmu to může být nástroj užitečný, protože výsledkem jeho používání opravdu je lépe čitelný kód. 
Obecně je dobré PEP 8 znát, pochopit principy, které popisuje, a řídit se podle nich, protože zaručuje lepší čitelnost kódu nejen pro ty, kteří pravidla PEP 8 znají, ale celkově pro všechny. Navíc pokud bude číst kód někdo, kdo pravidla zná, odhalí na první pohled místa, kde je něco jinak a na která je třeba se více soustředit.
Od Petra jsme také dostaly tip na zajímavou přednášku &lt;a href="https://www.youtube.com/watch?v=wf-BqAjZb8M"&gt;Beyond PEP 8&lt;/a&gt;, která mimo jiné zmiňuje i situace, kdy postupovat podle PEP 8 nemusí být úplně nejvhodnější.&lt;/p&gt;
&lt;p&gt;Jen pro dovysvětlení, &lt;a href="https://www.python.org/dev/peps/"&gt;PEP&lt;/a&gt; je zkratka pro Python Enhancement Proposal, což jsou dokumenty pro vylepšení Pythonu nebo informační dokumenty o Pythonu. &lt;/p&gt;
&lt;h3&gt;Tipy pro GitHub&lt;/h3&gt;
&lt;p&gt;Před časem GitHub zavedl novinku v rámci code review, &lt;strong&gt;suggested changes&lt;/strong&gt;. Díky ní je možné přímo na GitHubu v rámci pull requestu přímo navrhovat změny, které autor může jedním kliknutím odsouhlasit a začlenit. Je to příjemný rychlý způsob malých oprav například pro překlepy a drobné chyby, zatím je to ovšem pouze beta verze.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/suggested.png" target="_blank" title="suggested_changes"&gt;&lt;img alt="suggested_changes" src="./images/suggested.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Další tip na zrychlení práce na GitHubu se týká issues. Existuje také rychlý způsob zavření issue, pokud je vyřešena pomocí nějakého pull requestu v tom samém repozitáři. Posíláme-li nějaký pull request týkající se konkrétní issue, a pokud by se začleněním tohoto PR issue zcela vyřešilo, lze do popisu PR nebo do commit message napsat určité klíčové slovo spolu s číslem issue, nebo lépe s celým URL konkrétní issue, například &lt;code&gt;Fix #135&lt;/code&gt;. Jakmile se PR začlení, issue se automaticky zavře. Seznam všech klíčových slov lze najít &lt;a href="https://help.github.com/en/articles/closing-issues-using-keywords"&gt;zde&lt;/a&gt;. &lt;/p&gt;
&lt;h3&gt;Nebojme se dělat code reviews&lt;/h3&gt;
&lt;p&gt;Narazily jsme na problém, že část z nás si netroufá dělat code reviews, hlavně proto, že tolik nerozumí kódu jako jeho autorka, že je pro nás kód moc složitý. Code reviews ale nejsou jen o tom schválit, že kód je v pořádku a opravit případné chyby. Mohou také sloužit právě k lepšímu prozumění kódu. Když kód procházíme, je dobré se u věcí, kterým nerozumíme, zeptat, proč vypadají zrovna takhle, nebo co ten konkrétní kus kódu dělá. Ten, kdo kód psal, v něm už chyby tak snadno nevidí. Tím, že kód někomu vysvětlí, se také dají chyby odhalit. &lt;/p&gt;
&lt;h3&gt;Testovací framework pro funkční testy&lt;/h3&gt;
&lt;p&gt;Při procházení kódu jsme narazily na to, že nám v testech chybí, jak zjistit, zda je test jako takový správný a testuje, co má opravdu testovat. Aktuálně je třeba to kontrolovat manuálně, což není vždy úplně jednoduché.
Bylo by dobré vytvořit testovací framework, kód, který by zjednodušil vytváření funkčních testů. Například by test dostal adresář, kde by byla první mapa s roboty na konkrétních místech, textový soubor popisující, co se má stát během tahu, a výsledná mapa, která ukazuje, jak má kolo skončit. Test zkontroluje, že když dostane tuto mapu s roboty a tyto pokuny, po jejich provedení  bude výsledek takový, jako ukazuje druhá mapa. Cílem je zjistit, že souhlasí očekávaný výstup.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/testy.png" target="_blank" title="testy"&gt;&lt;img alt="testy" src="https://roboprojekt.pyladies.cz/images/thumbnails/testy.png" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Ve větším by pak test uměl projít všechny testovací adresáře, kde by se daly testovat například všechny efekty políček, všechnu efekty karet apod. 
Práci bude dobré rozdělit na dvě části, udělat test, který se provede v daném adresáři, a pak test, který bude procházet všechny adresáře a postupně je otestuje.&lt;/p&gt;
&lt;p&gt;Co se týče testů obecně, rády bychom je probraly podrobněji, stejně, jako jsme to v předchozích lekcích udělaly se zbytkem kódu, budeme jim tedy věnovat příští setkání.&lt;/p&gt;
&lt;h3&gt;Propojení backendu a frontendu&lt;/h3&gt;
&lt;p&gt;Abychom se posunuly dál a aby byla hra hratelná, je třeba propojit herní logiku s vyobrazením. Nejedná se o jednoduchý úkol a budeme se muset naučit spoustu nových věcí. Protože se jedná o složitější problematiku, rozhodl se Petr udělat za dva týdnu misto klasického srazu trošku větší workshop, rozsahem přesahující naše běžná úterní setkání, takový menší PyWorking orientovaný na asynchroní programování a WebSockets. Sejdeme se na čtyři hodiny a setkání otevřeme i pro kouče, pro které by také mohlo být téma zajímavé. &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Osmnáctý sraz - Odbočka: Git</title><link href="https://roboprojekt.pyladies.cz/osmnacty-sraz-git" rel="alternate"></link><published>2019-02-19T18:00:00+01:00</published><updated>2019-02-19T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-02-19:/osmnacty-sraz-git</id><summary type="html">&lt;div&gt;&lt;p&gt;Přestože Petr neměl tento týden prostor, rozhodly jsme se sraz nezrušit a domluvily jsme se s Martinem, který chodí koučovat začátečnické kurzy a chystá i nějaká témata na PyWorkingy, aby nám přišel ukázat rozšířené základy gitu. Přestože je používání gitu a GitHubu součástí našeho projektu, pracujeme pouze se základy, které …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Přestože Petr neměl tento týden prostor, rozhodly jsme se sraz nezrušit a domluvily jsme se s Martinem, který chodí koučovat začátečnické kurzy a chystá i nějaká témata na PyWorkingy, aby nám přišel ukázat rozšířené základy gitu. Přestože je používání gitu a GitHubu součástí našeho projektu, pracujeme pouze se základy, které jsme se naučily v rámci &lt;a href="https://naucse.python.cz/course/pyladies/git/basics/"&gt;PyLadies&lt;/a&gt;. Zajímalo nás, jaké jsou další možnosti, jak si s gitem ulehčit práci.&lt;/p&gt;
&lt;p&gt;Jako první věc nám Martin ukázal, že si git můžeme přizpůsobit "na míru". Příkaz &lt;code&gt;git config --global&lt;/code&gt; známe z &lt;a href="https://naucse.python.cz/course/pyladies/git/install/"&gt;instalace gitu&lt;/a&gt;, kde jsme jím nastavovaly uživatelské jméno a email. Pokud ale zadáme &lt;code&gt;git config --global -e&lt;/code&gt;, dostaneme se do editovatelného nastavení, kde toho jde udělat mnohem více, například nastavit aliasy pro různé přikazy, které v gitu používáme. Můžeme si tak definovat vlastní zkratky i pro delší sekvence, nejen pro jednoslovné příkazy. &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="aliasy" src="./images/alias.png" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Dostaly jsme ještě nějaké tipy k příkazové řádce obecně. Používáme pro pohyb v historii příkazů šipku nahoru, ale pomocí kombinace kláves Ctrl + R v ní mohu přímo vyhedávat zadáním požadovaného výrazu, najde jeho poslední výskyt. Pro zobrazení celé historie stačí zadat příkaz &lt;code&gt;history&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;git stash&lt;/h3&gt;
&lt;p&gt;Poté, co jsme si pohrály s nastavením, posunuly jsme se k novým příkazům. Jako první přišel na řadu &lt;code&gt;git stash&lt;/code&gt;. Tento příkaz může být užitečný například ve chvíli, kdy máme rozdělanou nějakou práci, ale náhle potřebujeme udělat něco jiného. Nechceme ještě dělat commit, ale můžeme využít stash, který uloží změny mimo větev, pouze lokálně. Stashů můžeme udělat tolik, kolik potřebujeme.
Stash se zobrazuje s pořadovým číslem, podle kterého je identifikovatelný: &lt;code&gt;stash@{0}&lt;/code&gt; označuje nejnověji uložený, &lt;code&gt;stash@{1}&lt;/code&gt; druhý nejnovější, atd. Pokud mu nepřidáme žádný popis, přiřadí se automaticky místo popisu commit message z aktuálního commitu, který se vypíše za pořadové číslo. Pokud mu popis dáme, nahradí tuto commit message. Jednou vytvořený stash již nelze přejmenovat.
Související příkazy:
&lt;code&gt;git stash push -m "název"&lt;/code&gt; vytvoří nový stash s vlastním názvem
&lt;code&gt;git stash list&lt;/code&gt; vypíše seznam všech stashů
&lt;code&gt;git stash pop&lt;/code&gt; vytahuje věci ze stashe od nejnovějšího záznamu. Pokud za tento příkaz přidám pořadové číslo stashe, například &lt;code&gt;git stash pop stash@{3}&lt;/code&gt;, vytáhne ten konkrétní stash. Jedná se o tzv. destruktivní čtení - po tomto příkazu je dotyčný stash odstraněn.
&lt;code&gt;git stash drop&lt;/code&gt; maže věci ze stashe od nejnovějšího záznamu, ale podobně jako pop umí mazat i konkrétní stash, pokud mu dám jeho pořadové číslo.
&lt;code&gt;git stash clear&lt;/code&gt; kompletně vyčistí stash, smaže všechny uložené stashe
Git takto pracuje pouze se soubory, které zná, které už do něj byly přidány. Pokud máme nějaké, které ještě do gitu přidány nebyly a git je netrackuje, ale přesto je chceme dát do stashe, je potřeba zadat &lt;code&gt;git stash push --include-untracked&lt;/code&gt;.
Stash ukládá práci mimo větve, do našeho lokálního repozitáře. Můžeme pracovat v jedné větvi, dát věci do stashe, přesunout se do nové větve a tam si změny vytáhnout. Jde v podstatě o dočasné úložiště rozpracovaných vecí. Je dobré používat stash s rozmyslem, abychom si zachovali přehled, co vše zde máme uloženo.
Více ke stasthi lze najít v &lt;a href="https://git-scm.com/docs/git-stash"&gt;dokumentaci&lt;/a&gt;. &lt;/p&gt;
&lt;h3&gt;git remote&lt;/h3&gt;
&lt;p&gt;Git je distribuovaný systém, mohu tedy pracovat s různými repozitáři a posílat mezi nimi commity tak, jak se nám to hodí. Tím hlavním bývá &lt;code&gt;origin&lt;/code&gt;, ale různých remote adresářů mohu mít celou řadu, pojmenovávat si je a předávat si mezi nimi změny apod. 
Příkaz &lt;code&gt;git remote add&lt;/code&gt; spolu s názvem, jak si chceme daný remote pojmenovat, a adresou repozitáře (například na GitHubu) přidá další remote do našeho gitového repozitáře. 
&lt;code&gt;git remote show&lt;/code&gt; ukáže výpis všech remote adresářů, které máme přidané jako součást daného projektu. Pokud za to přidáme ještě název konkrétního remote, jak jsme si jej u sebe pojmenovaly, ukáže nám jeho detaily.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="git_remote" src="./images/git_remote.png" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;&lt;code&gt;git fetch "název remote"&lt;/code&gt; se připojí na adresu remote repozitáře, stáhne si ho a označí vzdálené větve. Až pokud se na některou z nich budu chtít přeponout, přidá novou větev do našeho lokálního repozitáře. Git tedy o vzdálených větvích ví, ale lokální větev vytváří až tehdy, když se na ni přepnu. &lt;/p&gt;
&lt;h3&gt;git cherry-pick&lt;/h3&gt;
&lt;p&gt;Jedná se o příkaz, který umožňuje výběr konkrétních commitů libovolně z historie. 
&lt;code&gt;git cherry-pick&lt;/code&gt; spolu s identifikátorem commitu použije jen tento vybraný commit a udělá z něj nový commit na aktuální větvi, aplikuje změny z daného commitu. Pokud místo commitu napíšu název větve, je to jen jiný název commitu, na který daná větev ukazuje. Nevezme větev celou. 
Více k tomuto tématu viz &lt;a href="https://git-scm.com/docs/git-cherry-pick"&gt;dokumentace&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;git reset&lt;/h3&gt;
&lt;p&gt;Příkaz &lt;code&gt;git reset&lt;/code&gt; umí rušit commity. Pokud za příkaz zadáme název commitu, přesuneme se na něj a tedy v rámci gitu do stavu, v jakém tehdy repozitář byl. Změny, které se staly v pozdějších commitech, nejsou nyní v gitu, ale existují v našem repozitáři. Pokud se jich chci zbavit a úplně se vrátit do předchozího stavu, existují dvě cesty. Buď po &lt;code&gt;git reset "název commitu"&lt;/code&gt; zadám ještě &lt;code&gt;git checkout .&lt;/code&gt; Druhá cesta je přímější, a to pomocí &lt;code&gt;git reset --hard "název commitu"&lt;/code&gt; přímo pozmění repozitář do stavu v daném commitu a vše, co se stalo po něm, zahodí, včetně rozpracovaných věcí. 
Pomocníkem při pohybech po commitech může být &lt;code&gt;git reflog&lt;/code&gt;. Git si pamatuje, jak se posouval ukazatel &lt;code&gt;HEAD&lt;/code&gt; v rámci repozitáře, a &lt;code&gt;git reflog&lt;/code&gt; vypíše historii všech těchto pohybů, včetně vymazaných commitů a také včetně provedených příkazů, které k pohybu vedly. Historie se ale čas od času promazává, nelze tedy jít libovolně dávno do minulosti.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="git_reflog" src="./images/reflog.png" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;V rámci gitu se pohybjeme v podstatě ve třech úrovních - viz obrázek níže. Vycházíme z našeho pracovního adresáře, kde máme vztvořený gitový repozitář. Dokud gitu neřekneme pomocí &lt;code&gt;git add&lt;/code&gt;, aby sledoval nějaké změny, červenou barvou nám po zadání &lt;code&gt;git status&lt;/code&gt; vypíše soubory, které v adresáři jsou, ale nesleduje je. Když vložíme soubor do gitu, přesune se do zelené oblasti, tzv. Stage, kde je již sleduje, ale stále s nimi můžeme pracovat, měnit je apod. 
Pokud máme soubor ve Stagi, ale chceme jej odebrat a vrátit zpět do pracovního adresáře, lze to pomocí &lt;code&gt;git reset -- "název souboru"&lt;/code&gt;. 
Ze Stage pak pomocí příkazu &lt;code&gt;git commit&lt;/code&gt; git sledované soubory zabalí, dá jim identifikátor, hlavičku, datum, email apod., vytvoří commit a uloží ho. &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="git_colors" src="./images/git_colors.png" class="figure-img img-fluid img-rounded"&gt;&lt;figcaption class="figure-caption"&gt;
&lt;em&gt;&lt;a href="https://pyvec.github.io/cheatsheets/basic-git/basic-git-cs.pdf"&gt;Zdroj: Začátečnický kurz PyLadies&lt;/a&gt;&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;
&lt;h3&gt;git rebase&lt;/h3&gt;
&lt;p&gt;Příkaz &lt;code&gt;git rebase&lt;/code&gt; vykonává opakovaný &lt;code&gt;git cherry-pick&lt;/code&gt;. Zadáme-li &lt;code&gt;git rebase "název větve"&lt;/code&gt;, git se podívá, jak se od sebe dané větve liší a jaké jsou mezi nimi rozdílné commity. Postupně pak jednotlivé commity vezme a provede &lt;code&gt;git cherry-pick&lt;/code&gt;. Důležité je pořadí větví. Ta větev, na které aktuálně jsem, slouží jako zdroj commit. Větev, kterou předáme jako parametr příkazu &lt;code&gt;git rebase&lt;/code&gt;, bude ta, na kterou budou commity přibývat. 
Díky &lt;code&gt;git rebase&lt;/code&gt; můžeme naši větěv přesouvat libovolně po "stromě" našeho projektu, tedy vlastně přepisovat jeho historii, narozdíl od &lt;code&gt;git merge&lt;/code&gt;, který větve a změny v nich sloučí do jedné, ale jejich historii nechá paralelní. 
Pomocí &lt;code&gt;git rebase -i&lt;/code&gt; se dostaneme do interaktivního módu, kde je možné měnit, co se pomocí &lt;code&gt;git rebase&lt;/code&gt; má stát. Lze úplně vymazat některé commity, změnit jejich pořadí, změnit commit message, upravit commit před jeho začleněním apod. Interaktivní mód obsahuje seznam commitů spolu s tím, jak se mají začlenit, a nápovědu, jak provést konkrétní úpravy.
Pěkný návod ke &lt;code&gt;git rebase&lt;/code&gt; je například &lt;a href="https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase"&gt;zde&lt;/a&gt; a rozdíl mezi &lt;code&gt;git rebase&lt;/code&gt; a &lt;code&gt;git merge&lt;/code&gt;je pěkně popsaný například &lt;a href="https://www.atlassian.com/git/tutorials/merging-vs-rebasing"&gt;tady&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;git revert&lt;/h3&gt;
&lt;p&gt;Pomocí &lt;code&gt;git revert "název commitu"&lt;/code&gt; provedu inverzní operaci ke &lt;code&gt;git commit&lt;/code&gt;. Neodstraňuje ale změny z historie, nevrací se v ní zpět, narozdíl od &lt;code&gt;git reset&lt;/code&gt;. Postupuje dopředu, ale provádí opačné změny, než udělal daný commit.&lt;/p&gt;
&lt;h3&gt;Použití jen některých změn v souboru&lt;/h3&gt;
&lt;p&gt;Může se stát, že v nějakém souboru provedeme více změn, ale do commitu chceme dát jen některé z nich. K tomu slouží &lt;code&gt;git add -p "název souboru&lt;/code&gt;. Otevře se nám celý zdrojový soubor s vyznačenými změnami a zkratkami akcí, které můžeme se změnami provést. Zadáním otazníku se vypíše nápověda k jednotlivým pokynům. Můžeme například vybrat, jestli změnu do commitu přidáme, nepřidáme, přidáme od dané změny všechny následující, vynecháme všechny následující, ještě před přidáním konkrétní změnu upravíme apod. &lt;code&gt;git commit&lt;/code&gt; pak bude zahrnovat jen vybrané dílčí bloky daného souboru.&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Šestnáctý a sedmnáctý sraz - co máme a funguje</title><link href="https://roboprojekt.pyladies.cz/sestnacty_sedmnacty_sraz" rel="alternate"></link><published>2019-02-05T18:00:00+01:00</published><updated>2019-02-05T09:58:00+01:00</updated><author><name>Iveta Česalová</name></author><id>tag:roboprojekt.pyladies.cz,2019-02-05:/sestnacty_sedmnacty_sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Tyto srazy byly opět v duchu velkého vysvětlování, co všechno již v kódu je a co funguje. Začaly jsme základními soubory jako je README.md a narazily na malé nedostatky. Je nutno doplnit informaci o automatickém exportu obrázků pomocí &lt;code&gt;export_img.py&lt;/code&gt;. Dále je lepší změnit &lt;code&gt;python -m pip install pyglet …&lt;/code&gt;&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Tyto srazy byly opět v duchu velkého vysvětlování, co všechno již v kódu je a co funguje. Začaly jsme základními soubory jako je README.md a narazily na malé nedostatky. Je nutno doplnit informaci o automatickém exportu obrázků pomocí &lt;code&gt;export_img.py&lt;/code&gt;. Dále je lepší změnit &lt;code&gt;python -m pip install pyglet&lt;/code&gt; na &lt;code&gt;python -m pip install -r requirements.txt&lt;/code&gt;, v případě doplnění dalších potřebných programů (momentálně je v souboru requirements.txt pouze pyglet).&lt;/p&gt;
&lt;p&gt;Hra se bude pouštět souborem &lt;code&gt;game.py&lt;/code&gt;. V tomto souboru je nutno mít co nejméně kódu, který nejsme schopny testovat a bude spojovat všechny ostatní soubory dohromady. Je tam nyní pomocná funkce &lt;code&gt;def move_once(t)&lt;/code&gt;, kterou je nutno odstranit. 
A narazily jsme na zásadní věc, jak vlastně hra bude fungovat, jak zadat příkazy, aby se již dalo hrát. Je nutno propojit s interface. Drobná chybička je v souboru &lt;code&gt;interface_frontend.py&lt;/code&gt;, protože spouští aplikaci, což by neměl, protože jinak nepůjde importovat. Takže &lt;code&gt;window = init_window()&lt;/code&gt; a &lt;code&gt;pyglet.app.run()&lt;/code&gt; přesunout do &lt;code&gt;game.py&lt;/code&gt;, z kterého se pustí dvě okna.&lt;/p&gt;
&lt;p&gt;Pro zpřehlednění jsme vytvořily následující mapu, abychom věděly, která část kódu co obsahuje.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/mapa.jpg" target="_blank" title="mapa"&gt;&lt;img alt="mapa" src="https://roboprojekt.pyladies.cz/images/thumbnails/mapa.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;h3&gt;BACKEND.PY&lt;/h3&gt;
&lt;p&gt;Tady jsme narazily na problém ve třídě &lt;code&gt;Robot&lt;/code&gt;, kdy v &lt;code&gt;def_walk&lt;/code&gt; je problém, když robot couvá. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Rotation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;U_TURN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Rotation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;U_TURN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;V případě, že jde na sever nebo na jih, není problém. Ovšem pokud má jít na západ, je kód špatně. Je nutné ještě doplnit směr, kterým má jít.  V prvním kroku se otočí čelem vzad(&lt;code&gt;self.rotate(Rotation.U_TURN)&lt;/code&gt;) tedy na jih, druhý krok popojde (&lt;code&gt;self.walk((-distance), state&lt;/code&gt;) a při třetím kroku se opět otočí (&lt;code&gt;self.rotate(Rotation.U_TURN&lt;/code&gt;) a kouká tedy na sever - viz obrázek. &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="posun" src="./images/posun.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Občas se nám objevuje duplicitní část kódu, například v metodách &lt;code&gt;def_walk&lt;/code&gt;a &lt;code&gt;def_move&lt;/code&gt;. Je tedy nutno vyřešit. Stejně tak máme v &lt;code&gt;def_apply_card_effect&lt;/code&gt; dvakrát použitou podmínku &lt;code&gt;if_isinstance&lt;/code&gt;, měli bychom na tuto část vytvořit metodu.&lt;/p&gt;
&lt;h4&gt;Třída Robot&lt;/h4&gt;
&lt;p&gt;V backendu ve vlastnostech robota se objevuje &lt;code&gt;self.path = path&lt;/code&gt; a &lt;code&gt;self.path_front = path_front&lt;/code&gt;. Jelikož se jedná o cestu k obrázkům, patří to do frontedu a pokud to chceme propojit, je vhodné místo toho robota pojmenovat.&lt;/p&gt;
&lt;p&gt;V metodě &lt;code&gt;def_inactive(self)&lt;/code&gt; jsou jako souřadnice neaktivního robota použity &lt;code&gt;(-1, -1)&lt;/code&gt; . Nedávají nikdy smysl jako čísla (x, y), nutno změnit na &lt;code&gt;None&lt;/code&gt;, protože robot v té chvíli není na hrací ploše.&lt;/p&gt;
&lt;p&gt;Kód ve funkcích &lt;code&gt;def get_starting_coordinates(board)&lt;/code&gt; a &lt;code&gt;def get_robot_paths()&lt;/code&gt; obsahuje načítání obrázků, což má být ve frontendu, takže vyřešit pojmenováním robotů a políček. Bylo by hezké mít soubor (json) s informacemi o robotech, kteří jsou na začátku hry na výběr a jména robotů načítat z něj. &lt;code&gt;get_robot_paths()&lt;/code&gt; se změní na &lt;code&gt;get_robot_names()&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Třída Tile&lt;/h3&gt;
&lt;p&gt;Třída &lt;code&gt;Tile&lt;/code&gt; a všechny její podtřídy je velice obsáhlá a je v souboru &lt;code&gt;util.py&lt;/code&gt;. Bylo by více než vhodné vytvořit samostatný soubor &lt;code&gt;tile.py&lt;/code&gt;. 
Políčka (&lt;code&gt;Tile&lt;/code&gt;) by měla jako &lt;code&gt;properties&lt;/code&gt; dostat slovník jako např. &lt;code&gt;{'crossroads': True, 'direction': 90, 'count': 2}&lt;/code&gt; a neměla by ignorovat jména vlastností.&lt;/p&gt;
&lt;h3&gt;FRONTEND.PY&lt;/h3&gt;
&lt;p&gt;Ve frontendu jsme stále nevyřešily načítání obrázků mimo funkci &lt;code&gt;def create_sprites&lt;/code&gt;. Cyklus pro načítání obrázků dát na začátek kódu a v této funkci už na ně budeme odkazovat např. jménem (&lt;code&gt;tile_image&lt;/code&gt;, &lt;code&gt;robot_image&lt;/code&gt;). Nejtěžší bude vymyslet logiku s vracením jména.&lt;/p&gt;
&lt;h3&gt;INTERFACE.PY&lt;/h3&gt;
&lt;p&gt;Ve funkci &lt;code&gt;def switch_power_down&lt;/code&gt; by se mohl následující kód zjednodušit.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;indicator&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;power_down&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;power_down&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;power_down&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Lze nahradit:
&lt;code&gt;self.power_down = not self.power_down&lt;/code&gt;
Co dělá &lt;code&gt;not&lt;/code&gt;? Když je hodnota &lt;code&gt;True&lt;/code&gt;, vrátí &lt;code&gt;False&lt;/code&gt; a obráceně.&lt;/p&gt;
&lt;p&gt;Jak uvažuje programátor? :-) Když separujem backend a frontend, je dobré se zamyslet, jak by se mohl frontend napsat zcela jinak, například zcela jednoduše jen v příkazové řádce. &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="alternativni_frontend" src="./images/afrontend.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Nejčastější chybou v celém kódu je pojmenování proměnných, jejichž název nesouhlasí přesně s tím, co dělá kód, nebo se liší od komentářů apod.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tile_count&lt;/code&gt; se mezi &lt;code&gt;get_start_state&lt;/code&gt; a &lt;code&gt;State.__init__&lt;/code&gt; přejmenuje na &lt;code&gt;sizes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;State.game_round&lt;/code&gt; se podle pravidel řekne &lt;code&gt;register&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;v kódu je &lt;code&gt;next_coordinates&lt;/code&gt;, v komentáři "new coordinates“&lt;/li&gt;
&lt;li&gt;&lt;code&gt;def_walk&lt;/code&gt; - proměnná &lt;code&gt;robot_in_the_way = None&lt;/code&gt; – je to číslo robota, ne robot&lt;/li&gt;
&lt;li&gt;v &lt;code&gt;util.py&lt;/code&gt;- funkce se jmenuje &lt;code&gt;select_tile&lt;/code&gt;, ovšem ona ho vybere a zároveň vytvoří&lt;/li&gt;
&lt;li&gt;&lt;code&gt;def init_window&lt;/code&gt; by se měla přejmenovat na &lt;code&gt;create_window&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;def draw_board(state, window)&lt;/code&gt; vykreslí stav, přejmenovat :-)&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Patnáctý sraz</title><link href="https://roboprojekt.pyladies.cz/patnacty-sraz" rel="alternate"></link><published>2019-01-22T18:00:00+01:00</published><updated>2019-01-23T09:58:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2019-01-22:/patnacty-sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Tentokrát v kompletní sestavě. Na začátku jsme se shodly, že pro lepší porozumění tomu, kam se ve vývoji ubíráme, by stálo za to sepsat, jak má vlastně probíhat herní kolo, jaké kroky na sebe mají navazovat a co bude výsledkem. Ne konkrétně, jaké procesy se dějí na pozadí, skutečně jen …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Tentokrát v kompletní sestavě. Na začátku jsme se shodly, že pro lepší porozumění tomu, kam se ve vývoji ubíráme, by stálo za to sepsat, jak má vlastně probíhat herní kolo, jaké kroky na sebe mají navazovat a co bude výsledkem. Ne konkrétně, jaké procesy se dějí na pozadí, skutečně jen jednotlivé fáze herního kola tak, jak by měly jít po sobě. Přestože jsme hru hrály a každá z nás měla představu, jak by hra měla probíhat, i toto jednoduché cvičení nám ukázalo, že některé věci nejsou napsané tak, jak by měly.&lt;/p&gt;
&lt;p&gt;Řešily jsme také, že jednotlivé fáze hry, kdy roboti něco dělají, se ve hře jako takové musí dělat pomaleji, aby byly zaznamenatelné pohledem na herní plochu, případně aby hru provázel i textový zápis, co se děje. Ten by měl být součástí interaktivního rozhraní a měl by se objevit místo karet, ze kterých se vybírá program do jednotlivých registrů.&lt;/p&gt;
&lt;p&gt;Dohodly jsme se, jak budeme postupovat, pokud robot ve hře ztratí všechny 3 životy. Vzhledem k tomu, že se to může ve hře stát poměrně rychle, přišlo nám škoda, aby daný hráč už nemohl hrát. Robot se tedy nevyřadí ze hry, ale pokaždé, když by měl ztratit další život, dostane permanentně jedno zranění, které nelze vyléčit.&lt;/p&gt;
&lt;p&gt;Po úvodním ujasňování průběhu hry jsme se dostaly ke kódu. Karolina upozornila na některé řádky, které se v kódu několikrát (v některém případě hodněkrát) opakují. Zbavit se jich můžeme tím, že z nich uděláme funkce a pomocí zkratek, které nás Petr naučil v předchozích lekcích, můžeme i dané funkce znatelně zjednodušit. Například funkce&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_active_robots&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;active_robots&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;robot&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;robots&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;robot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_alive&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;active_robots&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;robot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;active_robots&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;může vypadat i takhle:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_active_robots&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;robot&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;robot&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;robots&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;robot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_alive&lt;/span&gt;&lt;span class="p"&gt;()]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Co kam a odkud?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Kód naší hry je poměrně komplexní, jednotlivé části jsou spolu úzce provázané a občas není úplně jasné, kam by který kus kódu měl patřit a kde by se na něj mělo odkazovat, aby to zbytečně nekomplikovalo další vývoj. Například některá z metod políčka používá na provedení svého efektu metodu robota, která něco s robotem udělá, nevyužívá na to přímo některou z metod políčka. Dostaly jsme ohledně tohoto problému dvě rady. První je jednoduchá - říct si nahlas, jak se metoda jmenuje a co dělá. Na příkladu zabití robota - políčko umí sice robota zabít (&lt;code&gt;kill_robot()&lt;/code&gt;), ale potřebuje si na to zavolat metodu robota, který sám ví, jak umřít (&lt;code&gt;robot.die()&lt;/code&gt;). Políčko neví, jakým způsobem robot umí umřít, jde o implementační detail, který by měl být definován na jednom místě. Druhá rada říká, abychom psaly metody v kódu tak, aby bylo vždy co nejjednodušší přidat další prvek dané třídy. Ideální je zachovat funkčnost třídy na jednom místě. Tedy například všechna funkcionalita políček by měla být nadefinována v třídě políčka, aby se jednoduše dal přidat další typ. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dekorátor property&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Python na rozdíl od jiných jazyků umí pracovat s atributy tak, aby se daly vypočítat. O to se stará dekorátor &lt;code&gt;property&lt;/code&gt;. Atribut pak můžeme napsat jako metodu a dáme-li jí tento dekorátor, Python ji bude brát jako atribut. Nemusíme ji volat, přistoupíme k ní jako k atributu a provede se akce definovaná metodou. Tento atribut je ale pouze ke čtení. Chceme-li ho změnit nebo nastavit, musíme použít setter, ve kterém metodu nadefinujeme znova. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Robot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
        &lt;span class="n"&gt;Self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;position&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;Return&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;

    &lt;span class="nd"&gt;@position.setter&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;position&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Co ještě umí hvězdička?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Na &lt;a href="https://roboprojekt.pyladies.cz/jedenacty-sraz"&gt;jedenáctém srazu&lt;/a&gt; jsme se naučily, že v pokud na určité místo v pythonním kódu dám hvězdičku, dějí se věci. Zatím víme, že hvězdička umí označit nějakou sekvenci kódu a určit tím, že se budou používat jednotlivé prvky dané skevence. 
Hvězdička ale umí i jinou magii. Pokud ji použijeme v definici funkce, umí si vynutit pojmenovaný argument. 
Na příkladu níže to tak znamená, že pokud se přidá do metody &lt;code&gt;walk&lt;/code&gt; jakýkoliv další argument za hvězdičku, vždy musí být zavolán pojmenovaný.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="hvezdicka" src="./images/hvezdicka.png" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;K čemu je to dobré? Když budeme danou funkci volat, bude už přímo ze zápisu volání funkce jasné, co daný argument znamená, není potřeba dívat se do kódu a hledat dokumentační řetězec pro danou funkci. Hodí se to pro případ, kdy má funkce řadu různých argumentů - usnadňuje to pak další práci s nimi a nevznikají zbytečné nejasnosti a chyby.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Jak dělat věci lépe&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;V závěrečné debatě o změnách v kódu jsme se bavily o některých "best practices" při vývoji v týmu - například pokud přejmenováváme nějaké funkce nebo proměnné, se kterými mohou pracovat i ostatní, je dobré o tom dát vědět. Stejně tak, když začleňujeme změny, které nejsou ideální. V tom případě je dobré rovnou vytvořit Issue, které zmiňuje, co není v pořádku a co je třeba opravit. 
Aby byl kód hezky čitelný a přehledný, je dobré dodržovat určité dané &lt;a href="https://www.python.org/dev/peps/pep-0008/"&gt;konvence&lt;/a&gt;. Kód jde naformátovat všelijak, Python se s tím popere, ale proto, aby se dalo s kódem dobře pracovat a jednoduše se v něm vyznat, jsou určité konvence velmi užitečné (například určité odsazování, mezery kolem operátorů apod.)&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Čtrnáctý sraz – opakování a vysvětlování</title><link href="https://roboprojekt.pyladies.cz/ctrnacty-sraz-vysvetlovani" rel="alternate"></link><published>2019-01-15T08:39:00+01:00</published><updated>2019-01-15T08:39:00+01:00</updated><author><name>Iveta Česalová</name></author><id>tag:roboprojekt.pyladies.cz,2019-01-15:/ctrnacty-sraz-vysvetlovani</id><summary type="html">&lt;div&gt;&lt;p&gt;Tento týden jsme se sešly v komorním počtu, navíc bez Petra. Ale cíl srazu byl jasný – abychom všechny rozuměly stávajícímu kódu.
Začaly jsme souborem &lt;em&gt;util.py&lt;/em&gt; a procházely metodu po metodě jednotlivých tříd. Vášnivá diskuze nastala u třídy HoleTile, která volá metodu robota – &lt;code&gt;robot.die()&lt;/code&gt;. Původně bylo v kódu napsáno …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Tento týden jsme se sešly v komorním počtu, navíc bez Petra. Ale cíl srazu byl jasný – abychom všechny rozuměly stávajícímu kódu.
Začaly jsme souborem &lt;em&gt;util.py&lt;/em&gt; a procházely metodu po metodě jednotlivých tříd. Vášnivá diskuze nastala u třídy HoleTile, která volá metodu robota – &lt;code&gt;robot.die()&lt;/code&gt;. Původně bylo v kódu napsáno, že si robot volal metodu díry, což Petrovi přišlo zvláštní :-) Nyní tedy metoda políčka vyvolá metodu robota, což je logičtější, než aby si robot vyvolal metodu políčka :-D&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HoleTile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Tile&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;kill_robot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;robot&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Call robot's method for dying&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;robot&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;die&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Byla to dlouhá hodina, ale smysluplná. Potom jsme se přesunuly k souboru &lt;em&gt;backend.py&lt;/em&gt; a následovalo další vysvětlování, což souviselo s opětovným probíráním pravidel hry.
Pokud robot umře, přiřadí se mu souřadnice [-1, -1], aby byl tedy mimo hrací plochu. Narazily jsme ovšem na problém, že když robot ožije, nemůžou se zobrazit dva roboti na sobě, pokud na jeho startovním políčku stojí jiný robot. Bude nutno se zamyslet, jak to vyřešit, jestli zobrazením dalšího okýnka, které se hráče zeptá, kam chce robota umístit, nebo náhodné rozmístění na volné startovní políčko…&lt;/p&gt;
&lt;p&gt;Dalším tématem bylo Rozhraní, aneb pull request s několika stovkami řádků. Pro přehlednost jsme narazily na jednu vychytávku, pokud se na githubu mění velké množství souborů, stačí zmáčknout &lt;code&gt;alt&lt;/code&gt; a kliknout na šipku a všechno se sroluje a snáze najdeme soubor, který potřebujeme.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/github.jpg" target="_blank" title="github"&gt;&lt;img alt="github" src="https://roboprojekt.pyladies.cz/images/thumbnails/github.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Prošly jsme kód a ukázaly jsme si, co všechno funguje, jak už obrazovka reaguje na různé klávesy atd. Trochu jsme se pozastavily nad balíčkem karet. Budeme pokaždé rozdávat z nového, stejného balíčku karet, který se zamíchá a nebudou se tam vracet rozdané, které si hráč nevybere.&lt;/p&gt;
&lt;p&gt;Příště se sejdeme již v plném počtu a určitě nás Petr nakopne správným směrem, jak dále pokračovat :-)&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Dvanáctý sraz - matice</title><link href="https://roboprojekt.pyladies.cz/dvanacty-sraz-matice" rel="alternate"></link><published>2018-12-18T18:00:00+01:00</published><updated>2018-12-18T18:00:00+01:00</updated><author><name>Iveta Česalová</name></author><id>tag:roboprojekt.pyladies.cz,2018-12-18:/dvanacty-sraz-matice</id><summary type="html">&lt;div&gt;&lt;p&gt;Po počátečním zmatku, kdy si Petr zapomněl svůj počítač, jsme poslední sraz roku zahájily opět rekapitulací, co kdo dělal. Doposud byla hra rozdělena na čtyři moduly – backend, frontend, game a testy. Nyní je v backendu pouze třída Robot, State a funkce pro načtení souřadnic, cesty k robotům, počtu políček a …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Po počátečním zmatku, kdy si Petr zapomněl svůj počítač, jsme poslední sraz roku zahájily opět rekapitulací, co kdo dělal. Doposud byla hra rozdělena na čtyři moduly – backend, frontend, game a testy. Nyní je v backendu pouze třída Robot, State a funkce pro načtení souřadnic, cesty k robotům, počtu políček a počáteční stav hry.&lt;/p&gt;
&lt;p&gt;V repozitáři přibylo několik souborů. Loading.py obsahuje funkce, které kompletně načtou mapu se všemi potřebnými komponenty a vlastnostmi a soubor Util.py zase třídy Tile a Direction. Soubor Validator.py kontroluje, zda je mapa správně vytvořena.&lt;/p&gt;
&lt;h4&gt;Kouzelné podtržítko&lt;/h4&gt;
&lt;p&gt;Pokud chceme, aby někdo ve zbytku kódu nepoužíval konkrétní proměnnou (slovník, seznam...), dáme před ni podtržítko, jako např u &lt;code&gt;_board&lt;/code&gt;. Značí věci, které jsou pro nějakou třídu interní a ten, kdo nemá dobrý důvod pracovat s vnitřnostmi určité třídy, měl by použít něco jiného. Podtržítkem říkám – vyhrazuji si právo cokoli změnit.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;State&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;robots&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sizes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_board&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;board&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;robots&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;robots&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sizes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sizes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;h4&gt;Nekombinovat více knihoven&lt;/h4&gt;
&lt;p&gt;Není dobré v kódu kombinovat více knihoven, když lze použít jen jednu :-) Konkrétně v souboru export_img.py, který nám automaticky převádí soubory SVG do PNG formátu jsou použity knihovny &lt;em&gt;os&lt;/em&gt; a &lt;em&gt;subprocess&lt;/em&gt;, tvorba adresáře příkazem &lt;code&gt;os.mkdir()&lt;/code&gt; lze nahradit &lt;code&gt;Path.mkdir()&lt;/code&gt; a není potřeba importovat os.&lt;/p&gt;
&lt;h4&gt;Matice&lt;/h4&gt;
&lt;p&gt;Velkým tématem srazu byly &lt;strong&gt;MATICE&lt;/strong&gt;. Řešíme totiž problém ohledně změny velikosti obrazovky a aby se mapa správně měnila. Matice je schéma čísel či matematických objektů, používají se na transformaci grafiky.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Druhy transformace&lt;/strong&gt;: posun, zvětšení, rotace, zkosení, zrcadlení.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Maticové násobení&lt;/em&gt; – transformace se zkombinují.&lt;/p&gt;
&lt;p&gt;Máme obrázek o souřadnicích x, y a vynásobím je maticí, která reprezentuje posun či jinou transformaci. „z“ bude vždy 1.
Petr nám to vysvětloval na dvou čtvercích, skládajících se z koleček. Bílá kolečka jsou původní, modrá transformované pomocí matice. Matici můžu v kódu jednoduše měnit.
Jednoduchý návod k nalezení &lt;a href="https://en.wikipedia.org/wiki/Transformation_matrix#/media/File:2D_affine_transformation_matrix.svg"&gt;zde&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Původní matice a výpis bílých koleček:&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/bile.jpg" target="_blank" title="bile"&gt;&lt;img alt="bile" src="./images/bile.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Transformace&lt;/strong&gt;&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/transformace.jpg" target="_blank" title="transformace"&gt;&lt;img alt="transformace" src="./images/transformace.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;h4&gt;Pyglet a knihovna OpenGL, aneb jak nastavit transformační matici pro celou scénu.&lt;/h4&gt;
&lt;p&gt;Pomocí funkce &lt;code&gt;pyglet.gl.glPushMatrix()&lt;/code&gt; řeknu – zapamatuj si počáteční stav. Naopak na konci &lt;code&gt;pyglet.gl.glPopMatrix()&lt;/code&gt; vrátí do původního stavu. Mezitím můžu upravovat transformační matici dle potřeby.&lt;/p&gt;
&lt;p&gt;Mezi základnější funkce patří:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pyglet.gl.glTranslatef()&lt;/code&gt; – posun&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pyglet.gl.glRotate()&lt;/code&gt; – rotace&lt;/p&gt;
&lt;p&gt;&lt;code&gt;pyglet.gl.glScale()&lt;/code&gt; - změna měřítka&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/gl.jpg" target="_blank" title="gl"&gt;&lt;img alt="gl" src="./images/gl.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;A jak vyřešit potřebnou změnu velikosti obrazovky? Pomocí &lt;code&gt;pyglet.gl.glScalef()&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@window.event&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_draw&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;pyglet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glPushMatrix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;zoom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;pyglet&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;glScalef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;zoom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;
            &lt;span class="n"&gt;sprite&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;draw&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;figure class="figure"&gt;&lt;img alt="zoom" src="./images/zoom.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Na začátku kurzu jsme plánovaly jeho trvání do konce prosince, ovšem bylo to přehnaně optimistické. V dalším roce nás bude o něco méně a pravděpodobně se nebudeme scházet každý týden, takže nečekejte pravidelný blog :-)&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Jedenáctý sraz - MVC a spousta práce</title><link href="https://roboprojekt.pyladies.cz/jedenacty-sraz" rel="alternate"></link><published>2018-12-11T18:00:00+01:00</published><updated>2018-12-11T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2018-12-11:/jedenacty-sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Vzhledem k tomu, že aktuální stav projektu sám generuje další a další úkoly a problémy k řešení, stejně jako schůzka minulá, i toto setkání se na začátku neslo v duchu řešení toho, na co jsme narazily při práci v uplynulém týdnu.&lt;/p&gt;
&lt;p&gt;Úspěchem od minulé lekce je, že se roboti zastavují …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Vzhledem k tomu, že aktuální stav projektu sám generuje další a další úkoly a problémy k řešení, stejně jako schůzka minulá, i toto setkání se na začátku neslo v duchu řešení toho, na co jsme narazily při práci v uplynulém týdnu.&lt;/p&gt;
&lt;p&gt;Úspěchem od minulé lekce je, že se roboti zastavují o zdi, pracujeme na rozdělení backendu na více modulů, snažíme se o aktualizaci glosáře pojmů, který nám bude užitečný při práci s kódem, pojmenovávání funkcí a tvorbě dokumentačních řetězců, aby názvosloví bylo jednotné, a přibyl také validátor map. &lt;/p&gt;
&lt;p&gt;Protože bychom měly rády v projektu většinu věcí automatizovanou, jedním z úkolů byl i automatický převod obrázků z vektorového SVG do PNG. Objevil se ale problém se spouštěním Inkscape z příkazové řádky. V Linuxu to funguje jednoduše - když člověk napíše do terminálu Inkscape, program se spustí. To bohužel není přenositelné do Windows. Nezbývá tedy, než vypsat všechny možné cesty, které může Win použít, aby kód fungoval i s tímto OS. 
Také bychom chtěly, aby se pak vygenerované soubory PNG ukládaly do jiného adresáře, je tedy třeba ve funkci pro převod nejen nastavit novou příponu souboru, ale i novou složku.
Užitečným pomocníkem zde je knihovna &lt;a href="https://docs.python.org/3/library/pathlib.html"&gt;pathlib&lt;/a&gt;, která umí například jednoduše měnit příponu, rozkouskovat cestu, zaměnit její části a tím pádem vytvořit cestu novou. Umí také vytvořit adresáře dané cesty a &lt;a href="https://github.com/pyvec/cheatsheets/blob/master/pathlib/pathlib-cs.pdf"&gt;další šikovné věci&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hvězdičková magie&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Při vytváření funkce na automatické generování souborů PNG jsme narazily na to, že potřebujeme jako argument funkce použít postupně všechny prvky seznamu, o kterém nevíme, kolik těch prvků celkově má. Pro tento případ lze použít hvězdičku. Hvězdička pak jednotlivé prvky seznamu naskládá jako argumenty dané funkce. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;

&lt;span class="n"&gt;arguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Hvězdička lze využít například i při tvorbě seznamu, princip je stejný, postupně použije jednotlivé prvky. Tedy &lt;code&gt;print([1, *arguments, 8, 9])&lt;/code&gt; vypíše &lt;code&gt;[1, 2, 3, 4, 5, 6, 7, 8]&lt;/code&gt;, zatímco bez hvězdičky by se vložil celý seznam arguments jako prvek nového seznamu, tedy &lt;code&gt;[1, [2, 3, 4, 5, 6, 7], 8]&lt;/code&gt;.
Hvězdička takto funguje na vše, co se dá rozložit na jednotlivé prvky, tedy i na řetězce. Hvězdička tedy označuje nějakou sekvenci a používá jednotlivé prvky dané sekvence. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stav hry&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;V současné chvíli je kód napsaný tak, že vytváří stav hry, který obsahuje herní plán (rozmístění jednotlivých políček), jeho velikost a také všechny roboty. Myšlenka je taková, že se při jakékoliv změně vytvoří nový stav hry. Tento přístup jsme zvolily na jednom z prvních setkání. V současnou chvíli ale stav hry vrací pouze funkce pro vytvoření stavu počátečního, vše ostatní s ním jen dále pracuje a upravuje ho, ale nevrací stav nový. Do budoucna bude třeba tuto problematiku řešit, až budeme chtít posílat stav hry na jiný počítač pro variantu multiplayeru, v současné fázi vývoje to však ještě není třeba. Je to ale něco, na co dříve či později narazíme.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rozhraní pro ovládání hry&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Na minulém srazu jsme se dohodly, že rozhraní pro ovládání hry bude vykresleno v samostatném okně. Do tohoto úkolu se pustila Terka. Pro ovládání hry zvolila klávesy. To ovšem generuje problém, jak sdělit programu, která klávesa je zmáčknutá. Existují dvě varianty. Lze vuyžít nadefinování uživatelem, kdy by si hráč sám určil, které klávesy chce pro ovládání používat, nebo varianty, kdy systém říká, jaký uživatel zadal text, nikoliv jakou zmáčkl klávesu. Tento přístup však neumožňuje pracovat s tím, když uživatel klávesu pustí, zpracovává jen vstup v podobě řetězce, který by se objevil v textovém editoru.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Jak navrhovat rozhraní&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Při návrhu uživatelského rozhraní se osvědčil tzv. MVC návrhový vzor, zkratka pro &lt;strong&gt;“Model - View - Controller”&lt;/strong&gt;.
Model v našem případě reprezentuje data. Jaké karty má hráč, kolik má který robot životů, kolik už nasbíral vlajek apod. Toto rozhraní pak dokážu vykreslit, což bude naše View. Operace “Vykreslit” vezme model a vykreslí ho do okénka. 
Když uživatel udělá nějakou změnu, udělá se na modelu a vykreslí se nový stav. Většinou se volí přístup, kdy vykreslování a reakce na události jsou od sebe oddělené, jsou to dvě různé funkce nebo i různé moduly. Reakce na události by tedy byl náš Controller, pokud bychom se držely MVC terminologie. 
Změny ve hře mohou pocházet i odjinud než z controlleru a view může zobrazovat různé věci. Obrázek níže tak ukazuje aplikaci MVC na náš současný kód, kdy View zobrazuje dvě různé věci, ovládání hry a herní plochu. Navíc máme stranou načítání, které umí vytvořit část modelu, konkrétně herní plán bez robotů. Ty potom dodá backend.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/mvc.jpg" target="_blank" title="MVC"&gt;&lt;img alt="MVC" src="https://roboprojekt.pyladies.cz/images/thumbnails/mvc.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;V současnou chvíli také pracujeme pouze s jedním stavem, který měníme, což bylo zmíněno výše. Ve chvíli, kdy budeme pracovat s tím, že se model bude synchronizovat mezi více počítači. Pak bude třeba, aby každá změna, která upravuje stav, zavolala funkci, která řekne, že se stav změnil a pošle novou verzi stavu. Je dobré mít změny oddělené a co nejmenší. 
Změny modelu lze řešit několika způsoby: úprava atributu/proměnné (jak to děláme teď), notifikace o změně, metoda modelu (nezáleží na tom, jak jsou data v modelu reprezentována, pracujeme pouze s tím, co se má stát) nebo vytvoření objektu, který reprezentuje změnu, což je dobré, pokud změna ovlivňuje více věcí, než model. Toto jsou věci, které budeme v budoucnu potřebovat nějak vyřešit. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Políčka&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Často se vracíme k problematice zdí a narazily jsme na ni i na této lekci. Tentokrát se jednalo o vzhled mapy. Zeď se nyní dá na políčko dát kamkoliv a v některém případě, kde na sebe zdi navazují, to může generovat nehezké vyobrazení (viz obrázek). &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="zdi" src="./images/zed.png" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Petr přišel s návrhem, kdy by nejen u zdi, ale i u laseru pomohlo, kdyby v budoucnu bylo odděleno to, jak mapa vypadá v editoru a jak bude poté vypadat ve hře. Například u laserů, kde hraje zásadní roli, kterým směrem laser střílí, by v editoru mohly být šipky, aby bylo vidět, že je laser správně otočený. Ve hře už by to viditelné nebylo. Stejně tak by to mohlo fungovat u zdí. Při tvorbě mapy by bylo jasné, součástí kterého je políčka, ale nerovnosti jako na obrázku výše už by nebyly vyobrazené v samotné hře. Například lze udělat obrázek posunutý o několik pixelů, takže bude vypadat, jako by zeď byla skutečně na hranici mezi dvěma políčky. Opět něco, co nás čeká v budoucnu. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dědičnost&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Jako jeden z dalších úkolů je rozpracovat efekty políček. Pro naši hru bude dobré zopakovat si dědičnost mezi třídami a vytvořit jednotlivá políčka jako podtřídy naší třídy &lt;code&gt;Tile&lt;/code&gt;, ze které budou dědit. Třída Tile tak bude obsahovat všechny metody, které mohou v jejích podtřídách nastat, ale bez vracení konkrétního efektu. Konkrétně pak metoda bude rozepsána až v dané podtřídě. Bohužel jsme dědičnost proletěly jen z rychlíku, tak bude tento úkol do příště poměrně náročný :) &lt;/p&gt;
&lt;p&gt;Spolu s ním nás čeká ještě dokončit rozdělení kódu na moduly, další práce s roboty a také s rozhraním hry. Potřebujeme dále zařídit, aby se dala měnit velikost vykreslených oken a zároveň se tomu přizpůsoboval jejich obsah. Stále máme i několik dlouhodobých úkolů, práce tedy není málo :) &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Desátý sraz - testy a bity</title><link href="https://roboprojekt.pyladies.cz/desaty-sraz-testy-a-bity" rel="alternate"></link><published>2018-12-05T10:17:00+01:00</published><updated>2018-12-05T10:17:00+01:00</updated><author><name>Karolina Surma</name></author><id>tag:roboprojekt.pyladies.cz,2018-12-05:/desaty-sraz-testy-a-bity</id><summary type="html">&lt;div&gt;&lt;h1&gt;Úvod&lt;/h1&gt;
&lt;p&gt;Po období zvýšené projektové aktivity jsme se trochu nechaly ovlivnit počasím a přestaly sypat pull requesty jeden za druhým. Další sraz proto Terka začala krátkým zjišťovacím kolečkem, když jsme řekly, na čem jsme pracovaly a co nám momentálně dělá problém. Projekt se nám poslední dobou hodně rozrostl a všechny …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;h1&gt;Úvod&lt;/h1&gt;
&lt;p&gt;Po období zvýšené projektové aktivity jsme se trochu nechaly ovlivnit počasím a přestaly sypat pull requesty jeden za druhým. Další sraz proto Terka začala krátkým zjišťovacím kolečkem, když jsme řekly, na čem jsme pracovaly a co nám momentálně dělá problém. Projekt se nám poslední dobou hodně rozrostl a všechny se potýkáme s tím, že i když tušíme, jak napsat novou vlastnost, vplést ji do stávajícího kódu je o dost těžší, než bylo na začátku. 
Daly jsme se na rekapitulaci otevřených pull requestů na témata:
- přidat načítání map jiné velikosti, než 12x12,
- přidat třídu Rotace (přejmenovaná na Směr - Direction) - podrobně popsaná &lt;a href="https://roboprojekt.pyladies.cz/par-slov-o-datovem-typu-enum"&gt;zde&lt;/a&gt;,
- napsat testy k jednotlivým funkcím v modulu backend,&lt;/p&gt;
&lt;p&gt;kde jsme dospěly k závěru, že cítíme blok k recenzování kódu kolegyň, když jsou změny složitější a nedokážeme vyhodnotit, zda použité metody jsou skutečně na správném místě. Zjistit, že program pořád funguje, není těžké. Vyhodnotit, zda změny dávají smysl v kontextu celého projektu - je. &lt;/p&gt;
&lt;h1&gt;K čemu vlastně potřebujeme testy?&lt;/h1&gt;
&lt;p&gt;Při procházení otevřených PR jsme se chvíli zdržely u tématu testování. Nejdřív jsme dostaly za úkol dopsat testy do každé funkce modulu backend, ale když už byly napsané, Petr poznamenal: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Nestudoval jsem to detailně (to je na vás), ale všiml jsem si, že se tu přidává spousta chybějících testů, ale nemění se kód. To mi přijde trošku podezřelé.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Nám zřejmě ne ;). Na srazu jsme si proto společně dali krátký pokec, jak vypadá smysluplné testování. 
Například při tvoření nových metod většinou shora víme, čeho chceme dosáhnout:
- pokud otočím robotem, bude směřovat na správnou světovou stranu, 
- pokud vykreslím konkrétní mapu, na koordinátách (5, 5) bude skutečně v první vrstvě políčko &lt;em&gt;ground&lt;/em&gt;,
- pokud postavím roboty na start, budou skutečně přiřazení na startovací políčka. &lt;/p&gt;
&lt;p&gt;To znamená, že společně s vývojem vznikají dobré testovací scénáře, které stojí za to rovnou dopsat do testovacího balíku. Je dobré psát testy, i když náš kód ještě nefunguje, ale již víme, jak chceme, aby se používal. Tím si při dalších krocích vývoje zlehčíme práci: testy v určitou chvíli zezelenají, díky čemuž víme, že jsme dosáhly naplánované funkčnosti a můžeme se vrhnout na integraci nového a starého kódu.&lt;/p&gt;
&lt;p&gt;Člověk, jenž v danou chvíli přemýšlí o testech ke kódu, který byl už napsán někým jiným, může objevit nelogičnosti a najít lepší způsoby uspořádání dat. V tuto chvíli jeho úkol je tyto změny zanést i do testovaného kódu. &lt;/p&gt;
&lt;p&gt;Čeká nás tedy revize stávajících testů a případné úpravy. &lt;/p&gt;
&lt;h1&gt;Rychlý kuk na glosář pojmů&lt;/h1&gt;
&lt;p&gt;Kromě projektu na GitHubu si zvlášť udržujeme glosář pojmů s cílem sjednocení názvosloví a významu v kódu. Měl by reflektovat třídní diagram nakreslený v začátcích (česky) a stávající stav našich modulů (anglicky). Zároveň by měl poskytovat co nejpřesnější popis, co daný pojem v našem projektu znamená.
Jako příklad nám Petr uvedl pojem &lt;em&gt;tile&lt;/em&gt;, jehož definice nebyla ideální. Původně jsme měly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;tile&lt;/em&gt; - třída definující dlaždici pomocí otočení dlaždice (‘rotation’) a cestou k souboru s obrázkem dlaždice (‘path’)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Po přepracování zní: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;tile&lt;/em&gt; je konkrétní efekt políčka (např laser nebo pohyblivý pás) s konkrétním směrem otočení. Na jednom políčku mapy může být víc těchto efektů políčka. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Další úkol je zapracovat na glosáři, aby definice co nejlépe odpovídaly pravdě. &lt;/p&gt;
&lt;h1&gt;Různé způsoby zápisu čísel&lt;/h1&gt;
&lt;p&gt;Téma poslední části srazu bylo mnou objednáno již před nějakou dobou. Do kódu jsme si přidaly po třetím srazu "magické formulky": &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2684354562&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;'0xa0000002'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFFFFFFF&lt;/span&gt; &lt;span class="c1"&gt;# kouzelná formulka pro zjištění ID dlaždice&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# kouzelná formulka pro zjištění otočení&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Při pokusu o napsání testu na tuto část jsem zjistila, že když formulce nerozumím, nedokážu ani jednou větou popsat, co se v ní odehrává.
Petr nám proto zařádil malé vyprávění o bitových operacích a číselných soustavách.&lt;/p&gt;
&lt;p&gt;Začalo to číslem &lt;em&gt;tři&lt;/em&gt;. Číslo je &lt;em&gt;něco&lt;/em&gt;, co můžeme &lt;em&gt;nějak&lt;/em&gt; zapsat. Konkrétně trojku můžeme ukázat na prstech, napsat tři čárky, nebo použít arabskou číslici: 3. V každém z těchto případů se bavíme o stejné myšlenkové reprezentaci počtu. 
V běžném životě používáme desítkovou soustavu, což znamená, že pokud před číslo 0 dáme na začátek 1, navýšily jsme ho o deset. Pokud přidáme další 1 před 10, navýšily jsme ho o deset desítek (sto), atd. Každé další číslo je další mocnina desítky. &lt;/p&gt;
&lt;p&gt;Počítače zase používají dvojkovou, neboli binární soustavu. Počítač zná dva stavy: buď něco (např. magnet, světlo, napětí) je, nebo není. K tomu mu stačí jen dva symboly: 0 a 1. Každé nové číslo postavené na začátek je další mocnina dvojky.&lt;/p&gt;
&lt;p&gt;Python umí pracovat s čísly zapsanými různými způsoby. Např. binární soustavu pozná podle &lt;code&gt;0b&lt;/code&gt; na začátku výrazu. Pořád se ale jedná o stejnou hodnotu, porovnání stejných čísel ve dvojkové a desítkové soustavě je tedy vždy pravda.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mb"&gt;0b010110&lt;/span&gt; 
&lt;span class="mi"&gt;22&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; 
&lt;span class="mi"&gt;22&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mb"&gt;0b010110&lt;/span&gt;
&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;'0b010110'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Počítače ukládají informace na určitých místech v paměti. Známe pojmy bit a bajt, kde bit je jeden takový znak (0 nebo 1), bajt - 8 znaků. V jednom bajtu, na osmi místech, můžeme zakódovat až 256 čísel (2&lt;sup&gt;8&lt;/sup&gt;). &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mb"&gt;0b11111111&lt;/span&gt;     &lt;span class="c1"&gt;# maximální možná hodnota&lt;/span&gt;
&lt;span class="mi"&gt;255&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Spousta věcí se dá zakódovat do 256 znaků. Podívejme se na znaky anglické abecedy, tzv. kódování ASCII: 6 bitů potřebuje na malou abecedu plus nějaké znaky kolem (čísla, závorky atd.), 1 bit pro zjištění, jestli písmenko je malé, nebo velké. 7 bitů stačí pro zapsání v podstatě celé standardní klávesnice, jak ji známe.&lt;/p&gt;
&lt;p&gt;Už 4 bajty jsou dostačující třeba na to, aby reprezentovaly barvu: červenou (R), zelenou (G) a modrou (B). Každá složka je osmibitové číslo (tedy 0 až 255), které tak nějak odpovídá tomu, kolik barev je schopné rozeznat lidské oko. Čtvrtý bajt se aktuálně nejvíc používá pro označení průhlednosti. 
32 bitů je ale spousta jedniček a nul. Zde nám přichází vhod jiná soustava, postavená na šestnáctkách (2&lt;sup&gt;4&lt;/sup&gt;). Jeden znak obsahuje stejnou informaci, jako 4 bity, s čímž se dá dobře pracovat. &lt;/p&gt;
&lt;p&gt;Pokud symboly &lt;code&gt;10&lt;/code&gt; v hexadecimální soustavě znamenají &lt;code&gt;16&lt;/code&gt; v desítkové, jak vyjádřit číslo 15? Šestnáctková soustava používá čísla 0-9 a dál: A, B, C, D, E, F. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mh"&gt;0x10&lt;/span&gt;
&lt;span class="mi"&gt;16&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mh"&gt;0x10&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mh"&gt;0xF&lt;/span&gt;
&lt;span class="mi"&gt;15&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Kódy barev můžeme tedy buď uvádět v rozsahu 0-255 pro každou barevnou složku, nebo v hexadecimální soustavě, kde na dvou místech máme červenou, na dvou zelenou, na dvou modrou a na dvou posledních - průhlednost. &lt;/p&gt;
&lt;p&gt;A zde, u hexadecimální soustavy, se dostáváme k programu Tiled a způsobu, jakým zapisuje čísla. Používá totiž čtveřice bajtů na reprezentaci políčka ve vrstvě mapy: tři jsou číslo dlaždice, a jeden - rotace. &lt;/p&gt;
&lt;p&gt;Pokud si testovací dlaždici uložíme ve čtyřech různých směrech a podíváme na čísla, které nám uvede Tiled po exportu mapy do JSONu, budou vypadat pro lidské oko dost šíleně. Pokud je ovšem převedeme do hexadecimální soustavy, začnou dávat trochu smysl:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cisla&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2684354609&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3221225521&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16160612785&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cisla&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'0x31'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'0xa0000031'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'0xc0000031'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'0x60000031'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;code&gt;000031&lt;/code&gt; je číslo naši dlaždice, její ID (ony tři vyhrazené bajty).
&lt;code&gt;00&lt;/code&gt;, &lt;code&gt;a0&lt;/code&gt;, &lt;code&gt;c0&lt;/code&gt;, &lt;code&gt;60&lt;/code&gt; je bajt s otočením. Jednotlivé bity skrývající se pod tímto označením mají speciální význam: jeden bit je na otočení ve vertikální ose, druhý - horizontální, třetí - transpozice. &lt;/p&gt;
&lt;p&gt;Existují způsoby, jak vzít konkrétní bity z nějakého čísla, slouží k tomu bitový operátor &lt;code&gt;&amp;amp;&lt;/code&gt; (AND). Mezi oběma čísly nad každým bitem proběhne logické vyhodnocení pravda/nepravda, které se promítne do výsledku: 
- &lt;code&gt;1&lt;/code&gt; neboli &lt;em&gt;pravda&lt;/em&gt; je pouze tam, kde na obou místech porovnávaných čísel byla jednička.
- &lt;code&gt;0&lt;/code&gt; neboli &lt;em&gt;nepravda&lt;/em&gt; pro všechny ostatní případy. 
Jinými slovy, pokud v naší porovnávací operaci uvedeme na některé místo nulu, zaručíme si tím, že výsledek bude vyhodnocen jako nepravda.&lt;/p&gt;
&lt;p&gt;Pokud vím, že informace o rotaci dlaždice je na dvou prvních místech, můžu si nadefinovat takovou operaci, která mi vrátí pouze první číslice, zbytek ignoruje:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x12345678&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;'0x12000000'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Další věc, kterou s ním můžu udělat, je posunout si bity na některou stranu pomocí operátoru &lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt; nebo &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt;. Pokud mě skutečně zajímají jen dvě první číslice, odstraním zbytek tak, že posunu výraz o 3 krát 8 bitů:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mh"&gt;0x12345678&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xff000000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="mh"&gt;0x12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Byla to fascinující odbočka od Pythonu, ale musím říct, že mi magie teď nepřipadá ani o kousek méně magická :). &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Pár slov o datovém typu Enum</title><link href="https://roboprojekt.pyladies.cz/par-slov-o-datovem-typu-enum" rel="alternate"></link><published>2018-12-04T20:48:00+01:00</published><updated>2018-12-04T20:48:00+01:00</updated><author><name>Karolina Surma</name></author><id>tag:roboprojekt.pyladies.cz,2018-12-04:/par-slov-o-datovem-typu-enum</id><summary type="html">&lt;div&gt;&lt;h1&gt;Třída Direction - příklad implementace&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;(dřív zde na blogu pojmenovaná Rotation)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Na dnešním srazu jsme řešily víc témat, z nichž jedno bylo použití třídy &lt;strong&gt;Direction&lt;/strong&gt; datového typu Enum. Protože je to látka nová pro nás všechny na Roboprojektu, zde si podrobněji rozepíšeme, k čemu a jak třídu tohoto typu můžeme použít …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;h1&gt;Třída Direction - příklad implementace&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;(dřív zde na blogu pojmenovaná Rotation)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Na dnešním srazu jsme řešily víc témat, z nichž jedno bylo použití třídy &lt;strong&gt;Direction&lt;/strong&gt; datového typu Enum. Protože je to látka nová pro nás všechny na Roboprojektu, zde si podrobněji rozepíšeme, k čemu a jak třídu tohoto typu můžeme použít.&lt;/p&gt;
&lt;p&gt;Doposud byly v projektu třídy tři: &lt;em&gt;Robot&lt;/em&gt;, &lt;em&gt;Tile&lt;/em&gt; a &lt;em&gt;State&lt;/em&gt;. Ta poslední obsahuje jak informace o mapě, tak o robotech a jejích koordinátách. Všechny byly napsány podle pravidel nám známých ze &lt;a href="https://naucse.python.cz/course/pyladies/beginners/class/"&gt;začátečnického kurzu PyLadies&lt;/a&gt;, to znamená, že můžeme (a měly bychom) vytvořit nové objekty dané třídy tak, že ho inicializujeme, např.:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;my_robot = Robot(&amp;lt;direction&amp;gt;, &amp;lt;picture&amp;gt;, &amp;lt;coordinates&amp;gt;)&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Mezi &lt;code&gt;&amp;lt;&amp;gt;&lt;/code&gt;  výše se nachází příklady argumentů, které musíme dát objektu třídy &lt;em&gt;Robot&lt;/em&gt;, aby se korektně objevil na mapě (tzn. vykreslil správný obrázek na správném místě mapy se zobáčkem nasměrovaným na sever/ jih/ západ/ východ). &lt;/p&gt;
&lt;p&gt;Třída &lt;strong&gt;Direction&lt;/strong&gt; je ale jiná. Zde víme předem, kolik objektů této třídy bude ve hře: 4. Víme, že samotné objekty se nebudou měnit, ale je možné změnit směr robota nebo políčka na nový. Nebudeme inicializovat nové objekty této třídy, ale uložíme si naše směry jako konstanty. Z objektu takové třídy by se měly dát vyčíst různé informace dle tabulky obsažené v &lt;a href="https://roboprojekt.pyladies.cz/devaty-sraz-upravujeme-navrhujeme"&gt;předchozím postu&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;O třídě, která se zdá být vhodná pro řešení tohoto zadání, jsme se již před nějakou dobou bavily. Jedná se o datový typ Enum, importovaný na začátku pythonního souboru:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt; 

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;
        &lt;span class="n"&gt;S&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;
        &lt;span class="n"&gt;W&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;270&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Pokud si tu třídu naimportujeme do konzole nebo vyzkoušíme .py soubor, můžeme k jejím objektům přistoupit velice jednoduše:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;K objektu takovéhle třídy se můžeme dostat jak skrz jeho &lt;em&gt;name&lt;/em&gt; (N, E, S, W), tak &lt;em&gt;value&lt;/em&gt; (0, 90, 180, 270). 
Díky tomu můžeme jednoduchým sčítáním otočit robota a aktualizovat jeho směr (tzn. přiřadit mu nový objekt této třídy).&lt;/p&gt;
&lt;p&gt;K čemu je datový typ &lt;em&gt;Enum&lt;/em&gt; dobrý? Jeho objekty jsou už uvnitř inicializované (nemusí se definovat metoda &lt;code&gt;__init__()&lt;/code&gt;) a dostupné pro využití v dalším kódu. 
O směru ale, jak jsme si psaly v tabulce, můžeme uvažovat na spoustu způsobů: 
- světová strana
- stupně otočení
- kudy se posune náš objekt, pokud na něm uplatním metodu pohyb v Xové a Yové ose (delta koordinát) 
- výčet (rozsah 0-3)&lt;/p&gt;
&lt;p&gt;Pro různé účely potřebujeme různé zápisy té stejné věci. Měly jsme si rozmyslet, které z výše uvedených informací informaci dáme třídě jako atribut, a které získáme metodou. Není jeden správný způsob, jak si tyto informace uložit. Mně se nelíbilo, že nové koordináty nebo výčet musím získat metodou, když hned při náhledu na objekt "vím", kam se nově posune. Udělala jsem tedy jinou fintu:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;enum&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Enum&lt;/span&gt; 

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;E&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;S&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;W&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;270&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Stávající implementace všechny potřebné informace ukládá jako atributy, ke kterým můžou sahat další části programu:
- stupně potřebujeme pro vykreslení objektů (robotů a políček) v pygletu
- díky deltě koordinát můžeme vypočítat nové místo robota na mapě
- mapy s políčky, které se exportují z programů Tiled, mají přidané "custom properties" - námi nadefinované vlastnosti, které pracují s integery.&lt;/p&gt;
&lt;p&gt;Tím pádem víme, co směr &lt;strong&gt;je&lt;/strong&gt;, ale co má tedy &lt;strong&gt;umět&lt;/strong&gt;? 
Cíl byl jasný: pokud se robot, který směruje na západ, otočí o 90 stupňů, bude směrovat na sever. Zdá se: nic jednoduššího, než napsat na to metodu, kopírující chování, které jsme si vyzkoušely před chvílí v konzoli! &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_new_direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;where_to&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;where_to&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Můj robotí příklad přeložen do Pythonu by měl znít takto:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;W&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_new_direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"right"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Jenže kód výše nefunguje. &lt;em&gt;Value&lt;/em&gt; totiž teď není jen &lt;code&gt;270&lt;/code&gt;, ale celá hodnotá - jakási trojice: &lt;code&gt;270, (-1, 0), 3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;V &lt;a href="https://docs.python.org/3/library/enum.html#planet"&gt;dokumentaci Pythonu&lt;/a&gt; se můžeme dočíst, že lze dát objektu typu Enum víc atributů, ale aby nebyly zapsané jako trojice, musíme přepsat metodu &lt;code&gt;__init__()&lt;/code&gt; a atributy v ní rozbalit. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coordinates_delta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tile_property&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;degrees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coordinates_delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coordinates_delta&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tile_property&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tile_property&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Díky tomu, když vypíšeme:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coordinates_delta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;E&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tile_property&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Dostaneme:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Ale co naše metoda? Žádný atribut &lt;em&gt;value&lt;/em&gt; nemáme, tak se přepíše na &lt;code&gt;self.degrees&lt;/code&gt;, a můžeme slavnostně spustit testovací otočení. V tu chvíli by to všechno mělo vybuchnout velkou chybou:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nv"&gt;Traceback&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;most&lt;/span&gt; &lt;span class="nv"&gt;recent&lt;/span&gt; &lt;span class="k"&gt;call&lt;/span&gt; &lt;span class="nl"&gt;last&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;:
  &lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;numer.py&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;38&lt;/span&gt;, &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nv"&gt;aa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;Direction&lt;/span&gt;.&lt;span class="nv"&gt;W&lt;/span&gt;.&lt;span class="nv"&gt;get_new_coordinates&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;right&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;numer.py&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;, &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;rotate&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;Direction&lt;/span&gt;&lt;span class="ss"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;self&lt;/span&gt;.&lt;span class="nv"&gt;degrees&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;270&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;360&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/usr/lib/python3.6/enum.py&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;293&lt;/span&gt;, &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;__call__&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;cls&lt;/span&gt;.&lt;span class="nv"&gt;__new__&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cls&lt;/span&gt;, &lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/usr/lib/python3.6/enum.py&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;535&lt;/span&gt;, &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;__new__&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;cls&lt;/span&gt;.&lt;span class="nv"&gt;_missing_&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
  &lt;span class="nv"&gt;File&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/usr/lib/python3.6/enum.py&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;, &lt;span class="nv"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;548&lt;/span&gt;, &lt;span class="nv"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;_missing_&lt;/span&gt;
    &lt;span class="nv"&gt;raise&lt;/span&gt; &lt;span class="nv"&gt;ValueError&lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%r is not a valid %s&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;value&lt;/span&gt;, &lt;span class="nv"&gt;cls&lt;/span&gt;.&lt;span class="nv"&gt;__name__&lt;/span&gt;&lt;span class="ss"&gt;))&lt;/span&gt;
&lt;span class="nv"&gt;ValueError&lt;/span&gt;: &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nv"&gt;is&lt;/span&gt; &lt;span class="nv"&gt;not&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt; &lt;span class="nv"&gt;valid&lt;/span&gt; &lt;span class="nv"&gt;Direction&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Python totiž ví, že objekt třídy &lt;strong&gt;Direction&lt;/strong&gt; nemůže mít jen jeden atribut - daly jsme mu až 3. Na druhou stranu, naši jednoduchou metodu na otočení nelze nyní napsat lépe, protože Python teď neví, jak zjistit, který objekt jeho třídy Direction má 0 stupňů, a následně mu přiřadit zbývající atributy tohoto konkrétního objektu. Uff.&lt;/p&gt;
&lt;p&gt;Řešení přinesl internet, a konkrétně &lt;a href="http://xion.io/post/code/python-enums-are-ok.html"&gt;tento post&lt;/a&gt;, kde přistál nápad na přepsání metody &lt;code&gt;__new__()&lt;/code&gt;, aby vynutila chování, které potřebujeme pro vyřešení problému.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;coor_delta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tile_property&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="fm"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_value_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;degrees&lt;/span&gt;
        &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;coor_delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;coor_delta&lt;/span&gt;
        &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;map_property&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tile_property&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Díky této metodě atribut &lt;em&gt;value&lt;/em&gt; jsou nyní stupně. Python ví, že pokud najde objekt třídy Direction, který má &lt;em&gt;value&lt;/em&gt; 90, pak tento objekt má zároveň &lt;em&gt;deltu&lt;/em&gt; (+1, 0) a &lt;em&gt;property&lt;/em&gt;: 1. A to je přesně ono!
Pokud nyní zavoláme naši metodu a otočíme objekt směřující na západ o 90 stupňů doprava, dostaneme objekt Direction.N, který bude mít správně přiřazené další atributy. &lt;/p&gt;
&lt;h1&gt;Metoda &lt;code&gt;__add__()&lt;/code&gt;&lt;/h1&gt;
&lt;p&gt;V jednom z commitů se našla metoda &lt;code&gt;__add__()&lt;/code&gt; (nedostala se do finální verze, ale vzbudila náš zájem, tak ji nám Petr vysvětlil na srazu).
Již známe speciální metodu &lt;code&gt;__init__()&lt;/code&gt;, která umožňuje inicializovat nové objekty dané třídy. Podtržítka u &lt;code&gt;__add__()&lt;/code&gt; naznačují, že se jedná o další speciální metodu.&lt;/p&gt;
&lt;p&gt;Můžeme si představit třídu Direction, která označí čtyři směry:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;FORWARD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;RIGHT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;BACK&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;LEFT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Už víme, jak se můžeme dostat k jednotlivým informacím obsaženým v objektech takové třídy.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BACK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;# Direction.BACK&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BACK&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;# 2&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;             &lt;span class="c1"&gt;# Direction.BACK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Občas se nám může hodit i jiná operace, např. sčítání. Pokud máme objekt směřující dolu a posuneme ho doleva, chceme se dostat do směru vpravo. 
Můžeme se pokusit o standardní sčítání. Víme, že Python umí pracovat s čísly, pokud mu tak dáme jako argumenty integery, poradí si s nimi bez chyby:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;new_direction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BACK&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;  &lt;span class="c1"&gt;# 1&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_direction&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;                 &lt;span class="c1"&gt;# Direction.RIGHT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Ale jak Python ví, že má sečíst dvě hodnoty po obou stranách znaku plus? Všechno, co Python umí, v něm někdo naprogramoval. Základní operace tvoří balík standardních funkcí - to jsou ty, které se pak učíme na začátečnickém kurzu. Nemusíme Python znovu učit, jak má zacházet např. se základní matematikou, protože objekty třídy integer nebo float mají nadefinované metody, které to umí udělat. 
V lekci o &lt;a href="https://naucse.python.cz/course/pyladies/beginners/inheritance/"&gt;dědičnosti&lt;/a&gt; jsme se učily, jak vytvářet podtřídy a přepisovat v nich metody nadtříd. Zde se jedná o stejný princip - pro naši třídu Direction můžeme pozměnit chování sčítání, aby si s ní dokázalo poradit.&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__add__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Říkáme touto metodou: &lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Pythone, pokud dostaneš dva objekty třídy Direction, vezmi atribut
&lt;em&gt;value&lt;/em&gt; obou těchto objektů, sečti je, a vrať objekt třídy Direction, jehož &lt;em&gt;value&lt;/em&gt; je zbytkem dělení provedeného součtu čtyřmi. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Proč zbytek z dělení? Máme čtyři validní směry a chceme, aby se součet "přesypal" přes nulu, místo aby se dostal do hodnot nad 4.&lt;/p&gt;
&lt;p&gt;Když nyní zkusíme sečíst dva směry, dosáhneme stejného výsledku jako výše, při výrazné zvýšení čitelnosti zápisu. &lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BACK&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Direction&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LEFT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# Direction.RIGHT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Devátý sraz - Upravujeme a navrhujeme</title><link href="https://roboprojekt.pyladies.cz/devaty-sraz-upravujeme-navrhujeme" rel="alternate"></link><published>2018-11-27T18:00:00+01:00</published><updated>2018-11-27T18:00:00+01:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2018-11-27:/devaty-sraz-upravujeme-navrhujeme</id><summary type="html">&lt;div&gt;&lt;p&gt;Na začátku srazu jsme dokončovaly řešení dlouhotrvajícího problému, jak na políčka, která umí ve hře hromadu věcí. Mimo jiné políčka mohou mít zdi, které neblokují jen robota v pohybu, ale zejména nás docela blokovaly v dalším vývoji, protože jsme nevěděly, jak na ně. Řešení padlo na &lt;a href="https://roboprojekt.pyladies.cz/osmy-sraz-malo-ukolu"&gt;minulém srazu&lt;/a&gt;, tedy vyřešit …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Na začátku srazu jsme dokončovaly řešení dlouhotrvajícího problému, jak na políčka, která umí ve hře hromadu věcí. Mimo jiné políčka mohou mít zdi, které neblokují jen robota v pohybu, ale zejména nás docela blokovaly v dalším vývoji, protože jsme nevěděly, jak na ně. Řešení padlo na &lt;a href="https://roboprojekt.pyladies.cz/osmy-sraz-malo-ukolu"&gt;minulém srazu&lt;/a&gt;, tedy vyřešit efekty políčka tím, že každé políčko bude mít typ a vlastnosti definované přímo v popisu při tvorbě mapy a budou pak součástí výstupu v JSON. Odtud se budou dát načíst pro použití ve hře, potřebná data pak bude obsahovat třída &lt;code&gt;Tile&lt;/code&gt;, kterou je o ně třeba rozšířit. Tím se pak mohou řešit i zdi, tedy třída &lt;code&gt;Tile&lt;/code&gt; může obsahovat metodu ověřující, zda se lze pohnout z daného políčka nebo na dané políčko. Až to bude fungovat, můžeme se pustit do dalších efektů.&lt;/p&gt;
&lt;p&gt;Poté jsme se posunuly k úpravám stávajícího kódu. První věc jsme si ukazovaly na příkladu načítání vstupu. Obecně je dobré psát programy tak, aby byly univerzálnější. V současnou chvíli naše hra pracuje pouze s formátem dat v JSON. Z JSON získáváme slovník &lt;code&gt;data&lt;/code&gt; obsahující hromadu informací, které pak dál zpracováváme v různých funkcích, a také z něj získáváme konkrétnější informace. Pokud bychom chtěly pracovat s jiným vstupem, bude obtížnější tuto část kódu měnit, protože má více výstupů. &lt;strong&gt;Je dobré stavět program z částí, které je možné jednoduše vyměnit.&lt;/strong&gt; V našem případě by tedy bylo ideální mít funkci, která dostane jako vstup jméno souboru a vrátí stav hry. Vše, co potřebujeme používat v kódu dál, by měl stav hry obsahovat. Cílem je stavět program z celků, které jsou na sobě více nezávislé. Stavebních bloků, které mají jeden vstup a jeden výstup. Toto budeme v naší hře aplikovat tím, že oddělíme část, která načítá data, do samostatného modulu, nebude tedy součástí backendu, a také budeme psát komplexnější funkce. Abychom si zajistily, že používáme minimální rozhraní, jen to, co je skutečně nutné, bylo by dobré importovat přímo funkce, ne celé moduly. 
Důležité je také vyhnout se cyklickým importům. To se nám stalo při načítání konstant. Řešením pro tento případ může být vytvoření separátního modulu s konstantami, abychom se vyhnuly problému, ve kterém ze stávajících modulů je mít, aby vše fungovalo bez problémů. Není také zpravidla dobré importovat v rámci funkce, většinou bývají lepší možnosti. &lt;/p&gt;
&lt;p&gt;V rámci úprav a oprav byla také zmíněna &lt;strong&gt;reprezentace směru&lt;/strong&gt;. Nyní máme v kódu směr reprezentovaný stupni a čísly. Když je zkombinujeme se směry otočení (doleva, doprava, o 180°), veškerý pohyb, který pro hru potřebujeme, reprezentuje je tato tabulka:&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="tabulka" src="./images/tabulka.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;V backendu se objevil následující if:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;:
    &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;distance&lt;/span&gt;
&lt;span class="nv"&gt;elif&lt;/span&gt; &lt;span class="nv"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;90&lt;/span&gt;:
    &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nv"&gt;distance&lt;/span&gt;
&lt;span class="nv"&gt;elif&lt;/span&gt; &lt;span class="nv"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;:
    &lt;span class="nv"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;distance&lt;/span&gt;
&lt;span class="nv"&gt;elif&lt;/span&gt; &lt;span class="nv"&gt;direction&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;270&lt;/span&gt;:
    &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nv"&gt;distance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Lepší provedení by bylo pomocí třídy otočení, která by uměla věci znázorněné v tabulce. Je třeba se rozmyslet, co bude lepší jako atribut a co jako metoda. Vytvoření této třídy je jeden z úkolů do příště. &lt;/p&gt;
&lt;p&gt;Po úpravách a vylepšeních jsme se dostaly k dalšímu vývoji. Úkolem z minulého setkání bylo navrhnout pro naši hru &lt;strong&gt;rozhraní&lt;/strong&gt;. Sešlo se několik nápadů, nejpropracovanější návrh přinesla Katka:&lt;/p&gt;
&lt;p&gt;&lt;a href="./images/rozhrani.jpg" target="_blank" title="rozhrani"&gt;&lt;img alt="rozhrani" src="https://roboprojekt.pyladies.cz/images/thumbnails/rozhrani.jpg" class="img-fluid img-rounded"&gt;
&lt;/a&gt;&lt;a href="./images/rozhrani_2.jpg" target="_blank" title="rozhrani_2"&gt;&lt;img alt="rozhrani_2" src="https://roboprojekt.pyladies.cz/images/thumbnails/rozhrani_2.jpg" class="img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Petr přišel s návrhem, že by bylo dobré mít dvě nezávislá okénka, jedno čistě na zobrazení mapy a druhé s interaktivní částí, kde se hra ovládá. Má to několik výhod, ať už při prezentaci projektu nebo jeho tvorbě - separátně se to bude lépe kreslit a také udržovat oddělené. Vykreslení mapy už máme, v tuto chvíli je tedy potřeba zkusit napsat program, který vykreslí (zatím statickou) verzi interaktivního rozhraní. Jako pracovní postup Petr navrhoval nakreslit si novou část v Inkscape pro představu, jak celá věc bude vypadat na obrazovce, a až pak začít kódovat.&lt;/p&gt;
&lt;p&gt;V rámci rozhraní jsme také řešily, jakým způsobem se budou vybírat karty. Možností je více, přetažení myší, výběr pořadí karty stiskem čísla na klávesnici, kdy se pak karta automaticky posune na první volné místo v registru, nebo kliknutí nejprve na kartu a poté na požadovanou pozici.&lt;/p&gt;
&lt;p&gt;Součástí hry by mohl být i výběr robota, kde by se ke každému krom jeho obrázku ukazoval i krátký text, příběh daného robota. Padaly i nápady do budoucna, například práce se skrýváním karet nebo speciální vlastnosti robotů, to ale pro tuto chvíli řešit nebudeme :)&lt;/p&gt;
&lt;p&gt;Na závěr jsme se bavily také o &lt;strong&gt;licenci&lt;/strong&gt;, kterou by náš projekt měl mít. Jako autorky projektu si ji můžeme samy zvolit. Musíme se tedy rozhodnout, jak chceme, aby náš projekt lidi používali a co s ním budou moci dělat. Budeme se rozhodovat mezi dvěma druhy open source licencí, které se liší podle toho, pod jakou licencí může daný projekt kdokoliv další rozšiřovat. Na tomto se tedy musíme také v dohledné době dohodnout.&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Osmý sraz - Málo úkolů?</title><link href="https://roboprojekt.pyladies.cz/osmy-sraz-malo-ukolu" rel="alternate"></link><published>2018-11-20T18:00:00+01:00</published><updated>2018-11-20T18:00:00+01:00</updated><author><name>Terezie Vahalová</name></author><id>tag:roboprojekt.pyladies.cz,2018-11-20:/osmy-sraz-malo-ukolu</id><summary type="html">&lt;div&gt;&lt;p&gt;Sraz začal tématem &lt;strong&gt;Máme málo úkolů&lt;/strong&gt;. Takže se Petr trochu rozjel a začal psát jeden Issue za druhým.&lt;/p&gt;
&lt;p&gt;Problém je, že některé úkoly můžeme začít dělat, až po dodělání jiných. Na to nám v GitHubu založil štítek &lt;strong&gt;blocked&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Veškerý další vývoj teď stojí na úkolu &lt;strong&gt;Předělat strukturu dat.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Aktuálně máme …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Sraz začal tématem &lt;strong&gt;Máme málo úkolů&lt;/strong&gt;. Takže se Petr trochu rozjel a začal psát jeden Issue za druhým.&lt;/p&gt;
&lt;p&gt;Problém je, že některé úkoly můžeme začít dělat, až po dodělání jiných. Na to nám v GitHubu založil štítek &lt;strong&gt;blocked&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Veškerý další vývoj teď stojí na úkolu &lt;strong&gt;Předělat strukturu dat.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Aktuálně máme mapu vyřešenou ve slovnících po vrstvách. Ke každé souřadnici ve vrstvě mapy je přiděleno jedno políčko a to včetně prázdných políček. Vhodnější je ale zápis obrátit. Pro každou souřadnici vytvořit seznam všech políček, co na ni jsou a nepřidávat do seznamu prázdná políčka &lt;code&gt;board = {(x,y):[Tile, Tile, Tile],… }&lt;/code&gt;. Po předělání struktury dat, se nám bude lépe určovat efekt políčka a nemusíme kvůli zjišťování všech efektů políčka procházet všechny vrstvy mapy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dopsat &lt;code&gt;__repr__&lt;/code&gt; do tříd&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Aktuálně se nám printované výstupy z funkcí zobrazují ve velice nehezkém formátu&lt;/p&gt;
&lt;p&gt;&lt;code&gt;{(0, 11): [&amp;lt;backend.Tile object at 0x7f10c49297f0&amp;gt;],… }&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Aby byla práce příjemnější, je potřeba použít metodu &lt;code&gt;__repr__&lt;/code&gt;, která nám převede výstupy z tříd do lidsky čitelného formátu.  &lt;/p&gt;
&lt;p&gt;Např. úprava:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Tile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  
&lt;span class="o"&gt;...&lt;/span&gt;  
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="fm"&gt;__repr__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;Tile {} {}&amp;gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fomat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rotation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;zformátuje původní slovník na: &lt;code&gt;{(0, 11): [&amp;lt;Tile 0 ./img/squares/png/ground.png&amp;gt;]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Efekty políček přidat do mapy jako "properties"&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;V Tiled je potřeba u každého obrázku, který mapa používá, nastavit typ políčka. Tato informace se nám pak přenese do jsonu a můžeme s ní dál pracovat.&lt;br&gt;
Typ políčka nastavíme jako “ground”, “hole”,… u některých je potřeba ještě typ doplnit o další vlastnosti (Custom Properties) jako třeba u pásů, o kolik se posunou =&amp;gt; int, u laserů počet a bool varianta pro start laserů, u otáčecího políčka směr…&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="tiled" src="./images/tiled.png" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Validace mapy&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;U mapy potřebujeme zkontrolovat, že jsou všechny prvky správně umístěny nad sebou. Na mapě nemusí být vidět vše. Destrukční políčky by mohla být omylem schována pod jiná a efekt by se provel i když by nebyl na mapě “vidět”. Validační program/test potvrdí, že díry, lasery a ostatní efektní políčka jsou ve správném pořadí a budou na mapě vidět.&lt;/p&gt;
&lt;p&gt;V případě, že mapa správně nebude, program vyhodí chybu ideálně i se souřadnicí, kde je potřeba udělat opravu.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Udělat pohyb robota – metodu "Robot.posuň se" z diagramu&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Úkolem je vymyslet metodu třídy Robot, která posune robota dopředu.
Metoda by měla brát stav a vzdálenost a vytvořit nový stav. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Automaticky exportovat PNG obrázky&lt;/strong&gt; &lt;/p&gt;
&lt;p&gt;Úkolem je udělat program, který při spuštění vygeneruje z svg obázků všechny png obrázky, které ještě nemáme. Tím si ulehčíme práci při přidávání dalších obrázků.&lt;/p&gt;
&lt;p&gt;Vzorový program pro jeden obrázek vypadá takto:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sys&lt;/span&gt;
    &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;subprocess&lt;/span&gt;  
    &lt;span class="err"&gt;​&lt;/span&gt;
    &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'inkscape'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'img/robots_map/svg/MintBot.svg'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="s1"&gt;'--export-png=ex.png'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'--export-area-page'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;check&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;V příkazové řádce pak spustíme program:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;inkscape&lt;/span&gt; &lt;span class="n"&gt;svg&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;MintBot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;svg&lt;/span&gt; &lt;span class="c1"&gt;--export-png=ex.png --export-area-page&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Úkolů máme pro příští týden hodně a navíc ještě máme každá vymyslet a nakreslit grafické rozhraní pro hru.&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Šestý sraz - Travis CI</title><link href="https://roboprojekt.pyladies.cz/sesty-sraz-travis-ci" rel="alternate"></link><published>2018-11-06T21:17:00+01:00</published><updated>2018-11-16T21:17:00+01:00</updated><author><name>Zuzana Kletzanderová</name></author><id>tag:roboprojekt.pyladies.cz,2018-11-06:/sesty-sraz-travis-ci</id><summary type="html">&lt;div&gt;&lt;p&gt;V úvodu našeho dalšího srazu jsme si ujasnily komunikaci týmu kolem celého projektu. Hlavní bod diskuze - neurážej se kvůli opravě tvého kódu! :) Dále aby byl lepší přehled o tom kdo na čem pracuje, v jakém je to stavu a aby byl &lt;em&gt;celkově&lt;/em&gt; lepší přehled co se v projektu děje, jsme …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;V úvodu našeho dalšího srazu jsme si ujasnily komunikaci týmu kolem celého projektu. Hlavní bod diskuze - neurážej se kvůli opravě tvého kódu! :) Dále aby byl lepší přehled o tom kdo na čem pracuje, v jakém je to stavu a aby byl &lt;em&gt;celkově&lt;/em&gt; lepší přehled co se v projektu děje, jsme se domluvily, že budeme vše řešit především na Slacku.&lt;/p&gt;
&lt;p&gt;Hlavním bodem našeho setkání bylo, pod vedením Jirky, jak funguje integrace GitHub-u a jak nám pomůže v testování &lt;strong&gt;Travis CI&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Ze začátečnického kurzu už víme, jak může vypadat test na kód, který napíšeme. Například pomocí příkazu 'assert'. Testy rozdělujeme na manuální a automatické (pytest). Hlavní je to, že testy umožňují říct, zda je kód v pořádku, nebo jestli s ním musíme dále něco dělat. S testy nečekáme až bude finální verze, ale testujeme už jednotlivé změny, které děláme.&lt;/p&gt;
&lt;p&gt;A teď něco k &lt;strong&gt;Travis CI&lt;/strong&gt; (Continuous Integration):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;je to služba, která spouští automatizované testy na GitHubu, které běží kontinuálně s tím co jsme na GitHub-u přidaly &lt;/li&gt;
&lt;li&gt;&lt;a href="https://travis-ci.org"&gt;travis-ci.org&lt;/a&gt; má službu poskytovanou zdarma pro veřejné repozitáře, &lt;a href="https://travis-ci.com"&gt;travis-ci.com&lt;/a&gt; je placená verze pro privátní účely&lt;/li&gt;
&lt;li&gt;a co Travis dělá? Travis si na testování vytvoří virtuální počítač, stáhne si zdrojový kód a v rámci zdrojového kódu provede příkazy, které chceme&lt;/li&gt;
&lt;li&gt;Travis se konfiguruje pomocí souboru &lt;code&gt;.travis.yml&lt;/code&gt; umístěným v kořenovém adresáři projektu. V souboru je uvedeno vše potřebné pro správné spuštění testů, včetně instalace závislostí atd. Mimo jiné se jedná o jazyk pro jaký se má nastavit prostředí, v jaké verzi (těch může být kolik potřebujeme), instalace závislostí (v našem případě pythoních modulů) a skript,  který po spuštění provede všechny testy. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Toto je příklad, který  použijeme v našem RoboProjektu:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;python&lt;/span&gt;
&lt;span class="n"&gt;python&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'3.5'&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'3.6'&lt;/span&gt;
&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;txt&lt;/span&gt;
&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;pytest&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Po spuštění testu na &lt;a href="https://travis-ci.org"&gt;travis-ci.org&lt;/a&gt; můžeme vidět , zda test proběhl správně, nebo jestli někde nastala chyba. Na pravé straně vidíme &lt;strong&gt;My repositories&lt;/strong&gt;,  kde je přehled našich testů. Po rozkliknutí testu vidíme, že proběhla změna např. na větvi &lt;strong&gt;master&lt;/strong&gt;, kdo změnu vytvořil, jak dlouho test trval, kdy byl vytvořen atd. Když máme test ve více verzích apod., tak se nám zobrazí &lt;strong&gt;Build jobs&lt;/strong&gt;, kde vybereme pro nás vhodný výběr např. verze Pythonu. Poté máme k dispozici také &lt;strong&gt;Job log&lt;/strong&gt;, který vygeneruje x řádků s tím, že většina jich je servisních, v první části vidíme server, kde byl test spuštěn, pak klon kódu z GitHub-u a instrukce které jsou dány ze souboru '.travis.yml'. V další části už je test, kde vidíme, zda test prošel (s chybou 0) a jak dlouho trval, nebo se zobrazí chyba.&lt;/p&gt;
&lt;p&gt;Postup pro spuštění Travis CI je tedy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;jdeme na &lt;a href="https://travis-ci.org"&gt;travis-ci.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;přihlásíme se přes &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;zapneme webhook pro repozitář (tím zapneme integraci mezi GitHub-em a Travis CI), nebo proběhne automaticky&lt;/li&gt;
&lt;li&gt;teď kliknout na tlačítko Aktivace a vybereme repozitáře z GitHub-u, které chceme používat s Travis CI&lt;/li&gt;
&lt;li&gt;přidáme soubor &lt;code&gt;.travis.yml&lt;/code&gt; do git-u, dáme commit a push &lt;/li&gt;
&lt;li&gt;zkontrolujeme na Travis CI stav&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Testy, které proběhly,  můžeme vidět na GitHub-u v seznamu commitů. Když někdo udělá Pull Request, tak jde vidět, jestli testy procházejí správně nebo ne.&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Pátý sraz - první důležité úkoly</title><link href="https://roboprojekt.pyladies.cz/paty-sraz-enum-dataclasses" rel="alternate"></link><published>2018-10-30T18:00:00+01:00</published><updated>2018-11-06T09:58:00+01:00</updated><author><name>Iveta Česalová</name></author><id>tag:roboprojekt.pyladies.cz,2018-10-30:/paty-sraz-enum-dataclasses</id><summary type="html">&lt;div&gt;&lt;p&gt;Z předminulé hodiny s Petrem jsme měly za úkol vytvořit slovník políček (STAV = slovník políček klíč: (x, y) hodnota: seznam efektů) a vykreslit v Pygletu mapu s jednou vrstvou bez otáčení prvků. Jelikož spousta z nás s tím měla problémy, probrali jsme na začátku srazu krok po kroku jak na …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Z předminulé hodiny s Petrem jsme měly za úkol vytvořit slovník políček (STAV = slovník políček klíč: (x, y) hodnota: seznam efektů) a vykreslit v Pygletu mapu s jednou vrstvou bez otáčení prvků. Jelikož spousta z nás s tím měla problémy, probrali jsme na začátku srazu krok po kroku jak na to.
Na githubu byly nahrané dvě verze kódu, od Terky a Karoliny, které úkol zvládly. Zvolili jsme ponechat &lt;a href="https://github.com/PyLadiesCZ/roboprojekt/blob/35a98aa967386d82a4dbca23a0ade65cc8b96767/karolina_state.py"&gt;Karolinin kód&lt;/a&gt;.
Postupně jsme procházely, co je v kódu a Petr zmínil, co je třeba opravit (sjednotit terminologii, pojmenování proměnných, správně přeložit do angličtiny, stejně jako komentáře…)&lt;/p&gt;
&lt;p&gt;A nastala otázka - Co dál? Jak si rozdělíme úkoly?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Načíst mapu s více vrstvami&lt;/li&gt;
&lt;li&gt;Načíst mapu s otočenými políčky&lt;/li&gt;
&lt;li&gt;Napsat testy&lt;/li&gt;
&lt;li&gt;Celý dosavadní kód rozdělit na jednotlivé funkce&lt;/li&gt;
&lt;li&gt;Popisek základního repozitáře v Githubu&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Důležitou věcí, jak pokračovat v našem projektu je jeho rozdělení na 4 moduly:
&lt;strong&gt;Backend&lt;/strong&gt; – načte mapu, tedy náš slovník Stav, &lt;strong&gt;Frontend&lt;/strong&gt; – vykreslí mapu, &lt;strong&gt;Game&lt;/strong&gt; – spustí hru, &lt;strong&gt;Testy&lt;/strong&gt; – vyzkouší, jestli funguje, co je v backendu.
Až budou tyto moduly hotové, smažeme původní script  kde je celý kód.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="moduly" src="./images/moduly.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;V další části jsme se naučily něco nového, využití knihoven &lt;strong&gt;enum&lt;/strong&gt; a &lt;strong&gt;dataclasses&lt;/strong&gt;. Kdo neměl nainstalované, použil v příkazovém řádku následující příkazy:
&lt;code&gt;python -m pip install dataclasses&lt;/code&gt;
&lt;code&gt;python -m pip install enum&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Tyto knihovny nám umožní jednodušeji psát výčtové typy a datové třídy. Kdo nezná třídy, zopakuje si ze začátečnického kurzu &lt;a href="https://naucse.python.cz/course/pyladies/sessions/class/"&gt;Třídy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Poté jsme v editoru vytvořily nový soubor – demo.py kde máme třídu Direction, která dědí z výčtového typu enum.Enum. Definovaly jsme si funkci, která vyhodnotí směr (nejdřív se sečtou hodnoty a zbytek po dělení 4 =&amp;gt; získáme směr).&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="demo" src="./images/demo.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Dále následovalo vysvětlování modulu &lt;strong&gt;dataclasses&lt;/strong&gt;. Tento modul poskytuje dekorátor a funkce pro automatické přidávání generovaných speciálních metod, jako jsou &lt;code&gt;__init__()&lt;/code&gt; a &lt;code&gt;__repr__()&lt;/code&gt; do uživatelsky definovaných tříd. 
Vytvořily jsme si soubor demo_dataclasses.py, kde máme třídu datového typu. Karta má jednotlivé vlastnosti (prioritu, efekt) určitého typu.
Více informací o dataclasses &lt;a href="https://docs.python.org/3/library/dataclasses.html"&gt;zde&lt;/a&gt;
Nevím, jak to pochopily ostatní, ale asi nám to Petr ještě dovysvětlí, k čemu to přesně slouží :-)&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="dataclasses" src="./images/dataclasses.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Do příště máme každá svůj úkol, rozdělení máme na githubu v záložce Issues.&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Čtvrtý sraz - GitHub</title><link href="https://roboprojekt.pyladies.cz/ctvrty-sraz-github" rel="alternate"></link><published>2018-10-23T18:05:00+02:00</published><updated>2018-11-06T18:05:00+01:00</updated><author><name>Hanka Střondalová</name></author><id>tag:roboprojekt.pyladies.cz,2018-10-23:/ctvrty-sraz-github</id><summary type="html">&lt;div&gt;&lt;p&gt;A jsme zpět. Co dnes? užitečný a u začátečníků respekt vzbuzující ... GIT... Abychom mohly naplno rozjet náš projekt, potřebujeme si naše kódy sdílet jako opravdové programátorky.&lt;/p&gt;
&lt;p&gt;Tentokráte se hodiny ujal Jirka a začal to jak se patří a to malým opáčkem. V rychlosti jsme si s ním projely informace, které …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;A jsme zpět. Co dnes? užitečný a u začátečníků respekt vzbuzující ... GIT... Abychom mohly naplno rozjet náš projekt, potřebujeme si naše kódy sdílet jako opravdové programátorky.&lt;/p&gt;
&lt;p&gt;Tentokráte se hodiny ujal Jirka a začal to jak se patří a to malým opáčkem. V rychlosti jsme si s ním projely informace, které jsme už dříve obdržely jako účastnice základního kurzu, ale co si budeme povídat - připomenutí se hodí vždy: git init, git status, git add, git commit, pozor změna - git diff, užitečný git log, grafický pomocníček gitk. To hlavní, k čemu jsme dnes směřovaly, je spolupráce na GitHub.&lt;/p&gt;
&lt;p&gt;Jirka nám vysvětloval pomalu a jistě (to abychom mu hned na začátku asi neutekly - nebo po něm něco rovnou nehodily :-)), že hlavními výhodami pro nás na GitHubu bude mergovaní našich výtvorů a nápadů. Každou větev (branch), kterou si uděláme a která bude obsahovat naše změny a nápady, prostřednictvím GitHubu někdo další zkontroluje a spojí, takže výsledek budeme mít každá k dispozici z pohodlí svého gauče.&lt;/p&gt;
&lt;p&gt;Něco málo o GitHubu:
Samotný repozitář nemáme pouze na svém počítači a tudíž je pravděpodobnost, že o něj s odchodem našich notebooků do křemíkového nebe, nepřijdeme.
GitHub je možno využívat zdarma a samozřejmě i v placené verzi, což zatím nepotřebujeme. Je zde také možná spolupráce dvojího typu - "firemní" a "open source" - u firemní spolupráce máme větší práva a naše změny jsou zaslány rovnou do hlavního repozitáře (git push). U open source spolupráce se musí naše změny nejdříve zaslat do našeho forku (git push [mé jméno]) a odsud následně pomocí Pull Request bude začleněno do hlavního repozitáře.)&lt;/p&gt;
&lt;p&gt;Jirka nám GitHub představil pomalu a po kouscích - vysvětlil nám, kde co v grafickém rozhraní najdeme a co to všechno znamená.&lt;/p&gt;
&lt;p&gt;Jednou ze záložek jsou například Issues neboli úkoly: každý má své číslo, můžeme je filtrovat podle různých parametrů - podle autora, milestone či assignees, což nám říká, komu byl úkol přidělen.&lt;/p&gt;
&lt;p&gt;Hlavním bodem večera byl "pull request". Projely jsme postupně celý proces krok po kroku, a abychom si to řádně vyzkoušely, vytvořily jsme si i testovací organizaci, kde se nemusíme bát, že něco pokazíme.&lt;/p&gt;
&lt;p&gt;Pro “firemní” spolupráci:
Nejdříve je třeba provést klonování repozitáře, které provedeme pomocí zeleného tlačítka Clone or Download - to je možné dvojím způsobem buď přes SSH key (programátorům se nechce pořád dokola přihlašovat, tak mají klíč :-)) a nebo přes HTTPS adresu, kterou budeme využívat my.
HTTPS adresu zkopírujeme a do příkazové řádky zadáme git clone &lt;em&gt;https://github.com/název&lt;/em&gt;, tímto nám proběhne naklonování repozitáře k nám na počítač. Tam provádíme libovolné změny, o které se zrovna chceme podělit se svým týmem. Pomocí příkazů git status si zobrazíme stav souborů v repozitáři a cokoliv, co je nové, přidáme (git add) a okomentujeme změny (git commit). Klidně pro klid duše použijeme znovu příkaz git status. Po kontrole se  můžeme  posunout dál a poslat naši změnu na GitHub. Master branch (větev) je chráněna a taknemůžeme posílat naše změny napřímo, ale musíme si vytvořit větev vlastní. Použijeme příkaz git push origin src:dst (zdrojová:cílová větev), například git push origin master:pridani_vlajky. Následně jsme  vyzváni k přihlášení pomocí našeho uživatelského jména a hesla.&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="master - pridani_vlajky" src="./images/kod.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;K vytvoření pull requestu je třeba otevřít web GitHubu a v našem repozitáři si zavolat na pomoc tlačítko Compare &amp;amp; Pull request&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="Compare &amp;amp; Pull request" src="./images/comparepull.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Zobrazí se prostor na naše poznámky a zároveň můžeme pull requestu přiřadit další parametry, můžeme určit uživatele, kteří pro nás udělají review aneb kontrolu změn.
Dokončíme pull request (Create pull request) a čekáme na potvrzení, zda nedochází ke kolizi a kontrolu našich "assignees", které (kteří) následně potvrdí sloučení naší změny s cílovým repozitářem (confirm merge). Pokud bychom ještě něco ve svém repozitáři /na své větvi před mergem měnily, je dobré tyto změny ukládat do té samé větve.  Po definitivním sloučení větví je fajn po sobě uklízet a naši větev smazat.&lt;/p&gt;
&lt;p&gt;Když se repozitář na GitHubu průběžně mění a chceme si aktualizovat i svůj repozitář v počítači, použijeme k tomu příkaz git pull.
“Open source” přístup je trochu jiný. Začíná se tím, že dáme na GitHubu fork, do počítače si naklonujeme repozitář pomocí stejného příkazu git clone &lt;em&gt;https://github.com/název&lt;/em&gt;.
V příkazové řádce se přepnu do naklonované složky a pomocí git remote add [me jmeno] &lt;em&gt;https://github.com/[me jmeno]/naklonovaný repozitář&lt;/em&gt;, si vytvoříme náš fork (stačí jednou na začátku). U sebe na počítači si vytvoříme novou větev a do ní ukládáme změny, obrázky, kódy a podle potřeby přidáváme do gitu (git add) a uděláme commit.
Následuje git push [me jmeno] -  čímž se na mém githubu objeví možnost pull requestu a zbytek už znáte :-)&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Třetí sraz - pokračujeme s UML a začínáme s grafikou</title><link href="https://roboprojekt.pyladies.cz/treti-sraz-pokracujeme-s-uml-a-zaciname-s-grafikou" rel="alternate"></link><published>2018-10-16T08:39:00+02:00</published><updated>2018-10-24T08:39:00+02:00</updated><author><name>Helena Olbertová</name></author><id>tag:roboprojekt.pyladies.cz,2018-10-16:/treti-sraz-pokracujeme-s-uml-a-zaciname-s-grafikou</id><summary type="html">&lt;div&gt;&lt;p&gt;V první části dvouhodinovky jsme se věnovaly aktivní týmové spolupráci při rozebírání &lt;a href="https://en.wikipedia.org/wiki/Class_diagram"&gt;diagramu tříd&lt;/a&gt; pro pohyb robotů, který máme rozdělaný už od minula. Poslední verzi nám Petr zase trošku zkorigoval a dál budeme na diagramu pracovat doma a příště. Aktuální diagram najdete tady:&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/UML1.jpg" target="_blank" title="UML1"&gt;&lt;img alt="UML1" src="https://roboprojekt.pyladies.cz/images/thumbnails/UML1.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/UML2.jpg" target="_blank" title="UML2"&gt;&lt;img alt="UML2" src="https://roboprojekt.pyladies.cz/images/thumbnails/UML2.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;V druhé části dvouhodinovky přišla na řadu …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;V první části dvouhodinovky jsme se věnovaly aktivní týmové spolupráci při rozebírání &lt;a href="https://en.wikipedia.org/wiki/Class_diagram"&gt;diagramu tříd&lt;/a&gt; pro pohyb robotů, který máme rozdělaný už od minula. Poslední verzi nám Petr zase trošku zkorigoval a dál budeme na diagramu pracovat doma a příště. Aktuální diagram najdete tady:&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/UML1.jpg" target="_blank" title="UML1"&gt;&lt;img alt="UML1" src="https://roboprojekt.pyladies.cz/images/thumbnails/UML1.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/UML2.jpg" target="_blank" title="UML2"&gt;&lt;img alt="UML2" src="https://roboprojekt.pyladies.cz/images/thumbnails/UML2.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;V druhé části dvouhodinovky přišla na řadu tvorba grafiky. Zatímco vymýšlíme, jak se budou naše herní figurky hýbat, musíme jim také připravit herní podklad. K tomuto účelu používáme pro tvorbu vektorové grafiky &lt;a href="https://inkscape.org/"&gt;Inkscape&lt;/a&gt; a pro skládání dlaždic do mapy &lt;a href="https://www.mapeditor.org/"&gt;Tiled&lt;/a&gt; (ideálně verzi 1.2 a novější).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inkscape&lt;/strong&gt; jsme si nastavily všechny stejně.
Soubor → Nastavení dokumentu (nebo Ctrl + Shift + D) → Zobrazovací jednotky a Jednotky plátna nastaveno na px → velikost 64px x 64px.&lt;/p&gt;
&lt;p&gt;V tom stejném nastavení přidáme mřížku - třetí záložka Grids → nová čtvercová mřížka → Počátek X = 0, Počátek Y = 0, Mezery X = 1, Mezery Y = 1, Hlavní čára mřížky každých: 8&lt;/p&gt;
&lt;p&gt;Prvně zkoušíme, jak se v Inkscape kreslí tužkou a vyplňuje obvod a obsah. Potom každá Pylady dostala za úkol nějaký typ dlaždice, celkově jsme zatím připravily tyhle typy dlaždic:
wall, flag, starting square, laser, laser base, pusher, repair, hole, ground, conveyor belt 1, conveyor belt 2.&lt;/p&gt;
&lt;p&gt;Všechny ukládáme ve vektorovém formátu SVG a navzájem si je sdílíme na Slacku, takže všechny máme k dispozici stejnou sadu dlaždic, kterou si ukládáme do složky Tiles. Nejsou to ještě konečné verze grafiky, ale už nám pomůžou orientačně rozložit mapu. Později budeme mít možnost je snadno nahradit nějakými více vychytanými s jednotnějším vzhledem.&lt;/p&gt;
&lt;p&gt;Alternativně, protože na některých operačních systémech takto uložené soubory zlobí (vykreslují se v Tiled se špatnou velikostí), se mohou obrázky z Inkscape vyexportovat do PNG. V menu Soubor najdeme Export PNG Image a na zobrazené boční liště vybereme tlačítka Page a Export. Takto vyexportované soubory se jednoduše naimportují do Tiled dle návodu níže.&lt;/p&gt;
&lt;p&gt;A teď hurá na druhý prográmek – &lt;strong&gt;Tiled&lt;/strong&gt;.
Dáme si Soubor → New → New Map (Ctrl + N), kde nastavíme
Orientace: ortogonální,
Formát vrstvy dlaždic: CSV,
Pořadí vykreslování dlaždic: Doprava a dolů,
Velikost mapy – Fixed 12 x 12 dlaždic,
Velikost dlaždice: 64 px x 64 px.
Projekt uložíme s libovolným názvem a koncovkou &lt;a href="https://naucse.python.cz/course/pyladies/intro/json/"&gt;JSON&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Pokračujeme s importem našich dlaždic.
Vpravo dole najdeme oddíl Sada dlaždic a stisknutím New Tileset pokračujeme na výběr názvu sady – dáváme „Robots“ a možnost Ze sady obrázků.
Vpravo dole pod oddílem dlaždic klikáme na malinkou ikonu s klíčem, na popisku stojí Edit Tileset. To nám otevírá novou záložku, kde v horní liště klikneme na ikonku + s popiskem Přidání dlaždic. Najdeme adresu naší složky Tiles a označíme všechny obrázky dlaždic.
Vracíme se do záložky s mapou a můžeme si trošku pohrát s naší první herní mapou. Z vektorové grafiky jsme získaly obrázky s průhledným pozadím a tak je můžeme pěkně vrstvit. Do spodní vrstvy se můžou dát třeba země, jáma, … Do další vrstvy další dlaždice typu zeď, posuvné pásy, lasery a podobně.
Jednotlivé objekty je možné i libovolně otáčet.
Náš výtvor můžeme nechat přes Soubor → Exportovat jako a nastavíme si typ JSON.&lt;/p&gt;
&lt;p&gt;Další část lekce jsme věnovaly průzkumu mapového souboru JSON v textovém editoru.&lt;/p&gt;
&lt;p&gt;Každý typ dlaždice má svoje ID – první má číslo 0 a je to abecedně název první dlaždice, další následují. V seznamu políček ale vidíme čísla typů dlaždic od 1, takže abecedně první typ dlaždice je v Tiled ID: 0 → v seznamu vidíme ID: 1.&lt;/p&gt;
&lt;p&gt;Teď se můžeme podívat do organizace vrstev – v Layers máme tentokrát jenom jednu vrstvu. Každé políčko mapy má svoje souřadnice – čísla běží jako seznam z levého horního rohu mapy doprava a pak následuje další řádek.&lt;/p&gt;
&lt;p&gt;Pokud máme komplikovanější mapu s více vrstvami a také otočenými dlaždicemi, můžeme v layers vidět více seznamů a v některých budou i veliká čísla, jako například 1610612738. To je číslo šestnáctkové soustavy. Rozluštit nám ho pomůže třeba Python přes příkaz hex(číslo).  &lt;/p&gt;
&lt;p&gt;Máme pro první řádek mapy například políčka:&lt;/p&gt;
&lt;p&gt;nic – dlaždice ID:1 (conveyor belt 2) – nic – ID 1 otočené doprava – nic - ID 1 otočené dolů – nic – ID 1 otočené doleva – nic - nic – nic- nic&lt;/p&gt;
&lt;p&gt;Zápis vypadá takto&lt;/p&gt;
&lt;p&gt;"data":[0, 2, 0, 2684354562, 0, 3221225474, 0, 1610612738, 0, 0, 0, 0 … a následují další řádky&lt;/p&gt;
&lt;p&gt;zadáme do Pythonu:&lt;/p&gt;
&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2684354562&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="s1"&gt;'0xa0000002'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="mh"&gt;0xFFFFFFF&lt;/span&gt; &lt;span class="c1"&gt;# kouzelná formulka pro zjištění ID dlaždice&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;cislo&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# kouzelná formulka pro zjištění otočení&lt;/span&gt;
&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;S dalšími čísly dostáváme 12 a 6.&lt;/p&gt;
&lt;p&gt;Takže otočení doprava v tomto případě je hodnota 10, dolů 12 a doleva 6.&lt;/p&gt;
&lt;p&gt;A to bylo tentokrát vše.&lt;/p&gt;
&lt;p&gt;Příští lekce se bude věnovat GITu s Jirkou, máme si zopakovat lekce &lt;a href="https://naucse.python.cz/course/pyladies/sessions/git/"&gt;Správa zdrojového kódu&lt;/a&gt; a &lt;a href="https://naucse.python.cz/course/pyladies/sessions/foss/"&gt;Spolupráce a Open-Source&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Za dva týdny bude následovat další lekce s Petrem, na kterou máme za úkol náš mapový podklad, prozatím s jednou vrstvou a bez otáčení prvků, uložit ve formátu JSON, naimportovat do Pythonu a mapu vykreslit v Pygletu.&lt;/p&gt;
&lt;p&gt;A jak na to? Chceme načíst herní plán jako slovník políček.&lt;/p&gt;
&lt;p&gt;STAV = slovník políček
klíč: (x, y)
hodnota: seznam efektů # ← číslo z JSON&lt;/p&gt;
&lt;p&gt;Nahrávaná mapa má pouze 1 vrstvu, bez otáčení dlaždic.&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>Druhý sraz, aneb pořád kreslíme</title><link href="https://roboprojekt.pyladies.cz/druhy-sraz-aneb-porad-kreslime" rel="alternate"></link><published>2018-10-13T16:13:00+02:00</published><updated>2018-10-13T16:13:00+02:00</updated><author><name>Karolina Surma</name></author><id>tag:roboprojekt.pyladies.cz,2018-10-13:/druhy-sraz-aneb-porad-kreslime</id><summary type="html">&lt;div&gt;&lt;p&gt;Kdyby se někdo zeptal, jak jedním slovem shrnu druhý sraz RoboProjektu, odpovím: "přituhuje".&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="mind mapa" src="./images/mindmap.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Za podzimního večera jsme se opět v hojném počtu sešly (žádná to po prvním srazu nevzdala, hurááá!), tentokrát nad našimi mapami. I když jsem si myslela, že si naše výsledky budou podobné, opak byl pravdou. Na některých …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Kdyby se někdo zeptal, jak jedním slovem shrnu druhý sraz RoboProjektu, odpovím: "přituhuje".&lt;/p&gt;
&lt;figure class="figure"&gt;&lt;img alt="mind mapa" src="./images/mindmap.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/figure&gt;
&lt;p&gt;Za podzimního večera jsme se opět v hojném počtu sešly (žádná to po prvním srazu nevzdala, hurááá!), tentokrát nad našimi mapami. I když jsem si myslela, že si naše výsledky budou podobné, opak byl pravdou. Na některých ze základních pojmů jsme se shodly, ostatní jsme zpracovaly každá úplně jinak.&lt;/p&gt;
&lt;p&gt;Prvním úkolem srazu bylo tedy vytvořit společnou mind mapu naší hry. Rozhodly jsme se, že začneme "pohybem", tedy tím, co se děje na již existujícím herním plánu. Výběr plánu, robotího programu a akce před zahájením daného kola jsme prozatím z uvažování vynechaly. Centrální postavou naší mapy se stal robot, doprovázen neméně důležitým herním políčkem. Postupně jsme dokreslovaly další objekty a souvislosti mezi nimi. Zhruba po hodině jsme se shodly na finální podobě mapy. Než jsme otevřely šampaňské, Petr nás přivolal zpátky na zem s tím, že teď naše dílo můžeme zahodit.&lt;/p&gt;
&lt;p&gt;Naštěstí ne úplně. Python je objektový jazyk, takže naše "lidská" mapa se musí postupně převést na pojmy jemu známé. Další díl projektové skladačky vyžadoval vytvoření &lt;a href="https://en.wikipedia.org/wiki/Unified_Modeling_Language"&gt;UML diagramu&lt;/a&gt;. Na základě poznatků, získaných díky mapě, jsme se pustily do modelování tříd budoucího kódu. S každou odpovědí na otázku, co robot &lt;em&gt;má&lt;/em&gt;, a co &lt;em&gt;umí&lt;/em&gt;, se rýsovaly výraznější rozdíly mezi atributy a metodami. Pro každý atribut se následně definoval jeho datový typ, a pro každou metodu argumenty, které vezme, spolu s výsledkem, který vrátí. Nejsme ještě u konce: v rámci domácího úkolu se pokusíme diagramy dokončit a popřemýšlet mj., jak naprogramovat políčkům zdi.&lt;/p&gt;
&lt;p&gt;Uff, a to jsme ještě nezaply počítače! Pro většinu z nás, ne-li všechny, je to první kontakt s tímto stylem uvažování o složitém a vcelku velkém problému.&lt;/p&gt;
&lt;p&gt;Pro odlehčení jsme chvilku debatovaly nad podobou, jakou dáme projektovému blogu. Na Petrovo doporučení jsme se rozhodly pro GitHub, kam posíláme příspěvky pomocí gitu. Myšlenka na git v nás sice zpočátku nevzbudila velké nadšení, ale všechny víme, že praxí se člověk učí nejlépe.&lt;/p&gt;
&lt;p&gt;Petr nám zdejší stránky vytvořil a připravil pracovní prostředí, za což mu zde jménem účastnic chci poděkovat :).&lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry><entry><title>První sraz</title><link href="https://roboprojekt.pyladies.cz/prvni-sraz" rel="alternate"></link><published>2018-10-10T09:58:00+02:00</published><updated>2018-10-10T09:58:00+02:00</updated><author><name>Anežka Müller</name></author><id>tag:roboprojekt.pyladies.cz,2018-10-10:/prvni-sraz</id><summary type="html">&lt;div&gt;&lt;p&gt;Letošní podzimní semestr se pro brněnské PyLadies nese částečně v duchu experimentů.
Krom klasického kurzu pro začátečníky se totiž pod vedením Petra Viktorina rozběhl nový formát tohoto kurzu a také novinka pro pokročilejší, kurz zaměřený na realizaci praktického projektu a týmovou spolupráci. &lt;/p&gt;
&lt;p&gt;V rámci kurzu budeme pod Petrovým dohledem v …&lt;/p&gt;&lt;/div&gt;</summary><content type="html">&lt;div&gt;&lt;p&gt;Letošní podzimní semestr se pro brněnské PyLadies nese částečně v duchu experimentů.
Krom klasického kurzu pro začátečníky se totiž pod vedením Petra Viktorina rozběhl nový formát tohoto kurzu a také novinka pro pokročilejší, kurz zaměřený na realizaci praktického projektu a týmovou spolupráci. &lt;/p&gt;
&lt;p&gt;V rámci kurzu budeme pod Petrovým dohledem v devítičlenné skupině převádět do počítačové podoby deskovou hru RoboRally.
Včetně dokumentace, testování, všeho potřebného.
Kurz nemá předpřipravené materiály, vše bude na nás.
Jak Petr krásně na úvod řekl, budeme se učit dělat software tak, jak by se dělal, kdyby na to byl dostatek času :).
Protože mi přesně něco takového, jako je praktický projekt, po absolvování začátečnického kurzu chybělo, rozhodla jsem se to zkusit.&lt;/p&gt;
&lt;p&gt;Jak jsem již zmínila, kurz nemá žádné materiály, padlo tedy rozhodnutí psát o jeho průběhu blog. &lt;/p&gt;
&lt;p&gt;Složení našeho pracovního týmu je čistě dámské a všechny z nás jsou již s PyLadies nějak spojeny, ať už jako absolventky kurzů, nebo organizátorky. Sešly jsme se poprvé tento týden v prostorách společnosti Kinali, která se stala sponzorem tohoto kurzu a nabídla nám svoje prostory. Vděčíme za to Karolině, organizátorce začátečnického kurzu a zároveň účastnici tohoto projektu, která pro Kinali pracuje jako testerka. Děkujeme :) &lt;/p&gt;
&lt;p&gt;První setkání bylo primárně seznamovací. A to jak v rámci týmu, tak s náplní samotného kurzu (nebo spíše projektu) a toho, co nás čeká.
Proběhlo představovací kolečko, kde jsme mluvily také o tom, co nás do kurzu přivedlo. 
Většina z nás do toho jde s podobnou motivací - zdokonalit se v tom, co známe ze začátečnických kurzů, naučit se to více prakticky využívat, spolupracovat na vývoji, mít nějaký projekt, který budeme moci prezentovat.
A to nejen my, jednotlivé členky týmu, ale také celkově PyLadies, když se například účastníme nějaké konference nebo prezentace - budeme moci ukázat nějaký reálný výsledek práce absolventek kurzu. &lt;/p&gt;
&lt;figure class="figure"&gt;&lt;a href="./images/hrajeme.jpg" target="_blank" title="hrajeme"&gt;&lt;img alt="hrajeme" src="https://roboprojekt.pyladies.cz/images/thumbnails/hrajeme.jpg" class="figure-img img-fluid img-rounded"&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;Po vzájemném představení přišla už praktičtější část setkání, vyzkoušely jsme si nakreslit mind mapu na příkladu šachů, abychom ji pak doma vytvořily pro RoboRally.
Poté přišla na řadu samotná hra. Patřila jsem k té části týmu, co ji nikdy předtím nehrála, takže to bylo rozhodně potřeba :)
Stihly jsme několik kol, abychom si trochu prošly pravidla a ukázaly, jak hra funguje.
Z časových důvodů se nám však hru nepodařilo dohrát.
Jako základ pro tvorbu myšlenkové mapy to ale určitě spolu s psanými pravidly postačí.&lt;/p&gt;
&lt;p&gt;Příště se tedy sejdeme nad našimi mapami a uvidíme, co bude dál.
V mezičase nám pro domluvu a týmovou komunikaci bude sloužit Slack. &lt;/p&gt;&lt;/div&gt;</content><category term="blog"></category></entry></feed>