Ročníkový projekt Systém vzdálené rezervace vstupenek
Transkript
Ročníkový projekt Systém vzdálené rezervace vstupenek
Univerzita Karlova v Praze Matematicko-Fyzikální fakulta Ročníkový projekt Systém vzdálené rezervace vstupenek dokumentace Vypracoval: David Šenkeřík Vedoucí: RNDr. Josef Zlomek Datum: 22.února 2006 Obsah 1. Úvod 2. Uživatelská dokumentace 2.1. Klientská aplikace 2.1.1. Rozhraní práce s aplikací 2.1.2. Uživatelé 2.1.3. Bezpečnost při komunikaci 2.1.4. Jazyková podpora 2.1.5. Editor rozvržení prostor 2.1.6. Editor události 2.1.7. Rezervace 2.1.8. Grafy prodeje 2.1.9. Ukládání konfigurace 2.2. PHP server 2.2.1. Nastavení 2.3. Databáze 2.4. Webové rozhraní 3. Programátorská dokumentace 3.1. Klientská aplikace 3.1.1. Objekty reprezentující místnost 3.1.2. Objekty reprezentující událost 3.1.3. Rozhraní aplikace 3.1.4. Uživatelé 3.1.5. Bezpečnost síťové komunikace 3.1.6. Hlavní okno aplikace 3.1.7. Algoritmy vyhledávání volných sedadel 3.1.8. Grafy prodeje 3.1.9. Okno Preview 3.1.10.Implementace jazykové podpory 3.1.11.Pomocné funkce 3.2. PHP Server 3.3. Databáze 3.4. Webové rozhraní 1. Úvod Cílem ročníkového projektu bylo navrhnout a naimplementovat komplexní systém pro rezervaci a prodej vstupenek, určený pro distribuci vstupenek na příležitostné akce převážně kulturně-společenského charakteru. Základním požadavkem projektu byla schopnost pracovat s centrálními daty z vícero prodejních míst. Projekt je rozčleněn na čtyři logicky oddělené části, které spolu vzájemně komunikují. Stěžejní částí je klientská aplikace, určená pro distributory vstupenek. Tato aplikace nabízí grafické rozhraní pro definování rozložení prostor, rozhraní pro vytváření akcí v těchto prostorách a samotné grafické rozhraní pro prodej vstupenek. Aplikace pracuje ve dvou možných rozhraních: práce s lokálními daty (soubory) nebo práce v síťovém rozhraní (sdílená data). Aplikace v síťovém rozhraní komunikuje s PHP serverem, který zprostředkovává komunikaci mezi klientem a SQL databází. V databázi jsou centrálně uložená všechna data: definice prostor, událostí, informace o vstupenkách, uživatelích, atd. Poslední částí projektu je webové rozhraní, které je určené pro cílové zákazníky. Pomocí tohoto rozhraní si zákazník zarezervuje vstupenky, vstupenka je mu poté prodána distributorem pomocí klientské aplikace. 2. Uživatelská dokumentace 2.1. Klientská aplikace Klientská aplikace je určena pro operační systém MS Windows XP. Jedná se o aplikaci určenou pro distributory, kteří prodávají vstupenky cílovým zákazníkům. 2.1.1. Rozhraní práce s aplikací Klientská aplikace může pracovat ve dvou rohraních: rozhraní pro lokální komunikaci (data se ukládají do souborů na disku) a rozhraní pro síťovou komunikaci (data se posílají na server). Rozhraní pro práci s klientskou aplikací se nastavuje v hlavním menu aplikace, v položce „Settings“. Rozhraní pro lokální komunikaci je určeno pro situace, kde není třeba centralizovat data z více prodejních míst, pro situace, kdy není k dispozici síť pro komunikaci atd. Tento režim také umožňuje nadefinování místnosti nebo akce, uložení do lokálního souboru a po přepnutí do síťového rozhraní uložení těchto dat na server. V tomto rozhraní jsou však k dispozici všechny základní funkce aplikace: definování prostor, událostí i samotná rezervace vstupenek. Při ukládání respektive načítání dat uživatel otevírá soubory pomocí standardních dialogů pro práci se soubory. Protože tento režim nepracuje se sdílenými daty, není v něm k dispozici přihlašování uživatelů. Rozhraní pro síťovou komunikaci je určeno pro práci s centralizovanými daty z vícero klientských aplikací. Nastavení adresy PHP skriptu se provádí v záložce „Server Settings” v hlavním okně aplikace. Je nutné nastavit obě části adresy, první částí je adresa stroje (např. „localhost“), druhou částí adresa RTRS skriptu v rámci stroje (např. „RTRSscript.php“). Dostupnost serveru je možno otestovat pomocí tlačítka „Test server accessibility” v téže záložce. V případě úspěšného spojení se skriptem aplikace vypíše dobu odezvy. Protože je v tomto rozhraní potřeba kontrolovat práva uživatelů na přístup k datům, je nutné se před prací přihlásit pomocí přihlašovacího jména a hesla. Přihlašování je k dispozici v záložce „User“, kde se také po přihlášení vypíší informace z databáze o přihlášeném uživateli. Heslo je v klientské aplikaci zahešováno pomocí hešovací funkce MD5, při komunikaci se nikdy na síti nevyskytne jako otevřený text. Uživateli je při přihlášení přidělen náhodně vygenerovaný autentizační kód (AC). Autentizace uživatele pomocí loginu a AC se pak provádí pokaždé, když se klient dotazuje serveru. 2.1.2. Uživatelé Aplikace nabízí pro síťovou komunikaci rozhraní pro práci s uživateli. Před prvním dotazem na server se musí klient přihlásit pomocí loginu a hesla. Práva na provádění jednotlivých kroků jsou pak kontrolovány jednak v klientské aplikaci, ale také při zápisu dat na serveru. Všechny následující vlastnosti jsou určeny pro síťovou komunikaci. V systému jsou definovány tři různé úrovně oprávnění uživatelů (role): Reserver(0), Creater(1) a Administrator(2). Stupeň oprávnění určuje kroky, na které má uživatel právo. Používá se také při rezervaci (uživatel smí rezervovat pouze vstupenky s úrovní ochrany, která je menší nebo rovna oprávnění uživatele). Role Reserver(0) je určena pro běžné uživatele s úkolem prodávat vstupenky. Uživatel s touto rolí nemá žádná jiná práva. Role Creater(1) obsahuje nadmnožinu práv Reservera. Kromě prodeje vstupenek má uživatel s touto rolí také právo navrhovat a editovat prostory akcí, vytvářet nové a upravovat stávající události. Role Administrator(2) obsahuje nadmnožinu práv Createra. Uživatel s touto rolí má absolutní práva na práci s aplikací. Kromě rezervace, editace prostorů a akcí má tento uživatel také právo přidávat nové uživatele do databáze. Nový uživatel se přidává v menu „User->Administrator->New user“. Klíčem v tabulce uživatelů je login, není tudíž možné přidat uživatele s již existujícím loginem. Každý uživatel (s libovolným oprávněním) má právo měnit svoje heslo pro přístup do aplikace. Heslo se mění v hlavním menu aplikace „User->Passwd change”. Uživatel musí změnu hesla potvrdit také platným starým heslem. I zde platí, že ani staré ani nové heslo nikdy není přenášeno po síti jako otevřený text! 2.1.3. Bezpečnost při komunikaci Před přístupem do databáze je kvůli bezpečnosti nutné autentizovat uživatele – autentizace probíhá primárně při přihlášení. Vzhledem k tomu, že heslo je základní autentizační prvek uživatele a uživatelé používají velmi často stejné heslo i v jiných aplikacích, je základním požadavkem to, aby heslo nešlo nikdy otevřeně po síti. K tomu slouží kryptografická funkce MD5, kterou klientská aplikace používá. Heslo není jako otevřený text uloženo ani v databázi, takže nehrozí prolomení bezpečnosti při průniku do databáze. Konkrétní implementace postupu při přihlašování (žádost o salt ze serveru, přidělení autentizačního kódu,...) je popsána v programátorské dokumentaci. 2.1.4. Jazyková podpora Klientská aplikace poskytuje podporu pro dva základní jazyky: angličtinu a češtinu. Implicitním jazykem aplikace je angličtina. Změna jazyka je možná pomocí položky hlavního menu „Settings->Languages“. Předdefinované řetězce jsou obsaženy v dynamicky linkovaných knihovnách v adresáři „./Languages“. Změna jazyka se týká menu, popisů, tlačítek, chybových MessageBoxů, atd. Server a editor však komunikují s uživatelem pouze anglicky. 2.1.5. Editor rozvržení prostor K nadefinování rozvržení prostor slouží okno, které se nazývá Editor. Editor se spouští výběrem položky z hlavního menu „Editor->New Room“ pro vytvoření nové místnosti, nebo „Editor>Load Room“ pro načtení rozpracované místnosti ze souboru resp. databáze. K jeho otevření je v síťovém rozhraní nutná role Creater (1). Editor je okno pevné velikosti, které se velikosti místnosti přizpůsobuje pomocí posuvníků, lze tedy nadefinovat libovolně velký prostor. Při otevření editoru se zaktivuje záložka „Text I/O“, která obsahuje export objektů místnosti. Editace vlastností místnosti nebo objektů v místnosti se provádí buď textově nebo graficky. Graficky se vlasnosti nastavují pomocí dvojitého kliknutím myší na objekt resp. do místnosti. Poté se otevře editační dialog s aktuálními vlastnostmi, které uživatel může upravovat. Dvojklikem na políčko s barvou objektu v dialogu se otevře standardní dialog pro výběr barvy, pomocí kterého uživatel může nastavovat barvu objektu. Textový vstup pak probíhá pomocí editboxu v záložce „Text I/O“. Po přidání nového řádku či upravení některého z již napsaných řádků uživatel zmáčkne klávesu F5 (export text), všechny staré objekty místnosti se odstraní a z textu editboxu se vytvoří nové objekty v místnosti. Přidávání a mazání objektů v místnosti lze provést také pomocí pravého tlačítka myši (při mazání kliknutím na objekt), po němž se rozvine plovoucí menu pro přidávání resp. mazání objektů. Editor má také vlastnost drag-and-drop, tzn. že objekt může být uchopen pomocí myši a tažen po mapě místnosti (mění se jeho logické souřadnice v rámci místnosti). Textová definice vlastností místnosti: param=value\n room parametr room_name room_width room_length room_color implicitně "" velikost editoru velikost editoru white poznámka jméno místnosti šířka místnosti v pixelech výška místnosti v pixelech barva místnosti Textová definice objektů: object param1=value param2=value ....\n Sedadlo : parametr x y number color povinný A A N N object seat implicitně poznámka --x-ová souřadnice --y-ová souřadnice první volné unikátní číslo v rámci místnosti RGB(200,200,255) barva sedadla Řada : object row parametr x y number chairs angle color povinný A A A N N N implicitně ------první volná 0 RGB(200,200,255) poznámka x-ová souřadnice y-ová souřadnice počet sedadel v řadě čísla sedadel v řadě .. Např: =[1,2,3] úhel natočení řady ve stupních (90-kolmá) barva sedadla v řadě Stůl: object table parametr x y number type width length radius chairs color seat_numbers seat_color povinný A A N N N N N N N N N implicitně ----první volné rectangular 60 50 50 4 RGB(160,80,0) první volná RGB(200,200,255) poznámka x-ová souřadnice y-ová souřadnice unikátní číslo stolu v rámci místnosti typ stolu ... rectangular / round šířka stolu v pixelech .. u type=rectangular délka stolu v pixelech ..u type=rectangular poloměr stolu .. U type=round počet židlí u stolu barva stolu čísla sedadel u stolu .. např. =[1,2,3] barva sedadla v řadě Stěna : object wall parametr x y width length text color povinný A A A A N N implicitně --------"" RGB(200,200,200) poznámka x-ová souřadnice y-ová souřadnice šířka stěny v pixelech délka stěny v pixelech textový popis ve stěně barva stěny Polygon : object polygon parametr povinný points A color N implicitně poznámka body určující polygon - parametr musí --obsahovat seznam minimálně 3 bodů...např: =[100,10],[200,10],[150,200] RGB(220,220,250) barva polygonu Při textové definici objektů je kvůli přehlednosti možno zadávat barvy dvěma způsoby: názvem barvy nebo RGB konstantou. Jsou definovány následející řetězce jako barevné konstanty: red, green, blue, white, black, yellow, lightblue, lightgreen, lightred, rose, orange, grey, brown. Tvar RGB konstanty je následedující: RGB(x,y,z), kde x je červená složka barvy, y zelená složka a z modrá složka výsledné barvy (x,y,z jsou v rozmezí 0-255). Zadávání názvem barvy i RGB konstantou je ekvivalentní, RGB konstanty však poskytují uživateli mnohonásobně větší škálu barev. Navržení prostor probíhá pouze v rámci aplikace, data se ukládají až v momentu, kdy uživatel zvolí požadavek uložení prostoru. Ukládání je k dispozici v hlavním menu v položce „Editor->Save Room“. Po požadavku na uložení prostor se podle definovaného rozhraní buď otevře standardní dialog ukládání do souboru (pro lokální rozhraní – místnosti se ukládají do souboru s příponou rom), nebo dojde k odeslání na server, kde se data ukládají do databáze. Jméno místnosti v rámci databáze musí být jedinečné, místnost se stejným jménem bude přepsána! Editor se zavírá pomocí hlavního menu položkou „Editor->Close Editor“ nebo klávesovou zkratkou CTRL+C. Data, která nebyla před uzavřením editoru uložena se nenávratně ztratí! Uživateli je k dispozici také náhled na celou místnost, ten se otevírá pomocí menu „Editor->Preview“. Uživatel tak může zobrazit místnost, která je větší než plocha obrazovky celou najednou. Okno náhledu lze libovlně zvětšovat a zmenšovat. Po nastavení potřebné velikosti může taktéž uživatel uložit náhled do bmp souboru. Uložení se provádí v menu „Preview->Save“. Uložený náhled pak může být použit ve webové aplikaci, aby zákazníci, kteří si chtějí rezervovat vstupenky přes webové rozhraní, měli k dispozici náhled na rozložení sedadel v místnosti. 2.1.6. Editor události Poté, co uživatel nadefinuje místnost v editoru prostor, je potřeba k jednotlivým vstupenky. sedadlům Návrh přiřadit prostor a nadefinování události v nich jsou dvě logicky oddělené části. Takto je možné do prostoru jednoho přiřadit vytvořeného více událostí, z nichž každá má definovanané své vlastní vlastnosti, druhy, ceny lístků, atd. Návrh události tedy probíhá v editoru události. Uživatel otevře editor událostí pomocí položek „Event->New Event“ (pro vytvoření nové události) nebo „Event->Load Event“ (pro úpravu již uložené události) v hlavním menu. K otevření editoru události je v síťovém rozhraní potřebné právo Creater (1). Při vytváření nové události nejdříve uživatel musí zadat nadefinovaný prostor (ze souboru či databáze), poté se uživateli otevře dialog pro editaci vlastností události, do kterého uživatel nastavuje jméno události, datum a čas konání události a druh události (sportovní, koncert, kulturní, doprava, ostatní). Tyto vlastnosti se dají nastavit (resp. změnit) i později. Nastavování vlastností akce a vstupenek probíhá podobně jako v editoru místnosti dvěma možnými způsoby – graficky nebo textově. Na začátku jsou všechny vstupenky neinitializované (neinitializovaná vstupenka se zobrazuje šedě zbarveným sedadlem). Po nastavení vstupenky se sedadlo zbarví do původní barvy definované v místnosti. Grafické nastavování vlastností probíhá pomocí dvojitého kliknutí myší na sedadlo resp. do místnosti (pro nastavení vlastností místnosti). Takto lze nastavovat vlastnosti i vícero objektům najednou, několik objektů se nejdříve označí jedním kliknutím, označené objekty změní barvu na černou, při dvojkliku se pak editují všechny označené objekty. Stoly a řady lze graficky nastavovat pouze celé, při nutnosti nastavovat jiné vlastnosti vstupenek v rámci jedné řady nebo stolu, musí uživatel použít textový vstup! Textové nastavování vlastností události a vstupenek probíhá pomocí editboxu „Text I/O“, který v editoru události funguje jako příkazavá řádka. Uživatel do ní napíše textový vstup a pomocí F5 exportuje informace. Druhy textových příkazů: • vlastnosti akce name=jméno .. nastavení jména události time=HH:MM .. nastavení času události date=DD.MM.YYYY .. nastavení data konání události type=sport / concert / culture / transport / other .. • nastavení typu akce vlastnosti vstupenek [číslo] / [seznam] / [all] / [rest] paremetr=value parametr=value … [číslo] .. nastavení vlastností vstupence s daným číslem (možno zadat i rozsah vstupenek např. [1-100] ) [seznam] .. nastavení vlastností vstupenkám ze seznamu (prvek seznamu může být i rozsah čísel) [all] .. [rest] nastavení vlastností všem vstupenkám v místnosti .. natavení vlastností všem neinitializovaným vstupenkám Vlastnosti vstupenek Parametr price deadline where status comment level reserved_by Hodnota číslo Komentář cena vstupenky doba, do které vstupenka může být DD.MM.YYYY vstupenka v klientské aplikaci prodána řetězec místo, kde je vstupenka k dostání status vstupenky (volná, rezervovaná přes free/reserved/sold web, prodaná) řetězec komentář ke vstupence stupeň ochrany vstupenky (kteří uživatelé 0/1/2 mohou vstupenku prodat) parametr slouží pro potřebu nastavení rezervace i na klientovi, to však bude "jméno,email,DD.MM.YYYY probíhat převážně přes webové rozhraní. HH:MM" Jméno, email a čas jsou informace o zákazníkovi a o času rezervace. Před ukončením editoru události musí uživatel uložit změny (do souboru nebo do databáze – podle zvoleného rozhraní), jinak dojde ke ztrátě dat. Událost se ukládá pomocí menu „Event->Save Event“. Při rozhraní lokálních souborů se otevře standardní dialog pro ukládání souborů, kde uživatel zvolí jméno a cestu k cílovému souboru (událost se ukládá do souborů s příponou eve). Při rozhraní po síti se událost buď uloží do databáze jako nová událost, nebo se stará událost přepíše (v případě že tato bylo načtená pomocí Load Event). Okno editoru události se zavírá pomocí položky hlavního menu „Event->Close Editor“ nebo klávesovou zkratkou CTRL+C. Data, která nebyla před uzavřením editoru uložena, se nenávratně ztratí! 2.1.7. Rezervace Další logickou součástí po navržení rozložení prostor a vytvoření události je samotný prodej vstupenek. K prodeji slouží okno, které se nazývá Reservation a v síťovém rozhraní k jeho spuštění stačí právo Reserver. Okno se otevře zvolením položky „Reservation->Open“, menu po jejímž zvolení uživatel musí v dialogu vybrat událost, na kterou chce vstupenky prodávat. V rozhraní pro síťovou komunikaci se z databáze vypíší uživateli k výběru pouze ty události, jejichž čas je větší než aktuální časové razítko. Takto se zamezí tomu, aby se zbytečně vypisovaly staré události. Sedadla v okně Reservation mají tři možné stavy: aktivní, neaktivní a vybraná. Sedadla, která uživatel nemůže prodávat (již prodané vstupenky, vstupenky s vyšší úrovní ochrany, než je oprávnění uživatele,...) nejsou „aktivní“ na kliknutí uživatelem, tzn. že uživatel je nemůže vybrat a prodat. Jsou zbarveny šedou barvou. Vstupenky, které uživatel může prodat (tzn. volné nebo rezervované) mají odpovídající sedadlo zbarveno původní barvou a toto sedadlo je aktivní, tzn. že uživatel může kliknutím na sedadlo přidat vstupenku mezi vybrané. Pokud uživatel klikne na aktivní sedadlo, přidá se vstupenka mezi vybrané, což se na mapě místnosti projeví změnou barvy sedadla na černou. Takto zbarvená sedadla jsou v daném okamžiku vybrána. Více vstupenek se vybírá pomocí klávesy CTRL, která symbolizuje přidání k výběru, jinak se změní celý výběr na aktuální sedadlo. Textové vlastnosti vybraných vstupenek jsou vyexportovány do editboxu „Text I/O“. Výběr vstupenky, která je rezervovaná z webového rozhraní nahlásí varování, uživateli se zobrazí data o zákazníkovi, který si lístek zarezervoval včetně datumu a času rezervace. Podle těchto informací se pak uživatel rozhodne, zda lístek přidá k vybraným či ne. Informace o vstupence se zobrazí pomocí kliknutí pravého tlačítka myši na dané sedadlo, po němž se otevře dialog s vlastnostmi. Vlastnosti zde nejsou aktivní, nedají se měnit, tento dialog je určen pouze pro informativní účely distributora. Uživatel odešle požadavek na rezervaci vybraných vstupenek pomocí klávesové zkratky CTRL+S. V případě lokální komunikace se přepíší data v souboru s událostí, v síťovém rozhraní se požadavek odesílá na PHP skript, který se pokusí uložit změny do databáze. Skript uzamkne databázi, aby nedošlo ke kolizi s jiným uživatelem při zápisu do tabulek. Poté provede kontrolu, jestli nejsou vstupenky prodané a updatuje data v databázi. Vždy se na serveru zarezervují buď všechny vstupenky, nebo žádná. Poté skript databázi odemkne a výsledek se odešle zpět na klienta, který tento zobrazí uživateli. Distributor má v hlavním menu také k dispozici tlačítko „Reload“ („Reservation->Reload“), které obnoví stav vstupenek ze serveru. Takto uživatel zjistí aktuální stav vstupenek, aniž by musel znova načítat událost. Vyhledávání ve volných sedadlech: Uživateli je v záložce „User“ k dispozici také funkce na prohledávání volných sedadel v rámci místnosti. Tato záložka je aktivní pouze při otevřeném okně Reservation. Uživatel nastaví nejprve počet vyhledávaných lístků. K dispozici jsou poté funkce „Best table“, která vyhledává lístky v rámci jednoho stolu. Vyhledán je vždy stůl s nejmenším dostatečně velkým počtem volných míst. Obecnější je druhá funkce, která vyhledává místa v rámci celé místnosti (ne jenom stolů). Pokud existuje možnost umístit daný počet vstupenek do jedné řady nebo k jednomu stolu, nabídne aplikace uživateli právě tyto možnosti, mezi kterými se uživatel může tlačítky posunovat. V opačném případě dojde k vyhledání sedadel, který jsou si v místnosti nejblíže. Aplikuje se zde logický požadavek, aby byla místa primárně umístěna do jednoho nadobjektu (stolu či řady) a až v momentu, kdy taková možnost neexistuje, se požadavek dělí mezi vícero těchto nadobjektů. Vyhledávání se dá použít zejména v situacích, kdy je potřeba zarezervovat větší počet vstupenek, resp. když je potřeba umísťovat hodně požadavků ke stolům tak, aby rozmístění bylo co nejúspornější. 2.1.8. Grafy prodeje Uživatel má v síťovém rozhraní po otevření události v okně Reservation pro přehled o prodeji lístků k dispozici grafy. Grafy o prodeji uživatel zobrazí pomocí menu „Reservation->Graphs->..“, kde má uživatel výběr ze dvou typů grafů: graf závislosti prodeje na čase a graf závislosti prodeje na uživateli. Uživatel si pro přehlednost může měnit barevné zobrazování grafů, to se ovšem zachovává pouze v rámci jednoho okna grafu. Barva pozadí, grafu, os a popisků se nastavuje v menu okna, které obsahuje graf. SDT Graph Jedná se o graf závislosti prodeje na čase (sale dependency time). Graf je rozdělen na tři části. V hlavním grafu je zobrazena četnost prodaných lístků, ve vedlejsím pak součet všech prodaných lístků do daného data. Spodní graf je četnostní histogram se zvýrazněným maximem, minimem a průměrem prodeje za den. SDU Graph Jedná se o graf závislosti prodeje na uživateli. Je vyobrazena v něm úspěšnost jednotlivých distributorů pro aktuálně otevřenou akci, i pro všechny události dohromady. Informace jsou vypisovány jednak v grafu, ale také do tabulky v okně. 2.1.9. Ukládání konfigurace Při ukončení klientské aplikace se ukládá aktuální konfigurace aplikace (rozhraní pro práci, jazyk, login uživatele, adresa serveru a cesta ke skriptu na serveru) do konfiguračního souboru „configuration.cfg“, aby uživatel při dalším spuštění nemusel všechno nastavovat znova. Pokud konfigurační soubor neexistuje, je při spuštění programu nastaveno prostředí aplikace na implicitní hodnoty (síťové rozhraní, anglický jazyk, bez loginu uživatele). 2.2. PHP server Servrová část aplikace je tvořena skriptem RTRSscript.php. Tento skript je určen pro obsluhu klientské aplikace běžící v rozhraní síťové komunikace. Dotazy na databázi jsou předávány tomuto skriptu v nadefinovaném formátu. Skript pak převede dotazy z tohoto formátu do SQL dotazů, připojí se do databáze, a dotaz vyhodnotí. Výsledek převede zpět do formátu, který rozpozná klient a tento výsledek vrátí. Dotazy na skript se dělí na dvě skupiny: dotazy, pro jejichž vyhodnocení uživatel nemusí být nalogován (bez nutnosti autentizace) a dotazy s nutnou autentizací. Pokud uživatel není přihlášen, není dotaz vyžadující autentizaci proveden a vrátí se chybový příznak. Mezi dotazy, nevyžadující autentizaci patří žádost o řetězec salt z databáze, přihlášení uživatele a test dostupnosti serveru. Všechny zbylé dotazy, kde se přistupuje k datům v databázi vyžadují autentizaci klienta. Před použitím skriptu je potředa nastavit informace o databázi, se kterou skript komunikuje. Tyto informace se nastavují v souboru „RTRSsettings.php“ na stejné adresářové úrovni, jako samotný skript. Je třeba nastavit jméno databáze, umístění databáze, login a heslo do databáze v proměnných: $RTRSdbsname $address $login $passwd .. .. .. .. jméno databáze adresa databáze login uživatele s právy na přístup do databáze heslo uživatele s právy na přístup do databáze Skript také umožnňuje nastavit několik konfiguračních informací, jako je doba, po které se z databáze odstraní záznam o přihlášení uživatele, který delší dobu nekomunikuje, délka řetězce salt v databázi (sůl, která se přidává k heslu před hešováním), atd. Tyto údaje se nastavují do konstant na začátku PHP skriptu. 2.3. Databáze Skript vyřizuje dotazy klienta do databáze. Databáze je složena z několika tabulek, které obsahují informace o uživatelích, nadefinovaných prostorách a také o akcích a vstupenkách. Informace o registrovaných uživatelích obsahují tabulky Users a Logged, informace o nadefinovaných prostorách jsou v tabulkách Rooms, Chairs, Rows, _Tables, Polygons a Walls, informace o událostech včetně vlastností vstupenek pak v tabulkách Event, Ticket, Reserved. Tabulka Users obsahuje i heslo uživatele, to je však zahešované pomocí hešovací funkce MD5, aby nedošlo k ohrožení bezpečnosti při prolomení databáze. K vytvoření tabulek databáze slouží SQL skript: RTRSdbs.sql. Pokud uživatel impotruje tento skript, vytvoří se v databázi tabulky požadovaného formátu. Součástí skriptu je i přidání uživatele s loginem „root“, zahešovaným heslem „root“ a právy administrátora do tabulky Users. Tento uživatel pak může změnit v klientské aplikaci své heslo a být použit pro přidávání dalších uživatelů. 2.4. Webové rozhraní Poslední součástí projektu je webové rozhraní pro přístup do databáze, které je určeno pro cílové zákazníky. Uživatel musí před prvním použitím nastavit do souboru „./settings.php“ nastavení přístupu do databáze (jméno, adresu databáze, login a heslo uživatele). Účelem rozhraní je možnost zákazníka zarezervovat si vstupenku před samotnou koupí u distributora. Webové rozhraní tedy dokáže zobrazit událost, kterou si vybere zákazník (akce jsou zde rozčleněny podle druhu, definovaného v klientské aplikaci při návrhu akce), a nabídne uživateli místa, která jsou k dispozici (se statusem volných míst s deadline větší než aktuální časové razítko). Aby se zákazník lépe zorientoval na mapě místnosti, zobrazí se (pokud je k dispozici) obrázek s mapou prostor. Tím může být například Náhled místnosti, uložený z klientské aplikace (samozřejmě je zde možné umístit libovoulnou jinou mapu prostor). Jméno bitmap souboru se musí shodovat se jménem místnosti (jméno.bmp) a je uložen v adresáři „./maps/“. Tento obrázek však není interaktivní, místa nelze rezervovat výběrem na mapě, jako v klientské aplikaci. Z nabídnutých vstupenek si uživatel vybere podle ceny, umístění, atd. místa, o která má zájem a zarezervuje tato na serveru. Před samotnou rezervací musí zákazník vyplnit celé jméno a email, na kterém může být kontaktován (vyplnění těchto položek je kontrolováno javascriptem). Před změnou dat na serveru je také zkontrolována platnost emailu, z nějž je vyříznuta adresa stroje, a pomocí příkazu nslookup se kontroluje, jestli na tomto stroji běží služba Mail Exchanger. Do tabulky Reserved v databázi se uloží údaje o rezervaci a změní se status vstupenky v tabulce Ticket na „rezervovaná“. Webové rozhraní také poskytuje prostředky ke změně již uskutečněné rezervace. Po vyhledání konkrétní události může uživatel pomocí odkazu „Change reservation“, po vyplnění osobních údajů (stejně jeko při rezervaci), vstupenek. stornovat rezervaci některých 3. Programátorská dokumentace 3.1. Klientská aplikace Klientská aplikace je určená pro operační systém Microsoft Windows XP. Naprogramována je v jazyce C/C++, v prostředí Microsoft Visual Studio 6.0. Pro práci s okny využívá rozhraní WIN API a také jeho nástavbu, třídy MFC. Aplikace je navržena kvůli přehlednosti a bezpečnosti objektově, pro objekty místnosti, vstupenky, uživatele,.. jsou navrženy třídy. Jako datové struktury pro uchování dat jsou použity převážně struktury STL knihovny (např. deque, map, multimap, atd.). 3.1.1. Objekty reprezentující místnost Definice prostor, navržená uživatelem, je ukládána v paměti pomocí tříd definovaných ve zdrojových souborech room.h, room.cpp. Navržená místnost je reprezentována třídou room. Ta obsahuje jako členské private proměnné vlastnosti místnosti a datové struktury (std::deque<object>), obsahující podobjekty místnosti. Kromě toho obsahuje třída také privátní a veřejné metody pro přístup k datům místnosti, vykreslení místnosti, a pomocné funkce pro práci s místností (export textu do objektů místnosti, objektů do textového výstupu,...). Objekty v místnosti jsou potomci odvození od abstraktní třídy object, která sdružuje společné vlastnosti a metody všech těchto podobjektů: souřadnice v rámci místnosti, barva objektu a identifikátor objektu. Třída obsahuje čtyři čistě virtuální metody: virtual void paint (CDC * pdc) = 0; virtual bool in (CPoint point) = 0; virtual void set_incl_obj_diff ( int diff_x, int diff_y ) = 0; virtual CString export () = 0; Paint je metoda pro vykresleni vykresleni objektu (při vykreslování místnosti se volá metoda paint na každý objekt v místnosti), in metoda, ktera vrací příznak, jestli bod point leží uvnitř objektu, set_inc_obj_diff mění souřadnice podobjektů objektu (např. sedadla v řadě) a metoda export vyexportuje objekt do textového výstupu. Každý objekt odvozený od třídy object musí tyto metody implementovat. Takto je zajištěna obecnost návrhu v případě požadavku na vytvoření nového typu objektu, stačí pro něj nadefinovat třídu odvozenou od třídy object a přidat do místnosti metody pro práci s tímto druhem objektu. Třída object si nastavuje od ní odvozené třídy jako friend class kvůli přístupu k privátním položkám. Potomky abstraktní třídy object jsou: wall (reprezentace stěny), chair (reprezentace sedadla), polyg (reprezentace polygonu), row (reprezentace řady), table (reprezentace stolu). Pro vytvoření místnosti z textového formátu slouží funkce room::export_text_to_objects(), ta dostane jako parametr textový formát místnosti (např z editboxu), rozdělí text na řádky a každý řádek převede na vlastnost místnosti nebo objekt v místnosti. Opačnou funkcí k této funkci je export_room_to_text(), která nejdříve vyexportuje vlasnosti mísnosti a poté na každý objekt místnosti zavolá metodu object::export(). Text vyexportovaný touto funkcí se pak nastavuje do editboxu v záložce „Text I/O“. Soubor room.h obsahuje také konstanty, definující implicitní vlastnosti objektů (implicitní barvy, rozměry, počet podobjektů,...). 3.1.2. Objekty reprezentující událost Zdrojové soubory ticket.h, ticket.cpp obsahují nadefinované třídy, reprezentující uživatele, zákazníka, vstupenku a událost. Soubor ticket.h také definuje předdefinované číselné konstanty pro: • práva uživatele • #define PER_ADMINISTRATOR 2 #define PER_CREATER 1 #define PER_RESERVER 0 status vstupenky • #define STATUS_FREE #define STATUS_RESERVED #define STATUS_SOLD druh události #define EVENT_TYPE_SPORT 0 1 2 0 #define EVENT_TYPE_CONCERT #define EVENT_TYPE_CULTURE #define EVENT_TYPE_TRANSPORT #define EVENT_TYPE_OTHER 1 2 3 4 Třída Person reprezentuje údaje o zákazníkovi, který si rezervoval vstupenku přes webový interface. Třída obsahuje jako členské proměnné jméno zákazníka, email a čas rezervace. Instance této třídy je pak členskou proměnnou třídy Ticket, která reprezentuje vstupenku, vyplněna je ale pouze v případě, že status vstupenky je STATUS_RESERVED. Třída Ticket reprezentuje vstupenku, obsahuje privátní proměnné s vlastnostmi vstupenky (číslo sedadla, status, deadline, cena, ...), metody pro nastavování a vracení těchto privátních položek (settery a gettery). Součástí je i členská proměnná owner_, která obsahuje informace o zákazníkovi, který si vstupenku zarezervoval. Metoda Ticket::ticket_to_text() vytvoří z dat vstupenky textový řetězec ve formátu textového vstupu. Třída Event reprezentuje událost, obsahuje v privátních proměnných informace o události, deque čísel sedadel v místnosti a deque vstupenek (deque<Ticket>). Event lze vytvořit exportováním textu pomocí funkce export_info(), opačnou funkcí je pak funkce export(), která převádí data třídy do textového formátu (na vstupenky z deque volá metodu ticket_to_text() ). Export se používá například při ukládání události, data ve výstupním formátu se ukládají do souboru nebo na server. 3.1.3. Rozhraní aplikace Aplikace může pracovat ve dvou různých rozhraních: práce s lokálními daty (v souborech) a práce s daty v databázi na serveru. Rozhraní určuje chování programu při přihlašovaní, ukládání a načítání místností, událostí, a při rezervaci vstupenek. Aktuální rozhraní je uloženo v proměnné hlavního okna RTRSDlg::net_interface_. Data v lokálním rozhraní se ukládají a načítají ze souborů (*.rom,*.eve), pro načítání je používána MFC třída pro práci se soubory: CFileDialog. Místnost i událost se ukládají do souborů ve formátu textového vstupu, ukládá se do nich textový export objektů. Vytvoření místnosti resp. události z textového formátu je shodná s nastavováním dat pomocí editboxu v záložce „Text I/O“ (funkce room::export_text_to_objects(...) a Event::export_info(...)). Síťové rozhraní je implementováno funkcí CRTRSDlg::SendDataToServer(int query), která dostane jako parametr označení dotazu na server. Definované konstanty pro dotaz na server jsou v souboru queryconst.h: #define SD_LOGINOUT #define SD_GET_SALT_VIA_NET #define SD_LOGIN_VIA_NET #define SD_LOGOUT_VIA_NET 0 SD_LOGINOUT + 6 SD_LOGINOUT + 7 SD_LOGINOUT + 8 #define SD_ROOM #define SD_STORE_ROOM_VIA_NET #define SD_LOAD_ROOM_VIA_NET #define SD_GET_ALL_ROOMS 10 SD_ROOM + 1 SD_ROOM + 2 SD_ROOM + 3 #define SD_EVENT #define SD_GET_ALL_EVENTS #define SD_STORE_EVENT_VIA_NE #define SD_LOAD_EVENT_VIA_NET 20 SD_EVENT + 1 SD_EVENT + 2 SD_EVENT + 3 #define SD_TEST_SERVER_ACCESSIBILITY 30 #define SD_GETGRAPHINFO #define SD_GETSOLDTIMES #define SD_GETSOLDBYUSERS 50 SD_GETGRAPHINFO + 1 SD_GETGRAPHINFO + 2 #define SD_RESERVATE_CHOOSEN_TICKETS 60 #define SD_PASSUSER #define SD_CHANGE_PASSWORD #define SD_GET_RANDOM_SALT #define SD_ADD_NEW_USER 70 SD_PASSUSER + 1 SD_PASSUSER + 2 SD_PASSUSER + 3 Fukce podle nastaveného vstupního parametr odešle data na server, jehož adresa je uložena v členských proměnných hlavního okna CRTRSDlg::server_address_ a CRTRSDlg::script_address_. Data jsou odesílána na server HTTP protokolem pomocí MFC tříd CInternetSession a CHttpConnection. Funkce SendDataToServer komunikuje pomocí funkce CRTRSDlg::GetResponseFromServer(...), které předá instance tříd CInternetSession, CHttpConnection a data, která se mají odeslat, návratovou hodnotou je pak odpověď serveru. 3.1.4. Uživatelé Třída User (ticket.h, ticket.cpp) reprezentuje nalogovaného uživatele. Obsahuje členské proměnné pro login, autentizační kók uživatele a proměnné pro uchování informací o uživateli z databáze. Při přihlášení uživatele se naalokuje dynamicky třída User a konstruktorem se nastaví data o uživateli. Při odhlášení se pak na třídu volá destruktor a paměť se uvolní. Jedna z členských proměnných, získaných při přihlašování z databáze, jsou práva uživatele. Úrovně oprávnění (role) jsou definována v souboru „ticket.h“: #define PER_ADMINISTRATOR #define PER_CREATER #define PER_RESERVER 2 1 0 Při každém kroku, který vyžaduje některou z úrovní oprávnění, je zavolána funkce: bool RTRSDlg::control_users_permition (int permition), která vrátí příznak, jestli nalogovaný uživatel má práva větší než potřebné právo permition (čím větší hodnota oprávnění, tím větší má uživatel práva). Funkce je imlementovaná tak, že vrací true v případě, že program běží v rozhraní lokální komunikace (v lokální komunikaci se práva nekontrolují, protože se nepracuje se sdílenými daty). Pokud uživatel není nalogován, vypíše funkce chybový MassageBox a vrátí false. Po nalogování uživatele se vytvoří v záložce „User“ v hlavním okně aplikace okno, obsahující informace o nalogovaném uživateli. Toto okno je implementované třídou UserInfoWnd, odvozené od třídy CWnd. Třída je definovaná a implementovaná ve zdrojových souborech UserInfoWnd.h, UserInfoWnd.cpp. Před vytvořením okna se pomocí funkce UserInfoWnd::SetUserWnd(...) nastaví ukazatel na třídu User, ze které se vypisují údaje o uživateli. Okno se vytváří vždy při přepnutí uživatele do záložky „User“, po přepnutí do jiné záložky se zavře. Třída User obsahuje také členskou proměnnou ticket_count_, která obsahuje počet prodaných vstupenek uživatelem od nalogování. Při každém úspěšném prodeji se tato informace updatuje a okno UserInfoWnd se překreslí s novou hodnotou. 3.1.5. Bezpečnost síťové komunikace Před přístupem do databáze je kvůli bezpečnosti nutné autentizovat uživatele – autentizace probíhá primárně při přihlášení. Vzhledem k tomu, že heslo je základní autentizační prvek uživatele a uživatelé používají velmi často stejné heslo i v jiných aplikacích, je základním požadavkem to, aby heslo nešlo nikdy otevřeně po síti. Poté, co uživatel zadá do aplikace svůj login a heslo, dotáže se klient na server o řetězec „salt“, který má přidělen každý uživatel (dotaz SD_GET_SALT_VIA_NET). Tento dotaz je neautorizovaný, tzn. není potřeba, aby byl uživatel před tímto dotazem přihlášen. Poté se v klientské aplikaci slepí řetězce „heslo“ a „salt“ a výsledný řetězec se zahešuje kryptografickou funkcí MD5. Teprve takto upravené heslo se pošle společně s loginem na server, kde je ve stejném formátu heslo uloženo, tam také dojde k porovnání hesel a k autentizaci. Řetězec „salt“ zmenšuje pravděpodobnost, že dva uživatelé mají na serveru uložený stejný heš hesla, pak by totiž mohla být ohrožena bezpečnost, pokud by jeden z těchto uživatelů rovnost zjistil. Poté, co byla zjištěna správnost hesla, je uživateli přidělen náhodný autentizeční řetězec. Pomocí tohoto řetězce a loginu se pak uživatel dále autentizuje při každém dalším přístupu až do odhlášení. Tento systém také povoluje, aby byl uživatel najednou přihlášen vícekrát, tzn. aby měl např. spuštěných více klientských aplikací najednou. Aby se při nestandardním ukončení aplikace (např. výpadek proudu) na serveru nehromadily v databázi staré záznamy o nalogování uživatelů, jsou tyto záznamy po určitém čase od posledního přístupu smazány. Tento čas je jedním z parametrů PHP skriptu. Podobný postup jako při přihlašování je pak uplatňován i při změně hesla a při přidávání nového uživatele. Při přidávání nového uživatele klient nejprve pošle na server požadavek na náhodný salt řetěze (dotaz SD_GET_RANDOM_SALT), server vygeneruje tento náhodný řetězec o dané délce a vrátí ho klientovi. Klient pak zahešuje heslo se salt a přidá tohoto uživatele do databáze. Algoritmus MD5 je implementován ve zdrojových souborech MD5.h, MD5.cpp (implementace algoritmu), MD5globals.h (definované konstanty), MD5worker.h, MD5worker.cpp (rozhraní pro požití algoritmu). 3.1.6. Hlavní okno aplikace Aplikace byla vytvořena jako MFC Dialog Aplication. Hlavním dialogem, který se volá při spuštění programu je dialog implementovaný třídou CRTRSDlg (RTRSDlg.h, RTRSDlg.cpp), odvouzenou od třídy CDialog a nadefinovanou v resourcech jako IDD_RTRS_DIALOG. Tato třída obsahuje jako členské proměnné instance tříd Editor, NewEvent, CReservationWnd, které reprezentují jednotlivé části aplikace (editor místnosti, editor události, okno pro reservaci). Kromě toho obsahuje třída CRTRSDlg také metody, které jsou reakcemi na události (výběr z menu, přepnutí záložky, stisk klávesové zkratky, atd). Třídy Editor, NewEvent, CReservationWnd jsou potomky třídy CShowWnd, která je definovaná a imlementovaná v souborech ShowWnd.h, ShowWnd.cpp. CShowWnd je potomkem třídy generic CWnd. Tato třída sdružuje společné vlastnosti svých potomků, obsahuje instanci třídy room, která je potřebná ve všech třech částech aplikace, a imlementuje proměnnou velikost místnosti vůči pevné velikosti okna pomocí posuvníků. Editor je třída odvozená od CShowWnd a definovaná v souborech Editor.h, Editor.cpp. Třída obsahuje metody, které reagují na události uživatele (rozvinutí plovoucího menu při kliknutí na pochu místnosti, implementace drag and drop vlastnosti editoru, atd). Funkce Editor::Paint() vykresluje editor, kvůli blikání při překreslování používá metodu OffScreen Device Context, místnost je nejprve vykreslena do pomocné bitmapy pbmMemory, poté je bitmapa okopírována do cílové bitmapy získaného DC. Takto je dosaženo odstranění blikání při překreslování místnosti. Při nastavování vlastností objektu, resp. při přidávání objektu se uživateli zobrazí dialog, implementovaný třídou ObjectProp (ObjectProp.h, ObjectProp.cpp). Tento dialog je obecný, obsahuje editboxy pro nastavení všech možných vlastností objektů, podle typu objektu pak jednotlivé editoxy zpřístupňuje. NewEvent je třída odvozená od CShowWnd a definovaná v souborech NewEvent.h, NewEvent.cpp, která implementuje editor události. Jako členskou proměnnou třída obsahuje instanci třídy Event, která sdružuje data o události. Nastavování události probíhá pomocí funkce NewEvent::export_text_to_objects(...), která dostane jako parametr textový export události. Kvůli blikání implementuje okno (podobně jako Editor) metodu kreslení do bitmapy v paměti. Třída implementuje jako své metody také reakce na události (kliknutí do místnosti,..). Vlastnosti události se nastavují pomocí dialogu EventProp (EventProp.h, EventProp.cpp), který je odvozený od třídy CDialog. Vlastnosti vstupenek se nastavují pomocí dialogu implementovaného třídou TicketsProp (TicketsProp.h, Ticketsprop.cpp), taktéž odvozeného od třídy CDialog. CReservationWnd je třída odvozená od třídy CShowWnd a definovaná v souborech ReservationWnd.h, ReservationWnd.cpp. Tato třída implementuje okno, ve kterém probíhá rezervace vstupenek. Jako členskou proměnnou obsahuje instanci třídy Event, která obsahuje data události. Třída implementuje metody, které jsou reakcemi na události v okně, např. kliknutí na sedadlo v místnosti. Třída obsahuje také strukturu std::deque<int>choosen_, která obsahuje aktuálně vybraná sedadla. Pro vykreslování místnosti pak třída využívá metodu room::paint_deactivated(...), která vykresluje sedadla podle příslušnosti do této fronty. 3.1.7. Algoritmy prohledávání volných sedadel Třída CReservationWnd implementuje také algoritmy pro prohledávání místnosti za účelem vyhledávání volných sedadel. Grafické rozhraní pro vyhledávání má uživatel k dispozici v hlavním okně v záložce „Search“, to je však aktivní pouze při otevřeném okně Reservation. K dispozici jsou dva možné způsoby prohledávání: vyhledávání nejlepšího stolu a prohledávání všech objektů (stolů, řad i samostatných sedadel). Pro prohledávání všech objektů na volná sedadla se používá metoda třídy CReservationWnd find(int). Parametrem je počet sedadel pro prohledávání. Funkce funguje podle následujícího schématu: 1. pokusí se nalézt místa v rámci jednoho stolu 2. pokusí se nalézt místa v rámci jedné řady 3. pokusí se nalézt místa kombinovaně, pokud 1) a 2) neuspěly Funkce zavolá zvolený algoritmus a vrací deque<deque<int> >, strukturu všech nalezených možností umístění (část 3. vrací vždy maximálně 1 pozici). Tuto strukturu nastaví do proměnné CReservationWnd::search_result_ a do proměnné CReservationWnd::act_search_pos_ nastaví aktuální prvek z této deque (hodnota 0). Poté nastaví frontu vybraných sedadel CReservationWnd::choosen_ na aktuální prvek z této struktury. Při posunu pomocí tlačítek „Search next“ a „Search Previous“ se volá funkce CReservationWnd::ChangeSearchPos (pos), která změní aktuální pozici ve struktuře search_result_ a nastavi aktualní prvek této struktury do fronty choosen_. Poté vrátí kód, podle kterého se určuje, jestli jsou tlačítka dialogu aktivní. Funkce CReservationWnd::find_best_table (int count) slouží k vyhledávání count volných sedadel u jednoho stolu. Pokud neexistuje stul s dostatečným počtem volných míst, funkce nevrací žádnou variantu umístění (nedělí požadavek meyi více stolů). Navržené algoritmy: • Best table – BEST FIT Vyhledávání nejlepšího stolu pro daný počet vstupenek, algoritmus je implementovaný metodou třídy CReservationWnd find_best_table_BF(int). Funkce dostane jako parametr počet sedadel, které má funkce umístit k jednomu ze stolů místnosti. Algoritmus obsazuje stoly metodou BEST FIT, tzn. že vybere takový stůl, u kterého po obsazení daného počtu míst zůstane co nejmenší počet volných míst. Výhoda tohoto algoritmu je zejména fakt, že takto nedochází ke zbytečnému rozdělování velkých stolů kvůli malým požadavkům. Na druhou stranu mohou díky tomuto algoritmu vznikat samotná místa u stolů, o která nebude mít nikdo zájem. Algoritmus byl vybrán zejména proto, že malý počet volných sedadel u velkého stolu není takový problém, jako situace, kdy nedokážeme umístit všechny vstupenky zákazníka k jednomu stolu (v důsledku přílišného rozdělení stolů). • Recursive Search Algoritmus rekurzivního prohledávání sedadel, implementovaný funkcí CReservationWnd::search_recursive(). Metoda se pokusí umístit požadavek na všechny možné pozice v místnosti. Hledá optimální pozici sedadel, tzn. takové umístění, kde největší vzdálenost z vybraných sedadel od prvního sedadla je nejmenší. Funkce pro zlepšení efektivity používá ořezávání těch větví, které nemohou přinést zlepšení, přesto je však metoda velmi neefektivní a proto se používají pro prohledávání jiné metody. Časová složitost: exponenciální vyhledem k počtu sedadel v místnosti. • Search Closest Funkce CReservationWnd::search_closest (...) implementuje prohledávání volných sedadel v místnosti. Metoda nejdříve zvolí pevně první sedadlo, postupně prochází zbylá sedadla a k vybraným vždy přidá sedadlo, které není vybráno a je nejblíže k prvnímu sedadlu. Tento postup funkce provede pro každé volné sedadlo v místnosti, které vybere jako „první“. Metoda používá pro třízení sedadel podle vzdáleností strukturu STL multimap. Výsledkem algoritmu jsou sedadla, která jsou všechna umístěna do kruhu s nejmenším poloměrem vzdálenosti od centrálního (prvního) sedadla. Časová složitost algoritmu je N^3. • Matrix search algorithm Algoritmus CReservationWnd implementovaný jako metoda třídy search_algorithm(...). Vyhledávání probíhá pomocí matice vrcholů (třída Vertex, implementovaná v souboru ticket.h, ticket.cpp) velikosti [free_seat_count, free_seat_count]. Matrix[i][j] obsahuje na začátku ve třídě Vertex číslo vrcholu j a vzdálenost vrcholu i od vrcholu j. Poté setřídíme každý řádek matice podle vzdálenosti od minima po maximum. Pro vyhledávání k sedadel pak nalezneme minimum (matrix[j][k-1]) . Prvních k sedadel z tohoto řádku jsou pak výsledkem prohledávání. Algoritmus má ze všech navržených algoritmů nejnižší časovou složitost: N^2 * log (N), kde N je počet sedadel v místnosti. Tento algoritmus se také díky lepší časové efektivitě používá v aplikaci. 3.1.8. Grafy prodeje Uživatel má k dispozici v síťovém rozhraní informace o prodeji lístků pomocí grafů o prodeji. Funkce, které reagují na volbu grafů v hlavním menu jsou: CRTRSDlg::OnReservationGraphsSaledeptime() – závislost prodeje vstrupenek na čase a CRTRSDlg::OnReservationGraphsSaledepuser() – závislost prodeje na uživateli. Funkce nejdříve zkontrolují, jestli je program v rozhraní síťové komunikace a jestli je otevřené okno Reservation (jedna z událostí musí být vybraná, protože se v grafech oddělují data aktuální události a všech ostatních událostí), pokud některá z těchto podmínek není splněna, funkce vypíše chybový MessageBox a skončí. V opačném případě funkce odešle pomocí metody CRTRSDlg::SendDataToServer dotaz podle druhu požadovaného grafu (SD_GETSOLDBYTIME, SD_GETSOLDBYUSERS), server vratí příslušná data a metoda SendDataToServer tyto data uloží do proměnné CRTRSDlg::graph_data_. Data ze serveru pro graf SDT mají následující formát: každá prodaná vstupenka na aktuálně načtenou akci tvoří jeden řádek obdržených dat, na tomto řádku je počet dní, před kterými byla vstupenka prodána (např. vstupenka prodaná včera je reprezentována řádkem s hodnotou „1“). SQL dotaz na serveru data setřídí od největšího časového razítka po nejmenší. Funkce OnReservationGraphsSaledeptime() načte tato data do struktury std::deque<int>, tato data předá instanci třídy CGraphSDTWnd společně s ID menu, které má okno zobrazit a handlem knihovny pro načítání stringů. Poté metoda vytvoří okno grafu. Data ze serveru pro graf SDU mají následující formát: každý řádek dat je tvořen jedním uživatel z databáze. Řádek je tvořen 5-ti položkami, které jsou navzájem oddělené znakem ‘|’ : login|jméno|příjmení|all|act, kde all je počet všech prodaných lístků, act je počet lístků prodaných na uživatelem na aktuální akci. Funkce OnReservationGraphsSaledepuser() zpracuje data ze serveru, pro jméno, příjmení, počet prodaných vstupenek na aktuální akci a počet vstupenek na všechny akce vytvoří struktury std::map, kde klíčem každé struktury je login uživatele a hodnotou odpovídající údaj z odpovědi serveru. Tato data předá instanci třídy CGraphSDUWnd společně s ID menu, které má okno zobrazit a handlem knihovny pro načítání stringů. Poté metoda vytvoří okno grafu. Okna, obsahující vykreslené grafy, jsou implementované pomocí tříd CGraphSDTWnd (GraphSDTWnd.h, GraphSDTWnd.cpp) a CGraphSDUWnd (GraphSDUWnd.h, GraphSDUWnd.cpp). Tyto třídy jsou potomky univerzální třídy CGraphWnd (GraphWnd.h, GraphWnd.cpp), která implementuje společné vlastnosti grafových oken (přepočítávání velikostí oddělovačů, vykreslování do offscreen bufferu atd.). Třída CGraphWnd je potomkem třídy CFrameWnd, vytvořené okno tedy „žije“ v aplikaci, dokud ho uživatel nezavře, nebo aplikace neskončí. Tímto způsobem může uživatel otevřít libovolný počet grafových oken najednou. Vykreslování grafů je implementováno pomocí API funkcí pro DC okna. Spojitý graf je vykreslován pomocí polygonu, přičemž každá hodnota grafu je jedním bodem polygonu. Četnostní histogramy prodeje jsou pak vykreslovány jako obdélníky funkcí CDC::FillRect. 3.1.9. Okno Preview Metoda CRTRSDlg::OnEditorPreview reaguje na událost z hlavního menu „Editor->Preview“. Metoda nejprve zkontroluje, zda je otevřeno okno editoru místnosti, pokud ne, vzpíše chybový MessageBox a skončí. V opačném případě vytvoří instanci třídy CPreview (implementována v Preview.h, Preview.cpp), té nastaví pomocí funce CPreview::SetSourceTo bitmapu, kterou má okno zobrazit, ukazatel na data místnosti (na třídu room), ID menu a handle knihovny pro načítání stringů. Třída CPreview je potomkem třídy CFrameWnd, „žije“ v aplikaci až do uzavření okna uživatelem, uživatel si takto může otevřít více náhledů najednou. Náhled reaguje na změnu velikosti, při události WM_SIZE vytvoří novou kompatibilní bitmapu s DC okna, starou paměť uvolní. Okno náhledu nabízí uživateli možnost uložení náhledu do BMP souboru, tento soubor pak může být použit ve webové aplikaci jako náhled na rozmístění sedadel v místnosti. Na událost „Preview->Save“ reaguje metoda CPreview::OnFileSave. Metoda uživateli nabídne standardní dialog pro uložení souboru CFileDialog. Poté metoda zavolá funkci CPreview::CreateBitmapInfoStruct, která pro bitmapu vrací nainitializovanou strukturu BITMAPINFO (zjistí barevnou hloubku, nainitializuje strukturu BitmapInfoHeader a nastaví velikost bitmapy). Tato struktura je pak předána funkci CPreview::CreateBMPFile, která dostane jako jeden ze svých parametrů jméno cílového souboru, nainitializovanou strukturu BITMAPINFO a samotnou bitmapu. Metoda vytvoří soubor, zapíše do něj hlavičku BITMAPFILEHEADER a poté zapíše data obrázku. Velikost uloženého obrázku odpovídá momentální velikosti okna Preview. 3.1.10. Implementace jazykové podpory Aplikace nabízí uživateli podporu pro dva jazyky: angličtinu a češtinu. S ohledem na možné budoucí rozšiřování jazykové podpory v aplikaci jsou řetězce aplikace uloženy v dynamicky linkovaných knihovnách. Jazyk je takto možno měnit přímo za běhu aplikace tím, že se načte knihovna, obsahující tabulku s řetězci. Členskou proměnnou třídy CRTRSDlg hlavního okna je HINSTANCE hLib, která obsahuje HANDLE načtené dynamické knihovny. Řetězce pro MessageBoxy a popisy ovládacích prvků jsou načítány funkcí LoadString, která dostane HANDLE na knihovnu. Pokud uživatel zvolí v menu změnu jazyka, zavolá se metoda třídy CRTRSDlg OnSettingsLanguageEnglish (resp. OnSettingsLanguageCzech). Ta načte pomocí funkce LoadLibraryEx knihovnu se String Table a handle na ni nastaví do proměnné CRTRSDlg::hLib. Funkce LoadLibraryEx dostane jako svuj parametr flag LOAD_LIBRARY_AS_DATAFILE, dynamická knihovna tedy neobsahuje žádný kód, slouží pouze k načítání řetězců z tabulky String Table. Funkce nastaví odpovídající menu a zavolá metodu CRTRSDlg::change_language(), která aktualizuje text na statických ovládacích prvcích okna. 3.1.11. Pomocné funkce Funkce, které se používají v aplikaci vícekrát jsou implementované v souborech functions.h a functions.cpp. Funkce, definované v těchto souborech, jsou uzavřené v namespace func. Namespace obsahuje funkce pro konverze mezi čísli a řetězci, práce se strukturou deque, převody mezi stupni a radiány, převody mezi jmény barev a RGB hodnotami, atd. 3.2. PHP server PHP skript RTRSScript.php tvoří servrovou část aplikace. Na začátek skriptu se vkládá konfigurační soubor RTRSsetting.php, který obsahuje nastavení přístupu do databáze: $RTRSdbsname $address $login $passwd .. .. .. .. jméno databáze adresa databáze login uživatele s právy na přístup do databáze heslo uživatele s právy na přístup do databáze Skript nejprve zkontroluje nastavení proměnné $query (druh dotazu klienta na server), pokud proměnná není nastavena, skript vypíše chybu a skončí. V opačném případě se skript pomocí mysql připojí k databázi $RTRSdbsname na adrese $address pod uživatelem $login, autentizuje se přitom heslem $passwd. Podle nastavení proměnné $query skript převede data z klienta do SQL dotazů a ty vyhodnotí pomocí funkcí mysql, výsledek dotazu pak vrátí klientovi. Hodnoty proměnné $query se musí pro jednotlivé dotazy shodovat s hodnotami definovanými v klientské aplikaci v souboru queryconst.h. Druhy dotazů podle proměnné $query: • $QUERY_ACCESIBILITY_TEST Ověření komunikativnosti skriptu. Skript vrátí řetězec „response=ok“. Dotaz nevyžaduju autentizaci uživatele. • $QUERY_GET_SALT: Žádost klienta o řetězec salt z databáze, přidělený uživateli, jehož login je nastaven v proměnné $users_login. Dotaz nevyžaduje autentizaci uživatele. • $QUERY_LOGIN: Žádost klienta o přihlášení uživatele s loginem $users_login a zahešovaným heslem $users_password. Server zjistí, jestli tabulka Users v databázi obsahuje záznam s daným loginem a heslem. Pokud ano, vygeneruje pomocí funkce GetRandomString náhodný autentizační kód a odešle jej společně s daty o uživateli na klienta. Zároveň do tabulky Logged přidá záznam o nalogování uživatele a jemu přidělený AC. Takto je možné, aby uživatel byl nalogován vícekrát zároveň, databáze schopná rozlišovat, který klient zrovna komunikuje. Dotaz nevyžaduje je autentizaci uživatele. • $QUERY_LOGOUT Žádost klienta o odhlášení uživatele, v $AC je utentizační kód získaný při přihlášení, v $users_login login uživatele. Nejprve se provede kontrola, jestli záznam s danými údaji existuje v tabulce Logged (dotaz vyžaduje autentizaci). Pokud ano, smaže se záznam z tabulky. Uživatel je tím bezpečně odhlášen od systému. • $QUERY_SENDROOMNAMES: Žádost klienta o zaslání názvů všech místností, definovaných v databázi v tabulce Rooms. Nejprve se zkontroluje přihlášení uživatele – dotaz vyžaduje autentizaci. • $QUERY_SENDROOM Žádost uživatele o zaslání místnosti z databáze. Jméno požadované místnosti je nastaveno v proměnné $name. Server zkontroluje přihlášenost uživatele, poté vrátí z databáze vlastnosti místnosti a objekty v ní definované. Formát, ve kterém vrací data je shodný s textovým formátem, kterým definuje místnost uživatel při vytváření. • $QUERY_INSERTROOM Žádost uživatele o přidání místnosti do databáze. Nejdříve se ověří přihlášení uživatele. Post proměnné $room_name, $room_width, $room_length, $room_color obsahují informace o místnosti, proměnná $textinput pak vyexportované objekty místnosti. Pokud v databázi existuje místnost se stejným názvem jako je obsah proměnné $room_name, stará místnost se odstraní z databáze. Poté se přidají objekty místnosti do tabulek a vrátí se počet úspěšně přidaných objektů do databáze. • $QUERY_INSERT_EVENT Žádost klienta o přidání události do databáze. Nejdříve je ověří přihlášení uživatele. Jsou nastaveny post proměnné $room_name – jméno místnosti, $event_name – jméno události a $textinput – export události. Pokud byla událost získána ze serveru, je nastavena také proměnná $event_ID_from_client, potom se událost s tímto ID přepíše, jinak se uloží pod nové ID. • $QUERY_SENDEVENTNAMES Žádost klienta o zaslání všech událostí definovaných na serveru. Nejprve se provede kontrola přihlášení uživatele. Poté server vrátí pro každou událost z databáze data ve formátu: „room_name|event_ID|event_name|event_date|event_time\n“ • $QUERY_LOADEVENT Žádost klienta o událost z databáze, ID požadované události předává klient v proměnné $event_ID. Před vrácením dat se však nejprve zkontroluje přihlášení uživatele. Data se vracejí ve stejném textovém formátu, jaký používá uživatel při definování události v klientské aplikaci. • $QUERY_RESERVATE Žádost klienta o prodej vstupenek. Nejdříve se ověří nalogování uživatele. Poté je postup následující: 1) server si uzamkne databázi 2) zkontroluje status všech vstupenek ze seznamu 3) změní status vstupenek 4) odemkne databázi K zamykání a odemykání databáze slouží funkce lock_DBS a unlock_DBS. Poté vrátí příznak, jestli se zápis do databáze povedl. • $QUERY_SENDSOLDTIME Žádost klienta o zaslání dat pro vytvoření grafu SDT. Nejprve se kontroluje přihlášení uživatele. V proměnné $event_ID je od klienta nastano ID události. Server zjistí z databáze časy všech prodaných vstupenek na tuto událost, pro každou prodanou vstupenku pak vrátí 1 řádek odpovědi, který obsahuje počet dní od prodeje. • $SD_SENDOSOLDBYUSERS Žádost klienta o zaslání dat pro vytvoření grafu SDU. Nejprve se zkontroluje přihlášení uživatele. Post proměnná $event_ID obsahuje ID aktuální události. Server vrátí pro každého uživatele z databáze řádek ve formátu: „user|fname|sname|all|act“, kde all je počet všech prodaných lístků uživatelem, act je počet prodaných lístků uživatelem na aktuální událost (s ID $event_ID). • $QUERY_CHANGEPASSWORD Žádost uživatele o změnu svého hesla, nejprve se zkontroluje přihlášení uživatele. Poté zkontroluje, jestli staré heslo souhlasí a pokud ano, updatuje tabulku Users. • $QUERY_GET_RANDOM_SALT Žádost klienta o vrácení náhodného řetězce délky salt. Dotaz nevyžaduje autentizaci uživatele. Dotaz se používá při přidávání nového uživatele do databáze. • $QUERY_ADD_NEW_USER Žádost o přidání nového uživatele do databáze, nejdříve se zkontroluje oprávněnost dotazu (přihlášení uživatele). Poté se z post proměnných, natsavených klientem získají data o uživateli, ty se uloží jako nový záznam do databáze. Aby se v tabulce Logged při nekorektním ukončení klientské aplikace (např. výpadek proudu) nehromadily staré záznamy o nalogovaných uživatelích, volá se před každým nalogováním nového uživatele funkce delete_old_logged, která odstraní z tabulky Logged záznamy, kde rozdíl aktuálního časového razítka a časového razítka při přihlášení je větší než konstanta $AUTOMATIC_LOGOUT_AFTER (rozdíl v sekundách). Ta je implicitně nastavena na 1 den, je ji však možno měnit při konfiguraci skriptu. Pomocné funkce ve skriptu RTRSscript.php: delete_old_logged ($id_spojeni) - Funkce vymaže z tabulky Logged záznamy uživatelů, kteří po zadanou dobu nekomunikují se serverem. Tato časová hodnota v sekundách je nastavena v $AUTOMATIC_LOGOUT_USER_AFTER. konfigurační Funkce je konstantě zde kvůli odstraňování uživatelů, kteříi se nekorektně odpojili od databáze check_if_user_logged ($id_spojeni,$login,$AC) - funkce zkontroluje, jestli v tabulce Logged existuje záznam s loginem $login a autentizačním kódem $AC. K databázi ořistupuje pomocí identifikátoru spojení $id_spojeni. Pokud odpovídající záznam v tabulce Logged není, funkce vypíše na výstup chybu a ukončí skript. check_users_permitions ($id_spojeni,$users_login,$needed_permition) - funkce přistoupí do databáze přes identifikátor spojení $id_spojeni a zjistí z tabulky Users úroveň oprávnění klienta s loginem $users_login. Poté porovná tuto položku s paramterem funkce $needed_permition (potřebná práva). Pokud uživatel nemá potřebná práva, funkce vypíše na výstup chybu a ukončí skript. GetRandomString($length) - funkce vrati nahodný řetězec délky $length, pro generování používá funkci rand function lock_DBS ( $ids, $str, $timeout ) - funkce přistoupí k databázi přes identifikátor spojení $ids, zamkne databázi ($str je klíč pro zamykáni) pomocí SQL funkce GET_LOCK, $timeout je maximalní čas, po který funkce čeká na uzamknutí. Funkce vrací příznak, jestli se podařilo databázi uzamknout. function unlock_DBS ($ids , $str ) - funkce uvolní pomocí SQL funkce RELEASE_LOCK zámek $str v databázi, ke které přistoupí přes identifikátor spojení $ids. 3.3. Databáze Tabulky databáze jsou navrženy v modelovacím prostředí programu CASE Studio 2.22. Model databáze je rozdělen do dvou souborů: „room.dm2“ a „users.dm2“. Z těchto souborů je pak automaticky vygenerován SQL skript „RTRSdbs.sql“, který obsahuje SQL dotazy pro vytvoření tabulek databáze. Do skriptu je navíc ke generování tabulek přidán SQL dotaz, který přidá uživatele s loginem root a zahešovaným heslem root do tabulky Users. 3.4. Webová aplikace Součástí projektu je i webové rozhraní pro cílové zákazníky, přes nějž si tito mohou rezervovat vstupenky před samotnou koupí u distributora. Webové rozhraní je napsáno podle normy XHTML 1.0, pro vzhled definuje soubor kaskádových stylů. Webová aplikace je validní podle normy XHTML 1.0 Transitional, validní podle CSS normy je i stylový soubor „styles/style.css“, který definuje vzhled aplikace. Aplikace byla testována v prohlížečích Internet Explorer 6.0 a Mozilla Firefox verze 1.0. Menu, definované v souboru „menu.php“, je pomocí php na serveru vkládáno do všech stránek, které se zobrazují uživateli. Hlavní stránkou aplikace je soubor „index.php“, který podle nastavení get proměnné $type zobrazí z databáze události daného typu, jejichž časové razítko je větší než aktuální čas. Pokud uživatel klikne na událost, zobrazí se soubor „event.php“, který obsahuje mapu místnosti (je-li k dispozici) a tabulku volných sedadel s checkboxy. Kontrola vyplnění údajů o uživateli (jména a emailu) probíhá pomocí javascriptu – funkce control(). Kvůli možnosti vypnutí javascriptu je tato kontrola prováděna taky pomocí PHP na počátku skriptu „reserve.php“. Pokud uživatel zmáčkne tlačítko „Book tickets“, předají se data z checkboxů souboru „reserve.php“, než se zapíší data do databáze, zkontroluje se platnost emailu. Kontroluje se pomocí příkazu nslookup, jestli na adrese emailu funguje služba Mail Exchanger. Pokud ne, skript vypíše chybovou hlášku a ukončí se. V opačném případě vypíše informace o průběhu rezervace. Ke změně rezervace (stornování rezervace nebo zjištění stavu rezervace) slouží stránka „cancel_reservation.php“.
Podobné dokumenty
Thermal Comfort Analyzer
na 16 řádku v souboru setup.csv na hodnodu 1. Real- time režim se liší od běžného tím, že při
výběru měření se objeví dialogové okno, kde uživatel zvolí umístění a sobour, do kterého
ovládací softw...
Cracking 4 newbies…
s ECX, tak získám původní EAX, tedy správné
registrační číslo. Výsledkem této operace je hodnota
5A494C42h, ale heslem musí být nějaký řetězec, a
proto převedeme toto číslo na znaky ASCII.
Poněvadž...