Safe Haskell | Safe |
---|
První domácí úloha do Semináře z funkcionálního programování IB016, semestr jaro 2019.
Zadání
Vaším úkolem bude vytvořit jednoduchou implementaci zjednodušeného systému residentního parkování v Brně.
Systém si uchovává informace o residentech, kteří pak mohou parkovat své jediné auto v libovolné brněnské zóně.
Parkovat v Brně však mohou i návštěvníci, avšak musí za každou minutu, již zde stáli, zaplatit jeden peníz.
Systém má uloženu databasi zón, kde je známo, zda v dané zóně mohou parkovat pouze residenti, nebo i návštěvníci.
Backend
Definujte datové typy Zones
, Parked
, ZoneType
, které odpovídají
vnitřní struktuře vašich databasí. Pomněte, že se nemusí (ale může) jednat o
typové aliasy.
Implementujte všechny funkce v zadání implementované jako undefined
krom
funkce interactive
. Držte se přesně dokumentace k těmto funkcím.
Interaktivní klient
Implementujte interaktivní klient čtoucí standardní vstup a píšící na
standardní výstup. Všechny po něm požadované funkce najdete v jeho
dokumentaci (funkce interactive
).
Bonus
Brněnští strážníci mají vyfoceno auto, kterak pádí po brněnských ulicích nepovolenou rychlostí. Kvůli této však není poznávací značka jasně čitelná. Pomozte mužům zákona identifikovat pachatele (pokud je registrovaným Brňanem).
Přidejte do interaktivního klientu funkci, jíž bude zadána poznávací značka, kde některé znaky (krom mezery na čtvrté posici) budou nahrazeny znakem '_'. Nalezněte všechna vozidla, která se nachází v databasi, jejichž poznávací značky mohou nahrazením některých znaků znakem '_' splynout se vstupem. Navíc vrácená vozidla opatřete informací o majiteli, je-li tento v databasi residentů, a zóně, je-li vozidlo v některé právě zaparkováno.
Bodování
Rozdělení bodů do částí je následující:
- Za backend část můžete získat 7 bodů.
- Za interaktivní část můžete získat 3 body.
- Za bonus můžete získat další 1 bod (a k tomu spoustu zábavy s Haskellem).
- Za peer review můžete získat až 3 body.
Povolené knihovny
Můžete použít libovolný modul z balíčku base a containers
Dále, pro hezčí zdrojový kód, je povoleno užívat balíček unicode-prelude
Užití žádných jiných balíků dovoleno není.
Mějte na paměti, že psaní vlastních funkcí, které je lze nalézt v povolených modulech, BUDE penalisováno. Proto doporučujeme pečlivě prostudovat především moduly Data.Set a Data.Map. Rozhodně neprohloupíte, když si navíc prohlédnete i Prelude, Data.List a Data.Maybe
Synopsis
- data Car
- data Person
- type Database = (Residents, Zones, Parked)
- createCar :: String -> Maybe Car
- addResident :: Residents -> Person -> Maybe Car -> Residents
- updateCar :: Residents -> Person -> Maybe Car -> Residents
- deleteResident :: Residents -> Person -> Residents
- carPrice :: Database -> Time -> Car -> Integer
- payForCar :: Database -> Time -> Car -> Parked
- unparkCar :: Database -> Time -> Car -> Parked
- fines :: Database -> Parked
- visitors :: Database -> Parked
- potential :: Database -> Time -> Integer
- interactive :: Database -> Time -> IO (Database, Time, Money)
Documentation
Datová struktura pro ukládání osob.
Dvě osoby jsou stejné právě tehdy, když mají stejná čísla občanských průkazů.
type Database = (Residents, Zones, Parked) #
Typový alias vyjadřující typ všech informací, které má úřad v kterékoli chvíli k disposici.
:: String | poznávací značka |
-> Maybe Car |
Vrátí hodnotu automobilového typu za předpokladu, že má řetězec tvar poznávací značky.
Tvar poznávací značky je následující:
{Čís}{VP}{Čís|VP}{mezera}{Čís}{Čís}{Čís}{Čís}
kde {Čís}
je libovolná číslice
a {VP}
je libovolné velké písmeno anglické abecedy, kromě G, O, Q, W.
Pokud nemá řetězec požadovaný tvar, vrátí Nothing, jinak vrátí řetězec
zabalený do konstruktorů Just
Car
V celém zbytku řešení je zakázáno používat konstruktor Car
k vytváření
hodnot typu Car
(tedy je povoleno jej používat právě k pattern matchingu).
Přidá nového residenta.
Pokud již daná osoba je uložena, nebo daný vůz napsaný na některou osobu, vrátí funkce hodnotu nezměněného prvního argumentu.
Pokud je jako samohyb předána hodnota Nothing
je přidána osoba bez
přiřazeného samohybu.
Změní vůz napsaný na danou osobu, případně přiřadí vůz nový, pokud na danou
osobu zatím žádný vůz napsán nebyl. Pokud je již vůz napsán u jiné osoby nebo
osoba vůbec není uložena jako resident, je vrácen první argument nezměněn.
Pokud je jako nový samohyb předána hodnota Nothing
, odebere jakýli vůz
přiřazený k dané osobě z databáze residentů.
:: Residents | residenti |
-> Person | osoba odstanuvší se residentem |
-> Residents |
Odstraní osobu (a s ní asociovaný samohyb) z residentů. Pokud osoba nebyla residentem, je vrácen první argument beze změn.
Cena, kterou musí zaplatit majitel daného vozidla, aby je mohl odparkovat v této chvíli. Vozidlo lze odparkovat jen tehdy, pokud je hodnota této funkce pro toto vozidlo rovna 0.
Cena se počítá různě podle následujícího:
- pokud je vůz zapsán na nějakého residenta a stojí v libovolné zóně uložené v databasi, pak je cena rovna 0.
- pokud vůz v databasi residentů není a stojí v zóně označené jako
Visitors, pak je cena rovna délce zaparkování, tedy
{aktuální čas} – {čas zaparkování}
- ve všech jiných případech je vůz pokutován a cena se tedy rovná pokutě,
ke které je přičtena zvýšená minutová taxa, tedy
fine
+fineMultiplier
* ({aktuální čas} – {čas zaparkování})
Nastaví dobu parkování tak, aby aktuální cena za parkování (carPrice
)
byla rovna 0. Může pro tento účel nastavit čas zaparkování i do budoucnosti.
Tedy nastaví čas zaparkování samohybu na:
aktuální čas
, pokud samohyb není zatížen pokutou,aktuální čas +
, pokud zatížen pokutou je.fine
`div`fineMultiplier
Odebere automobil z database zaparkovaných vozidel, pokud je za něj uhrazen příslušný poplatek za parkování či příslušná pokuta, tedy jeho carPrice je rovna 0.
:: Database | městská database |
-> Parked |
Vrátí databasi zaparkovaných vozidel ochuzenou o vozidla, která NEJSOU pokutována (vrátí tedy právě ta pokutovaná).
:: Database | městská database |
-> Parked |
Vrátí databasi zaparkovaných vozidel ochuzenou o vozidla, která NEJSOU zatížena BĚŽNÝM poplatkem za parkování (nikoliv pokutou).
:: Database | městská database |
-> Time | aktuální čas |
-> Integer |
Vrátí množství peněz, které by připutovaly do městské pokladnice, pokud by za všechna aktuálně zaparkovaná vozidla byly v aktuální chvíli zaplaceny všechny pokuty a poplatky, kterými jsou ta která vozidla zatížena.
Interaktivní přístup k městské databasi mající následující funkce:
- Je lze ho ukončit.
- Zvýší čítač času o 1 a zobrazí nový čas.
- Výpočet množství peněz, které by připutovaly do pokladnice při okamžitém
zaplacení všech pohledávek (vizte
potential
). - Zaparkování vozu v dané zóně. Zóna nemusí existovat, v tom případě bude
vypsáno upozornění o pokutě. Stejně tak, pokud osoba je návštěvníkem a
parkuje v residentské zóně. Nedovolí zaparkovat vůz, který již zaparkován
je. Vůz, který není vozem (dle
createCar
) zaparkován nebude! - Zaplacení poplatku/pokuty za zaparkované vozidlo. Vypíše, kolik bylo zaplaceno. Ošetřete neexistenci vozidla.
- Odparkování vozu. Bude provedeno pouze tehdy, pokud vozidlo není zatíženo poplatkem, ani pokutou (uživatel bude informován, zda bylo vozidlo odparkováno). Ošetřete neexistenci vozidla.
Výpis všech dostupných informací, tedy:
- aktuální čas
- peníze doposud utržené
- výpis residentů seřazených podle čísel OP
- výpis zaparkovaných vozů a jejich aktuální hodnota (vizte
carPrice
)
- „Odtah“ všech pokutovaných vozidel, do utržených financí se započítají pokuty a navíc 100 peněz za odtah každého jednoho vozidla.
Provedení libovolné funkce krom čekání netrvá žádný čas.
Funkce vrací nový stav database, nový čas a peníze utržené za zaplacení pokut a parkovacích poplatků za dobu běhu interaktivního asistentu.