% Programozási nyelvek (Java), utolsó utáni utóvizsga, 2014.02.04. # Általános tudnivalók Ebben az ismertetésben az osztályok, valamint a minimálisan szükséges metódusok leírásai fognak szerepelni. A feladatmegoldás során fontos betartani az elnevezésekre és típusokra vonatkozó megszorításokat. Segédfüggvények létrehozhatóak, a feladatban nem megkötött adattagok és elnevezéseik is a feladat megoldójára vannak bízva. Törekedjünk arra, hogy az osztályok belső reprezentációját a lehető legjobban védjük, tehát csak akkor engedjünk, és csak olyan hozzáférést, amelyre a feladat felszólít, vagy amit azt osztályt használó kódrészlet megkíván! A beadott megoldásodnak működnie kell a mellékelt tesztprogramokkal, de ez nem elégséges feltétele az elfogadásnak. Törekedjünk, hogy a megírt forráskód kellően általános és újrafelhasználható legyen! Használható segédanyagok: [Java dokumentáció](http://pnyf.inf.elte.hu/ebr/public/java7/api/), legfeljebb egy üres lap és toll. Ha bármilyen kérdés, észrevétel felmerül, azt a felügyelőknek kell jelezni, *NEM* a diáktársaknak! # A feladat összefoglaló leírása Készítsünk egy adott napon belül előforduló, ezredmásodperc pontosságú időpillanatok tárolására alkalmas osztályt! Valamint ezt egészítsük ki úgy, hogy ezeket az adatokat egy szöveges állományból be lehessen olvasni és el tudjunk végezni rajtuk bizonyos műveleteket. [Tesztek](tests.zip) # A feladat részletes ismertetése A feladat több részfeladatból áll. A bennük szereplő összes osztálynak a `time` csomagba kell kerülnie. ## Kettes szint Valósítsuk meg a `time.Time` osztályt, amelynek az a feladata, hogy ábrázolja a feladatban kezelendő időpillanatokat. - Benne el kell tudnunk tárolni a következő tulajdonságokat: óra, perc, másodperc és ezredmásodperc. Ezek mindegyikéhez legyen egy-egy getter -- `getHour()`, `getMinute()`, `getSecond()`, `getMilisecond()` --, de ne legyenek setterek, és ne is lehessen kívülről módosítani a tulajdonságokat! Továbbá készítsünk egy függvényt -- `getRawValue()` --, amely visszaadja a tárolt idő nyers értékét, az az éjfél óta eltelt ezremásodperc számát. - A típusnak legyen két olyan kívülről el nem érthető konstruktora, amelyekkel vagy a négy komponens (óra, perc, másodperc, ezredmásodperc) vagy pedig a nyers érték alapján tudunk létre hozni új elemeket! Mivel ezeket belülről fogjuk meghívni (ld. `makeTime()`), ezért itt nem kell ellenőrizni, hogy a megadott paraméterek szabályos időpillanatot definiálnak vagy sem. - Legyen egy kívülről elérhető konstruktor, amely egy másik `time.Time` típusú objektumot kap meg, és annak állapotának megfelelően inicializálja az értékeket! - Vegyünk fel egy osztályszinű metódust -- `makeTime()` --, amely segítségével egy `String` értékből tudunk `time.Time` értékeket készíteni. De csak olyan esetben engedjük ezt, amikor: - A szöveg formátuma a következő alakú: 99:99:99.999 ahol a `9` decimális számjegyeket jelöl. - A értékek rendre óra, perc, másodperc, ezredmásodperc alakban szerepelnek. Ennek megfelelően az óra értéke csak `0` és `23` között lehet, a percé és a másodpercé `0` és `59`, az ezredmásodpercé pedig `0` és `999` között. Ügyeljünk arra, hogy az egyes pozíciókon egyaránt szerepelhetnek rövidebb (pl. `1`) és elölről nullával kiegészített (pl. `001`) értékek is! Minden más esetben a metódus `null` referenciával térjen vissza! Ne felejtsük el kezelni az átalakítás közben felmerülő lehetséges kivételeket! - Valósítsuk meg a `time.Time` értékek egyenlőségvizsgálatát! Két `time.Time` objektumot akkor tekintünk egyenlőnek, ha pontosan ugyanazt az időpillanatot ábrázolják. - Adjuk meg, miként lehet szöveggé (`String` értékké) alakítani a `time.Time` értékeket! Tehát, például dél így jelenik meg: `12:00:00.000`. ## Hármas szint Valósítsuk meg a `time.Journal` osztályt, amely `time.Time` értékek sorozatát tudja tárolni! Ezeket az értékeket egy szöveges állományból olvassa be, másként nem is tudjuk létrehozni. - Legyen egy kívülről el nem érhető konstruktora, amely `time.Time` értékek egy tömbjéből tudja létrehozni az objektumot! - Vegyünk fel egy osztályszintű -- `readJournal()` -- metódust, amely megkap egy állománynevet és abból megpróbál szövegesen beolvasni a `time.Time` formátumának megfelelő, soronként tárolt értékeket! Amennyiben egy sor nem felel meg ennek a formátumnak (vagy éppen üres), akkor hagyjuk figyelmen kívül. Ha a megadott állomány nem létezik vagy nem elérhető, illetve egyetlen értelmezhető időpont sincs benne, akkor adjunk vissza `null` referenciát. - Adjunk az osztályhoz egy `getEntries()` metódust, amellyel kívülről le tudjuk kérdezni a tárolt értékeket! Az eredményt a metódus egy `time.Time` értékek tömbjeként adja vissza. - Valósítsuk meg `time.Journal` értékek egyenlőségvizsgálatát! Két `time.Journal` típusú objektumot egyenlőnek tekintünk, ha ugyanazokat a `time.Time` értékeket tartalmazzák, ugyanabban a sorrendben. - Tegyük a `time.Journal` értékeket szöveggé alakíthatóvá! A generált szöveges reprezentációban soroljuk fel a tárolás sorrendjében a tárolt `time.Time` értékeket, szövegesen. ## Négyes szint Egészítsük ki a `time.Time` osztályt úgy, hogy az értékei összehasonlíthatóak, rendezhetőek legyenek! Egy `time.Time` értéket kisebbnek tekintünk egy másiknál, ha időben hamarabbi. Tehát, pl. a `01:02:03.004` érték kisebb, mint `02:03:04.005`. Adjunk a `time.Time` osztályhoz egy olyan osztályszinű metódust -- `diffTime()` --, amellyel két időpillanat közt eltelt időt tudjuk kiszámítani! ## Ötös szint Készítsük el a `time.View` absztraktosztály-sablont, amely segítségével `T` értékek tömbjét tudjuk akár láncba fűzve manipulálni! Az osztálynak legyenek a következő tagjai: - `transform()`: egy belső absztrakt metódus, amely megvalósít egy tömbmanipulációt. Paraméterként `T` értékek sorozatát kapja, eredményként pedig azok megváltoztatott változatait adja vissza. - `then()`: egy kívülről elérhető metódus, amellyel az adott `time.View` értéket tudjuk összekapcsolni másik `time.View` értékkel. Ezt azt jelenti, hogy miután elvégeztük az osztályban megvalósított transzformációs műveletet, következőként még futtassuk le a paraméterként adott osztály transzformációját is. Ennek segítségével akár transzformációs láncokat tudunk könnyedén felépíteni majd a leszármazottakból. A `then()` eredményként az aktuális `time.View` értéket adja vissza (technikai szempontból így kényelmesebb). - `view()`: az osztályban megvalósított transzformáció lefuttatása a paraméterként megadott `T` elemek tömbjére, amelynek eredménye a módosított `T` értékek tömbje. A `time.View` felhasználásával valósítsuk meg a következő transzformációkat: - `time.Reversed`: megfordítja a `T` értékek sorrendjét a tömbben. - `time.Sorted`: rendezi a `T` értékek sorozatát. - `time.TimeIntervals`: kiszámítja a tömbben szereplő értékek közt eltelt időket (a `timeDiff()` segítségével). Jó munkát! :-)