Files
JR-priprava-na-skusku/priprava/rust_skuska_priprava.md
2026-02-14 15:10:11 +01:00

21 KiB

Intenzívna príprava na skúšku z Rustu

Analýza vzoru skúšok

Z troch skúšok (Knižnica, Obesenec, Milionár) vyplýva vždy rovnaký vzor:

  1. Štruktúry s derives (Serialize, Deserialize, Default, Clone, PartialEq)
  2. Enumy s derives + Display
  3. Asociované funkcie (konštruktory ::new, ::nacitaj_zo_suboru)
  4. Metódy na štruktúrach (CRUD operácie, filtrovanie, štatistiky)
  5. JSON serializácia/deserializácia cez serde
  6. File I/O s PathBuf → Option alebo bool
  7. CLI aplikácia s knižnicou clap (subcommands + argumenty)
  8. Trait definícia + implementácia (IOManager, Display)
  9. Iterátory (filter, find, map, collect)
  10. Option/Result return typy všade

Povolené knižnice

  • clap (derive), serde (derive), serde_json, itertools, rand
  • chrono (serde), futures, color-eyre, dotenvy

BLOK 1: Štruktúry, Enumy, Derives (základ všetkého)

Cvičenie 1.1 — Filmová databáza

Implementuj nasledovné:

Enum Zaner:
  - Hodnoty: Akcia, Komedia, Horor, Drama, SciFi, Dokumentarny
  - Požadované traity: Default, Display, Serialize, Deserialize, PartialEq, Clone
  - Default vráti hodnotu Drama

Štruktúra Film:
  - nazov: String
  - reziser: String
  - rok: u16
  - zaner: Zaner
  - hodnotenie: f32 (0.0 - 10.0)
  - Požadované traity: Default, Serialize, Deserialize, Clone

Štruktúra Filmoteka:
  - filmy: Vec<Film>
  - Požadované traity: Default, Serialize, Deserialize

Úlohy:

  1. Implementuj Display pre Zaner (výstup: slovenský názov žánru)
  2. Implementuj Display pre Film (formát: "Nazov (rok) - Reziser [Zaner] ★hodnotenie")
  3. Implementuj Default pre Zaner

Cvičenie 1.2 — Enum s dátami

Enum Stav:
  - Aktivny
  - Pozastaveny { dovod: String }
  - Ukonceny { datum: String, hodnotenie: u8 }
  - Požadované traity: Serialize, Deserialize, Clone, PartialEq

Implementuj Display pre Stav:

  • Aktivny → "Aktívny"
  • Pozastaveny → "Pozastavený: {dovod}"
  • Ukonceny → "Ukončený dňa {datum} s hodnotením {hodnotenie}"

BLOK 2: Asociované funkcie a Konštruktory

Cvičenie 2.1 — ::new a ::nacitaj_zo_suboru

Pre štruktúru Filmoteka:

// Asociovaná funkcia - načíta z JSON súboru
// Parameter: &std::path::PathBuf
// Návratová hodnota: Option<Filmoteka>
// Ak súbor neexistuje → None
// Ak sa nepodarí deserializovať → None
fn nacitaj_zo_suboru(cesta: &std::path::PathBuf) -> Option<Filmoteka>

// Metóda - uloží do JSON súboru
// Parameter: &std::path::PathBuf
// Návratová hodnota: bool (true ak úspech)
fn uloz_do_suboru(&self, cesta: &std::path::PathBuf) -> bool

Kľúčové vzory na zapamätanie:

// Čítanie súboru
let obsah = std::fs::read_to_string(cesta).ok()?;
let data: T = serde_json::from_str(&obsah).ok()?;

// Zápis do súboru
let json = serde_json::to_string_pretty(&self).ok()?;
std::fs::write(cesta, json).ok()?;

Cvičenie 2.2 — Konštruktor s validáciou

// Pre štruktúru Film:
// Funkcia ::new berie nazov: &str, reziser: &str, rok: u16, zaner: Zaner, hodnotenie: f32
// Ak hodnotenie nie je v rozsahu 0.0..=10.0, vráti None
// Inak vráti Some(Film)
fn new(nazov: &str, reziser: &str, rok: u16, zaner: Zaner, hodnotenie: f32) -> Option<Film>

BLOK 3: Metódy — CRUD + Filtrovanie + Štatistiky

Cvičenie 3.1 — CRUD operácie (vzor z Knižnica)

Pre Filmoteka:

// Pridaj film. Ak film s rovnakým názvom už existuje → Err(())
fn pridaj_film(&mut self, film: Film) -> Result<(), ()>

// Odstráň film podľa názvu. Ak neexistuje → Err(())
fn odstran_film(&mut self, nazov: &str) -> Result<Film, ()>

Cvičenie 3.2 — Filtrovanie (vzor z Knižnica)

// Vráti film podľa názvu
fn daj_film_podla_nazvu(&self, nazov: &str) -> Option<&Film>

// Vráti všetky filmy daného režiséra
fn daj_filmy_rezisera(&self, reziser: &str) -> Vec<&Film>

// Vráti všetky filmy daného žánru
fn daj_filmy_podla_zanru(&self, zaner: &Zaner) -> Vec<&Film>

// Vráti filmy s hodnotením vyšším ako zadané
fn daj_filmy_nad_hodnotenie(&self, min: f32) -> Vec<&Film>

Cvičenie 3.3 — Štatistiky (vzor z Knižnica)

// Pre každý žáner vypíše počet filmov
// Formát: "Žáner: počet filmov"
fn vypis_statistiky_zanrov(&self)

// Priemerné hodnotenie filmov daného režiséra
fn priemerne_hodnotenie_rezisera(&self, reziser: &str) -> Option<f32>

Tip: Použi itertools alebo HashMap na zoskupenie:

use std::collections::HashMap;
let mut mapa: HashMap<&str, Vec<&Film>> = HashMap::new();
for film in &self.filmy {
    mapa.entry(&film.reziser).or_default().push(film);
}

BLOK 4: Traity (vzor z Obesenec — IOManager)

Cvičenie 4.1 — Definícia a implementácia traitu

// Trait pre vstup/výstup
trait IOManager {
    fn ziskaj_vstup(&self) -> String;
    fn zobraz_spravu(&self, sprava: &str);
}

// Implementuj pre štruktúru ConsoleIO (prázdna štruktúra)
struct ConsoleIO;

impl IOManager for ConsoleIO {
    fn ziskaj_vstup(&self) -> String {
        let mut vstup = String::new();
        std::io::stdin().read_line(&mut vstup).unwrap();
        vstup.trim().to_string()
    }
    fn zobraz_spravu(&self, sprava: &str) {
        println!("{}", sprava);
    }
}

Cvičenie 4.2 — Trait s generickým parametrom

// Trait pre validáciu
trait Validator {
    fn je_platny(&self) -> bool;
    fn chyby(&self) -> Vec<String>;
}

// Implementuj pre Film:
// - hodnotenie musí byť 0.0..=10.0
// - nazov nesmie byť prázdny
// - rok musí byť 1888..=2026

BLOK 5: Hra — Game Loop Pattern (vzor z Obesenec + Milionár)

Cvičenie 5.1 — Kvízová hra

Implementuj jednoduchú kvízovú hru:

Štruktúra Odpoved:
  - text: String
  - je_spravna: bool
  - Traity: Serialize, Deserialize, Clone

Štruktúra Otazka:
  - text: String
  - odpovede: Vec<Odpoved>  (presne 4)
  - Traity: Serialize, Deserialize, Clone

Štruktúra Kviz:
  - otazky: Vec<Otazka>
  - aktualne_skore: u32
  - Traity: Serialize, Deserialize, Default

Metódy:

impl Odpoved {
    fn new(text: &str, je_spravna: bool) -> Odpoved
}

impl Otazka {
    // Vytvorí otázku. Ak odpovede.len() != 4, vráti None
    // Ak žiadna odpoveď nie je správna, vráti None
    fn new(text: &str, odpovede: Vec<Odpoved>) -> Option<Otazka>

    // Pridá odpoveď. Ak je už 4, vráti false.
    fn pridaj_odpoved(&mut self, odpoved: Odpoved) -> bool
}

impl Kviz {
    fn nacitaj_zo_suboru(cesta: &std::path::PathBuf) -> Option<Kviz>
    fn uloz_do_suboru(&self, cesta: &std::path::PathBuf) -> bool

    // Vyberie náhodnú otázku
    fn nahodna_otazka(&self) -> Option<&Otazka>

    // Vyhodnotí odpoveď (index 0-3), vráti bool
    fn vyhodnot(&mut self, otazka: &Otazka, index: usize) -> bool

    // Game loop - používa IOManager trait
    fn hraj(&mut self, io: &impl IOManager)
}

Cvičenie 5.2 — Implementuj hraj metódu

Vzor game loopu (toto sa opakuje na KAŽDEJ skúške):

fn hraj(&mut self, io: &impl IOManager) {
    loop {
        // 1. Zobraz stav hry
        io.zobraz_spravu(&format!("Skóre: {}", self.aktualne_skore));

        // 2. Vyber otázku
        let otazka = match self.nahodna_otazka() {
            Some(o) => o.clone(),
            None => { io.zobraz_spravu("Žiadne otázky!"); return; }
        };

        // 3. Zobraz otázku + odpovede
        io.zobraz_spravu(&otazka.text);
        for (i, odp) in otazka.odpovede.iter().enumerate() {
            io.zobraz_spravu(&format!("  {}: {}", i + 1, odp.text));
        }

        // 4. Načítaj vstup
        let vstup = io.ziskaj_vstup();

        // 5. Spracuj vstup
        match vstup.trim().parse::<usize>() {
            Ok(n) if n >= 1 && n <= 4 => {
                if self.vyhodnot(&otazka, n - 1) {
                    io.zobraz_spravu("Správne!");
                } else {
                    io.zobraz_spravu("Nesprávne!");
                }
            }
            _ => {
                io.zobraz_spravu("Neplatný vstup!");
                continue;
            }
        }

        // 6. Kontrola konca
        io.zobraz_spravu("Pokračovať? (a/n)");
        if io.ziskaj_vstup().trim() == "n" {
            break;
        }
    }
    io.zobraz_spravu(&format!("Konečné skóre: {}", self.aktualne_skore));
}

BLOK 6: CLI s Clap (toto je na KAŽDEJ skúške za 5-6 bodov!)

Cvičenie 6.1 — Základný clap vzor

use clap::{Parser, Subcommand};

#[derive(Parser)]
#[command(name = "filmoteka")]
struct Cli {
    #[command(subcommand)]
    prikaz: Prikazy,
}

#[derive(Subcommand)]
enum Prikazy {
    /// Pridaj nový film
    Pridaj {
        /// Cesta k súboru s filmami
        cesta: std::path::PathBuf,
        /// Názov filmu
        nazov: String,
        /// Režisér
        reziser: String,
        /// Rok vydania
        rok: u16,
    },
    /// Odstráň film
    Odstran {
        cesta: std::path::PathBuf,
        nazov: String,
    },
    /// Zobraz filmy režiséra
    FilmyRezisera {
        cesta: std::path::PathBuf,
        reziser: String,
    },
    /// Štatistiky
    Statistiky {
        cesta: std::path::PathBuf,
    },
}

fn main() {
    let cli = Cli::parse();
    match cli.prikaz {
        Prikazy::Pridaj { cesta, nazov, reziser, rok } => {
            // 1. Načítaj filmotéku zo súboru (alebo vytvor novú)
            let mut filmoteka = Filmoteka::nacitaj_zo_suboru(&cesta)
                .unwrap_or_default();
            // 2. Vytvor film a pridaj
            let film = Film { nazov, reziser, rok, ..Default::default() };
            match filmoteka.pridaj_film(film) {
                Ok(()) => {
                    filmoteka.uloz_do_suboru(&cesta);
                    println!("Film pridaný.");
                }
                Err(()) => println!("Film už existuje."),
            }
        }
        Prikazy::Odstran { cesta, nazov } => {
            // podobne...
        }
        // ... ďalšie príkazy
    }
}

Cvičenie 6.2 — Clap s viacerými argumentmi

Vzor príkazu s 3 argumentmi (ako v Milionár a Obesenec):

#[derive(Subcommand)]
enum Prikazy {
    PridajOtazku {
        /// Cesta k JSON súboru
        cesta: std::path::PathBuf,
        /// Text otázky
        otazka: String,
    },
    Hraj {
        /// Cesta k JSON súboru
        cesta: std::path::PathBuf,
        /// Kategória
        kategoria: String,
    },
}

BLOK 7: HashSet + Iterátory (vzor z Obesenec)

Cvičenie 7.1 — Práca s HashSet

use std::collections::HashSet;

struct SlovnaHra {
    hladane_slovo: String,
    uhadnute_pismena: HashSet<char>,
    skusane_pismena: HashSet<char>,
    pocet_zivotov: u8,
}

impl SlovnaHra {
    fn new(slovo: &str) -> SlovnaHra {
        SlovnaHra {
            hladane_slovo: slovo.to_lowercase(),
            uhadnute_pismena: HashSet::new(),
            skusane_pismena: HashSet::new(),
            pocet_zivotov: 6,
        }
    }

    // Vráti slovo s neuhádnutými písmenami nahradenými '_'
    fn daj_slovo_skryto(&self) -> String {
        self.hladane_slovo.chars().map(|c| {
            if self.uhadnute_pismena.contains(&c) { c } else { '_' }
        }).collect()
    }

    // Tipni písmeno - vráti enum VysledokPokusu
    fn tipni_pismeno(&mut self, pismeno: char) -> VysledokPokusu {
        let p = pismeno.to_lowercase().next().unwrap();
        if self.skusane_pismena.contains(&p) {
            return VysledokPokusu::Neplatne;
        }
        self.skusane_pismena.insert(p);
        if self.hladane_slovo.contains(p) {
            self.uhadnute_pismena.insert(p);
            VysledokPokusu::Uhadnute
        } else {
            self.pocet_zivotov -= 1;
            VysledokPokusu::Neuhadnute
        }
    }

    fn je_koniec_hry(&self) -> bool {
        self.pocet_zivotov == 0 || self.je_vyhra()
    }

    fn je_vyhra(&self) -> bool {
        self.hladane_slovo.chars().all(|c| self.uhadnute_pismena.contains(&c))
    }
}

Cvičenie 7.2 — Iterátory s impl Iterator

// Vráti iterátor na uhádnuté písmená
fn daj_uhadnute_pismena(&self) -> impl Iterator<Item = &char> {
    self.uhadnute_pismena.iter()
}

// Vráti iterátor na skúšané písmená
fn daj_skusane_pismena(&self) -> impl Iterator<Item = &char> {
    self.skusane_pismena.iter()
}

BLOK 8: rand — Náhodné generovanie

Cvičenie 8.1

use rand::Rng;
use rand::seq::SliceRandom;

// Vyber náhodné slovo z vektora
fn nahodne_slovo(slova: &[String]) -> Option<&String> {
    let mut rng = rand::thread_rng();
    slova.choose(&mut rng)
}

// Náhodné číslo v rozsahu
fn nahodne_cislo(min: u32, max: u32) -> u32 {
    let mut rng = rand::thread_rng();
    rng.gen_range(min..=max)
}

// Zamiešaj vektor
fn zamiesaj<T>(vektor: &mut Vec<T>) {
    let mut rng = rand::thread_rng();
    vektor.shuffle(&mut rng);
}

BLOK 9: Nové knižnice — chrono, color-eyre, futures

Cvičenie 9.1 — chrono (dátumy)

use chrono::{NaiveDate, Local, Datelike};
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Clone)]
struct Udalost {
    nazov: String,
    datum: NaiveDate,  // chrono s serde feature
}

impl Udalost {
    fn new(nazov: &str, rok: i32, mesiac: u32, den: u32) -> Option<Udalost> {
        let datum = NaiveDate::from_ymd_opt(rok, mesiac, den)?;
        Some(Udalost { nazov: nazov.to_string(), datum })
    }

    fn je_dnes(&self) -> bool {
        self.datum == Local::now().date_naive()
    }

    fn dni_do_udalosti(&self) -> i64 {
        let dnes = Local::now().date_naive();
        (self.datum - dnes).num_days()
    }
}

Cvičenie 9.2 — color-eyre (error handling)

use color_eyre::eyre::{Result, eyre, WrapErr};

fn nacitaj_zo_suboru(cesta: &std::path::PathBuf) -> Result<Filmoteka> {
    let obsah = std::fs::read_to_string(cesta)
        .wrap_err_with(|| format!("Nepodarilo sa otvoriť súbor: {:?}", cesta))?;
    let filmoteka: Filmoteka = serde_json::from_str(&obsah)
        .wrap_err("Nepodarilo sa deserializovať JSON")?;
    Ok(filmoteka)
}

fn main() -> Result<()> {
    color_eyre::install()?;
    // ... zvyšok kódu s ? operátorom
    Ok(())
}

BLOK 10: Kompletné cvičné zadanie — Správca úloh (TODO app)

Toto je simulácia skúšky. Skús to celé implementovať za 90 minút.

Zadanie: Správca úloh

Cieľom je implementovať aplikáciu na správu úloh s nasledovnými funkcionalitami:

  • pridávanie úloh
  • odstraňovanie úloh
  • označovanie úloh ako dokončené
  • filtrovanie úloh podľa rôznych kritérií
  • štatistiky
  • načítavanie a ukladanie do súboru vo formáte JSON

Enum Priorita

  • Nazov: Priorita
  • Hodnoty: Nizka, Stredna, Vysoka, Kriticka
  • Požadované traity: Default, Display, Serialize, Deserialize, PartialEq, Clone
  • Default vráti hodnotu Stredna

Enum StavUlohy

  • Hodnoty: Nova, Rozpracovana, Dokoncena, Zrusena
  • Požadované traity: Default, Display, Serialize, Deserialize, PartialEq, Clone
  • Default vráti hodnotu Nova

Štruktúra Uloha

  • nazov: String
  • popis: String
  • priorita: Priorita
  • stav: StavUlohy
  • kategoria: String
  • Požadované traity: Default, Serialize, Deserialize, Clone

Štruktúra SpravcaUloh

  • ulohy: Vec
  • Požadované traity: Default, Serialize, Deserialize

Funkcia SpravcaUloh::nacitaj_zo_suboru

  • Parameter: &PathBuf → Option

Metóda spravca_uloh.uloz_do_suboru

  • Parameter: &PathBuf → bool

Metóda spravca_uloh.pridaj_ulohu

  • Parameter: Uloha → Result<(), ()>
  • Err ak úloha s rovnakým názvom existuje

Metóda spravca_uloh.odstran_ulohu

  • Parameter: &str (názov) → Result<Uloha, ()>

Metóda spravca_uloh.oznac_dokoncenu

  • Parameter: &str (názov) → Result<(), ()>
  • Zmení stav úlohy na Dokoncena

Metóda spravca_uloh.daj_ulohy_podla_priority

  • Parameter: &Priorita → Vec<&Uloha>

Metóda spravca_uloh.daj_ulohy_podla_stavu

  • Parameter: &StavUlohy → Vec<&Uloha>

Metóda spravca_uloh.daj_ulohy_podla_kategorie

  • Parameter: &str → Vec<&Uloha>

Metóda spravca_uloh.vypis_statistiky_kategorii

  • Pre každú kategóriu vypíše počet úloh
  • Formát: "Kategória: počet úloh"

Metóda spravca_uloh.vypis_ulohy_podla_priority

  • Vypíše všetky úlohy zoskupené podľa priority

Ovládanie aplikácie (main.rs s clap)

Príkazy:

  • pridaj — 2 argumenty: cesta k súboru, názov úlohy. Interaktívne sa opýta na popis, prioritu a kategóriu.
  • odstran — 2 argumenty: cesta k súboru, názov úlohy
  • dokonci — 2 argumenty: cesta k súboru, názov úlohy
  • zoznam — 2 argumenty: cesta k súboru, filter (vsetky/dokoncene/nedokoncene)
  • statistiky — 1 argument: cesta k súboru

BLOK 11: Ďalšie simulácie skúšok

Simulácia 2 — Správca kontaktov

Enum TypKontaktu: Osobny, Pracovny, Rodina
Štruktúra Kontakt: meno, priezvisko, email, telefon, typ_kontaktu
Štruktúra Adresar: kontakty: Vec<Kontakt>

Metódy:
- nacitaj_zo_suboru, uloz_do_suboru
- pridaj_kontakt (duplicita podľa emailu → Err)
- odstran_kontakt (podľa emailu)
- najdi_podla_mena(&str) → Vec<&Kontakt>
- najdi_podla_typu(&TypKontaktu) → Vec<&Kontakt>
- vypis_kontakty_podla_typu()

CLI: pridaj, odstran, hladaj-meno, hladaj-typ, statistiky

Simulácia 3 — Hudobná knižnica (s chrono)

Enum Zaner: Rock, Pop, Jazz, Klasicka, HipHop, Elektronicka
Štruktúra Piesnicka: nazov, interpret, zaner, trvanie_sekundy: u32, datum_pridania: NaiveDate
Štruktúra Playlist: nazov, piesnicky: Vec<Piesnicka>
Štruktúra HudobnaKniznica: playlisty: Vec<Playlist>

Metódy pre Playlist:
- pridaj_piesnicku, odstran_piesnicku
- celkove_trvanie() → u32
- piesnicky_interpreta(&str) → Vec<&Piesnicka>

Metódy pre HudobnaKniznica:
- nacitaj_zo_suboru, uloz_do_suboru
- vytvor_playlist, odstran_playlist
- najdi_piesnicku_v_kniznici(&str) → Vec<(&Playlist, &Piesnicka)>
- statistiky_zanrov()

CLI: vytvor-playlist, pridaj-piesnicku (3 arg: cesta, playlist, piesnicka),
     zoznam, statistiky

Simulácia 4 — Hra s kartami (trait + rand)

Trait Hratelna {
    fn tahaj_kartu(&mut self) -> Option<Karta>;
    fn je_koniec(&self) -> bool;
    fn daj_skore(&self) -> u32;
}

Enum Farba: Srdce, Karo, Piky, Krize (Display)
Enum Hodnota: Cislo(u8), Dolnik, Hornik, Kral, Eso (Display)
Štruktúra Karta: farba, hodnota
Štruktúra Balicek: karty: Vec<Karta>
Štruktúra HraBlackjack: balicek, hrac_karty, dealer_karty, stav_hry

impl Balicek:
- fn novy() → Balicek  // vytvorí 32 kariet
- fn zamiesaj(&mut self)
- fn tahaj(&mut self) -> Option<Karta>

impl HraBlackjack: Hratelna
- fn hraj(&mut self, io: &impl IOManager)

CLI: hraj (cesta k uloženej hre), nove-hry

Kľúčové vzory na zapamätanie (cheat sheet)

1. Serde JSON čítanie/zápis

// Čítanie
let obsah = std::fs::read_to_string(&cesta).ok()?;
let data: MojTyp = serde_json::from_str(&obsah).ok()?;
Some(data)

// Zápis
let json = serde_json::to_string_pretty(&self).unwrap_or_default();
std::fs::write(&cesta, json).is_ok()

2. Vec filtrovanie

// Referencia
self.polozky.iter().filter(|p| p.nazov == hladany).collect()

// Hľadanie jedného
self.polozky.iter().find(|p| p.nazov == hladany)

// Odstránenie
if let Some(pos) = self.polozky.iter().position(|p| p.nazov == hladany) {
    Ok(self.polozky.remove(pos))
} else {
    Err(())
}

3. Display implementácia

impl std::fmt::Display for MojEnum {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match self {
            MojEnum::Varianta1 => write!(f, "Text 1"),
            MojEnum::Varianta2 => write!(f, "Text 2"),
        }
    }
}

4. Clap šablóna

use clap::{Parser, Subcommand};

#[derive(Parser)]
struct Cli {
    #[command(subcommand)]
    prikaz: Prikazy,
}

#[derive(Subcommand)]
enum Prikazy {
    NazovPrikazu {
        cesta: std::path::PathBuf,
        argument: String,
    },
}

fn main() {
    let cli = Cli::parse();
    match cli.prikaz {
        Prikazy::NazovPrikazu { cesta, argument } => { /* ... */ }
    }
}

5. HashMap štatistiky

use std::collections::HashMap;
let mut mapa: HashMap<String, usize> = HashMap::new();
for polozka in &self.polozky {
    *mapa.entry(polozka.kategoria.clone()).or_insert(0) += 1;
}
for (kluc, pocet) in &mapa {
    println!("{}: {}", kluc, pocet);
}

6. rand

use rand::seq::SliceRandom;
let mut rng = rand::thread_rng();
let nahodny = vektor.choose(&mut rng);
vektor.shuffle(&mut rng);

7. Čítanie vstupu z konzoly

let mut vstup = String::new();
std::io::stdin().read_line(&mut vstup).unwrap();
let vstup = vstup.trim();
// Parsovanie na číslo:
let cislo: usize = vstup.parse().unwrap_or(0);

Postup na skúške

  1. Prečítaj celé zadanie (2 min)
  2. Vytvor Cargo.toml s potrebnými závislosťami (1 min)
  3. Implementuj enumy a štruktúry s derives v lib.rs (10 min)
  4. Implementuj Display pre enumy (5 min)
  5. Implementuj nacitaj_zo_suboru + uloz_do_suboru (5 min) — toto je vždy rovnaké!
  6. Implementuj CRUD metódy (15 min)
  7. Implementuj filtrovacie metódy (10 min)
  8. Implementuj štatistiky/špeciálne metódy (10 min)
  9. Implementuj game loop ak je hra (15 min)
  10. Implementuj CLI v main.rs (15 min)
  11. Testuj s cargo test + manuálne (zvyšok)

CELKOM: ~90 minút