Create IT Blog - co se děje v Cleverlance

 

 

Jak vytvořit Pacmana v Pythonu - 2. částhttps://www.create-it.cz/Blog/Stranky/Pacman2.aspxJak vytvořit Pacmana v Pythonu - 2. část<p>Vítejte ve druhé části seriálu o tom, jak vytvořit hru Pac-Man v Pythonu. V <a href="/Blog/Stranky/Pacman1.aspx" target="_blank">minulém díle </a>jsme si představili základní principy hry Pac-Man a navrhli si její datovou strukturu. V tomto díle se budeme zabývat implementací několika důležitých prvků hry, jako je například kolize s duchy, počítání score, umělá inteligence duchů, power-upy, koncové stavy hry, animace a textury.<br></p><p>Nejprve si ale připomeneme, jakým způsobem bude hra fungovat. Hráč ovládá Pacmana a snaží se získat co nejvíce bodů za snězení všech cookies na mapě. Pacman je ale pronásledován duchy, kteří se po mapě pohybují podle určitých pravidel. Hra končí, pokud Pacmana chytí jeden z duchů, nebo pokud Pacman sní všechna cookies.<br></p><p>V tomto finálním díle se zaměříme na implementaci kolizí s duchy, které jsou pro hru důležité, jelikož jejich kontakt s Pacmanem může vést k jeho zničení. Dále se podíváme na to, jak můžeme počítat skóre hráče a jak implementovat umělou inteligenci duchů, aby se po mapě pohybovali realističtěji.<br></p><p>Power-upy jsou speciální prvky, které mohou hráči pomoci zvýšit jeho šance na vítězství. V našem případě to mohou být například různé druhy cookies, které mohou Pacmanovi dodat speciální schopnosti nebo ho ochránit před duchy.<br></p><p>Koncové stavy hry jsou důležité, abychom mohli oznámit hráči, zda vyhrál nebo prohrál. V našem případě budeme mít dva možné koncové stavy: vítězství, pokud Pacman sní všechna cookies, a prohru, pokud ho chytí jeden z duchů.<br></p><p>Animace a textury postav duchů a Pacmana zase zajistí, aby hra vypadala živěji a realističtěji. V našem případě budeme animovat pohyb Pacmana a duchů po mapě.<br></p><p>Pokud budete následovat tento článek až do konce, tak výsledná hra bude vypadat takhle:<br></p><p> <img src="/Blog/PublishingImages/Stranky/Pacman2/pacman4.gif" data-themekey="#" alt="" style="width:100%;" />  </p><h2>Kolize s duchy a počítání životů<br></h2><p>Počítání životů je spojeno se systémem kolizí hráče s duchy. V minulém díle jsme však pořádně neodlišili duchy od ostatních herních objektů, proto pro ducha založíme samostatnou funkcionalitu pro jeho ukládání, získávání a kontrolu kolize s hráčem. Logika je totožná s kolizí s cookie z prvního dílu. Také připravíme proměnné pro powerupy (schopnost podle originálního jména “kokoro”), životy, skóre a časovače událostí. Pro počítání životů jsem přidal jednoduchou funkci <em>kill_pacman</em> - pokud se ho dotkne duch, odeberu mu jeden život a umístím ho znovu na startovní pozici. Pokud mu dojdou životy, tak zničím jeho objekt.<span style="font-size:15px;"></span></p><pre> <code class="language-python hljs">#class GameRenderer: def __init__(self, in_width: int, in_height: int): self._won = False self._powerups = [] self._ghosts = [] self._hero: Hero = None self._lives = 3 self._score = 0 self._score_cookie_pickup = 10 self._score_ghost_eaten = 400 self._score_powerup_pickup = 50 self._kokoro_active = False self._current_mode = GhostBehaviour.SCATTER self._mode_switch_event = pygame.USEREVENT + 1 # custom event self._kokoro_end_event = pygame.USEREVENT + 2 self._pakupaku_event = pygame.USEREVENT + 3 self._modes = [ (7, 20), (7, 20), (5, 20), (5, 999999) # infinite chase ] self._current_phase = 0 def add_ghost(self, obj: GameObject): self._game_objects.append(obj) self._ghosts.append(obj) def get_ghosts(self): return self._ghosts def end_game(self): if self._hero in self._game_objects: self._game_objects.remove(self._hero) self._hero = None def kill_pacman(self): self._lives -= 1 self._hero.set_position(32, 32) self._hero.set_direction(Direction.NONE) if self._lives == 0: self.end_game() #class Hero def tick(): self.handle_cookie_pickup() self.handle_ghosts() def handle_ghosts(self): collision_rect = pygame.Rect(self.x, self.y, self._size, self._size) ghosts = self._renderer.get_ghosts() game_objects = self._renderer.get_game_objects() for ghost in ghosts: collides = collision_rect.colliderect(ghost.get_shape()) if collides and ghost in game_objects: if self._renderer.is_kokoro_active(): game_objects.remove(ghost) self._renderer.add_score(ScoreType.GHOST) else: if not self._renderer.get_won(): self._renderer.kill_pacman() </code></pre> <span style="color:#333333;font-family:farnham-web-medium, open-sans, sans-serif;font-size:1.46em;">Power-upy a počítání skóre</span> <p>Skóre je v Pacmanovi udělování za snězení cookie, power-upu nebo ducha. Hodnoty se pro každý ze zmíněných objektů liší. Specifikujeme si je proto do enumu <em>ScoreType</em>.<span style="font-size:15px;"></span></p><pre> <code class="language-python hljs">class ScoreType(Enum): COOKIE = 10 POWERUP = 50 GHOST = 400 </code></pre> <span style="text-align:justify;">V Pacmanovi existují speciální cookies, které mu udělí schopnost požírání duchů. V prvním díle jsme schopnost popsali původním japonským slovem “kokoro”, proto ji tak referencuji i v kódu. Vytvoříme novou třídu </span><em style="text-align:justify;">Powerup</em><span style="text-align:justify;"> - v podstatě totožné s </span><em style="text-align:justify;">Cookie</em><span style="text-align:justify;">, jen o něco větší. Do ASCII bludiště použijeme pro power-up písmeno “O” a ve funkci </span><em style="text-align:justify;">main </em><span style="text-align:justify;">lehce modifikujeme kód pro zpracování volných míst v bludišti. Také upravíme funkci pro kolizi s cookies  </span><em style="text-align:justify;">handle_cookie_pickup</em><span style="text-align:justify;">, a zahrneme i novou třídu </span><em style="text-align:justify;">Powerup</em><span style="text-align:justify;">. Když Pacman sebere power-up, aktivujeme tuto schopnost na 15 sekund. Po sebrání cookie i powerupu ještě zavoláme funkci </span><em style="text-align:justify;">add_score</em><span style="text-align:justify;"> s odpovídajícím typem skóre. Přidáme taky </span><em style="text-align:justify;">set_won</em><span style="text-align:justify;"> pro konec hry, kdy hráč (Pacman) sebral všechny cookies.</span><span style="font-size:15px;"></span> <pre> <code class="language-python hljs">class Powerup(GameObject): def __init__(self, in_surface, x, y): super().__init__(in_surface, x, y, 8, (255, 255, 255), True) # class GameRenderer def add_powerup(self, obj: GameObject): self._game_objects.append(obj) self._powerups.append(obj) def start_kokoro_timeout(self): pygame.time.set_timer(self._kokoro_end_event, 15000) # 15s def activate_kokoro(self): self._kokoro_active = True self.set_current_mode(GhostBehaviour.SCATTER) self.start_kokoro_timeout() def _handle_events(self): for event in pygame.event.get(): if event.type == self._kokoro_end_event: self._kokoro_active = False # class Hero def handle_cookie_pickup(self): collision_rect = pygame.Rect(self.x, self.y, self._size, self._size) cookies = self._renderer.get_cookies() powerups = self._renderer.get_powerups() game_objects = self._renderer.get_game_objects() cookie_to_remove = None for cookie in cookies: collides = collision_rect.colliderect(cookie.get_shape()) if collides and cookie in game_objects: game_objects.remove(cookie) self._renderer.add_score(ScoreType.COOKIE) cookie_to_remove = cookie if cookie_to_remove is not None: cookies.remove(cookie_to_remove) if len(self._renderer.get_cookies()) == 0: self._renderer.set_won() for powerup in powerups: collides = collision_rect.colliderect(powerup.get_shape()) if collides and powerup in game_objects: if not self._renderer.is_kokoro_active(): game_objects.remove(powerup) self._renderer.add_score(ScoreType.POWERUP) self._renderer.activate_kokoro() # main for powerup_space in pacman_game.powerup_spaces: translated = translate_maze_to_screen(powerup_space) powerup = Powerup(game_renderer, translated[0] + unified_size / 2, translated[1] + unified_size / 2) game_renderer.add_powerup(powerup) </code></pre><h2>Umělá inteligence duchů</h2><p>V originální hře se duchové chovají podle následujícího vzorce:</p><ol><li>vlna - SCATTER 7 sekund, pak CHASE 20 sekund<br></li><li>vlna - SCATTER 7 sekund, pak CHASE 20 sekund<br></li><li>vlna - SCATTER 5 sekund, pak CHASE 20 sekund<br></li><li>vlna - SCATTER 5 sekund, pak permanentně CHASE<br></li></ol><p>SCATTER je režim, ve kterém se duchové chovají náhodně a vybírají si náhodná místa v bludišti (ve skutečnosti mají ještě další specifičtější vzorce pro pohyb okolo překážek, ale do tyto složitější vzorce zde řešit nebudeme). CHASE je režim, ve kterém si duchové dají za cíl pozici hráče - využijeme pro to kód z prvního dílu a jen upravíme cílovou lokaci z náhodné na danou pozici hráče <em>get_hero_position</em>.<br></p><p>Tyto časovače máme v kódu od začátku článku, teď jen musíme přidat přepínání mezi režimy CHASE a SCATTER a kód pro zjištění trasy na pozici hráče.<span style="font-size:15px;"></span></p><pre> <code class="language-python hljs"># class GameRenderer def tick(self, in_fps: int): self.handle_mode_switch() def handle_mode_switch(self): current_phase_timings = self._modes[self._current_phase] print(f"Current phase: {str(self._current_phase)}, current_phase_timings: {str(current_phase_timings)}") scatter_timing = current_phase_timings[0] chase_timing = current_phase_timings[1] if self._current_mode == GhostBehaviour.CHASE: self._current_phase += 1 self.set_current_mode(GhostBehaviour.SCATTER) else: self.set_current_mode(GhostBehaviour.CHASE) used_timing = scatter_timing if self._current_mode == GhostBehaviour.SCATTER else chase_timing pygame.time.set_timer(self._mode_switch_event, used_timing * 1000) def get_hero_position(self): return self._hero.get_position() if self._hero != None else (0, 0) def set_current_mode(self, in_mode: GhostBehaviour): self._current_mode = in_mode def get_current_mode(self): return self._current_mode def _handle_events(self): for event in pygame.event.get(): if event.type == self._mode_switch_event: self.handle_mode_switch() # class Ghost def request_path_to_player(self, in_ghost): player_position = translate_screen_to_maze(in_ghost._renderer.get_hero_position()) current_maze_coord = translate_screen_to_maze(in_ghost.get_position()) path = self.game_controller.p.get_path(current_maze_coord[1], current_maze_coord[0], player_position[1],player_position[0]) new_path = [translate_maze_to_screen(item) for item in path] in_ghost.set_new_path(new_path) def calculate_direction_to_next_target(self) -> Direction: if self.next_target is None: if self._renderer.get_current_mode() == GhostBehaviour.CHASE and not self._renderer.is_kokoro_active(): self.request_path_to_player(self) else: self.game_controller.request_new_random_path(self) return Direction.NONE diff_x = self.next_target[0] - self.x diff_y = self.next_target[1] - self.y if diff_x == 0: return Direction.DOWN if diff_y > 0 else Direction.UP if diff_y == 0: return Direction.LEFT if diff_x < 0 else Direction.RIGHT if self._renderer.get_current_mode() == GhostBehaviour.CHASE and not self._renderer.is_kokoro_active(): self.request_path_to_player(self) else: self.game_controller.request_new_random_path(self) return Direction.NONE</code></pre><h2>Animace a textury<br></h2><p>Duchy a Pacmana upravíme tak, aby se místo dosavadních základních geometrických tvarů zobrazovali jako textury, respektive “sprites”. Do <em>MovableObject</em> třídy přidáme proměnnou image a upravíme funkci draw následovně:<span style="font-size:15px;"></span></p><pre> <code class="language-python hljs"># class MovableObject def __init__(self, in_surface, x, y, in_size: int, in_color=(255, 0, 0), is_circle: bool = False): self.image = pygame.image.load('images/ghost.png') def draw(self): self.image = pygame.transform.scale(self.image, (32, 32)) self._surface.blit(self.image, self.get_shape()) </code></pre><p>Referencované obrázky jsou dostupné na mém <a href="https://github.com/janjilecek/pacman_python_pygame" target="_blank">githubu</a>.<br></p><p>Každý duch bude mít jiný obrázek (specifikujeme ve funkci main) a když hráč aktivuje powerup, přepnou se duchové na texturu <em>fright</em>.<span style="font-size:15px;"></span></p><pre> <code class="language-python hljs"># class Ghost def __init__(self, in_surface, x, y, in_size: int, in_game_controller, sprite_path="images/ghost_fright.png"): super().__init__(in_surface, x, y, in_size) self.game_controller = in_game_controller self.sprite_normal = pygame.image.load(sprite_path) self.sprite_fright = pygame.image.load("images/ghost_fright.png") def draw(self): self.image = self.sprite_fright if self._renderer.is_kokoro_active() else self.sprite_normal super(Ghost, self).draw() </code></pre> <img src="/Blog/PublishingImages/Stranky/Pacman2/pacman1.gif" data-themekey="#" alt="" style="width:100%;" /> <p>Animace otevírání a zavírání pusy Pacmana uděláme přes časovanou událost <em>_pakupaku_event</em>, která se volá každých 200ms (implementujeme v kapitole níže). Ta zneguje binární hodnotu mouth_open a podle toho se vykreslí jeden nebo druhý sprite Pacmana.</p><pre> <code class="language-python hljs"># class Hero def __init__(self, in_surface, x, y, in_size: int): super().__init__(in_surface, x, y, in_size, (255, 255, 0), False) self.last_non_colliding_position = (0, 0) self.open = pygame.image.load("images/paku.png") self.closed = pygame.image.load("images/man.png") self.image = self.open self.mouth_open = True def draw(self): half_size = self._size / 2 self.image = self.open if self.mouth_open else self.closed self.image = pygame.transform.rotate(self.image, self.current_direction.value) super(Hero, self).draw() # class GameRenderer def _handle_events(self): if event.type == self._pakupaku_event: if self._hero is None: break self._hero.mouth_open = not self._hero.mouth_open </code> </pre><h2>Koncové stavy hry a textové UI<br></h2><p>Zobrazení stavu hry je na konec jednoduché. Funkcí <em>display_text</em> vykreslíme text o dané velikosti na danou pozici. V hlavní tick funkci zobrazíme na základě výsledku <em>get_won </em>text pro výhru “YOU WON”. Pokud neexistuje objekt hráče - což mohlo nastat jen při “smrti”, když objekt zničíme - tak zobrazíme text “YOU DIED”.</p><pre> <code class="language-python hljs"># class GameRenderer def display_text(self, text, in_position=(32, 0), in_size=30): font = pygame.font.SysFont('Arial', in_size) text_surface = font.render(text, False, (255, 255, 255)) self._screen.blit(text_surface, in_position) def set_won(self): self._won = True def get_won(self): return self._won def tick(self, in_fps: int): black = (0, 0, 0) self.handle_mode_switch() pygame.time.set_timer(self._pakupaku_event, 200) # open close mouth while not self._done: for game_object in self._game_objects: game_object.tick() game_object.draw() self.display_text( f"[Score: {self._score}] [Lives: {self._lives}]") if self._hero is None: self.display_text("YOU DIED", (self._width / 2 - 256, self._height / 2 - 256), 100) if self.get_won(): self.display_text("YOU WON", (self._width / 2 - 256, self._height / 2 - 256), 100) pygame.display.flip() self._clock.tick(in_fps) self._screen.fill(black) self._handle_events() </code></pre> <img src="/Blog/PublishingImages/Stranky/Pacman2/pacman2.gif" data-themekey="#" alt="" style="width:100%;" /> <h2>Závěrem</h2><p>Ve finální části seriálu o vývoji hry Pac-Man v Pythonu jsme se zaměřili na implementaci několika důležitých prvků hry.<br></p><p>Nejprve jsme si ukázali, jak můžeme implementovat kolize s duchy a počítat skóre hráče. Poté jsme se zaměřili na umělou inteligenci duchů, která je důležitá pro realistický pohyb těchto objektů po mapě. Dále jsme se věnovali implementaci power-upů, které mohou hráčům pomoci zvýšit šance na vítězství.<br></p><p>V závěru jsme se podívali na koncové stavy hry a implementovali jsme animace a textury objektů hry. Díky těmto prvkům se nám podařilo vytvořit kompletní prototyp legendární hry Pac-Man. V případě nejasností je můj kód k dispozici na <a href="https://github.com/janjilecek/pacman_python_pygame/blob/main/pacman_final.py" target="_blank">githubu</a>.<br></p><p>Doufám, že vám tento seriál pomohl pochopit, jak vytvořit hru Pac-Man v Pythonu, a že jste se při implementaci dozvěděli něco nového. Pokud máte zájem o další informace o vývoji her v Pythonu, neváhejte se podívat na další <a href="/Blog/Stranky/hra-v-pythonu.aspx" target="_blank">články</a> na našem webu.<br></p><p> <em>Jan Jileček</em><br></p>​<br>odborné;#hobby;#
Jak vytvořit Pacmana v Pythonu - 1. částhttps://www.create-it.cz/Blog/Stranky/Pacman1.aspxJak vytvořit Pacmana v Pythonu - 1. část<p>​​Pacman je kultovní plošinovka, kterou zná pravděpodobně každý. Jméno “Pac-man" pochází z japonského slova “paku", které označuje otevírání a zavírání úst. Tvůrce Toru Iwatani se inspiroval u japonské pohádky o bytosti, která ochraňuje děti před monstry tím, že monstra požírá. Při tvorbě hry použil jako odrazový můstek klíčová slova z příběhu, a sloveso “jíst" se stalo základem všeho.<br></p><p>Monstra jsou znázorněna jako čtyři duchové, kteří na hráče útočí v postupných vlnách, podobně jako ve Space Invaders. Každý z duchů má také unikátní osobnost. V pohádce je ještě jeden důležitý element, totiž koncept životní síly “kokoro", která bytosti umožňovala požírat monstra. Ve hře je tato energie znázorněna jako power-up cookiesky, které Pacmanovi uděluji krátkodobou schopnost požírat monstra.</p><p>V návodu vás nejprve provedu základním nastavením, pak vytvoříme herní objekty pro zeď bludiště, Pacmana a duchy, zajistíme hledání cesty bludištěm, duchům přidáme náhodný pohyb, u hráče implementujeme ovládání šipkami a nakonec do bludiště rozmístíme jídlo ve formě cookies. Vše budu doprovázet obrázky a gify pro lepší znázornění.</p><h2>Základní nastavení</h2><p>Výsledná hra má přibližně 300 řádků kódu, proto zde uvádím pouze nejdůležitější části. Kód v úplné podobě je dostupný na <a href="https://github.com/janjilecek/pacman_python_pygame/blob/main/pacman.py">mém github repozitáři</a>. Prvním krokem je instalace potřebných balíčků. Budeme potřebovat <em>pygame, numpy </em>a<em> tcod</em>. Nainstalujte si všechny přes nástroj pip (jak na to najdete <a href="/Blog/Stranky/Python-aplikace.aspx">v článku o Python aplikacích</a>). Pokud používáte vývojové prostředí jako např. PyCharm (doporučuji), instalace proběhne po kliknutí na hlášku o chybějícím balíčku.</p><p>Nejprve si vytvoříme herní okno, podobným způsobem jako v <a href="/Blog/Stranky/hra-v-pythonu.aspx">předchozím návodu na hru Space Invaders</a> (ta měla pouhých 100 řádků). Zde připravím parametry pro specifikaci velikosti okna, název hry, obnovovací frekvenci a několik datových polí, které budou držet reference na herní objekty a hráče. Funkce <em>tick </em>všechny herní objekty opakovaně prochází a volá jejich vnitřní logiku a vykreslování. Pak zbývá už jen překreslit celou herní plochu a zajistit zpracování vstupních událostí, jako jsou kliknutí myši a vstup z klávesnice. K tomu bude sloužit funkce <em>_handle_events</em>.</p><pre>​ <code class="language-python hljs"> import pygame # importy balíků import numpy as np import tcod class GameRenderer: def __init__(self, in_width: int, in_height: int): pygame.init() self._width = in_width self._height = in_height self._screen = pygame.display.set_mode((in_width, in_height)) pygame.display.set_caption('Pacman') self._clock = pygame.time.Clock() self._done = False self._game_objects = [] self._walls = [] self._cookies = [] self._hero: Hero = None def tick(self, in_fps: int): black = (0, 0, 0) while not self._done: for game_object in self._game_objects: game_object.tick() game_object.draw() pygame.display.flip() self._clock.tick(in_fps) self._screen.fill(black) self._handle_events() print("Game over") def add_game_object(self, obj: GameObject): self._game_objects.append(obj) def add_wall(self, obj: Wall): self.add_game_object(obj) self._walls.append(obj) def _handle_events(self): pass # dodelame </code> </pre><p></p><p>Vytvoření třídy pro zeď pak bude vypadat jednoduše. Barvu pro zdi volím modrou podle originálního Pacmana (parametr color - Blue 255, zbytek 0). <br></p><pre> <code class="language-python hljs"> class Wall(GameObject): def __init__(self, in_surface, x, y, in_size: int, in_color=(0, 0, 255)): super().__init__(in_surface, x * in_size, y * in_size, in_size, in_color) </code> </pre><p>Kód pro vykreslování a objekt pro zdi máme připraven. Při psaní se ujistěte, že třídy <em>Wall </em>a <em>GameObject </em>jsou nad třídou <em>GameRenderer</em>, aby je třída “viděla". Dalším krokem je vykreslení bludiště na obrazovku. Ale ještě předtím musíme vytvořit jednu pomocnou třídu.<br></p><h2>Třída game controller</h2><p>Bludiště ve formě ASCII znaků uložím do proměnné v nové třídě <em>PacmanGameController</em>. Použiju velikost bludiště jako v originále - 28x31 dlaždic. Později budu muset zajistit, aby duchové mohli správně hledat cestu v bludišti a případně i najít hráče. Bludiště nejprve načtu jako znaky a převedu ho na pole jedniček a nul, kde zeď bude nula a průchodný prostor bude jedna. Tyto hodnoty slouží algoritmu hledání cesty jako tzv. cost funkce. Nula značí nekonečnou cenu průchodu, proto nebudou takto označené položky pole považovány za průchodné. Všimněte si pole <em>reachable_spaces</em>, které drží průchozí části bludiště. K tomu ale až později, jako první musím připravit struktury třídy. Bludiště v ASCII podobě můžete zkopírovat z mého <a href="https://github.com/janjilecek/pacman_python_pygame/blob/main/pacman.py">githubu</a>. Ve znakovém zápisu jsem použil “X" pro zeď, “P" pro Pacmana a “G" pro ducha. </p><pre> <code class="language-python hljs"> class PacmanGameController: def __init__(self): self.ascii_maze = [ "XXXXXXXXXXXXXXXXXXXXXXXXXXXX", "XP XX X", "X XXXX XXXXX XX XXXXX XXXX X", "X XXXX XXXXX XX XXXXX XXXX X", "X XXXX XXXXX XX XXXXX XXXX X", "X X", "X XXXX XX XXXXXXXX XX XXXX X", "X XXXX XX XXXXXXXX XX XXXX X", "X XX XX XX X", "XXXXXX XXXXX XX XXXXX XXXXXX", "XXXXXX XXXXX XX XXXXX XXXXXX", "XXXXXX XX XX XXXXXX", "XXXXXX XX XXXXXXXX XX XXXXXX", "XXXXXX XX X G X XX XXXXXX", " X G X ", "XXXXXX XX X G X XX XXXXXX", # zkraceno pro clanek "XXXXXXXXXXXXXXXXXXXXXXXXXXXX", ] self.numpy_maze = [] self.cookie_spaces = [] self.reachable_spaces = [] self.ghost_spawns = [] self.size = (0, 0) self.convert_maze_to_numpy() #self.p = Pathfinder(self.numpy_maze) # pouzijeme pozdeji def convert_maze_to_numpy(self): for x, row in enumerate(self.ascii_maze): self.size = (len(row), x + 1) binary_row = [] for y, column in enumerate(row): if column == "G": self.ghost_spawns.append((y, x)) if column == "X": binary_row.append(0) else: binary_row.append(1) self.cookie_spaces.append((y, x)) self.reachable_spaces.append((y, x)) self.numpy_maze.append(binary_row) </code> </pre><h2>Vykreslení bludiště</h2><p>Vše nutné pro vykreslení bludiště je připraveno, takže už jen stačí vytvořit instance našich tříd <em>PacmanGameController,</em> projít 2D pole s pozicemi zdí a na těchto místech vytvořit objekt <em>Wall </em>(používám neuvedenou funkci <em>add_wall</em>, opět nahlédněte do úplného kódu na mém <a href="https://github.com/janjilecek/pacman_python_pygame/blob/main/pacman.py">githubu</a>). Obnovovací frekvenci nastavuji na 120 snímků za vteřinu. </p><pre> <code class="language-python hljs"> if __name__ == "__main__": unified_size = 32 pacman_game = PacmanGameController() size = pacman_game.size game_renderer = GameRenderer(size[0] * unified_size, size[1] * unified_size) for y, row in enumerate(pacman_game.numpy_maze): for x, column in enumerate(row): if column == 0: game_renderer.add_wall(Wall(game_renderer, x, y, unified_size)) game_renderer.tick(120) </code> </pre><p style="text-align:center;"> <img src="/Blog/PublishingImages/Stranky/Pacman1/unnamed-3.png" alt="pacman" data-themekey="#" style="max-width:400px;" /><br></p><h2>Přidání duchů</h2><p>V originálním Pacmanovi byli čtyři duchové jmény Blinky, Pinky, Inky a Clyde, každý s individuálním charakterem a schopnostmi. Koncept hry je založen na japonské pohádce (více <a href="https://www.gamedeveloper.com/design/the-pac-man-dossier">zde</a> a <a href="https://gameinternals.com/understanding-pac-man-ghost-behavior">zde</a>) a originální jména v japonštině i naznačují jejich schopnosti (např. Pinky má japonské jméno Lupič, Blinky je zase Stín). Pro naši hru ale nebudeme zacházet do takových detailů a každý z duchů bude používat jen základní behaviorální smyčku jako v originále - tzn. módy <em>Chase</em>, <em>Scatter </em>a <em>Frightened. </em>Tyto AI módy si popíšeme a zpracujeme ve druhém díle.</p><p>Třída pro ducha bude jednoduchá, většinu chování zdědí od rodičovské třídy <em>MovableObject </em>(nahlédněte na <a href="https://github.com/janjilecek/pacman_python_pygame/blob/main/pacman.py">github</a>, ta třída je o něco složitější a obsahuje logiku pro pohyb ve čtyřech směrech, následování trasy a ověřování kolize se zdí). </p><pre> <code class="language-python hljs"> class Ghost(MovableObject): def __init__(self, in_surface, x, y, in_size: int, in_game_controller, in_color=(255, 0, 0)): super().__init__(in_surface, x, y, in_size, in_color, False) self.game_controller = in_game_controller </code> </pre><p> </p><p>Do třídy <em>PacmanGameController</em> přidám hodnoty RGB barev jednotlivých duchů a ve funkci <em>main</em> vygeneruji čtyři barevné duchy. Připravím si také statickou funkci pro převod souřadnic, která jednoduše převede souřadnice bludiště (např. x=16 y=16 je přibližně střed bludiště, a pronásobením s velikostí buňky, neboli tile, dostanu souřadnici na herní ploše v pixelech). </p><pre> <code class="language-python hljs"> # v PacmanGameController self.ghost_colors = [ (255, 184, 255), (255, 0, 20), (0, 255, 255), (255, 184, 82) ] # ve funkci main for i, ghost_spawn in enumerate(pacman_game.ghost_spawns): translated = translate_maze_to_screen(ghost_spawn) ghost = Ghost(game_renderer, translated[0], translated[1], unified_size, pacman_game, pacman_game.ghost_colors[i % 4]) game_renderer.add_game_object(ghost) # obecné funkce pro převod souřadnic, umístěte na začátek kódu def translate_screen_to_maze(in_coords, in_size=32): return int(in_coords[0] / in_size), int(in_coords[1] / in_size) def translate_maze_to_screen(in_coords, in_size=32): return in_coords[0] * in_size, in_coords[1] * in_size </code> </pre><p>V této fázi se již budou po spuštění hry vykreslovat čtyři duchové v bludišti. Dále je chceme rozpohybovat. </p><h1>Hledání cesty bludištěm</h1><p>Nyní přichází možná nejsložitější část. Hledání cesty ve 2D prostoru, nebo grafu, je obtížný problém. Implementovat algoritmus pro vyřešení takového problému by dalo na další článek, proto použijeme hotové řešení. Nejefektivnějším algoritmem pro hledání cesty je <a href="https://cs.wikipedia.org/wiki/A%2a">A* algoritmus</a>. Ten nám poskytne balíček <em>tcod</em>, který jsme instalovali na začátku.</p><p>Vytvořím teď třídu Pathfinder. V konstruktoru inicializuji <em>numpy</em> pole s cenou průchodu (pole jedniček a nul, popsané výše) a vytvořím třídní proměnnou <em>pf, </em>která bude držet instanci A* pathfinderu. Funkce <em>get_path</em> nám pak po zavolání se souřadnicemi v bludišti (odkud, kam) vypočítá a vrátí trasu ve formě jednotlivých kroků polem. </p><pre> <code class="language-python hljs"> class Pathfinder: def __init__(self, in_arr): cost = np.array(in_arr, dtype=np.bool_).tolist() self.pf = tcod.path.AStar(cost=cost, diagonal=0) def get_path(self, from_x, from_y, to_x, to_y) -> object: res = self.pf.get_path(from_x, from_y, to_x, to_y) return [(sub[1], sub[0]) for sub in res] </code> </pre><p>Do funkce <em>main</em> přidám úsek pro demonstraci vyhledání trasy. Volím souřadnice začátku trasy [1,1] a cíle trasy [24,24].<br></p><pre> <code class="language-python hljs"> # Vykreslení cesty red = (255, 0, 0) green = (0, 255, 0) _from = (1, 1) _to = (24, 24) path_array = pacman_game.p.get_path(_from[1], _from[0], _to[1], _to[0]) # print(path_array) # [(1, 2), (1, 3), (1, 4), (1, 5), (2, 5), (3, 5), (4, 5), (5, 5), (6, 5), (6, 6), (6, 7) ... # white = (255, 255, 255) for path in path_array: game_renderer.add_game_object(Wall(game_renderer, path[0], path[1], unified_size, white)) # from_translated = translate_maze_to_screen(_from) game_renderer.add_game_object( GameObject(game_renderer, from_translated[0], from_translated[1], unified_size, red)) # to_translated = translate_maze_to_screen(_to) game_renderer.add_game_object( GameObject(game_renderer, to_translated[0], to_translated[1], unified_size, green)) </code> </pre><p>Ve hře vypadá vykreslení nejkratší trasy takto:</p><div style="text-align:center;"> <img src="/Blog/PublishingImages/Stranky/Pacman1/unnamed.gif" alt="pacman" data-themekey="#" style="max-width:400px;" />  </div><h2>Náhodný pohyb duchů</h2><p>Ve třídě <em>PacmanGameController </em>vytvářím novou funkci pro zvolení náhodného bodu z pole dosažitelných míst <em>reachable_spaces</em>. Každý duch tuto funkci použije po tom, co dorazí do cíle. Jednoduše si tak duchové donekonečna volí cestu ze své aktuální pozice v bludišti do náhodného cíle. Složitější chování, jako útěk a honění hráče, implementujeme v dalším díle. </p><pre> <code class="language-python hljs"> def request_new_random_path(self, in_ghost: Ghost): random_space = random.choice(self.reachable_spaces) current_maze_coord = translate_screen_to_maze(in_ghost.get_position()) path = self.p.get_path(current_maze_coord[1], current_maze_coord[0], random_space[1], random_space[0]) test_path = [translate_maze_to_screen(item) for item in path] in_ghost.set_new_path(test_path) </code> </pre><p>Duchovi přidáme ve třídě <em>Ghost </em>novou logiku pro následování trasy. Funkce <em>reached_target</em> je volaná každý snímek a kontroluje, zda duch již dorazil do cíle. Pokud ano, zjistí jakým směrem je další krok cesty bludištěm a podle toho začne měnit svoji pozici buď nahoru, dolů, doleva nebo doprava (logika pro pohyb je volaná v rodičovské třídě <em>MovableObject</em>). </p><pre> <code class="language-python hljs"> def reached_target(self): if (self.x, self.y) == self.next_target: self.next_target = self.get_next_location() self.current_direction = self.calculate_direction_to_next_target() def set_new_path(self, in_path): for item in in_path: self.location_queue.append(item) self.next_target = self.get_next_location() def calculate_direction_to_next_target(self) -> Direction: if self.next_target is None: self.game_controller.request_new_random_path(self) return Direction.NONE diff_x = self.next_target[0] - self.x diff_y = self.next_target[1] - self.y if diff_x == 0: return Direction.DOWN if diff_y > 0 else Direction.UP if diff_y == 0: return Direction.LEFT if diff_x < 0 else Direction.RIGHT self.game_controller.request_new_random_path(self) return Direction.NONE def automatic_move(self, in_direction: Direction): if in_direction == Direction.UP: self.set_position(self.x, self.y - 1) elif in_direction == Direction.DOWN: self.set_position(self.x, self.y + 1) elif in_direction == Direction.LEFT: self.set_position(self.x - 1, self.y) elif in_direction == Direction.RIGHT: self.set_position(self.x + 1, self.y) </code> <br><br></pre><p>Duchové se teď vytvoří na pozicích určených písmenem “G" v původním ASCII bludišti a začnou si hledat náhodnou cestu. Já jsem zavřel tři duchy do klece - jako v původním Pacmanovi budou vypouštěni postupně - a jeden bloudí bludištěm:</p><p style="text-align:center;"> <img src="/Blog/PublishingImages/Stranky/Pacman1/unnamed-2.gif" alt="pacman" data-themekey="#" style="max-width:400px;" /> <br> </p><h2>Přidání hráče a jeho ovládání</h2><p>Pro hráče dělám třídu Hero. Většina logiky pro ovládání hráče i duchů je řešena ve funkci <em>MovableObject</em>, proto stačí pouze pár funkcí pro upřesnění chování. V originále se Pacman hýbe ve čtyřech směrech, šipkami ovládáme jeho chůzi bludištěm. Pokud nezmáčkneme žádnou směrovou klávesu, bude pokračovat posledním validním směrem. Pokud zmáčkneme klávesu ve směru, kterým ještě nelze jít, směr se uloží a použije se při příští dostupné zatáčce. Stejné chování replikuji do naší hry a přidal jsem i Pacmanovu schopnost teleportovat se z jednoho konce bludiště na druhý - prostě zkontroluji, jestli je mimo herní plochu zleva nebo zprava, a podle toho nastavím jeho pozici na opačnou stranu bludiště. Pacman má taky upravenou funkci pro vykreslování, musíme ho vykreslit s poloviční velikostí, kterou by normálně zabíral jako čtverec (<em>pygame.rect</em>).<br></p><pre> <code class="language-python hljs"> class Hero(MovableObject): def __init__(self, in_surface, x, y, in_size: int): super().__init__(in_surface, x, y, in_size, (255, 255, 0), False) self.last_non_colliding_position = (0, 0) def tick(self): # TELEPORT if self.x < 0: self.x = self._renderer._width if self.x > self._renderer._width: self.x = 0 self.last_non_colliding_position = self.get_position() if self.check_collision_in_direction(self.direction_buffer)[0]: self.automatic_move(self.current_direction) else: self.automatic_move(self.direction_buffer) self.current_direction = self.direction_buffer if self.collides_with_wall((self.x, self.y)): self.set_position(self.last_non_colliding_position[0], self.last_non_colliding_position[1]) self.handle_cookie_pickup() def automatic_move(self, in_direction: Direction): collision_result = self.check_collision_in_direction(in_direction) desired_position_collides = collision_result[0] if not desired_position_collides: self.last_working_direction = self.current_direction desired_position = collision_result[1] self.set_position(desired_position[0], desired_position[1]) else: self.current_direction = self.last_working_direction def handle_cookie_pickup(self): collision_rect = pygame.Rect(self.x, self.y, self._size, self._size) cookies = self._renderer.get_cookies() game_objects = self._renderer.get_game_objects() for cookie in cookies: collides = collision_rect.colliderect(cookie.get_shape()) if collides and cookie in game_objects: game_objects.remove(cookie) def draw(self): half_size = self._size / 2 pygame.draw.circle(self._surface, self._color, (self.x + half_size, self.y + half_size), half_size) </code> </pre><p>Třídu <em>Hero</em> instancuji na konci funkce main. Pozice nastavuji na souřadnici [1,1] - <em>unified_size </em>je velikost jedné dlaždice. Do <em>GameRenderer</em> třídy ještě musíme přidat zpracování vstupních události, abychom mohli herní postavu ovládat.<br></p><pre> <code class="language-python hljs"> # ve třídě GameRenderer def add_hero(self, in_hero): self.add_game_object(in_hero) self._hero = in_hero def _handle_events(self): for event in pygame.event.get(): if event.type == pygame.QUIT: self._done = True pressed = pygame.key.get_pressed() if pressed[pygame.K_UP]: self._hero.set_direction(Direction.UP) elif pressed[pygame.K_LEFT]: self._hero.set_direction(Direction.LEFT) elif pressed[pygame.K_DOWN]: self._hero.set_direction(Direction.DOWN) elif pressed[pygame.K_RIGHT]: self._hero.set_direction(Direction.RIGHT) # na konci funkce main pacman = Hero(game_renderer, unified_size, unified_size, unified_size) game_renderer.add_hero(pacman) game_renderer.tick(120) </code> </pre><p>Po spuštění můžeme Pacmana vodit bludištěm!</p><p style="text-align:center;"> <img src="/Blog/PublishingImages/Stranky/Pacman1/unnamed-3.gif" alt="pacman" data-themekey="#" style="max-width:400px;" /><br></p><h2>Přidání cookies</h2><p>Nebyl by to Pacman bez cookies v bludišti. Z herního hlediska určují míru prozkoumanosti světa a některé cookies i obrací schopnosti duchů a Pacmana. Jsou tedy ultimátní odměnou pro hráče a hlavním ukazatelem jeho postupu úrovní. V dnešních hrách se běžně odměňuje chování, které chce herní designér podporovat ve hráči. Krásným příkladem je např. letošní <em>Elden Ring</em>, kde dostane odměnu každý, kdo prozkoumává všechny kouty světa. Čím nebezpečnější a odlehlejší, tím větší odměna. Naopak hry jako novodobý <em>Assassin's Creed</em> podporují plnění úkolů, takže máte při hraní pocit, že jste v práci, a ne ve hře.</p><p>Přidání cookies bude nejsnadnější věcí celého návodu, a proto jsem ji nechal na konec, jako třešničku na dortu. Vytvořím třídu <em>Cookie</em>. Její instance bude mít vždy velikost čtyři pixely, žlutou barvu a kruhový tvar. Ve funkci main vytvořím cookies na všech dlaždicích, které jsme na začátku uložili do pole <em>cookie_spaces</em> (totožné s <em>reachable_spaces</em>). Hráčovi přidám funkci <em>handle_cookie_pickup</em>, ve které si neustále ověřuji, jestli nedochází ke kolizi hráče s nějakou cookie. Pokud tomu tak je, cookie odstraním z pole a ta se přestane vykreslovat.<br></p><pre> <code class="language-python hljs"> class Cookie(GameObject): def __init__(self, in_surface, x, y): super().__init__(in_surface, x, y, 4, (255, 255, 0), True) # ve třídě GameRenderer přidat: def add_cookie(self, obj: GameObject): self._game_objects.append(obj) self._cookies.append(obj) # ve třídě Hero přidat: def handle_cookie_pickup(self): collision_rect = pygame.Rect(self.x, self.y, self._size, self._size) cookies = self._renderer.get_cookies() game_objects = self._renderer.get_game_objects() for cookie in cookies: collides = collision_rect.colliderect(cookie.get_shape()) if collides and cookie in game_objects: game_objects.remove(cookie) # ve funkci main: for cookie_space in pacman_game.cookie_spaces: translated = translate_maze_to_screen(cookie_space) cookie = Cookie(game_renderer, translated[0] + unified_size / 2, translated[1] + unified_size / 2) game_renderer.add_cookie(cookie) </code> </pre><p>Výsledek našeho snažení:<br></p><p style="text-align:center;"> <img src="/Blog/PublishingImages/Stranky/Pacman1/unnamed-4.gif" alt="pacman" data-themekey="#" style="max-width:400px;" />  </p><p> </p><p>Malá zajímavost za závěr - v originální hře se Pacman zastaví na dobu jednoho snímku po každém požití cookie, takže ho duchové snáze dohoní v počátku hry, když je ještě pole zaplněné. V příštím díle zpracujeme podobnou herní mechaniku a můžete se těšit i na umělou inteligenci duchů, počítání score, zvuky, animace, textury, power-upy, screen-shake efekty, životy a koncové stavy hry.<br></p><p><br></p><p><i>Jan Jileček</i></p><p> <br> </p>​<br>odborné;#hobby;#
​Pět současných trendů UX https://www.create-it.cz/Blog/Stranky/UX-trendy.aspx​Pět současných trendů UX <p>​Když jsme v roce 2009 vydávali první almanach Uživatelsky přívětivá rozhraní v ČR, bylo u nás kolem dvaceti odborníků zabývající se tímto fenoménem. Dnes podle údajů Glassdoor, celosvětového lídra v oblasti informací o pracovních místech a trendech zaměstnanosti, UX designer celosvětově patří mezi 25 nejžádanějších povolání. Vstup společnosti Google do světa vzdělávání způsobil, že v oboru UX bylo vydáno více než půl milonů certifikátů. Obor se vyvíjí a s ním i požadavky a výstupy této kreativní činnosti. Pojďme se podívat, které jsou podle nás aktuálně ty nejzajímavější.<br></p><h2> 1. Uživatelská rozhran​​í jsou nositelé brandu </h2><p> Čím více o uživatelích díky výzkumům víme, tím více mají vývojové týmy času a prostředků soustředit se na formu a konzistenci výstupů uživatelských rozhraní. Pro maximální uživatelský zážitek musí všechny výstupy vypadat obdobně, firmy si nemohou dovolit mluvit na zákazníka pokaždé jiným jazykem. Mnoho firem přitom v současnosti řeší ovládání a vzhled aplikace maximálně na úrovni korporátní barvy. Brand esence značky nesená přes uživatelské rozhraní je ale důležitý rozměr komunikace nejenom směrem k zákazníkům, ale i dovnitř samotných společností. Ukazuje to příklad Nike, u jejíchž uživatelských rozhraní je na první pohled vždy rozpoznatelné, že se jedná právě o tuto značku. </p><h2> 2. Design systém jako součást UX dodá​​vky<br></h2><p> Aby si brand zachoval svoji jedinečnost, není možné, aby vzhled jednotlivých technologických řešení závisel pouze na dodavateli nebo platformě. Standardem se stává Design system management (DSM), což je soubor standardů pro správu designu ve velkém měřítku. Díky nástrojům, které v této oblasti vznikly, je možné mít nepřetržitý přístup k aktuálnímu designovému manuálu, a to i pro třetí strany. Výsledkem je vizuální konzistence napříč různými rozhraními nebo digitálními kanály. </p><h2> 3. Budování důvěryhodnosti skrze uživatelský záži​​tek<br></h2><p> Uživatel si stejně jako dříve s produktem kupuje i zážitek z koupě, jen tentokrát v digitálním prostředí. Fakt, že konzistence vzhledu a ovládání je pro uživatele zásadní ve vztahu ke značce, potvrzují i mnohé studie. Například podle Adobe Trust Report (The digital economy is personal, 2022) 57 % spotřebitelů tvrdí, že jakmile společnost naruší jejich důvěru, už jí znovu nedají šanci. 70 % spotřebitelů pak tvrdí, že nepřesná personalizace snižuje jejich důvěru ve značku. S tím souvisí i nakládání se zákaznickými daty. I zde platí pravidlo, že čím transparentnější přístup v digitálním prostředí směrem ke zpracovávaným datům zákazníka, tím je zákazník ochotnější podělit se o svá data se společností, které důvěřuje. <br></p><p> <a href="https://www.cleverlance.com/cz/kariera/Stranky/Skoleni/UX-Akademie.aspx?utm_source=web&utm_medium=blog&utm_campaign=nabor&utm_id=kariera" target="_blank"><img src="/Blog/PublishingImages/Stranky/UX-trendy/skoleniUX.png" alt="skoleniUX.png" data-themekey="#" style="max-width:690px;" />​</a> <br> </p><h2> 4. Typografie - drobnost s fatálním ​dopadem<br></h2><p> Malý, ale významný detail brandu v sobě ukrývá typografie, Čím více textu se přenáší do digitálních zařízení, tím více se od písma vyžaduje kvalita. UX designér si musí uvědomovat, že se dnes text používá v nejrůznějších situacích a místech: řidič sledující přístrojovou desku v autě, běžec nastavující tempo ve své aplikaci, ranní čtení zpráv na mobilu cestou do práce, skladník kontrolující data ze čtečky, operátor nastavující přístroj ve výrobním závodě… Všechny tyto situace mají jedno společné: uživatel často drží zařízení v ruce a čte z roztřeseného displeje. To samozřejmě klade na písmo mnohem větší nároky, než když se používá na stabilním podkladu. V Cleverlance na žádost klientů společně s typografy vytváříme nové písmo, které čitelnost a čtivost textu v náročných podmínkách zvýší. </p><h2> 5. Limity interních UX​ týmů<br></h2><p> Touha mnoha firem odejít od UX konzultantů a zřídit interní UX týmy naráží na své limity. Očekávání, že jeden interní odborník v UX obsáhne všechny UX dovednosti, se často ukazuje jako nereálné. Podobory UX jako výzkum, copywriting nebo design se specializovaly do takové míry, kdy je jeden expert není schopen ovládnout na požadované úrovni. Ve firmách proto postupně vznikají stále početnější UX týmy, na trhu práce je zároveň stále obtížnější najít specialisty s očekávanou úrovní znalostí a dovedností. Výsledkem je pak zaměření se interního týmu jen na jednu z oblastí UX, například na výzkum. Ten ale bez kvalitního designéra přináší jen teoretické výsledky. Významným handicapem těchto týmu je také přílišné (i když pochopitelné) zaměření se na konkrétní produkt společnosti. Designérům i výzkumníkům pak chybí srovnání s jinými odvětvími, nadhled a best practices. Do hry tak​ znovu vstupují technologické společnosti, které jsou díky pestrosti svých zakázek schopny obohatit firmy novými přístupy a interní UX týmy smysluplně doplnit.</p><p> <br> </p><p> <i>Michal Hořava</i></p><p>QUB Digital<br>​<br><br></p>odborné;#
Když se řekne analytik, znamená to, že…https://www.create-it.cz/Blog/Stranky/analytici.aspxKdyž se řekne analytik, znamená to, že…<p>​​Z pohledu IT být analytikem znamená několik různých pracovních pozic s různou náplní práce. Patří sem role IT analytik, který bývá také označován jako systémový analytik, nebo business analytik, datový analytik či test analytik. Co ale vlastně člověk v té které pracovní pozici dělá a za co zodpovídá? Podívejme se na jednotlivé role chronologicky, tak jak vstupují do průběhu IT projektu.<br></p><h2>Business analytik​​<br></h2><p>První analytickou pozicí, která se zapojuje do projektu, je <strong>business analytik</strong>. Jeho zodpovědností, velice zjednodušeně řečeno, je komunikace s klientem, se zástupci businessu u zákazníka​. Cílem jeho práce je sběr potřeb klienta, jejich transformace do požadavků a seřazení dle důležitosti. Následně analytik vypracovává návrh řešení, tj. de facto staví software z pohledu uživatele. Svůj návrh zaznamenává do business analýzy, což znamená tvorbu procesních diagramů, Use Case modelů nebo User Stories, aktivity diagramů, popsání uživatelských rolí, nakreslení drátěných modelů obrazovek atd., tedy všeho, z čeho bude možné vyčíst, jak má systém fungovat z pohledu uživatele. Co všechno musí znát dobrý business analytik se můžete dočíst <a href="/Blog/Stranky/analyza.aspx">zde</a>.<br></p><h2>IT analytik​​<br></h2><p><strong>IT analytik</strong> neboli také systémový analytik, vstupuje do procesu projektu záhy nebo společně s business analytikem. Jeho zodpovědností je návrh technického řešení systému. Při své práci intenzivně komunikuje jak s IT architektem, který má na starosti návrh konceptu vývoje aplikace, tak s business analytikem, který mu předkládá funkční požadavky a popis řešení z pohledu businessu. IT analytik pak navrhuje a popisuje detaily technického řešení, jednotlivých modulů systému, datových a objektových struktur včetně jejich vazeb, definuje rozhraní, modeluje sekvenční diagramy atd. Výstupy IT analytika jsou společně s výstupy business analytika zadáním, dle kterého vývojáři programují požadovaný systém. I proto je u IT analytika standardním požadavkem znalost programovacích jazyků jako např. Java, .NET, SQL nebo XML. Oč​​​ekávaná je také znalost metodik jako RUP a ITIL nebo v poslední době rozšířeného <a href="/Blog/Stranky/DevOps.aspx" target="_blank">DevOps</a> přístupu k vývoji software.<br></p><h2>Test analytik​​<br></h2><p><strong>Test analytik</strong> zpracovává test analýzu. Nastuduje si vstupy business a IT analytika, projde s nimi procesy a logiku celého očekávaného řešení tak, aby pochopil, jak má ve výsledku systém fungovat. Z toho vyplývá, že do projektu vstupuje buď až po zpracování business a IT analýzy, nebo před jejím ukončením. Po seznámení se s analytickými dokumenty vypracovává testovací scénáře (Test Case), test suits (logické seskupení testů, které spolu souvisí) a testovací skripty. Může se také stát, že při tvorbě testovacích scénářů narazí na nějaký nedostatek v business či IT analýze. V daném případě na tuto skutečnost upozorní, aby mohl business nebo IT analytik zjištěný nedostatek do analýzy dopracovat. Test analytik také v průběhu tvorby testovacích scénářů definuje potřebná testovací data pro otestování software. Ve finále je schopen navrhnout plán testování, tj. pořadí testování jednotlivých testovacích scénářů. Někdy také bývá tím, kdo testovací data připravuje, případně se účastní samotného testování software.<br></p><h2>Datový analytik​​<br></h2><p><strong>Datový analytik</strong>, jak již vyplývá z názvu, pracuje s daty. V každém systému jsou tisíce, někdy i miliony datových záznamů, ze kterých lze pro potřeby businessu vytěžit množství zajímavých informací. Jedná se o číselné hodnoty, ale také data textového charakteru. Datový analytik pracuje jak s primárními zdroji dat, tj. daty z hlavního systému, tak sekundárními, například s daty ze systémů, které řeší méně důležité, tedy podpůrné procesy. Analytik data třídí, čistí a analyzuje prostřednictvím standardních statistických nástrojů. Vytváří různé typy reportů a vizualizace pro business nebo management. Navrhuje a tvoří relační databáze, definuje korelace a vzorce v komplikovaných datových setech. Mezi primární znalosti datového analytika patří navrhování databází, orientace v datových skladech a BI platformách, SQL, data mining, schopnost vizualizovat výsledná data a prezentovat zjištěné výsledky. Ale také znalost statistických technik, matematické vědomosti a orientace ve finančnictví. Datový analytik se může do projektu zapojit vlastně kdykoliv. Může být součástí týmu téměř od začátku, pokud se například jedná o projekt, kterého součástí je migrace dat z původního systému do nového. Nebo se může zapojit do projektu po nasazení systému do produkce, aby vydoloval a zpracoval první výstupy pro business či management klienta, přičemž v této práci může pokračovat a průběžně připravovat různé reporty a vizualizace.</p><p>Jak je z popisu výše vidět, do vytvoření návrhu systému vstupuje hned několik analytiků, přičemž jejich práce na sebe navazuje. I proto je pro všechny důležitá průběžná více či méně intenzivní komunikace. Vlastně by se dal návrh nového software popsat jako hra symfonického orchestru, kdy housle doplní flétna či hoboj, sem tam do toho zazní lesní rohy nebo bouchne tympán. Pokud jsou všichni sladěni, zní nádherná melodie, no a pokud ne, pak si všichni kolem zakrývají uši. V případě software by se „falešná hra“ projevila nefunkčním řešením, které by nesplňovalo potřeby klienta a navíc nejspíš nebylo použitelné.​<br></p><p><i>Zuzana Drotárová​</i></p><p><br></p>odborné;#vzdělávání;#
Proč nám cookies otravují život?https://www.create-it.cz/Blog/Stranky/Cookies.aspxProč nám cookies otravují život?<p>​Všimli jste si, že poslední dobou na nás vyskakuje souhl​​as s používáním cookies (tzv. cookies lišta) skoro z každého webu? Je to velmi otravné, že?<br></p><p>Znamená to, že by společnosti konečně začaly brát vážně naše soukromí? Je od nich určitě hezké, že se vždy zeptají, pokud chtějí cookies používat. Ale realita je taková, že provozovatelé webu toto nedělají dobrovolně, ale protože musí.<br></p><p> <img src="/Blog/PublishingImages/Stranky/Cookies/cookies%20lišta.jpg" data-themekey="#" alt="cookies" style="max-width:690px;" /> <br> </p><p> <span style="color:#333333;font-family:farnham-web-medium, open-sans, sans-serif;font-size:1.46em;">Nová legislativa</span><br></p><p>Od 1. ledna 2022 totiž vešla v platnost nová legislativa, která mění <a href="https://www.zakonyprolidi.cz/cs/2005-127" target="_blank">zákon č. 127/2005 Sb., o elektronických komunikacích</a>. Jedná se o velmi rozsáhlou novelu čítající více než 400 změn. V rámci této novely došlo také ke změnám v celé řadě dalších zákonů, jako například zákona o pozemních komunikacích, zákona o provozování rozhlasového a televizního vysílání, a dalších. Veškeré změny, které novela přináší, byly přijaty z důvodu zavedení evropské směrnice 2018/1972 do českého právního řádu, do oblasti týkající se elektronické komunikace.</p><h2>Cookies dříve a nyní</h2><p>Tento nový zákon má zásadní dopad na používání cookies na webu. I dříve musel mít provozovatel webu souhlas uživatele s ukládáním cookies (dle nařízení GDPR). Ale předpokládalo se, že uživatel s používáním cookies primárně souhlasí, pokud výslovně nezvolí opak (tzv. princip opt-out). Vyjádření nesouhlasu muselo být vždy na webu umožněno.</p><p>Ale od roku 2022 platí pro využívání cookies opačný postup (princip opt-in). Provozovatel webu musí od začátku předpokládat, že uživatel s cookies primárně nesouhlasí. A nemůže je tedy využívat k ukládání dat. Cookies lze na webu používat pouze od doby, kdy uživatel výslovně a aktivně vyjádřil svůj souhlas. Výjimkou jsou pouze základní technické cookies, které jsou nezbytné k fungování stránek a pro poskytování služby. Pro takový typ cookies není třeba mít předchozí souhlas uživatele. Ale stále zde platí podmínka, že jde o zpracování osobních údajů a musí být splněny náležitosti nařízení GDPR. A webová stránka musí o cookies uživatele informovat.</p><h2>Jak má vypadat nová cookies lišta?</h2><p>Cookies lišta se používá pro souhlas již delší dobu, ale nyní musí splňovat novou legislativu. Nestačí již jen informovat uživatele, jaké cookies web využívá. Už nelze mít předem zaškrtnuté checkboxy se souhlasem. Souhlas nelze nově vyjádřit využíváním stránky, na které jsou cookies nasazeny.</p><p>Lišta musí mít předepsané vlastnosti, nesmí být agresivní nebo blokovat obsah webu. Musí splňovat tyto náležitosti:</p><ul><li> <strong> <em>Uživatel musí souhlas s využitím cookies aktivně zvolit. Do té doby je práce s cookies na webu zakázána.</em></strong></li><li> <strong> <em>Webová stránka musí uživatele jasně a transparentně informovat, jaké typy cookies využívá a k čemu slouží.</em></strong></li><li> <strong> <em>Webová stránka umožňuje uživateli zaškrtnout souhlas jen s některými typy cookies.</em></strong></li><li> <strong> <em>Web musí fungovat i bez souhlasu s využíváním cookies, nesmí souhlas vynucovat.</em></strong></li><li> <strong> <em>Uživatel musí mít možnost se k nastavení cookies opakovaně vrátit a poskytnuté souhlasy opět odvolat.</em></strong></li></ul><h2>Co jsou to vlastně cookies?</h2><p>Každý z vás asi zažil situaci, kdy si hledáte na webu ubytování nebo pronájem auta na dovolenou. Surfujete na stránkách, zkoumáte alternativy, dostupnost a cenu. Po chvíli se na nejlepší nabídku vrátíte a ejhle… Divíte se, že cena služby poskočila výše!!</p><p>Jak je to možné? Ano, můžou za to cookies! Marketéři předpokládají, že pokud se k nabídce vrátíte, máte o ní opravdový zájem, a proto cenu zvyšují. Je to příklad využití tzv. marketingových cookies, s nimiž se běžně na webu setkáváme. A ani o tom nevíme.</p><p>Cookies je jednoduchá technologie, která je součástí webu a webového prohlížeče. Jedná se přesně o soubor u vás na disku na počítači. Webová stránka si tam ukládá různé informace o nastavení a o vašem chování na stránce. Pokud se na web připojíte po čase znovu, stránka si tyto informace načte, může s nimi pracovat a web přizpůsobit vašim dříve nastaveným preferencím.</p><p>Z toho chování pochází název této technologie – cookies znamená v angličtině „sušenky“. Tyto sladkosti nabízejí hostitelé v anglosaském světě příchozí návštěvě, aby se u nich cítila dobře.</p><p> <img src="/Blog/PublishingImages/Stranky/Cookies/cookies_unsplash.jpg" data-themekey="#" alt="cookies" style="max-width:690px;" /> <br> </p><h4 style="text-align:center;">​Fotografie ​​od <a href="https://unsplash.com/%40rumeyysaben?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">RUMEYSA AYDIN</a> via <a href="https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>.<br></h4><p>​Některé cookies jsou pro uživatele užitečné, protože umožňují příjemnější prohlížení webu. Například si web bude pamatovat, že preferujete „dark mode“ a bude se pro vás vždy zobrazovat v tmavých barvách. Jiné druhy cookies umožňují sledovat chování uživatelů a využívat je v reklamě a marketingu. Toto je jediné reálné riziko pro uživatele, pokud cookies zapne - vnucování obsahu a cílené reklamy. Ale určitě se nestane to, že se daný web nenačte, bude zpomalený nebo se dokonce přenese virus.<br></p><h2>Tři čtvrtiny populace neví, k čemu cookies slouží</h2><p>V dubnu 2022 zadala společnost Avast realizaci <a href="https://press.avast.com/cs-cz/pruzkum-polovina-cechu-bezmyslenkovite-prijima-vsechny-cookies-tri-ctvrtiny-z-nich-nevi-k-cemu-slouzi" target="_blank">veřejného výzkumu</a> okolo cookies, odkud vypadly poměrně zajímavé závěry. Jak jsme dopadli? No moc dobře ne …</p><p> <strong><em>Polovina Čechů bezmyšlenkovitě přijímá všechny cookies.</em></strong></p><p>Většina Čechů přesně neví, co jsou cookies. K čemu tato webová technologie slouží ví jen čtvrtina uživatelů (26 %). Při návštěvě webu <strong>celá polovina domácí populace zvolí automaticky souhlas</strong> ke sběru a případnému poskytování veškerých přístupných informací třetím stranám. Lidé tedy takzvaně „přijmou vše“. Nejčastěji proto, že se na web chtějí dostat co nejrychleji (31 %), stránkám důvěřují (20 %) nebo je navštěvují opakovaně (18 %). Někteří (31 % dotázaných) si dokonce myslí, že zamítnutí cookies způsobí, že daný web nebude možné vůbec zobrazit. Ale jak my už víme, toto by se díky novému zákonu stávat nemělo.</p><p>Další možností je cookies zcela zamítnout, což ale dělá jen 9 % lidí, a jde většinou o ty, kteří o nich něco ví. Téměř polovina (41 %) těch, kteří cookies neznají, ani neví, jak je zamítnout. Je vidět, že internetová populace je v tomto směru dost nevzdělaná. Podle výzkumu se například 29 % respondentů domnívá, že cookies web zpomalují a podle 7 % jej dokonce mohou zavirovat.</p><p>Na základě výsledků výzkumu se Avast rozhodl připravit pro veřejnost vzdělávací kampaň s názvem <strong>Muž, který povolil vše</strong> (k dispozici​ 5 epizod také na <a href="https://www.youtube.com/watch?v=vLdyFzWG-c4&list=PLsmQTW-n3GdmsADIF9SqgTvhixSHxmrle&index=1">YouTube</a>). Tváří kampaně je herec Martin Kraus a jejím cílem je vysvětlit Čechům, jak cookies fungují a v čem jsou prospěšné. Ale také to, jak si chránit své soukromí na internetu.</p><h2>Odstraňovač cookies lišty</h2><p>Tak a nyní jsme se dozvěděli, že společnosti a provozovatelé webů nemohou defaultně pracovat s cookies, pokud jim to uživatel výslovně nepovolí. Takže pokud zavíráte cookies lištu křížkem, web se musí chovat stejně, jako byste cookies zamítli. Musí to mít logicky stejný výsledek. Přitom zavírání lišty je tak otravné. Pokud cookies na konkrétním webu zamítneme, web si tuto volbu nemá jak jednoduše uložit (cookies jsou přeci vypnuté) a při další načtení lišta vyjede znovu. Jak z toho ven?</p><p>Existuje jednoduché řešení. Můžete si nainstalovat plugin <a href="https://www.i-dont-care-about-cookies.eu/" target="_blank">I-DONT-CARE-ABOUT-COOKIES.EU</a>, který lze instalovat do většiny webových prohlížečů (Chrome, Firefox, Opera, Edge). Zařídí to, že browser nebude cookies lištu vůbec zobrazovat. A funguje překvapivě dobře!​<br></p><p> <br> </p><p> <i>Jan Čermák</i></p><p> <br> </p>odborné;#
Květen ve jménu designuhttps://www.create-it.cz/Blog/Stranky/grafika-pro-deti-II.aspxKvěten ve jménu designu<p>​​Všechny květnové středy a první červnovou jsme zasvětili grafice a designu. Kreativní oddělení QUB si připravilo pětidílný kurz grafiky pro děti. Lekce jsme nachystali jako pět hodinových online setkání a byli jsme nadšení, co všechno 11 malých designerů ve věku 7–12 let během kurzu zvládlo. Ostatně možná jste četli <a href="/Blog/Stranky/grafika-pro-deti.aspx">článek od dvanáctileté Viky</a>.<br></p><p> Postupovali jsme od základů – vysvětlili jsme si základy barevné teori​e, prošli jsme zajímavosti z tvorby pigmentů a první hodinu zakončili tvorbou barevné palety, bez které se začátek žádného designového projektu neobejde. </p><p> Při druhém setkání jsme se lehce dotkli historie. Od piktogramů, hieroglyfů a jeskynních maleb jsme se dostali až k rozdělení typografie na expresivní a funkční a děti se naučily mimo jiné rozlišit mezi patkovým a bezpatkovým písmem. Buďte připraveni, až vás malí designeři doma ohromí zajímavými fakty o stavbě písma a budou správně tvrdit, že některé znaky mají bříška, chvosty a oka a že kuželka nemusí být jen ta na bowlingu! Lekci jsme zakončili tréninkem správného prostrkání písma. </p><p> Na třetím setkání jsme společně vypátrali, že styl komixových hrdinů s černou obrysovou linkou má původ v japonském tradičním dřevořezu a secesních plakátech. Nasdíleli jsme si pár tipů na přidání dynamiky do příběhu, práci s bublinami a ujasnili si, že komix by měl mít hrdinu, zápletku, prostředí a vybraný jednotný grafický styl. Společně jsme tvořili krátký strip na téma Překvapení. </p><p> Ve čtvrté lekci jsme zabrousili do obalového designu, procvičili jsme si nabyté dovednosti o barvách a typografii a postavili jsme malé designery před nelehký úkol ­– design obalu sáčku na bonbony. Opět jsme postupovali stejně jako v běžné praxi, začali jsme rešerší a všímali si detailů a rozdílů například mezi designy ovocných a čokoládových bonbonů. Děti ukázaly ohromnou míru kreativity a kromě designu obalu přišly i s nápady na názvy nových bonbonů – zaujaly by vás v obchodě třeba Slepičí zobáky?<br></p><p> V prvních čtyřech lekcích jsme se záměrně vyhýbali počítači a pracovali s návrhy na papír (o​pět stejně jako v designové praxi). V páté poslední lekci jsme zkusili zabrousit do grafického editoru a představili jsme dětem <a href="https://www.figma.com/">Figmu</a>. Vyzkoušeli jsme si převést svůj návrh bonbónového sáčku do počítače. I touhle poslední zkouškou ​téměř ohněm děti prošly a my v současné sobě sbíráme všechny jejich výtvory. </p><p><i>​​ Za <a href="https://qub.digital/en/index/">QUB Digital</a> Ivana Stránská, Michal Hořava a Jan Čermák<br></i><br></p>odborné;#vzdělávání;#
Grafika pro děti očima Vikyhttps://www.create-it.cz/Blog/Stranky/grafika-pro-deti.aspxGrafika pro děti očima Viky<p>​Dvanáctiletá Viky napsala skvělou autentickou reportáž z kurzu grafiky pro dě​​ti pořádaného Cleverlance.​ Publikováno bez úprav.​​​<br></p><h2>1. lekce​<br></h2><p>Úplně na začátku 1. lekce jsme se představili ostatním jako na jiných kurzech, ale k tomu jsme ještě řekli co bychom se chtěli naučit. Jakmile jsme se představili lekce mohla začít. Nejdřív nám řekli barvu roku (která se jmenuje Very Peri) a jak je pro designéra důležitá. Vlastně designér používá barvu roku skoro všude. Taky jsme se bavili o kole barev, kde je krásně vidět kontrast barev. Potom jsme měli historii barev. Je hodně zajímavé že už v pravěku používali bílou barvu, protože bílá se získává blbě a ještě pomocí nějakých chemických látek. A třeba Římané měli rádi různé odstíny hnědé takže takový romantický styl. Další téma byl pigment. Podle toho jaké dáme pojidlo do pigmentu vzniknou různé barvy. Dřív se jako pojidlo používal med, olej nebo vajíčko. Třeba když se dá do pigmentu jako pojidlo med tak vzniknou akvarelové barvy nebo taky to stejné akorát s vajíčkem tak vzniknou tempery. Poslední téma bylo z jakých různých kamenů se dělají různé barvy. Třeba žlutá se dělá ze sopečného kamene nebo je zajímavé že bílá se dělá z černého kamene sice je tam nějaká chemická úprava, ale to je věc vedlejší. Na konci hodiny jsme dostali “domácí úkol" vymyslet vlastní barevnou paletu do příštího týdne. Mě to hrozně moc bavilo a těším se na další lekce grafiky.</p><p> <img src="/Blog/PublishingImages/Stranky/grafika-pro-deti/obrazek-1.jpg" alt="paleta" data-themekey="#" style="max-width:690px;" /><br><br></p><h2>2. lekce​<br></h2><p>V 2. lekci jsme se bavili o typografii. Nejdřív jsme probírali historii psaní. Úplně první písmo byly hieroglyfy, které vymysleli v Egyptě.Tenhle druh písma byl časově náročný. Si představte kdybyste museli kreslit třeba kachnu kvůli jednomu slovu. Další písmo vymysleli Féničané a bylo to první hláskové písmo a z něho potom vznikla Latinka, kterou píšeme i v dnešní době. Jedno z předposledních témat bylo to že jsme si vysvětlovali co je patkové a nepatkové písmo momentálně píšu nepatkovým. Dále co jsou versálky a mínusky. A předposlední co jsme dělali bylo že nám vysvětlovali plakátové a takové to které se dává do novin a tak dále. Plakátové má zaujmout a udělat dojem, ale někdy je skoro nečitelné. Zase naopak to novinářské se musí dobře číst. Poslední co jsme dělali bylo to že nám poslali odkaz na webovou stránku do chatu. Tam jsme si mohli cvičit rozmístění písmen v nadpisech a tak dále. Jako minule nám dali “domácí úkol" ale tentokrát jsme měli nakreslit nebo namalovat svoje jméno (viz obrázek v záhlaví článku). Zase jako minule mě to fakt hodně bavilo a těším se na příště.</p><h2>3. lekce<br></h2><p>Ve 3. lekci jsme se zajímali o komiksech. Úplně první téma co jsme probírali byly takové ty okénka a říkali jsme si že ty okénka můžou být různě uspořádané tak aby čtenáře zaujali. Potom takové stínování v černobílém komiksu, že třeba 1. okénko je do šeda, 2. a 3. okénko je do bíla a tak dále. Nějak uprostřed hodiny jsme si zkoušeli si namalovat svůj komiks, ale jenom strip. To je komiks s dvěma nebo třemi okénky. Jakmile jsme dodělali svůj “komiks" tak hodina skončila. I teďka mě to moc bavilo a těším se na příště.</p><p>​<br><img src="/Blog/PublishingImages/Stranky/grafika-pro-deti/komix.jpg" alt="komix" data-themekey="#" style="max-width:690px;" /><br><br></p><h2>4. lekce<br><br></h2><p>Na 4. lekci jsme malovali a vymýšleli svůj pytlík bonbónů. Nejdřív jsme museli vymyslet název, já jsem vymyslela Japonky. Potom styl písma a když jsme měli hotový náčrt tužkou tak jsme si vymysleli paletu barev. Jakmile jsme vybarvili název, tak jsme udělali design jako třeba obrázek příchuti: meloun, marshmelouny atd. Kolem toho lístky nebo něco jiného. Taky jsme tam museli napsat kolik to váží jaká je to příchuť (pro jistotu). Během toho nám říkali Michal s Ivanou o kontrastu a zlatém řezu. Naše pytlíky bonbónů jsme jim na konci hodiny ukázali. Pochválili nás a řekli ať tomu doděláme nějaké zajímavé pozadí a vyfotíme jim to. Jako každá lekce grafiky mě bavila a navíc na tomhle jsme si procvičili typografii a výběr barev, které se k sobě hodí.<br><br></p><h2>5. lekce​ <br></h2><p>Na 5. lekci jsme pracovali s Figmou. Předělávali jsme pytlík bonbónů do počítače, který jsme dělali minule. Nejdřív jsme si nastavili formát papíru a nastavili mu barvu. Potom jsme udělali nadpis a upravili ho. Taky jsme tam dali různé tvary a na jedné webové stránce jsme našli různé vektorové obrázky. Do dalšího týdne jsme to měli dodělat a poslat. K tomu ten co to měl nejhezčí tak dostane pytlík bonbónů. Všechny lekce grafiky byly super a asi nejvíc mě bavila 3. lekce. Pokud by byly další tak bych se určitě zapojila.<br><br></p><p> <i>Viky</i><br></p><p><br>Sledujte nás a v brzké době vám přineseme výtvory i ostatních účastníků kurzu - protože kdo by nechtěl vidět nejhezčí pytlík bonbónů!​<i></i></p><p><i><br></i></p><p> <br> </p>hobby;#vzdělávání;#
​​Apple myslí na bezpečnost svých uživatelůhttps://www.create-it.cz/Blog/Stranky/apple-account-deletion.aspx​​Apple myslí na bezpečnost svých uživatelů<p>​Mobilní aplikace jsou mezi uživateli čím dál tím více oblíbené. Každý den jsou jich z <a href="https://play.google.com/store/" target="_blank">Google Play</a> a <a href="https://www.apple.com/cz/app-store/">Apple App Store</a> stahovány tisíce. Ovšem ne všechny aplikace jsou pro své uživatele úplně bezpečné a ne všechny korektně spravují osobní data uživatelů. Výše uvedené společnosti se snaží hlídat, aby se do jejich obchodů dostaly jen ty apky, které „hrají s uživateli fér hru“.<br></p><p> Z důvodu ochrany osobních údajů uživatelů iOS aplikací vydal Apple <a href="https://developer.apple.com/support/offering-account-deletion-in-your-app">nařízení</a>, že „<b>od 30. června 2022 musí všechny mobilní​ aplikace v App Storu, které podporují vytvoření účtu, uživatelům umožnit také jeho smazání".</b> </p><p> Původně měl tento pokyn platit už od konce ledna roku 2022, termín byl však kvůli tlaku vývojářů a společností provozujících aplikace posunut o 5 měsíců. Ne vždy se totiž jedná o jednoduchou proceduru. Apple předepisuje pro mazání účtu jasná pravidla: </p><p></p><ul><li>Proces mazání účtu musí být jasný, intuitivní a transparentní, v aplikaci lehce k nalezení (např. tlačítko do profilu uživatele nebo správy účtu).<br></li><li>Musíme nabídnout smazání kompletně celého záznamu účtu, včetně přidružených osobních údajů. Pouze nabídka deaktivace (dočasného vypnutí) účtu nestačí. </li><li>Pokud uživatelé musí navštívit web, aby dokončili smazání svého účtu, měli bychom přidat přímý odkaz na stránku na webu, kde mohou proces dokončit. </li><li>Uživatelé musí být dobře informováni. Má-li dokončení žádosti o smazání trvat delší dobu, musíme jim dát vědět. </li><li>​Pokud aplikace podporuje nákupy v aplikaci, musíme lidem srozumitelně vysvětlit, jak bude probíhat následující fakturace a rušení účtu. </li><li>Všechny aplikace musí obsahovat snadno dostupný odkaz na zásady ochrany osobních údajů v popisu na App Store Connect v rámci aplikace. </li><li>​​A v neposlední řadě je nutné​ dodržovat platné zákonné požadavky na zpracování a uchovávání osobních údajů klienta. A také na jejich mazání. To zahrnuje dodržování místních zákonů - v našem případě tedy platnou směrnici GDPR.</li></ul> <p></p><p> <a href="https://www.cleverlance.com/cz">Cleverlance</a> jako technologická společnost pomáhá svým zákazníkům řešit tyto požadavky. Jako dodavatel mobilních aplikací jsme tuto problematiku úspěšně vyřešili například v mobilní aplikaci <a href="https://apps.apple.com/cz/app/my%C5%A1koda/id1161648654?l=cs">MyŠkoda</a> společnosti ŠKODA AUTO a.s. Přesně podle direktivy GDPR, zde může zákazník ve svém profilu zcela smazat svůj účet, včetně svých osobních údajů. Musí ovšem předem odpojit své vozy, které přes aplikaci ovládá. </p><p> V bankovnictví je situace trochu odlišná. Uživatel sice může svůj účet a přístup do mobilní aplikace smazat, ovšem jeho produkty dál v bance zůstávají nedotčeny. Stejně jako osobní data, která v systémech musí zůstat z důvodu oprávněného zájmu zpracování osobních​ údajů a plnění legislativní povinnosti. Uživatel si tak může svůj účet v apce zrušit a tím přestane aplikaci používat. Ale dál zůstává plnohodnotným klientem banky. </p><h2>Co na to G​​oogle?<br></h2><p> A jak se k tomuto tématu staví další gigant Google? Pravidla pro vystavení apky v Google Play říkají, že aplikace musí být transparentní a informovat uživatele, jak zpracovává jeho osobní data. Zakazují přímo podvodné nebo nečestné jednání. Ale k nařízení, aby každá apka, pokud vytváří uživatelský účet, umožnila také jeho smazání, se dosud Google neodhodlal. </p><p> Tento krok Applu určitě zlepší transparentní a férové chování aplikací ke svým uživatelům. Je to dobrý krok dopředu k poctivějšímu elektronickému světu. </p><h2> ​Doporučení pro vý​​​vojáře </h2><p> Pro implementaci nové funkcionality mazání účtu doporučuji naplánovat samostatný release, a to po uvedeném datu. Apple totiž bude pravděpodobně funkčnost důsledně prověřovat a může se stát, že se tak vydání nové verze opozdí. To by mohlo mít neblahý vliv na další důležité nové funkčnosti apky, pokud by byly vydávány pohromadě s tímto releasem. A uživatelé neradi čekají.​<br></p><p><em>Jan Čermák</em> <br></p>odborné;#projekty;#
Praha byla centrem blockchainového multivesmíruhttps://www.create-it.cz/Blog/Stranky/Gateway-to-Cosmos.aspxPraha byla centrem blockchainového multivesmíru<p>​​Na pražské konferenci Gateway to Cosmos jsme byli svědky otevření dveří do blockchainového multivesmíru. Podobně jako v posledním marvelovském filmu s Doktorem Strangem, je Cosmos branou do paralelních světů, které mají schopnost navzájem spolu komunikovat. Těmito světy jsou blockchainy vzniklé právě z mateřského Cosmosu.</p><p>Nekompatibilita a přenos inforací mezi jednotlivými blockchainy je jedním z kritických míst, které vývojáři řeší. Blockchain 3.0, jak se Cosmos nazývá, umožňuje programátorům plynule budovat nové blockchainy bez nutnosti následné tvorby tzv. mostů mezi nimi. Cílem celého projektu je vytvoření internetu blockchainů – sítě blockchainů a aplikací na nich postavených schopných vzájemně komunikovat decentralizovaným způsobem.<br></p><p> <img src="/Blog/PublishingImages/Stranky/Gateway-to-Cosmos/cosmos.jpg" alt="cosmos.jpg" data-themekey="#" style="max-width:690px;" /> <br> </p><h2>Napojení Cosmosu na da​lší blockchainy</h2><p> <strong></strong>Interoperabilita je pojem, který  v blockchainovém prostoru rezonuje již dlouhou dobu. Téměř každý den vznikají nové blockchainy nebo kopie těch starých a vzniká u nich dříve nebo později přirozená potřeba komunikovat s ostatními. I když funkce Cosmosu tento problém uvnitř svého ekosystému řeší, potřebuje pomoc s překladem do jiných jazyků a neměnným přenosem informací do jiných sítí.</p><p> <a href="https://axelar.network/">Axelar</a>, jeden z hlavních partnerů akce, představil, jak zajistit bezpečnou interakci s jakýmkoli aktivem, kteroukoliv decentralizovanou aplikací na jakémkoli blockchainu. Takže můžete poslat své NFT z Etherea do libovolného blockchainu Cosmos a naopak. Takto jsou přes axelar propojeny všechny hlavní blockchainy a v brzké době se chystá i přemostění s Bitcoinem.<br></p><p> <img src="/Blog/PublishingImages/Stranky/Gateway-to-Cosmos/dao.jpg" alt="dao.jpg" data-themekey="#" style="max-width:690px;" /> <br> </p><h2>DAO jako středobod decentraliz​​ovaných projektů</h2><p> <strong></strong>Zajímavou myšlenkou je, že skutečně decentralizované řešení by mělo vždy začínat vznikem <a href="https://en.wikipedia.org/wiki/Decentralized_autonomous_organization">DAO</a> – decentralizované organizace vytvořené podle pravidel zakódovaných jako počítačový program (Wikipedie). Jake Hartnell, spoluzakladatel <a href="https://www.junonetwork.io/">Juno</a> a <a href="https://daodao.zone/">DAO DAO</a>, demonstroval na svých projektech, že za funkční organizací nemusí stát žádný konkrétní investor či <a href="https://en.wikipedia.org/wiki/Venture_capital">VC</a>. Jsou čistě postaveny a sponzorovány svou komunitou. Rizikem je, že programovatelná pravidla  na nichž tyto struktury stojí, stále nemají dostatek příkladů použití, jak to udělat správným způsobem. Na druhou stranu i zde může být rozmanitost, jak to vidíme na současné politické scéně. Juno tento problém řeší vytvářením podskupin - tzv. subDAO. To se dá připodobnit firemní struktuře, kde má každý subjekt svou odpovědnost (CoreDev DAO, Event DAO, Hack DAO). Díky tomu by specifická rozhodnutí v rámci organizace měla být vykonávána kvalifikovanou částí komunity.<br></p><p> <img src="/Blog/PublishingImages/Stranky/Gateway-to-Cosmos/smart-contract.jpg" alt="smart-contract.jpg" data-themekey="#" style="max-width:690px;" />Agoricu, blockchainu vycházejícího z Cosmos SDK, představil řešení, které by mohlo zvrátit celou hru. Smyslem není přesvědčit vývojáře, aby se učili nový programovací jazyk, jako je Solidity u Etherea. Jde o to jim umožnit stavět na tom, co již znají. Hovoříme o 10 milionech vývojářů, kteří získají možnost budování Smart kontraktů v JavaScriptu. Díky Agoricu se tak programování aplikací na blockchainu stane dostupné i “běžným lidem".</p><p>Souhrnným poselstvím konference bylo “It's time to build", tedy iniciovat vývojáře a týmy po celém světě, aby začali tvořit svá řešení v Cosmosu. Díky <a href="https://rbf.capital/">Rockaway blockchain fund</a>, který byl hlavním pořadatelem, se podařilo na jednom místě propojit zakladatele blockchainů, tvůrce nástrojů, programátory aplikací, investory a další entity tohoto ekosystému. Přednášky se prolínaly s hackathonem a workshopy a kdokoliv měl možnost získat odpovědi na své otázky hned na místě.</p><p>Misí <a href="https://cleverlance.com/blockchain42">Cleverlance Blockchain 42</a> týmu bylo prohloubit znalosti o Cosmosu, přidružených nástrojích a především pak získání nových zkušeností s Agoric blockchainem a dalšími Cosmos-chainy. Mise dopadla úspěšně a náš tým pokračuje dál. Plní se nám náš dětský sen stát se kosmonauty. Brzy se ohlásíme s dalšími novinkami z tohoto vesmíru.<br></p><p> <em>Filip Dítě</em></p><p><br></p><p><em></em><span style="color:#242424;font-family:-apple-system, system-ui, "segoe ui", "apple color emoji", "segoe ui emoji", "segoe ui web", sans-serif;font-size:14px;">Z​droj fotografií: </span><a aria-label="Link https://gateway.events/" title="https://gateway.events/" href="https://gateway.events/" rel="noopener noreferrer" target="_blank" tabindex="-1" style="box-sizing:border-box;outline-style:none;color:#4f52b2;text-decoration-line:none;font-family:-apple-system, system-ui, "segoe ui", "apple color emoji", "segoe ui emoji", "segoe ui web", sans-serif;font-size:14px;">https://gateway.events/</a>​​​<br></p>odborné;#vzdělávání;#
Typescript: typy pro manipulaci s řetězcihttps://www.create-it.cz/Blog/Stranky/Type_script_3.aspxTypescript: typy pro manipulaci s řetězci<p>​Pojďme se tentokrát seznámit s vestavěnými typy, které nám usnadní práci s řetězci / proměnnými, a mohou být použity v šablonách (tzv. template string literals).<br></p><p> <b>Které typy to jsou?</b></p><ul><li>Uppercase<StringType> - transformuje vstupní řetězec do řetězce s pouze velkými písmeny</li><li>Lowercase<StringType>- transformuje vstupní řetězec do řetězce s pouze malými písmeny</li><li>Capitalize<StringType> - transformuje vstupní řetězec do řetězce s prvním znakem psaným velkým písmem</li><li>Uncapitalize<StringType> - transformuje vstupní řetězec do řetězce s prvním znakem psaným malým písmenem</li></ul><p>Každý z typů přijímá jeden parametr typu string. Pokud se pokusíme předat parametr jiného typu, pak dostaneme chybovou zprávu, upozorňující nás na porušení daného omezení.</p><p>Výše zmíněné typy jsou z výkonnostních důvodů poskytovány TypeScriptovým kompilátorem a nejsou definovány v TypeScriptovém .d.ts souboru. Implementace těchto typů využívá přímo JavaScriptové funkce pro manipulaci s řetězci a nebere v potaz locale běhového prostředí (je to soubor parametrů, které definují uživatelův jazyk, stát a jiné zvláštnosti, které se následně projeví v uživatelském rozhraní). Implementace v TypeScriptu 4.1 vypadá následovně:<span style="font-size:15px;"></span></p><pre> <code class="language-typescript hljs">function applyStringMapping(symbol: Symbol, str: string) { switch (intrinsicTypeKinds.get(symbol.escapedName as string)) { case IntrinsicTypeKind.Uppercase: return str.toUpperCase(); case IntrinsicTypeKind.Lowercase: return str.toLowerCase(); case IntrinsicTypeKind.Capitalize: return str.charAt(0).toUpperCase() + str.slice(1); case IntrinsicTypeKind.Uncapitalize: return str.charAt(0).toLowerCase() + str.slice(1); } return str; } </code></pre><p></p><h2> <strong>Uppercase<StringType></strong></h2><p>Transformuje vstupní řetězec do řetězce pouze s velkými písmeny.</p><p>Mějme typový alias PointsOfTheCompass, jehož definice je následující<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type PointsOfTheCompass = 'north' | 'west' | 'east' | 'south'</code></pre><p>Výsledkem následujícího př​​iřazení<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type Result = Uppercase<PointsOfTheCompass>;</code></pre><p>je typový alias se všemi položkami psanými velkými písmeny.​<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type Result = 'NORTH' | 'WEST' | 'EAST' | 'SOUTH'</code><br></pre><p></p><h2> <strong>Lowercase<StringType></strong></h2><p>Mějme typový alias PointsOfTheCompass, jehož definice je následující<br></p><span style="font-size:15px;"></span><pre><code class="language-typescript hljs">type PointsOfTheCompass = 'NORTH' | 'WEST' | 'EAST' | 'SOUTH'</code></pre><p></p><p>Výsledkem následujícího přiřazení<br></p><pre><code class="language-typescript hljs">type Result = Lowercase<PointsOfTheCompass>;</code><br></pre><p></p><p>je typový alias se všemi položkami psanými malými písmeny.<br></p><pre><code class="language-typescript hljs">​type Result = 'north' | 'west' | 'east' | 'south'</code><br></pre><p></p><h2> <strong>Capitalize<StringType></strong></h2><p>Mějme typový alias PointsOfTheCompass, jehož definice je následující<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type PointsOfTheCompass = 'north' | 'west' | 'east' | 'south'</code></pre><p>Výsledkem následujícího přiřazení<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type Result = Lowercase<PointsOfTheCompass>;</code></pre><p>je typový alias, kde každá položka má první písmeno psáno velkým písmenem<br></p><pre><code class="language-typescript hljs">type Result = 'North' | 'West' | 'East' | 'South'</code><br></pre><p></p><h2> <strong>Uncapitalize<StringType></strong></h2><p>Mějme typový alias PointsOfTheCompass, jehož definice je následující<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type PointsOfTheCompass = 'NORTH' | 'WEST' | 'EAST' | 'SOUTH'</code></pre><p>A výsledkem následujícího přiřazení<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type Result = Uncapitalize<PointsOfTheCompass>;</code></pre><p></p><p>je typový alias, kde každá položka má první písmeno psáno malým písmenem<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type Result = 'nORTH' | 'wEST' | 'eAST' | 'sOUTH'</code><br></pre><p></p><h2> <strong>Použití</strong></h2><p>Nejčastější použití nalezneme spolu s template literal type. Mějme typový alias Point, jehož definice je následující<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">interface Point {  <p> longitude: double; <span style="font-family:source-sans-pro, open-sans, sans-serif;"> </span></p><p> latitude: double;<span style="font-family:source-sans-pro, open-sans, sans-serif;"><br>}</span></p></code></pre><pre>Výsledkem následujícího přiřazení<br></pre><p></p><pre><br><code class="language-typescript hljs">type CapitalizedPoint = Capitalize<keyof Point>;</code></pre><p></p><p>pak je<span style="font-size:15px;"></span></p><pre><code class="language-typescript hljs">type CapitalizedPoint = 'Longitude' | 'Latitude'</code></pre><p>pokud náš příklad rozvineme dále a aplikujeme spolu s template literal type, pak můžeme například generovat další typ<br></p><pre> <code class="language-typescript hljs">type PointGetAccessoryNames = `get${Capitalize<keyof Point>}`;</code></pre><p></p><p>kde jako výsledek dostáváme<br></p><pre><code class="language-typescript hljs">type PointAccessoryNames = 'getLongitude' | 'getLatitude'</code></pre><p>pokud tento přístup následně nakombinujeme i s mapováním<br></p><pre><code class="language-typescript hljs">type PointAccessors = {  <p>​[K in keyof Point as `get${Capitalize<K>}`]: () => Point[K];<span style="font-family:source-sans-pro, open-sans, sans-serif;"><br>}</span></p></code></pre><p>pak dostaneme následující typový alias<br></p><pre><code class="language-typescript hljs">type PointAccessors = {    <p> getLongitude: () => number;   <span style="font-family:source-sans-pro, open-sans, sans-serif;"> </span></p><p> getLatitude: () => number;<br></p>}</code><p></p></pre><p></p><h2> <strong>Závěrem</strong></h2><p>Výše jsme představili typy, které můžeme použít pro manipulaci s řetězci a způsob, jakým je můžeme použít spolu s template string literals a jaké výhody nám to přináší. A na co se můžete těšit příště? </p><p>Typy, jako jsou Readonly<Type> ; Record<Keys, Type> ; Pick<Type, Keys> a Omit<Type, Keys><br></p><p><i>Václav Kandus​</i></p>odborné;#