IT rekvalifikácia. Seniorní programátori zarábajú až 6 000 €/mesiac a rekvalifikácia je prvým krokom. Zisti, ako na to!

15. diel - Diár s databázou v Kotlin - Dokončenie

V minulej lekcii, Diár s databázou v Kotlin , sme rozpracovali jednoduchý diár s databázou pomocou List u. V dnešnom Kotlin tutoriálu aplikáciu dokončíme.

Do triedy Diar pridajme pomocnú metódu zjistiLocalDateTime(), ktorá vyzve používateľa na zadanie dátumu a času a vráti inštanciu LocalDateTime nastavenú na túto hodnotu. Najprv si metódu ukážme, vzápätí si ju 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)
    }
}

Metóda vracia inštanciu LocalDateTime a v parametri berie Formatter. V bloku try sa pokúšame přechroupat vstup od užívateľa metódou parse(). Keby sa prejavila prípadná chyba v zadaní (napr. 30. február a podobne), program prejde do bloku catch, užívateľa upozorníme na chybu a zadanie vykonáme znova. Všimnite si, že metóda volá seba sama pre nové zadanie. Je to bežná programátorská praktika, ktorej sa hovorí rekurzia. Túto metódu si schovajte, bude sa vám iste hodiť aj do budúcich konzolových aplikácií :) K blokom try - catch sa ešte podrobne vrátime, až sa budeme učiť pracovať so súbormi.

Do triedy si pridajme 2 verejné companion objects (statické atribúty). Budú to Formatter dátumu a času. Statické preto, aby boli použiteľné aj pre ďalšie triedy v našej aplikácii. Každá trieda môže používať tieto Formatter, ktoré máme definované na jednom mieste.

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

Jeden Formatter obsahuje dátum i čas, jeden iba dátum bez času. Prejdime do triedy Zaznam.kt a metódu toString() pozmení takto:

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

Keby sme si robili inštanciu Formatter znovu v každom zázname, bolo by to nepraktické. Takto máme Formatter na jednom mieste a keď sa rozhodneme formát zmeniť, zmeníme ho len v triede Diar. So statikou ale opatrne, nie vždy ju je vhodné použiť.

Vráťme sa do triedy Diar. Pridáme 2 metódy pre zistenie dátumu 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()
}

Obe využívajú našu metódu zjistiLocalDateTime (), ale dávajú ju iný Formatter. Pomocou zjistiDatumCas() budeme zadávať dátum a čas. Pomocou zjistiDatum() budeme zadávať len dátum, všimnite si, že vracia iba LocalDate. Druhá metóda bude slúžiť na vyhľadávanie záznamov v určitý deň, pretože určite nebudeme chcieť vypísať záznam v danú hodinu a minútu, ale záznamy v daný deň bez určenia času.

Pridajme metódu vypisZaznamy(), ktorá nájde záznamy v daný deň a vypíše je:

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

Metóda pre vyzvanie užívateľov k vloženie parametrov nového záznamu a jeho pridanie do databázy bude nasledujúci:

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

Zostáva záznamy vyhľadávať a mazať. Metóda na vyhľadanie vráti List s nájdenými záznamami (len podľa dátumu, presný čas nebude hrať úlohu). Vyzveme užívateľa na zadanie dátumu a to odovzdáme databázu. Výsledok 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.")
    }
}

Mazanie záznamov je triviálne:

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

Ako posledný pridajme metódu pre vypísanie úvodnej obrazovky programu s aktuálnym dátumom a časom a udalosťami na dnešok a zajtrajšok.

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íťazoslávne prejsť do Main.kt a vytvoriť inštanciu diáre. Tu umiestnime tiež hlavný cyklus programu s menu programu a reakcií na voľbu používateľa. Je to tá najvyššia 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ýška nie je zložitý a už sme tu podobný mali veľakrát. Výslednú aplikáciu som na vyskúšanie požičal priateľku, tu vidíte výsledok :) :

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 sme si List osvojili a bude nám pomerne dlho stačiť. Na záver by som dodal, že takto si môžete urobiť databázu čohokoľvek. Môžete použiť napr. Triedu Uzivatel z lekcie Vlastnosti v Kotlin alebo ktorúkoľvek inú triedu. Môžete ukladať články, úlohy, slony, čokoľvek, čo chcete v databáze spravovať. A čo ďalej? V budúcej lekcii, Riešené úlohy k 10.-15. lekciu OOP v Kotlin , to bude o rozhranie. V OOP nás toho čaká ešte dosť :)

V nasledujúcom cvičení, Riešené úlohy k 10.-15. lekciu OOP v Kotlin, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 41x (16.52 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Kotlin

 

Predchádzajúci článok
Diár s databázou v Kotlin
Všetky články v sekcii
Objektovo orientované programovanie v Kotlin
Preskočiť článok
(neodporúčame)
Riešené úlohy k 10.-15. lekciu OOP v Kotlin
Článok pre vás napísal Samuel Kodytek
Avatar
Užívateľské hodnotenie:
1 hlasov
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