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

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...

Více

Cracking 4 newbies…

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ž...

Více