IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 15 - Diář s databází v Kotlin - Dokončení

V minulé lekci, Diář s databází v Kotlin, jsme rozpracovali jednoduchý diář s databází pomocí kolekce List.

V dnešním Kotlin tutoriálu dokončíme aplikaci diář.

Do třídy Diar přidejme pomocnou metodu zjistiLocalDateTime(), která vyzve uživatele k zadání data a času a vrátí instanci LocalDateTime nastavenou na tuto hodnotu. Nejprve si metodu ukažme, záhy si ji popíšeme:

private fun zjistiLocalDateTime(formatData: DateTimeFormatter): LocalDateTime {
    try {
        return LocalDateTime.parse(readLine(), formatData)
    } catch (e: Exception) {
        println("Nesprávně zadáno, zadejte prosím znovu")
        return zjistiLocalDateTime(formatData)
    }
}

Metoda vrací instanci LocalDateTime a v parametru bere formatter. V bloku try se pokoušíme přechroupat vstup od uživatele metodou parse(). Kdyby se projevila případná chyba v zadání (např. 30. únor a podobně), program přejde do bloku catch, uživatele upozorníme na chybu a zadání provedeme znovu. Všimněte si, že metoda volá sebe sama pro nové zadání. Je to běžná programátorská praktika, které se říká rekurze. Tuto metodu si schovejte, bude se vám jistě hodit i do budoucích konzolových aplikací :) K blokům try-catch se ještě podrobně vrátíme, až se budeme učit pracovat se soubory.

Do třídy si přidejme 2 veřejné companion objects (statické atributy). Budou to formattery data a času. Statické proto, aby byly použitelné i pro další třídy v naší aplikaci. Každá třída může používat tyto formattery, které máme definované na jednom místě.

companion object {
    val formatData = DateTimeFormatter.ofPattern("d.M.yyyy H:m")
    val formatDataBezCasu = DateTimeFormatter.ofPattern("d.M.yyyy")
}

Jeden formatter obsahuje datum i čas, jeden pouze datum bez času. Přejděme do třídy Zaznam.kt a metodu toString() pozměňme takto:

override fun toString(): String {
    return "${datumCas.format(Diar.formatDataBezCasu)} $text"
}

Kdybychom si dělali instanci formatteru znovu v každém záznamu, bylo by to nepraktické. Takto máme formattery na jednom místě a když se rozhodneme formát změnit, změníme ho jen ve třídě Diar. Se statikou ale opatrně, ne vždy ji je vhodné použít.

Vraťme se do třídy Diar. Přidáme 2 metody pro zjištění data a času:

private fun zjistiDatumCas(): LocalDateTime {
    println("Zadejte datum a čas ve tvaru [1.1.2013 14:00]:")
    return zjistiLocalDateTime(formatData)
}

private fun zjistiDatum(): LocalDate {
    println("Zadejte datum ve tvaru [1.1.2013]:")
    return zjistiLocalDateTime(formatDataBezCasu).toLocalDate()
}

Obě využívají naši metodu zjistiLocalDateTime(), ale dávají ji jiný formatter. Pomocí zjistiDatumCas() budeme zadávat datum a čas. Pomocí zjistiDatum() budeme zadávat pouze datum, všimněte si, že vrací pouze LocalDate. Druhá metoda bude sloužit k vyhledávání záznamů v určitý den, jelikož určitě nebudeme chtít vypsat záznam v danou hodinu a minutu, ale záznamy v daný den bez určení času.

Přidejme metodu vypisZaznamy(), která najde záznamy v daný den a vypíše je:

fun vypisZaznamy(den: LocalDateTime) {
    val zaznamy = databaze.najdiZaznamy(den, false)
    for (z in zaznamy) {
        println(z)
    }
}

Metoda pro vyzvání uživatele k vložení parametrů nového záznamu a jeho přidání do databáze bude následující:

fun pridejZaznam() {
    val datumCas = zjistiDatumCas()
    println("Zadejte text záznamu: ")
    val text = readLine()!!
    databaze.pridejZaznam(datumCas, text)
}

Zbývá záznamy vyhledávat a mazat. Metoda k vyhledání vrátí List s nalezenými záznamy (jen podle data, přesný čas nebude hrát roli). Vyzveme uživatele k zadání data a to předáme databázi. Výsledek zobrazíme:

fun vyhledejZaznamy() {
    // Zadání data uživatelem
    val datumCas = zjistiDatum().atStartOfDay()
    // Vyhledání záznamů
    val zaznamy = databaze.najdiZaznamy(datumCas, false)
    // Výpis záznamů
    if (zaznamy.size > 0) {
        println("Nalezeny tyto záznamy: ")
        for (z in zaznamy) {
            println(z)
        }
    } else { // Nenalezeno
        println("Nebyly nalezeny žádné záznamy.")
    }
}

Mazání záznamů je triviální:

fun vymazZaznamy() {
    println("Budou vymazány záznamy v daný den a hodinu")
    val datumCas = zjistiDatumCas()
    databaze.vymazZaznamy(datumCas)
}

Jako poslední přidejme metodu pro vypsání úvodní obrazovky programu s aktuálním datem a časem a událostmi na dnešek a zítřek.

fun vypisUvodniObrazovku() {
    println()
    println()
    println("Vítejte v diáři!")
    val dnes = LocalDateTime.now()
    println("Dnes je: ${dnes.format(formatDataBezCasu)}")
    println()
    // výpis hlavní obrazovky
    println("Dnes:\n-----")
    vypisZaznamy(dnes)
    println()
    println("Zítra:\n------")
    val zitra = LocalDateTime.now().plusDays(1)
    vypisZaznamy(zitra)
    println()
}

Můžeme vítězoslavně přejít do Main.kt a vytvořit instanci diáře. Zde umístíme také hlavní cyklus programu s menu programu a reakcí na volbu uživatele. Je to ta nejvyšší vrstva programu:

fun main(args: Array<String>) {
    val diar = Diar()
    var volba = ""
    // hlavní cyklus
    while (volba != "4") {
        diar.vypisUvodniObrazovku()
        println()
        println("Vyberte si akci:")
        println("1 - Přidat záznam")
        println("2 - Vyhledat záznamy")
        println("3 - Vymazat záznam")
        println("4 - Konec")
        volba = readLine()!!
        println()
        // reakce na volbu
        when (volba) {
            "1" -> diar.pridejZaznam()
            "2" -> diar.vyhledejZaznamy()
            "3" -> diar.vymazZaznamy()
            "4" -> println("Libovolnou klávesou ukončíte program...")
            else -> println("Neplatná volba, stiskněte libovolnou klávesu a opakujte volbu.")
        }
    }
}

Kód výše není složitý a již jsme tu podobný měli mockrát. Výslednou aplikaci jsem na vyzkoušení půjčil přítelkyni, zde vidíte výsledek :) :

Vítejte v diáři!
Dnes je: 13.6.2016 20:22

Dnes:
-----
13.6.2016 10:00 Shopping - Arkády Pankrác
13.6.2016 19:30 Vyvenčit mého yorkšírka Dennyho

Zítra:
------
14.6.2016 14:00 Power plate

Vyberte si akci:
1 - Přidat záznam
2 - Vyhledat záznamy
3 - Vymazat záznam
4 - Konec
2
Zadejte datum ve tvaru [1.1.2012]:
15.6.2016
Nalezeny tyto záznamy:
15.6.2016 9:30 Zkouška - Ekonomika cestovního ruchu

Tímto jsme si List osvojili a bude nám poměrně dlouho stačit. Na závěr bych dodal, že takto si můžete udělat databázi čehokoli. Můžete použít např. třídu Uzivatel z lekce Vlastnosti v Kotlin nebo kteroukoli jinou třídu. Můžete ukládat články, úlohy, slony, cokoli, co chcete v databázi spravovat. A co dál?

V následujícím cvičení, Řešené úlohy k 10.-15. lekci OOP v Kotlin, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 41x (16.52 kB)
Aplikace je včetně zdrojových kódů v jazyce Kotlin

 

Předchozí článek
Diář s databází v Kotlin
Všechny články v sekci
Objektově orientované programování v Kotlin
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 10.-15. lekci OOP v Kotlin
Článek pro vás napsal Samuel Kodytek
Avatar
Uživatelské hodnocení:
11 hlasů
Autor se věnuje všem jazykům okolo JVM. Rád pomáhá lidem, kteří se zajímají o programování. Věří, že všichni mají šanci se naučit programovat, jen je potřeba prorazit tu bariéru, který se říká lenost.
Aktivity