Zadání
Vaším úkolem je:
- Implementovat třídu
timetable
reprezentující jízdní řád.
- Implementovat funkci
read_timetable
pro naplnění třídy timetable
daty ze souboru.
- Implementovat předepsané funkce pro procházení jízdním řádem.
- Implementovat funkci
print_platform_timetables
pro generování jízdních řádů pro vyvěšení na daném nástupišti dané zastávky.
Splnění zadání ověříte pomocí testovacího frameworku, který provádí:
- Vytvoření prázdného objektu typu
timetable
.
- Načtení dat pomocí funkce
read_timetable
ze souboru, jehož jméno je zadáno jako první parametr příkazové řádky.
- Vypsání všech dat do souboru téhož formátu jako vstupní data (na povel druhým parametrem příkazové řádky).
- Volání
print_platform_timetables
pro vybranou zastávku a nástupiště.
- Nalezení a vypsání nejrychlejšího spojení mezi vybranými dvojicemi zastávek.
Předepsané rozhraní
Vaše implementace musí naplnit zde popsané veřejné rozhraní (můžete však publikovat i další funkce). Testovací aplikace používá pouze typ timetable
a níže jmenované funkce.
Rozhraní můžete realizovat libovolným způsobem, pro který bude testovací framework přeložitelný a funkční. Do testovacího frameworku přitom nezasahujte (můžete si samozřejmě napsat další testy).
Předepsané rozhraní vynucuje určitou základní strukturu reprezentace jízdního řádu, ponechává však volnost ve volbě druhu vnitřních kontejnerů a neurčuje formát jednotlivých objektů.
Reprezentace času
Čas je reprezentován číselným typem packed_time
jako minuty v daném dni. Ke konverzi z a na čitelnou formu jsou určeny funkce
packed_time pack_time(int hh, int mm)
,
int hours(packed_time tm)
a int minutes(packed_time tm)
.
(V
kostře ke stažení
jsou tyto funkce již implementovány.)
Předepsané typy
timetable
- jízdní řád. Konstruktor bez parametrů inicializuje jízdní řád jako prázdný. Další obsah třídy není předepsán.
Ostatní typy používané v předepsaném rozhraní nemají předepsaná jména ani obsah.
Modifikující funkce
read_timetable(timetable & tt, std::istream & ifs)
- naplnění objektu tt
daty ze streamu ifs
. Formát streamu(souboru) je popsán spolu s testovacími daty ke stažení.
Funkce k procházení struktury jízdního řádu
Všechny tyto funkce dostávají jako první parametr odkaz na objekt. Tímto objektem je buďto celý jízdní řád, nebo vnitřní objekt reprezentující nějaký prvek jízdního řádu. Vnitřní objekty jsou součástí datové struktury jízdního řádu a testovací aplikace s nimi manipuluje pouze prostřednictvím odkazů na ně. Obsah vnitřních objektů je zpřístupněn pouze nepřímo funkcemi popsanými v této sekci. Objekty těchto typů se nesmějí vyskytovat mimo datovou strukturu jízdního řádu.
Jména typů vnitřních objektů ani jejich obsah není předepsán. (V
kostře ke stažení
jsou jména některých typů navržena tak, aby bylo možno přeložit alespoň hlavičky předepsaných funkcí.)
Některé z těchto funkcí vracejí odkazy na kontejnery, obsahující výše zmíněné objekty. Procházení těchto kontejnerů je nejčastější způsob, kterým se získávají odkazy na další objekty. Kontejnery mohou být libovolných typů, vnějším uživatelům je povoleno používat pouze základní funkce begin
, end
a size
.
Některé z těchto funkcí vracejí odkazy přímo na jednotlivé prvky těchto kontejnerů, a to buďto ve formě iterátoru (pak je možné procházet sousedy prvků až po začátky či konce těchto kontejnerů), nebo ve formě reference (pak je procházení sousedů nemožné).
Srozumitelný příklad použití těchto funkcí naleznete ve funkci dump_stopwise
v testovacím frameworku
dump.hpp
Celý jízdní řád
stops(tt)
- odkaz na kontejner se všemi zastávkami jízdního řádu tt
get_stop(tt, name)
- odkaz na zastávku se zadaným jménem name
(pokud neexistuje, funkce vyvolává výjimku)
trips(tt)
- odkaz na kontejner se všemi jízdami jízdního řádu tt
Zastávka
stop_name(st)
- jméno zastávky st
platforms(st)
- odkaz na kontejner se všemi nástupišti zastávky st
get_platform(st, name)
- odkaz na nástupiště se zadaným identifikátorem name
(pokud neexistuje, funkce vyvolává výjimku)
Nástupiště
platform_name(pl)
- identifikátor nástupiště pl
routes(pl)
- odkaz na kontejner se všemi linkami na nástupišti pl
Linka na nástupišti
Tento objekt reprezentuje dvojici linka-nástupiště, nikoliv samotnou linku.
route_name(pr)
- číslo (označení) linky pr
departures(pr)
- odkaz na kontejner se všemi odjezdy linky z nástupiště st
, odjezdy jsou v kontejneru uspořádány podle času
departure_at(pr, tm)
- iterátor odkazující na první odjezd v čase větším nebo rovném tm
(pokud neexistuje, vrací departures(pr).end()
). Vrácený iterátor lze použít k procházení všech odjezdů po zadaném čase.
Odjezd linky od nástupiště
Tento objekt odpovídá trojici nástupiště-linka-jízda a určuje tedy čas průjezdu linky nástupištěm pro danou jízdu.
departure_time(rd)
- čas odjezdu
trip(rd)
- odkaz na jízdu, jíž je odjezd součástí
position_in_trip(rd)
- iterátor odkazující do kontejneru departures(trip(rd))
na pozici odpovídající průjezdu dané jízdy daným nástupištěm
Funkce splňují invariant departure_time(* position_in_trip(rd)) == departure_time(rd)
. Jinými slovy, každý odjezd je zaznamenán dvakrát, jednou v kontejneru odjezdů příslušné linky od příslušného nástupiště, jednou v kontejneru odjezdů příslušné jízdy.
Jízda
trip_name(tr)
- identifikátor jízdy tr
departures(tr)
- odkaz na kontejner se všemi odjezdy na trase linky st
, záznamy v kontejneru jsou uspořádány ve směru jízdy
sequence_id(tr, tdit)
- pořadové číslo odjezdu v rámci jízdy - tdit
musí být iterátor ukazující do kontejneru departures(tr)
Poznámka: Časy odjezdů v kontejneru departures(tr)
nemusí být uspořádány vzestupně, pokud jízda překračuje půlnoc. Kromě toho některé jízdy stíhají projet dvěma nástupišti v téže minutě.
Poznámka: Z tohoto objektu nelze určit, o jakou linku se jedná. Pojem linka je chápán pouze jako označení tramvaje v okamžiku průjezdu daným nástupištěm, čímž je umožněna změna čísla linky během jízdy.
Odjezd během jízdy
departure_time(td)
- čas odjezdu
stop(td)
- odkaz na objekt reprezentující zastávku
Poznámka: Z tohoto objektu nelze přímo určit, z kterého nástupiště a pod kterým číslem linky se odjezd koná, přestože tato informace v datech je zaznamenána. Důvodem je zjednodušení rozhraní i implementace.
Aplikační funkce
print_platform_timetables(std::ostream & oss, const timetable & tt, const std::string & sid, const std::string & pid)
- vytištění zastávkových jízdních řádů pro zastávku sid
a nástupiště pid
.
- Příklad výstupu je ve vzorovém výstupu testovací aplikace:
jr_tue.output.txt
(odjezdy ze zastávky Hellichova ve směru Malostranské náměstí).
Soubory ke stažení
Testovací data
Jízdní řád je reprezentován jedním textovým souborem ve formátu tab-separated-values. Význam jednotlivých polí je následující:
- route_short_name - označení linky (libovolný řetězec)
- trip_id - identifikátor jedné jízdy s cestujícími (celé číslo)
- stop_sequence - pořadové číslo zastávky v rámci jedné jízdy (celé číslo)
- stop_id - interní identifikátor nástupiště (libovolný řetězec)
- stop_name - název zastávky (řetězec)
- departure_time - odjezd ve tvaru hh:mm (předpokládá se příjezd v téže minutě)
-
jr_tue.txt
- jízdní řád pražských tramvají pro úterý 6.12.2016
- 206 649 záznamů, 7.7 MB, 7-bit ASCII
-
jr_tue_16.txt
- výřez pro interval 16:00-16:59
- 13 253 záznamů, 493 KB, 7-bit ASCII
Kostra řešení
Kostru je možné s testovacím frameworkem přeložit, nikoliv však slinkovat, protože chybí implementace většiny funkcí. Vašim úkolem je doplnit tyto implementace, k tomu však budete muset pozměnit nebo doplnit i jiné části kostry.
Testovací framework
-
dump.hpp
- dvě funkce pro výpis dat do souboru téhož formátu jako vstupní data
- liší se způsobem procházení daty a tudíž pořadím záznamů ve výstupu
-
connection.hpp
- funkce pro nalezení nejkratšího spojení mezi dvěma zastávkami
-
jrmain.cpp
- testovací aplikace
Testy v recodexu nyní probíhají s těmito parametry:
- jr_tue.txt -sc Balabenka Florenc 16 0 1 -sc Balabenka Hellichova 16 0 1
- jr_tue.txt -pt Hellichova U138Z2
- jr_tue.txt -tw
- jr_tue_16.txt -sc Balabenka Hellichova 16 0 5 -sc Motol Kobylisy 16 0 2
- jr_tue_16.txt -pt Hellichova U138Z2
Projekt pro Visual Studio 2019
Stahujte pomocí "save link as" v prohlížeči.
Vzorové výstupy