TlačiťTlačiť Slovenčina English Hľadať RSS

© 2005 – 2024 Roman Horváth, všetky práva vyhradené. Dnes je 19. 4. 2024.

Stránka sa načítava, prosím čakajte…

Dátum: 23. 7. 2020, pred štyrmi rokmi

Tento projekt je jedným z najstarších. Jeho odľahčená a konfigurovateľne generovateľná verzia bola (je) súčasťou generátora projektov, ktorý je v súčasnosti považovaný za zastaraný.

Projekt prešiel mnohými aktualizáciami. Toto je jeho posledná verzia prispôsobená pre verziu rámca 2.00.

  
obrázok 
Ukážka okna po spustení a potvrdení príkazu stav. 
 

~

import knižnica.Farba;
import knižnica.GRobot;
import knižnica.Kláves;
import knižnica.Svet;
import knižnica.Súbor;
import knižnica.ÚdajeUdalostí;
import knižnica.Zoznam;
import static java.lang.Math.*;
import java.io.IOException;
import java.util.Calendar;

/**
 * Trieda {@code KonzolováBanka} slúži na jednoduchú konzolovú simuláciu
 * základnej práce s účtom v banke – vklady a výbery v hotovosti,
 * overenie stavu účtu.
 *
 * @author   Roman Horváth; Meno Priezvisko
 * @version  1.0
 */
public class KonzolováBanka extends GRobot
{
	// ----------------------------------------------------------------------
	//  Verejné a súkromné atribúty triedy {@code KonzolováBanka}
	//

	/**
	 * Konštanta povoleného limitu prečerpania.
	 */
	public final static long povolenéPrečerpanie = -1_000_000;

	/** Atribúty súvisiace s uchovaním aktuálnej sumy na účte: */
	private long sumaNaÚčte, prečítanáSuma;

	/**
	 * Toto sú deaktivované atribúty, ktoré môžu slúžiť na počítanie chýb
	 * a varovaní, ktoré sa vyskytli počas používania aplikácie (ak budú
	 * aktivované všetky ich výskyty):
	 */
	// private int početChýb = 0, početVarovaní = 0;

	/**
	 * Tento zoznam slúži na uchovanie odoslaných vstupných (príkazových)
	 * riadkov.
	 */
	private Zoznam<String> história;

	/**
	 * Tento atribút zálohuje obsah aktuálneho riadka pri začatí pohybu
	 * v histórii príkazov. Zálohovaná hodnota sa vráti do vstupného riadka
	 * po opustení histórie príkazov (na jej konci).
	 */
	private String aktuálnyRiadok = "";

	//##
	/**
	 * Táto trieda slúži na uchovanie definícií vlastných príkazov.
	 */
	private class Príkaz
	{
		public final String identifikátor;
		public String príkazy;
		public String pomocník = null;
		public boolean použitý = false;

		public Príkaz(String identifikátor, String príkazy)
		{
			this.identifikátor = identifikátor;
			this.príkazy = príkazy;
		}
	}

	/**
	 * Tento zoznam slúži na uchovanie definícií vlastných príkazov.
	 */
	private Zoznam<Príkaz> vlastnéPríkazy;

	/**
	 * Toto sú špeciálne (rezervované) skupiny príkazov. Ak sú
	 * definované tak sú automaticky spúšťané v rôznych situáciách.
	 * Príkazy skupiny „úvod“ (definovateľnej aj rezevovaným slovom bez
	 * diakritiky – „uvod“) sú spustené automaticky pri spustení
	 * aplikácie, pričom ak nie sú definované, tak je spustený príkaz
	 * „pomoc“ bez parametra. Príkazy „pred“ sú spustené pred vykonaním
	 * každého potvrdeného príkazového riadka a príkazy „po“ zase po jeho
	 * vykonaní. Zvyšné príkazy „predVkladom“, „poVýbere“ atď. sú
	 * špecifickejšie, spúšťajú sa len tesne pred/po vklade/výbere z/na účet.
	 * Všetky skupiny príkazov typu pred/po sú použiteľné len automaticky,
	 * preto k nim nie je definovaný žiadny pomocník.
	 */
	private String úvod, pred, po, predVkladom, poVklade,
		predVýberom, poVýbere;

	/**
	 * Tieto semafory majú zabrániť vzniku nekonečného cyklu pri používaní
	 * príkazov „vlož“ a „vyber“ v súvislosti s definíciami príkazov
	 * vykonávaných „pred“ a „po“ ich spustení.
	 */
	private boolean semaforPredPoVklade = true, semaforPredPoVýbere = true;

	/**
	 * Nasledujúce dva atribúty pomáhajú zabrániť redundantným výpisom
	 * stavu účtu.
	 */
	private Long poslednýStav = null;
	private boolean vypíšKontrolu = false;

	/**
	 * Toto je príznak vykonania príkazu „stop“, ktorý okamžite zastaví
	 * spracovanie príkazového riadka a zabráni aj vykonaniu definície
	 * rezervovanej skupiny príkazov „po“.
	 */
	private boolean neboloZastavené = true;

	/**
	 * Táto trieda slúži na uchovávanie transakcií. Obsahuje viacero
	 * atribútov, ktoré majú slúžiť na uchovanie detailov o každej transakcii
	 * a zároveň na jednoduchú detekciu nedovolenej úpravy záznamu zvonka
	 * aplikácie.
	 */
	private class Transakcia
	{
		/**
		 * Atribúty na uchovanie stavu účtu pred a po transakcii.
		 */
		public final long sumaPred, sumaPo;

		/**
		 * Príznak vkladu na účet (false znamená výber).
		 */
		public final boolean vklad;

		/**
		 * Príznak úspešnosti transakcie.
		 */
		public final boolean úspech;

		/**
		 * Detaily o sume transakcie.
		 */
		public final long eur, centov;

		/**
		 * Časová pečiatka transakcie.
		 */
		public final long čas;

		/**
		 * Kontrolný súčet, ktorý má slúžiť na primitívnu detekciu manipulácie
		 * so záznamom – ak „útočník“ nevie ako upraviť tento súčet, aplikácia
		 * zistí, že so záznamom bolo manipulované.
		 */
		public final long kontrolnýSúčet;

		/**
		 * Toto je základný konštruktor obsahujúci inicializáciu všetkých
		 * atribútov, okrem kontrolného súčtu, ktorý je vyrátaný automaticky.
		 */
		public Transakcia(long sumaPred, long sumaPo, boolean vklad,
			boolean úspech, long eur, long centov, long čas)
		{
			this.sumaPred = sumaPred;
			this.sumaPo = sumaPo;
			this.vklad = vklad;
			this.úspech = úspech;
			this.eur = eur;
			this.centov = centov;
			this.čas = čas;

			kontrolnýSúčet = (sumaPred + sumaPo) + (vklad ? 1 : -1) +
				(úspech ? 1 : -1) + (eur + centov) + čas;
		}

		/**
		 * Tento konštruktor obsahuje aj inicializáciu kontrolného súčtu.
		 * Používa sa na indikáciu transakcií, s ktorými bolo manipulované.
		 */
		public Transakcia(long sumaPred, long sumaPo, boolean vklad,
			boolean úspech, long eur, long centov, long čas,
			long kontrolnýSúčet)
		{
			this.sumaPred = sumaPred;
			this.sumaPo = sumaPo;
			this.vklad = vklad;
			this.úspech = úspech;
			this.eur = eur;
			this.centov = centov;
			this.čas = čas;

			this.kontrolnýSúčet = kontrolnýSúčet;
		}

		/**
		 * Táto metóda slúži na zápis údajov o transakcii do zadaného súboru
		 * so zadaným ID.
		 */
		public void zapíš(Súbor súbor, String ID)
		{
			String záloha = súbor.mennýPriestorVlastností();
			súbor.mennýPriestorVlastností(
				(null == záloha ? "" : (záloha + ".")) + ID);

			súbor.zapíšVlastnosť("sumaPred", sumaPred);
			súbor.zapíšVlastnosť("sumaPo", sumaPo);
			súbor.zapíšVlastnosť("vklad", vklad);
			súbor.zapíšVlastnosť("úspech", úspech);
			súbor.zapíšVlastnosť("eur", eur);
			súbor.zapíšVlastnosť("centov", centov);
			súbor.zapíšVlastnosť("čas", čas);

			súbor.zapíšVlastnosť("kontrolnýSúčet", kontrolnýSúčet);

			súbor.mennýPriestorVlastností(záloha);
		}
	}

	/**
	 * Čítanie transakcie musí byť zabezpečené „zvonka“ triedy, pretože všetky
	 * atribúty triedy sú finálne. Táto metóda prečíta údaje o transakcii
	 * so zadaným ID zo zadaného súboru a vytvorí z nich novú inštanciu
	 * triedy transakcia.
	 */
	private Transakcia čítajTransakciu(Súbor súbor, String ID)
	{
		String záloha = súbor.mennýPriestorVlastností();
		súbor.mennýPriestorVlastností(
			(null == záloha ? "" : (záloha + ".")) + ID);

		try
		{
			long sumaPred = súbor.čítajVlastnosť("sumaPred", (Long)null);
			long sumaPo = súbor.čítajVlastnosť("sumaPo", (Long)null);
			boolean vklad = súbor.čítajVlastnosť("vklad", (Boolean)null);
			boolean úspech = súbor.čítajVlastnosť("úspech", (Boolean)null);
			long eur = súbor.čítajVlastnosť("eur", (Long)null);
			long centov = súbor.čítajVlastnosť("centov", (Long)null);
			long čas = súbor.čítajVlastnosť("čas", (Long)null);

			long kontrolnýSúčet = súbor.čítajVlastnosť(
				"kontrolnýSúčet", (Long)null);

			Transakcia transakcia = new Transakcia(
				sumaPred, sumaPo, vklad, úspech, eur, centov, čas);

			if (kontrolnýSúčet != transakcia.kontrolnýSúčet)
			{
				// ++početVarovaní;
				String varovanie = "Varovanie! S transakciou ID " + ID +
					" bolo manipulované.";
				Farba zálohaFarby = podlaha.farbaTextu();
				podlaha.farbaTextu(oranžová);
				podlaha.vypíšRiadok(varovanie);
				podlaha.farbaTextu(zálohaFarby);
				System.err.println(varovanie);

				transakcia = new Transakcia(sumaPred, sumaPo,
					vklad, úspech, eur, centov, čas, kontrolnýSúčet);
			}

			return transakcia;
		}
		catch (IOException e)
		{
			return null;
		}
		finally
		{
			súbor.mennýPriestorVlastností(záloha);
		}
	}

	/**
	 * Zoznam transakcií.
	 */
	private Zoznam<Transakcia> transakcie;

	// ----------------------------------------------------------------------
	//  Konštruktory objektov triedy {@code KonzolováBanka}
	//

	/**
	 * Predvolený konštruktor – v rámci tohto projektu štartuje aplikáciu.
	 */
	private KonzolováBanka()
	{
		// Nastavenie titulku okna (prostredníctvom nadradeného konštruktora)
		// a skrytie robota:
		super("Konzolová banková aplikácia…");
		skry();

		// Vytvorenie zoznamu histórie príkazov (ak nejestvuje):
		if (null == história) história = new Zoznam<String>();

		//##
		// Vytvorenie zoznamu vlastných príkazov (ak nejestvuje):
		if (null == vlastnéPríkazy) vlastnéPríkazy = new Zoznam<Príkaz>();

		// Vytvorenie zoznamu transakcií (ak nejestvuje):
		if (null == transakcie) transakcie = new Zoznam<Transakcia>();

		// Zabezpečenie permanentného zobrazenia vstupného (príkazového)
		// riadka:
		Svet.začniVstup();
		Svet.neskrývajVstupnýRiadok();
		if (Svet.prvéSpustenie()) Svet.zbaľ();

		// Úprava parametrov konzoly (tmavomodré pozadie, biely text a typ
		// písma Cambria s veľkosťou 24 bodov):
		Svet.farbaPozadia(tmavomodrá.tmavšia(0.4));
		strop.písmo("Cambria", 24);
		strop.farbaTextu(biela);

		// Pridá klávesové skratky pracujúce s históriou (príkazov):
		Svet.pridajKlávesovúSkratkuVstupnéhoRiadka(
			"späť", Kláves.HORE, 0);
		Svet.pridajKlávesovúSkratkuVstupnéhoRiadka(
			"vpred", Kláves.DOLE, 0);

		// Spustenie úvodných príkazov:
		úvod(null);
	}

	// ----------------------------------------------------------------------
	//  Metódy triedy {@code KonzolováBanka}
	//

	/**
	 * Táto metóda slúži na prevod zadaného reťazca na celočíselnú hodnotu,
	 * ktorá bude vyjadrovať buď eurovú, alebo centovú časť sumy.
	 *
	 * @param  vstup  reťazec, ktorý má byť prevedený na číslo
	 * @return celé číslo prevedené z reťazca
	 */
	private long dajČíslo(String vstup)
	{
		try
		{
			// Pokúsi sa previesť reťazec zo vstupu na celé číslo:
			return Long.parseLong(vstup);
		}
		catch (Exception e)
		{
			// ++početChýb;

			// V prípade zlyhania prevodu sa vypíše chybové hlásenie:
			strop.vypíšRiadok("Chyba! Toto nie je číslo: ", vstup);
			return 0;
		}
	}

	/**
	 * Táto metóda prevedie zadaný reťazec na dvojprvkové pole celočíselných
	 * hodnôt. Prvý prvok obsahuje eurovú časť sumy a druhý centovú. Ak prevod
	 * zlyhá, tak metóda vráti prázdne pole (s nulovým počtom prvkov).
	 *
	 * @param  vstup  reťazec, ktorý má byť prevedený na čísla
	 * @return dvojprvkové celočíselné pole prevedené z reťazca alebo prázdne
	 *         pole
	 */
	private long[] dajSumy(String vstup)
	{
		long[] výsledok;

		// Rozdelenie vstupného reťazca na eurovú a centovú časť (oddeľovačom
		// môže byť bodka aj čiarka):
		String[] častiSumy = vstup.split("[,.]+");

		// Ak je častí sumy viac než dve…
		if (častiSumy.length > 2)
		{
			// ++početChýb;

			// …tak vypíše chybu a vráti prázdne pole:
			strop.vypíšRiadok("Zadaná hodnota je neplatná!");
			return new long[0];
		}

		// Vymazanie všetkých znamienok z reťazcov a zároveň odstránenie
		// všetkých medzier, tabulátorov a pevných medzier:
		for (int i = 0; i < častiSumy.length; ++i)
			častiSumy[i] = častiSumy[i].replaceAll("[-−–—+  \\t]+", "");

		// Prázdna eurová časť bude znamenať nulu, ak jestvuje centová časť:
		if (častiSumy.length > 1 && častiSumy[0].isEmpty()) častiSumy[0] = "0";

		// Prázdne údaje značia nezadanie číselných hodnôt, takže metóda
		// vypíše chybové hlásenie a vráti prázdne pole:
		if (častiSumy.length < 1 || častiSumy[0].isEmpty())
		{
			// ++početChýb;
			strop.vypíšRiadok("Tento príkaz vyžaduje zadanie číselnej sumy.");
			return new long[0];
		}

		// Nasledujúce premenné budú obsahovať hodnoty dvoch prvkov poľa,
		// ktoré má tvoriť návratovú hodnotu tejto metódy. Definícia sumaEur
		// priamo preberá výsledok metódy dajČíslo, ktorý bude prakticky
		// výslednou hodnotou (v ďalšom kroku bude iba overená jej
		// nezápornosť):
		long sumaEur = dajČíslo(častiSumy[0]);
		long sumaCentov = 0;

		// Výsledok nesmie byť záporný, ak je zistený opak, metóda vypíše
		// varovanie a prevedie hodnotu na kladnú:
		if (sumaEur < 0)
		{
			// ++početVarovaní;
			strop.vypíšRiadok("Varovanie! Suma eur „", sumaEur,
				"“ bola prevedená na kladnú hodnotu!");
			sumaEur = -sumaEur;
		}

		// Spracovanie centovej časti je zamerané na správne určenie
		// skutočnej hodnoty centov, ktoré je založené na jej orezaní
		// alebo doplnení na tri desatinné miesta.
		//
		// Krátke vysvetlenie:
		// Metóda Javy parseInt použitá v metóde dajČíslo „netuší“, že
		// pracuje s desatinnou časťou, naopak, vstupný reťazec spracúva
		// ako celé číslo a nesprávne zarovnané „desatinné“ číslo by
		// v tomto prípade znamenalo nesprávne určenie centovej hodnoty.
		//
		// Príklad:
		// Ak by používateľ zadal 0,1, tak bez zarovnania by to bol
		// jeden cent, rovnako ako keby zadal 0,01 alebo 0,001. Ak by
		// zadal 0,10, tak by to bez správneho zarovnania bolo desať
		// centov, rovnako ako keby zadal 0,010 a tak ďalej. Preto je
		// dôležité reťazec správne zarovnať na tri rády sprava. Potom
		// môže výsledok reprezentovať správne centové miesta.
		if (častiSumy.length > 1 && !častiSumy[1].isEmpty())
		{
			if (častiSumy[1].length() > 3)
			{
				// ++početVarovaní;
				strop.vypíšRiadok("Varovanie! Príliš veľa centových miest!",
					"Nasledujúca časť sumy bola odstránená: ",
					"0,000" + častiSumy[1].substring(3));
				častiSumy[1] = častiSumy[1].substring(0, 3);
			}
			else if (častiSumy[1].length() < 2) častiSumy[1] += "00";
			else if (častiSumy[1].length() < 3) častiSumy[1] += "0";

			sumaCentov = dajČíslo(častiSumy[1]);
		}

		// Ani centová časť nesmie byť záporná:
		if (sumaCentov < 0)
		{
			// ++početVarovaní;
			strop.vypíšRiadok("Varovanie! Suma centov „", sumaCentov,
				"“ bola prevedená na kladnú hodnotu!");
			sumaCentov = -sumaCentov;
		}

		// Vytvorenie a vrátenie dvojprvkového poľa:
		return new long[] {sumaEur, sumaCentov};
	}

	/**
	 * Táto špeciálna definícia skupiny príkazov je automaticky vykonaná
	 * pred každým úspešným vykonaním príkazu „vlož“.
	 */
	private void spustiPredVkladom()
	{
		if (null != predVkladom && semaforPredPoVklade)
		{
			semaforPredPoVklade = false;
			try
			{
				// Vykonanie definície „predVkladom“:
				vykonajPríkazy(predVkladom);
			}
			finally
			{
				semaforPredPoVklade = true;
			}
		}
	}

	/**
	 * Táto špeciálna definícia skupiny príkazov je automaticky vykonaná
	 * po každom úspešnom vykonaní príkazu „vlož“.
	 */
	private void spustiPoVklade()
	{
		if (null != poVklade && semaforPredPoVklade)
		{
			semaforPredPoVklade = false;
			try
			{
				// Vykonanie definície „poVklade“:
				vykonajPríkazy(poVklade);
			}
			finally
			{
				semaforPredPoVklade = true;
			}
		}
	}

	/**
	 * Táto špeciálna definícia skupiny príkazov je automaticky vykonaná
	 * pred každým úspešným vykonaním príkazu „vyber“.
	 */
	private void spustiPredVýberom()
	{
		if (null != predVýberom && semaforPredPoVýbere)
		{
			semaforPredPoVýbere = false;
			try
			{
				// Vykonanie definície „predVýberom“:
				vykonajPríkazy(predVýberom);
			}
			finally
			{
				semaforPredPoVýbere = true;
			}
		}
	}

	/**
	 * Táto špeciálna definícia skupiny príkazov je automaticky vykonaná
	 * po každom úspešnom vykonaní príkazu „vyber“.
	 */
	private void spustiPoVýbere()
	{
		if (null != poVýbere && semaforPredPoVýbere)
		{
			semaforPredPoVýbere = false;
			try
			{
				// Vykonanie definície „poVýbere“:
				vykonajPríkazy(poVýbere);
			}
			finally
			{
				semaforPredPoVýbere = true;
			}
		}
	}

	/**
	 * Táto metóda vykonáva proces vloženia sumy na účet.
	 *
	 * @param  objemProstriedkov  reťazec vyjadrujúci požadovaný objem
	 *         prostriedkov
	 */
	private void vklad(String objemProstriedkov)
	{
		//##
		if (null == objemProstriedkov || objemProstriedkov.isEmpty())
		{
			objemProstriedkov = Svet.zadajReťazec("Zadaj objem prostriedkov:");
			if (null != objemProstriedkov)
				strop.vypíšRiadok("»", objemProstriedkov);
		}

		if (null == objemProstriedkov || objemProstriedkov.isEmpty())
		{
			// ++početChýb;
			strop.vypíšRiadok("Tento príkaz vyžaduje zadanie číselnej sumy.");
			return;
		}
		//##

		// Zadaný objemProstriedkov je prevedený na dvojprvkové pole:
		long[] častiSumy = dajSumy(objemProstriedkov);

		// Ak pole nie je dvojprvkové, znamená to chybu a nebude spracované:
		if (2 == častiSumy.length)
		{
			if (0 == častiSumy[0] && 0 == častiSumy[1])
			{
				// Ak sú oba prvky poľa nulové, aplikácia ohlási, že sa nie
				// je čím zaoberať:
				strop.vypíšRiadok("Žiadna akcia nebola vykonaná.");
			}
			else
			{
				// V opačnom prípade vloží sumu a túto skutočnosť ohlási
				// (popri tom vykoná rezervované skupiny príkazov „pred/po“
				// vklade, ak sú definované a uchová transakciu):

				long sumaPred = sumaNaÚčte;

				spustiPredVkladom();

				sumaNaÚčte += častiSumy[0] * 1000 + častiSumy[1];
				strop.vypíšRiadok("Vložená suma ",
					častiSumy[0], " € a ", častiSumy[1] / 10.0, " ¢.");

				spustiPoVklade();

				long sumaPo = sumaNaÚčte;

				transakcie.pridaj(new Transakcia(sumaPred, sumaPo,
					true, true, častiSumy[0], častiSumy[1],
					Calendar.getInstance().getTimeInMillis()));
			}
		}
	}

	/**
	 * Táto metóda vykonáva proces výberu sumy z účtu, pričom kontroluje
	 * povolený limit prečerpania.
	 *
	 * @param  objemProstriedkov  reťazec vyjadrujúci požadovaný objem
	 *         prostriedkov
	 */
	private void výber(String objemProstriedkov)
	{
		//##
		if (null == objemProstriedkov || objemProstriedkov.isEmpty())
		{
			objemProstriedkov = Svet.zadajReťazec("Zadaj objem prostriedkov:");
			if (null != objemProstriedkov)
				strop.vypíšRiadok("»", objemProstriedkov);
		}

		if (null == objemProstriedkov || objemProstriedkov.isEmpty())
		{
			// ++početChýb;
			strop.vypíšRiadok("Tento príkaz vyžaduje zadanie číselnej sumy.");
			return;
		}
		//##

		// Zadaný objemProstriedkov je prevedený na dvojprvkové pole:
		long[] častiSumy = dajSumy(objemProstriedkov);

		// Ak pole nie je dvojprvkové, znamená to chybu a nebude spracované:
		if (2 == častiSumy.length)
		{
			if (0 == častiSumy[0] && 0 == častiSumy[1])
			{
				// Ak sú oba prvky poľa nulové, aplikácia ohlási, že sa nie
				// je čím zaoberať:
				strop.vypíšRiadok("Žiadna akcia nebola vykonaná.");
			}
			else if (sumaNaÚčte - častiSumy[0] * 1000 - častiSumy[1] <
				povolenéPrečerpanie)
			{
				// ++početChýb;

				// Potom overí, či je požadovaná suma k dispozícii a ak nie,
				// tak túto skutočnosť ohlási (zároveň to uchová ako
				// neúspešnú transakciu):
				//##
				strop.vypíšRiadok("Požadovaná suma nie je na účte ",
					"k dispozícii.");

				transakcie.pridaj(new Transakcia(sumaNaÚčte, sumaNaÚčte,
					false, false, častiSumy[0], častiSumy[1],
					Calendar.getInstance().getTimeInMillis()));
			}
			else
			{
				// V opačnom prípade vyberie sumu a túto skutočnosť ohlási
				// (popri tom vykoná rezervované skupiny príkazov „pred/po“
				// výbere, ak sú definované a uchová transakciu):

				long sumaPred = sumaNaÚčte;

				spustiPredVýberom();

				sumaNaÚčte -= častiSumy[0] * 1000 + častiSumy[1];
				strop.vypíšRiadok("Vybraná suma ",
					častiSumy[0], " € a ", častiSumy[1] / 10.0, " ¢.");

				spustiPoVýbere();

				long sumaPo = sumaNaÚčte;

				transakcie.pridaj(new Transakcia(sumaPred, sumaPo,
					false, true, častiSumy[0], častiSumy[1],
					Calendar.getInstance().getTimeInMillis()));
			}
		}
	}

	/**
	 * Táto metóda vypíše aktuálny stav účtu. Na zabránenie výpisu
	 * redunantných stavov je stav účtu v rámci jedného vykonania
	 * príkazového riadka kontrolovaný a vypísaný len po splnení
	 * určitých podmienok – viac je v textoch pomocníka tohto príkazu.
	 */
	private void stav(boolean kontrolnýVýpis)
	{
		if (null == poslednýStav || sumaNaÚčte != poslednýStav)
		{
			// Vypísanie aktuálneho stavu na účte:
			strop.vypíšRiadok("Aktuálny stav účtu je ",
				sumaNaÚčte / 1000.0, " €.");
			poslednýStav = sumaNaÚčte;
		}
		else if (kontrolnýVýpis && vypíšKontrolu)
		{
			// Vypísanie informácie o nezmenenom stave účtu:
			strop.vypíšRiadok("Príkazy prípadne vykonané od posledného ",
				"výpisu stavu účtu tento stav nezmenili.");
		}
		else
		{
			// Nastavenie príznaku vypísania kontroly
			vypíšKontrolu = true;
		}
	}

	//##
	/**
	 * Toto je príkaz slúžiaci na vymazanie rôznych cieľov (histórie alebo
	 * jej jednotlivých príkazov, jednotlivých definícií alebo obrazovky).
	 */
	private void vymaž(String čo)
	{
		// Skrátenie reťazca určeného na porovnanie:
		čo = čo.trim().toLowerCase();

		if (čo.startsWith("históriu") || čo.startsWith("historiu"))
		{
			// Ďalšie skrátenie reťazca určeného na porovnanie:
			čo = čo.substring(8).trim();

			// Vymazanie zhodných príkazov z histórie:
			for (int i = 0; i < história.dĺžka(); ++i)
			{
				if (história.daj(i).trim().toLowerCase().startsWith(čo))
				{
					strop.vypíšRiadok("Z histórie bol vymazaný riadok: ",
						história.daj(i));
					história.odober(i);
					--i;
				}
			}

			// Nastavenie počítadla za poslednú položku histórie:
			história.počítadlo(história.veľkosť());
		}
		else if (čo.startsWith("definíciu") || čo.startsWith("definiciu"))
		{
			// Ďalšie skrátenie reťazca určeného na porovnanie:
			čo = čo.substring(9).trim();

			// Najprv skontrolujem rezervované názvy a nakoniec prehľadám
			// zoznam definícií:
			if (čo.equals("úvod") || čo.equals("uvod"))
			{
				úvod = null;
				strop.vypíšRiadok("Definícia príkazu „úvod“ bola vymazaná. ",
					"Odteraz bude príkaz vykonávať predvolenú aktivitu.");
			}
			else if (čo.equals("pred"))
			{
				pred = null;
				strop.vypíšRiadok("Definícia rezervovanej skupiny ",
					"príkazov „pred“ bola vymazaná.");
			}
			else if (čo.equals("po"))
			{
				po = null;
				strop.vypíšRiadok("Definícia rezervovanej skupiny ",
					"príkazov „po“ bola vymazaná.");
			}
			else
			{
				if (čo.startsWith("pred"))
				{
					String čoĎalej = čo.substring(4).trim();

					if (čoĎalej.equals("vkladom"))
					{
						predVkladom = null;
						strop.vypíšRiadok("Definícia rezervovanej skupiny ",
							"príkazov „pred vkladom“ bola vymazaná.");
						return;
					}
					else if (čoĎalej.equals("výberom") ||
						čoĎalej.equals("vyberom"))
					{
						predVýberom = null;
						strop.vypíšRiadok("Definícia rezervovanej skupiny ",
							"príkazov „pred výberom“ bola vymazaná.");
						return;
					}
				}
				else if (čo.startsWith("po"))
				{
					String čoĎalej = čo.substring(4).trim();

					if (čoĎalej.equals("vklade"))
					{
						poVklade = null;
						strop.vypíšRiadok("Definícia rezervovanej skupiny ",
							"príkazov „po vklade“ bola vymazaná.");
						return;
					}
					else if (čoĎalej.equals("výbere") ||
						čoĎalej.equals("vybere"))
					{
						poVýbere = null;
						strop.vypíšRiadok("Definícia rezervovanej skupiny ",
							"príkazov „po výbere“ bola vymazaná.");
						return;
					}
				}

				for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				{
					// Ak nájdem prislúchajúcu definíciu, tak ju vymažem:
					if (vlastnýPríkaz.identifikátor.equals(čo))
					{
						strop.vypíšRiadok("Definícia „",
							vlastnýPríkaz.identifikátor,
							"“ bola vymazaná.");
						vlastnéPríkazy.odober(vlastnýPríkaz);
						return;
					}
				}
				strop.vypíšRiadok("Definícia „", čo, "“ nebola nájdená.");
			}
		}
		// Inak sa vymaže obrazovka:
		else
		{
			poslednýStav = null;
			strop.vymažTexty();
		}
	}

	//##
	/**
	 * Tento príkaz je automaticky vykonaný pri spustení aplikácie a môže
	 * byť spustený aj z príkazového riadka.
	 */
	private void úvod(String parametre)
	{
		if (null == úvod)
			// Ak je reťazec „úvod“ prázdny, tak úvodné zobrazenie
			// pozostáva zo zobrazenia textu pomocníka (bez parametrov):
			pomocník(parametre);
		else
		{
			// Inak sú vykonané úvodné príkazy reťazca „úvod“:
			if (null == parametre)
				vykonajPríkazy(úvod.replace("$", ""));
			else
				vykonajPríkazy(úvod.replace("$", parametre));
		}
	}

	/**
	 * Táto pomocná metóda nastaví rovnakú hodnotu okrajov (odsadenia )
	 * textov stropu zľava a sprava.
	 */
	private void symetrickéOkraje(Integer okraje)
	{
		strop.zmeňOdsadenieZľava(okraje);
		strop.zmeňOdsadenieSprava(okraje);
	}

	//##
	/**
	 * Táto metóda spracuje zadanú «definíciu», podľa ktorej buď vytvorí novú
	 * definíciu vlastného príkazu, alebo predefinuje jestvujúcu definíciu.
	 */
	private void definuj(String definícia)
	{
		if (definícia.isEmpty())
		{
			// Ak bol zadaný prázdny reťazec, tak vypíšem všetky definície
			// (ak také sú). Zahŕňa to výpis definícií rezervovaných
			// a vlastných identifikátorov príkazov.

			// Ak je príkaz „úvod“ predefinovaný, tak o tejto
			// skutočnosti informujem:
			if (null != úvod && !úvod.isEmpty())
			{
				strop.vypíšRiadok("Príkaz „úvod“ je predefinovaný takto:");
				symetrickéOkraje(20);
				strop.vypíšRiadok(úvod);
				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			// Ak je definovaná rezervovaná skupina príkazov „pred“, tak
			// o tejto skutočnosti informujem:
			if (null != pred && !pred.isEmpty())
			{
				strop.vypíšRiadok("Rezervovaná skupina príkazov „pred“ ",
					"je definovaná takto:");
				symetrickéOkraje(20);
				strop.vypíšRiadok(pred);
				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			// Ak je definovaná rezervovaná skupina príkazov „po“, tak
			// o tejto skutočnosti informujem:
			if (null != po && !po.isEmpty())
			{
				strop.vypíšRiadok("Rezervovaná skupina príkazov „po“ ",
					"je definovaná takto:");
				symetrickéOkraje(20);
				strop.vypíšRiadok(po);
				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			// Ak je definovaná rezervovaná skupina príkazov „predVkladom“,
			// tak o tejto skutočnosti informujem:
			if (null != predVkladom && !predVkladom.isEmpty())
			{
				strop.vypíšRiadok("Rezervovaná skupina príkazov ",
					"„pred vkladom“ je definovaná takto:");
				symetrickéOkraje(20);
				strop.vypíšRiadok(predVkladom);
				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			// Ak je definovaná rezervovaná skupina príkazov „poVklade“, tak
			// o tejto skutočnosti informujem:
			if (null != poVklade && !poVklade.isEmpty())
			{
				strop.vypíšRiadok("Rezervovaná skupina príkazov „po vklade“ ",
					"je definovaná takto:");
				symetrickéOkraje(20);
				strop.vypíšRiadok(poVklade);
				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			// Ak je definovaná rezervovaná skupina príkazov „predVýberom“,
			// tak o tejto skutočnosti informujem:
			if (null != predVýberom && !predVýberom.isEmpty())
			{
				strop.vypíšRiadok("Rezervovaná skupina príkazov ",
					"„pred výberom“ je definovaná takto:");
				symetrickéOkraje(20);
				strop.vypíšRiadok(predVýberom);
				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			// Ak je definovaná rezervovaná skupina príkazov „poVýbere“, tak
			// o tejto skutočnosti informujem:
			if (null != poVýbere && !poVýbere.isEmpty())
			{
				strop.vypíšRiadok("Rezervovaná skupina príkazov „po výbere“ ",
					"je definovaná takto:");
				symetrickéOkraje(20);
				strop.vypíšRiadok(poVýbere);
				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			// Nakoniec vypíšem jestvujúce vlastné definície (ak také sú):
			if (vlastnéPríkazy.prázdny())
			{
				strop.vypíšRiadok("Nie je definovaný ",
					"žiadny vlastný príkaz.");
			}
			else
			{
				strop.vypíšRiadok("Sú definované ",
					"nasledujúce vlastné príkazy:", riadok);
				for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				{
					symetrickéOkraje(20);
					strop.vypíšRiadok(
						vlastnýPríkaz.identifikátor, ":");
					symetrickéOkraje(40);
					strop.vypíšRiadok(vlastnýPríkaz.príkazy);
				}
				symetrickéOkraje(0);
			}
		}
		else
		{
			// Vyrobím verziu definície tvorenú len malými písmenami,
			// aby som ju mohol porovnávať s rezervovanými reťazcami
			// (úvod, uvod, pred, po a pomocník):
			String definíciaMalými = definícia.toLowerCase();

			// Ak sa definícia bude začínať jedným zo štyroch rezervovaných
			// názvov (kľúčových slov) „úvod“, „uvod“, „pred“ alebo „po“, tak
			// definujem inštanciu zodpovedajúcu tomuto slovu:
			if (definíciaMalými.startsWith("úvod") ||
				definíciaMalými.startsWith("uvod"))
			{
				úvod = definícia.substring(4).trim().replace("&", ";");
				strop.vypíšRiadok("Príkaz „úvod“ ",
					"bol predefinovaný takto: ", úvod, ".");
			}
			else if (definíciaMalými.startsWith("pred"))
			{
				definícia = definícia.substring(4).trim().replace("&", ";");
				definíciaMalými = definícia.toLowerCase();

				// Tento rezervovaný názov má ešte dva odtiene:
				if (definíciaMalými.startsWith("vkladom"))
				{
					predVkladom = definícia.substring(7).trim();
					strop.vypíšRiadok("Rezervovaná skupina príkazov ",
						"„pred vkladom“ bola definovaná takto: ",
						predVkladom, ".");
				}
				else if (definíciaMalými.startsWith("výberom") ||
					definíciaMalými.startsWith("vyberom"))
				{
					predVýberom = definícia.substring(7).trim();
					strop.vypíšRiadok("Rezervovaná skupina príkazov ",
						"„pred výberom“ bola definovaná takto: ",
						predVýberom, ".");
				}
				else
				{
					pred = definícia;
					strop.vypíšRiadok("Rezervovaná skupina príkazov „pred“ ",
						"bola definovaná takto: ", pred, ".");
				}
			}
			else if (definíciaMalými.startsWith("po"))
			{
				definícia = definícia.substring(2).trim().replace("&", ";");
				definíciaMalými = definícia.toLowerCase();

				// Tento rezervovaný názov má ešte dva odtiene:
				if (definíciaMalými.startsWith("vklade"))
				{
					poVklade = definícia.substring(6).trim();
					strop.vypíšRiadok("Rezervovaná skupina príkazov ",
						"„po vklade“ bola definovaná takto: ",
						poVklade, ".");
				}
				else if (definíciaMalými.startsWith("výbere") ||
					definíciaMalými.startsWith("vybere"))
				{
					poVýbere = definícia.substring(6).trim();
					strop.vypíšRiadok("Rezervovaná skupina príkazov ",
						"„po výbere“ bola definovaná takto: ",
						poVýbere, ".");
				}
				else
				{
					po = definícia;
					strop.vypíšRiadok("Rezervovaná skupina príkazov „po“ ",
						"bola definovaná takto: ", po, ".");
				}
			}
			else if (definíciaMalými.startsWith("pomocníka"))
			{
				// Ak sa definícia začína kľúčovým slovom „pomocníka“,
				// tak ho odrežem a hľadám vo zvyšnom reťazci medzeru:
				definícia = definícia.substring(9).trim();
				int indexOf = definícia.indexOf(' ');
				if (-1 == indexOf)
				{
					// ++početChýb;

					// Ak nenájdem medzeru, tak je to chyba:
					strop.vypíšRiadok("Chyba! Neviem odlíšiť ",
						"identifikátor od textu pomocníka v definícii: ",
						definícia);
				}
				else
				{
					// Inak použijem medzeru na oddelenie identifikátora
					// a zvyšku reťazca, ktorý bude tvoriť text pomocníka:
					String pomocník = definícia.substring(1 + indexOf);
					String identifikátor = definícia.substring(0, indexOf).
						trim().toLowerCase();

					// Toto je príznak nájdenia jestvujúcej definície
					// príkazu:
					boolean nenašielSom = true;

					// Hľadám definíciu príkazu (aby som jej mohol upraviť
					// text pomocníka):
					for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
					{
						// Ak ju nájdem, tak jej (pre)definujem pomocníka:
						if (identifikátor.startsWith(
							vlastnýPríkaz.identifikátor))
						{
							nenašielSom = false;
							vlastnýPríkaz.pomocník = pomocník;
							strop.vypíšRiadok("Text pomocníka príkazu „",
								identifikátor, "“ bol upravený na „",
								pomocník, "“.");
							break;
						}
					}

					// Ak som medzi jestvujúcimi definíciami príkaz
					// nenašiel, tak to oznámim ako chybu:
					if (nenašielSom)
					{
						// ++početChýb;
						strop.vypíšRiadok("Chyba! Príkaz „", identifikátor,
							"“ nebol nájdený. Nemôžem upraviť text pomocníka.");
					}
				}
			}
			// Pred začatím samotnej definície je dôležité skontrolovať jej
			// prípadnú kolíziu so skupinou preddefinovaných (hlavných)
			// príkazov aplikácie, pretože postačí, aby sa identifikátor
			// začínal kľúčovým slovom príkazu a už by nebol použiteľný:
			else if (definícia.startsWith("vklad") ||
				definícia.startsWith("vlož") ||
				definícia.startsWith("vloz") ||
				definícia.startsWith("výber") ||
				definícia.startsWith("vyber") ||
				definícia.startsWith("stav") ||
				definícia.startsWith("riadok") ||
				definícia.startsWith("text") ||
				definícia.startsWith("vymaž") ||
				definícia.startsWith("vymaz") ||
				definícia.startsWith("úvod") ||
				definícia.startsWith("uvod") ||
				definícia.startsWith("definuj") ||
				definícia.startsWith("pomocník") ||
				definícia.startsWith("pomocnik") ||
				definícia.startsWith("pomoc") ||
				definícia.startsWith("stop") ||
				definícia.startsWith("koniec"))
			{
				// ++početChýb;
				strop.vypíšRiadok("Chyba! Definícia (jej identifikátor) ",
					"sa začína rezervovaným slovom (predvoleným príkazom ",
					"aplikácie). Takto definovaný vlastný príkaz by nebol ",
					"použiteľný.");
			}
			else
			{
				// Po všetkých kontrolách vykonám samotnú definíciu
				// vlastného príkazu. Najprv hľadám v reťazci definície
				// medzeru:
				int indexOf = definícia.indexOf(' ');
				if (-1 == indexOf)
				{
					// ++početChýb;

					// Ak medzeru nenájdem, tak je to chyba:
					strop.vypíšRiadok("Chyba! Neviem odlíšiť ",
						"identifikátor od príkazov v definícii: ", definícia);
				}
				else
				{
					// Inak použijem medzeru na oddelenie identifikátora
					// a zvyšku reťazca, ktorý bude tvoriť «príkazy» – telo
					// definície:
					String príkazy = definícia.substring(1 + indexOf).
						replace("&", ";");
					String identifikátor = definícia.substring(0, indexOf).
						trim().toLowerCase();

					// Toto je príznak nájdenia jestvujúcej definície
					// príkazu:
					boolean nenašielSom = true;

					// Hľadám jestvujúcu definíciu príkazu:
					for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
					{
						// Ak takú definíciu nájdem, tak ju predefinujem:
						if (identifikátor.startsWith(
							vlastnýPríkaz.identifikátor))
						{
							nenašielSom = false;
							vlastnýPríkaz.príkazy = príkazy;
							strop.vypíšRiadok(
								"Jestvujúca definícia príkazu „",
								identifikátor, "“ bola upravená na „",
								príkazy, "“.");
							break;
						}
					}

					// Ak som medzi jestvujúcimi definíciami príkaz
					// nenašiel, tak definujem nový:
					if (nenašielSom)
					{
						vlastnéPríkazy.pridaj(new Príkaz(
							identifikátor, príkazy));
						strop.vypíšRiadok(
							"Bola pridaná definícia nového príkazu „",
							identifikátor, "“ – „", príkazy, "“.");
					}
				}
			}
		}
	}

	/**
	 * Tento príkaz podľa identifikátora vyrobí príkaz „definuj“ a vloží ho
	 * do vstupného riadka. Ak je identifikátor neznámy, tak pípne a vráti
	 * do vstupného riadka príkaz „uprav“ so zadaným (neznámym)
	 * identifikátorom.
	 */
	private void uprav(String identifikátor)
	{
		// Definujem príznak nenájdenia identifikátora, pričom sprvu
		// predpokladám, že bude nájdený medzi rezervovanými identifikátormi:
		boolean nenašielSom = false;

		// Zálohujem originál prijatého reťazca a vyrobím novú verziu, ktorú
		// orežem a prevediem na malé písmená:
		String originál = identifikátor;
		identifikátor = identifikátor.trim().toLowerCase();

		// Najprv identifikátor porovnám s rezervovanými slovami „úvod“,
		// „uvod“, „pred“ a „po“ a až potom budem hľadať vo všetkých
		// definíciách (vrátane definície pomocníka)…

		if (identifikátor.equals("úvod") || identifikátor.equals("uvod"))
		{
			// Vložím do vstupného riadka príkaz na predefinovanie
			// príkazu „úvod“:
			Svet.textVstupnéhoRiadka("definuj úvod " +
				(null == úvod ? "" : úvod.replace(";", "&")));
		}
		else if (identifikátor.equals("pred"))
		{
			// Vložím do vstupného riadka príkaz na definovanie rezervovanej
			// skupiny príkazov „pred“:
			Svet.textVstupnéhoRiadka("definuj pred " +
				(null == pred ? "" : pred.replace(";", "&")));
		}
		else if (identifikátor.equals("po"))
		{
			// Vložím do vstupného riadka príkaz na definovanie rezervovanej
			// skupiny príkazov „po“:
			Svet.textVstupnéhoRiadka("definuj po " +
				(null == po ? "" : po.replace(";", "&")));
		}
		else if (identifikátor.startsWith("pomocníka"))
		{
			// Kľúčové slovo „pomocníka“ presmeruje začatie úprav
			// do oblasti elektronického pomocníka k vlastným príkazom:
			identifikátor = identifikátor.substring(9).trim();

			// Nastavenie príznaku nenájdenia definície:
			nenašielSom = true;

			// Hľadanie definíciu príkazu (na začatie úprav textu pomocníka):
			for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
			{
				if (identifikátor.equals(vlastnýPríkaz.identifikátor))
				{
					// Reset príznaku nenájdenia a vloženie prislúchajúceho
					// príkazu do vstupného riadka:
					nenašielSom = false;
					Svet.textVstupnéhoRiadka("definuj pomocníka " +
						identifikátor + " " + vlastnýPríkaz);
					break;
				}
			}
		}
		else
		{
			// Hľadanie ďalších definícií na zahájenie úprav príkazovej časti…

			// Nastavenie príznaku nenájdenia definície:
			nenašielSom = true;

			// Najprv rezervované…
			if (identifikátor.startsWith("pred"))
			{
				String čoĎalej = identifikátor.substring(4).trim();

				if (čoĎalej.equals("vkladom"))
				{
					// Vložím do vstupného riadka príkaz na definovanie
					// rezervovanej skupiny príkazov „predVkladom“:
					Svet.textVstupnéhoRiadka("definuj pred vkladom " +
						(null == predVkladom ? "" : predVkladom.replace(
							";", "&")));
					nenašielSom = false;
				}
				else if (čoĎalej.equals("výberom") ||
					čoĎalej.equals("vyberom"))
				{
					// Vložím do vstupného riadka príkaz na definovanie
					// rezervovanej skupiny príkazov „predVkladom“:
					Svet.textVstupnéhoRiadka("definuj pred výberom " +
						(null == predVýberom ? "" : predVýberom.replace(
							";", "&")));
					nenašielSom = false;
				}
			}
			else if (identifikátor.startsWith("po"))
			{
				String čoĎalej = identifikátor.substring(4).trim();

				if (čoĎalej.equals("vklade"))
				{
					// Vložím do vstupného riadka príkaz na definovanie
					// rezervovanej skupiny príkazov „poVklade“:
					Svet.textVstupnéhoRiadka("definuj po vklade " +
						(null == poVklade ? "" : poVklade.replace(
							";", "&")));
					nenašielSom = false;
				}
				else if (čoĎalej.equals("výbere") || čoĎalej.equals("vybere"))
				{
					// Vložím do vstupného riadka príkaz na definovanie
					// rezervovanej skupiny príkazov „poVklade“:
					Svet.textVstupnéhoRiadka("definuj po výbere " +
						(null == poVýbere ? "" : poVýbere.replace(
							";", "&")));
					nenašielSom = false;
				}
			}

			// Potom vlastné…
			if (nenašielSom)
			{
				// Hľadanie definície príkazu:
				for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				{
					if (identifikátor.equals(vlastnýPríkaz.identifikátor))
					{
						// Reset príznaku nenájdenia a vloženie prislúchajúceho
						// príkazu do vstupného riadka:
						nenašielSom = false;
						Svet.textVstupnéhoRiadka("definuj " + identifikátor +
							" " + vlastnýPríkaz.príkazy.replace(";", "&"));
						break;
					}
				}
			}
		}

		// Ak nebol správne identifikovaný príkaz, tak pípnem a do
		// vstupného riadka vložím príkaz „uprav“ s originálnym reťazcom
		// (mohlo ísť o preklep, nech si to používateľ opraví):
		if (nenašielSom)
		{
			Svet.pípni();
			Svet.textVstupnéhoRiadka("uprav" + originál);
		}
	}

	//##
	/**
	 * Táto metóda vypíše krátky všeobecný text pomocníka alebo stručnú
	 * informáciu o zadanom príkaze.
	 */
	private void pomocník(String príkaz)
	{
		// Výpis stručného pomocníka:

		if (null == príkaz || príkaz.trim().isEmpty())
		{
			strop.vypíšRiadok("Táto konzolovo orientovaná banková ",
				"aplikácia slúži na simuláciu jednoduchej ",
				"práce s bankovým účtom cez príkazový riadok. ",
				"K dispozícii sú nasledujúce predvolené príkazy ",
				"(v zátvorkách sú uvedené čiarkami oddelené ",
				"alternatívy rovnakého príkazu):");
			symetrickéOkraje(20);
			strop.vypíšRiadok("(vklad, vlož, vloz), (výber, vyber), ",
				"(úvod, uvod), stav, riadok, text, (vymaž, vymaz), ",
				"(pomoc, pomocník, pomocnik), definuj, uprav, stop a koniec.");

			symetrickéOkraje(0);
			strop.vypíšRiadok();

			if (!vlastnéPríkazy.prázdny())
			{
				strop.vypíšRiadok("Okrem toho sú definované ",
					"nasledujúce vlastné príkazy:");
				symetrickéOkraje(20);
				boolean prvý = true;
				for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				{
					if (prvý) prvý = false; else strop.vypíš(", ");
					strop.vypíš(vlastnýPríkaz.identifikátor);
				}
				strop.vypíšRiadok();

				symetrickéOkraje(0);
				strop.vypíšRiadok();
			}

			strop.vypíšRiadok("Ak chcete poznať podrobnosti o konkrétnom",
				"príkaze, zadajte ho ako argument príkazu pomocníka, ",
				"napríklad: pomoc vklad.", riadok);

			strop.vypíšRiadok("V jednom príkazovom riadku môže byť ",
				"uvedených aj viacero príkazov oddelených bodkočiarkou ",
				"(;). Znak „and“ (& – angl. aj „ampersand“) je ",
				"rezervovaný pre príkaz „definuj“ – pozri pomocníka ",
				"tohto príkazu.");
		}
		else
		{
			príkaz = príkaz.trim().toLowerCase();
			symetrickéOkraje(20);

			if (príkaz.equals("vklad") || príkaz.equals("vlož") ||
				príkaz.equals("vloz"))
			{
				strop.vypíšRiadok("(vklad, vlož, vloz) [«suma»]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Vykoná vloženie zadanej «sumy» na ",
					"účet. Ak suma nie je zadaná, tak sa príkaz pokúsi ",
					"si ju vyžiadať prostredníctvom dialógu.");
			}
			else if (príkaz.equals("výber") || príkaz.equals("vyber"))
			{
				strop.vypíšRiadok("(výber, vyber) [«suma»]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Vykoná výber zadanej «sumy» z účtu. ",
					"Ak suma nie je zadaná, tak sa príkaz pokúsi si ju ",
					"vyžiadať prostredníctvom dialógu.");
			}
			else if (príkaz.equals("stav"))
			{
				strop.vypíšRiadok("stav:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Vypíše aktuálny stav financií na účte. ",
					"Na zabránenie viacnásobných nadbytočných výpisov ",
					"stavu účtu je príkaz v rámci jedného spracovania ",
					"príkazového riadka kontrolovaný. Výpis stavu skutočne ",
					"nastane len v nasledujúcich situáciách:");
				symetrickéOkraje(60);
				strop.vypíšRiadok("1. Ak ide o prvý výpis v rámci ",
					"spracovania príkazového riadka.");
				strop.vypíšRiadok("2. Ak bola medzičasom vymazaná obrazovka.");
				strop.vypíšRiadok("3. Ak sa stav účtu medzičasom zmenil.");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Okrem uvedených prípadov bude ",
					"vypísaná záverečná informácia (t. j. informácia ",
					"zobrazená po úplnom spracovaní príkazového riadka) ",
					"o tom, že stav účtu sa nezmenil, ak bol počas ",
					"spracovania príkazového riadka takýto výpis aspoň ",
					"raz požadovaný.");
			}
			else if (príkaz.equals("riadok"))
			{
				strop.vypíšRiadok("riadok [«text»]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Vypíše riadok s «textom». ",
					"(Ak text nie je zadaný, tak vypíše prázdny riadok.)");
			}
			else if (príkaz.equals("text"))
			{
				strop.vypíšRiadok("text [«text»]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Vypíše zadaný «text» v rámci jedného ",
					"riadka. Bez zadania «textu» nemá vykonanie tohto ",
					"príkazu žiadny efekt.");
			}
			else if (príkaz.equals("vymaž") || príkaz.equals("vymaz"))
			{
				strop.vypíšRiadok("(vymaž, vymaz) [obrazovku, (definíciu, ",
					"definiciu) (úvod, uvod, pred [vkladom | výberom | ",
					"vyberom], po [vklade | výbere | vybere], ",
					"«identifikátor»), (históriu, historiu) [«začiatok»]]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Vymaže zadaný cieľ, predvolene ",
					"je to obrazovka. Keď za príkazom nasleduje ",
					"kľúčové slovo «definíciu», tak ďalšie očakávané ",
					"slovo je «identifikátor» definície, ktorá má byť ",
					"vymazaná (vrátane predvolených identifikátorov – ",
					"úvod…). Keď za príkazom nasleduje kľúčové slovo ",
					"«históriu» tak zvyšok reťazca označuje «začiatok» ",
					"príkazového riadka, ktorý určí riadok alebo riadky, ",
					"ktoré budú vymazané z histórie príkazov, pričom ",
					"prázdny reťazec spôsobí úplné vymazanie histórie ",
					"príkazov.");
			}
			else if (príkaz.equals("úvod") || príkaz.equals("uvod"))
			{
				strop.vypíšRiadok("(úvod, uvod):");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Buď zobrazí predvolený text pomocníka, ",
					"alebo spustí príkazy rezervovanej definície „úvod“. ",
					"(Pozri aj pomocníka k príkazu definuj.)");
			}
			else if (príkaz.equals("pred") || príkaz.equals("po"))
			{
				strop.vypíšRiadok("pred [vkladom | výberom | vyberom], ",
					"po [vklade | výbere | vybere]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Toto sú rezervované identifikátory. Viac ",
					"podrobností nájdete v pomocníkovi k príkazu definuj.");
			}
			else if (príkaz.equals("pomoc") || príkaz.equals("pomocník") ||
				príkaz.equals("pomocnik"))
			{
				strop.vypíšRiadok("(pomoc, pomocník, pomocnik) [«príkaz»]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Vypíše text pomocníka k zadanému ",
					"príkazu, alebo všeobecný text pomocníka. Ak je ",
					"zadaný príkaz vlastným definovaným príkazom ",
					"a text pomocníka nie je definovaný (pozri aj ",
					"pomocníka k príkazu definuj), tak sú zobrazené ",
					"príkazy definície.");
			}
			else if (príkaz.equals("definuj"))
			{
				strop.vypíšRiadok("definuj [(úvod, uvod, pred [vkladom | ",
					"výberom | vyberom], po [vklade | výbere | vybere], ",
					"«identifikátor») «príkazy» | pomocníka ",
					"«identifikátor» «text pomocníka»]:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Tento príkaz pracuje s definíciami ",
					"vlastných príkazov. Ak nie je zadaný žiadny ",
					"parameter, tak príkaz vypíše informácie o jestvujúcich",
					"definíciách.", riadok);
				strop.vypíšRiadok("Identifikátory „úvod“, „uvod“, „pred“ ",
					"a „po“ sú rezervované – prvé dva predefinujú príkaz ",
					"„úvod“:");
				symetrickéOkraje(60);
				strop.vypíšRiadok("Príklad: definuj úvod ",
					"vymaž;pomoc;riadok;stav");
				symetrickéOkraje(40);
				strop.vypíšRiadok(riadok, "Ďalšie dva („pred“ a „po“) sú ",
					"určené na definovanie rezervovaných skupín príkazov. ",
					"Tie sú použiteľné výhradne automaticky. Rezervovaná ",
					"skupina príkazov „pred“ je vykonaná pred ",
					"vykonaním každého potvrdeného príkazového riadka (bez ",
					"ohľadu na prípadné chyby). Rezervovaná skupina ",
					"príkazov „po“ je vykonaná po spracovaní príkazového ",
					"riadka.", riadok);
				strop.vypíšRiadok("Obidve naposledy opísané rezervované ",
					"skupiny príkazov majú dve modifikácie – jedna súvisí ",
					"s vkladmi, druhá s výbermi. Tieto modifikácie sú ",
					"vykonávané tesne pred/po príkazoch vkladu/výberu. ",
					"Vzniku nekonečného cyklu bránia vnútorné semafory, ",
					"ktoré nedovolia tieto skupiny príkazov vykonávať ",
					"rekurzívne.", riadok);
				strop.vypíšRiadok("Ak tesne za príkazom „definuj“ nasleduje ",
					"kľúčové slovo „pomocníka“, tak ďalšie slovo je ",
					"«identifikátorom» jestvujúcej definície vlastného ",
					"príkazu (okrem rezervovaných identifikátorov). Za ",
					"ním nasleduje text pomocníka príkazu.", riadok);
				strop.vypíšRiadok("Znak „and“ (& – angl. aj „ampersand“) ",
					"je rezervovaný. Všetky znaky and (&) sú v rámci ",
					"definície zmenené na znaky bodkočiarky (;), takže ",
					"definícia môže vďaka tomu obsahovať aj viacero ",
					"príkazov.");
			}
			else if (príkaz.equals("uprav"))
			{
				strop.vypíšRiadok("uprav (úvod, uvod, pred [vkladom | ",
					"výberom | vyberom], po [vklade | výbere | vybere], ",
					"[pomocníka] «identifikátor»):");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Toto nie je „pravý“ príkaz, neukladá sa ",
					"do histórie, ani nie je použiteľný ako príkaz ",
					"ľubovoľnej definície vlastných príkazov. Funguje ",
					"tak, že po potvrdení vstupného riadka prehľadá ",
					"definície jestvujúcich vlastných príkazov (pričom ",
					"berie do úvahy aj rezervované identifikátory ",
					"– úvod…) a ak takú nájde, tak vloží naspäť do ",
					"príkazového riadka prislúchajúci príkaz „definuj“, ",
					"čím v podstate zaháji úpravu príkazovej časti ",
					"definície vlastného príkazu (prípadne rezervovanej ",
					"definície). Ak je pred identifikátorom vlastnej ",
					"definície kľúčové slovo „pomocníka“, tak zaháji ",
					"úpravu pomocníka určeného príkazu.");
			}
			else if (príkaz.equals("stop"))
			{
				strop.vypíšRiadok("stop:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Ukončí spracovanie príkazového riadka. ",
					"Ak je definovaná skupina príkazov „po“, tak po ",
					"vykonaní tohto príkazu nebude spustená.");
			}
			else if (príkaz.equals("koniec"))
			{
				strop.vypíšRiadok("koniec:");
				symetrickéOkraje(40);
				strop.vypíšRiadok("Ukončí aplikáciu. Ak za týmto príkazom ",
					"nasledujú ďalšie príkazy, tak tie už nebudú vykonané.");
			}
			else
			{
				// Naposledy skúsim nájsť pomocníka k definícii vlastného
				// príkazu:

				boolean nenašielSom = true;

				for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				{
					if (príkaz.equals(vlastnýPríkaz.identifikátor))
					{
						nenašielSom = false;
						strop.vypíšRiadok(vlastnýPríkaz.identifikátor, ":");
						symetrickéOkraje(40);
						if (null == vlastnýPríkaz.pomocník ||
							vlastnýPríkaz.pomocník.isEmpty())
							strop.vypíšRiadok(vlastnýPríkaz.príkazy);
						else
							strop.vypíšRiadok(vlastnýPríkaz.pomocník);
						break;
					}
				}

				symetrickéOkraje(0);
				if (nenašielSom)
					strop.vypíšRiadok("Nepodarilo sa nájsť ",
						"pomocníka pre zadaný príkaz: ", príkaz, ".");
			}

			symetrickéOkraje(0);
		}
	}

	/**
	 * Táto metóda uchová zadaný príkazový riadok v histórii. Opakujúce sa
	 * príkazové riadky budú z histórie automaticky vymazané.
	 */
	private void uchovajRiadok(String reťazec)
	{
		for (int i = 0; i < história.veľkosť(); ++i)
			if (história.daj(i).equals(reťazec)) história.odober(i);
		história.pridaj(reťazec);
		história.počítadlo(história.veľkosť());
	}

	//##
	/**
	 * Táto metóda interpretuje zadané jestvujúce príkazy a zároveň
	 * rozvíja a vykonáva vlastné definované príkazy.
	 */
	private void vykonajPríkazy(String reťazec)
	{
		// Prázdny reťazec je ignorovaný:
		if (reťazec.isEmpty()) return;

		// Reťazec je rozdelený na jednotlivé príkazy oddelené
		// bodkočiarkami (;):
		String[] príkazy = reťazec.split(";+");
		for (String príkaz : príkazy)
		{
			// Uložíme pôvodný príkaz, ak by sme ho náhodou potrebovali:
			String pôvodný = príkaz;

			// Každý príkaz je orezaný (zbavený bieleho priestoru na začiatku
			// a na konci) a prevedený na malé písmená:
			príkaz = príkaz.trim().toLowerCase();

			// Prázdne príkazy sú ignorované:
			if (príkaz.isEmpty()) continue;

			// Spracovanie (rozpoznanie) príkazu:

			if (príkaz.startsWith("vklad"))
			{
				vklad(príkaz.substring(5));
			}
			else if (príkaz.startsWith("vlož") || príkaz.startsWith("vloz"))
			{
				vklad(príkaz.substring(4));
			}
			else if (príkaz.startsWith("výber") || príkaz.startsWith("vyber"))
			{
				výber(príkaz.substring(5));
			}
			else if (príkaz.startsWith("stav"))
			{
				stav(false);
			}
			else if (príkaz.startsWith("riadok"))
			{
				strop.vypíšRiadok(pôvodný.replaceAll("(?i)^ *riadok ?", ""));
			}
			else if (príkaz.startsWith("text"))
			{
				strop.vypíš(pôvodný.replaceAll("(?i)^ *text ?", ""));
			}
			else if (príkaz.startsWith("vymaž") || príkaz.startsWith("vymaz"))
			{
				vymaž(príkaz.substring(5));
			}
			else if (príkaz.startsWith("úvod") || príkaz.startsWith("uvod"))
			{
				úvod(pôvodný.trim().substring(4).trim());
			}
			else if (príkaz.startsWith("definuj"))
			{
				// Do definície vlastného príkazu pošlem orezanú relevantnú
				// časť pôvodného príkazového riadka:
				definuj(pôvodný.trim().substring(7).trim());
			}
			else if (príkaz.startsWith("pomocník") ||
				príkaz.startsWith("pomocnik"))
			{
				pomocník(príkaz.substring(8));
			}
			else if (príkaz.startsWith("pomoc"))
			{
				pomocník(príkaz.substring(5));
			}
			else if (príkaz.startsWith("stop"))
			{
				// Spustenie príkazu „stop“ neznamená okamžité ukončenie
				// spracovania príkazového riadka. Je to ľahšia verzia
				// príkazu „koniec“.
				neboloZastavené = false;
				return;
			}
			else if (príkaz.startsWith("koniec"))
			{
				// Spustenie príkazu „koniec“ neznamená okamžité ukončenie
				// aplikácie, preto zároveň ukončíme metódu – aby neboli
				// spracúvané žiadne ďalšie príkazy:
				Svet.koniec();
				neboloZastavené = false;
				return;
			}
			else
			{
				// Naposledy je prehľadaný zoznam definícií vlastných
				// príkazov…

				// Príznak nájdenia príkazu medzi vlastnými príkazmi:
				boolean nenašielSomVlastný = true;

				// Hľadanie definície vlastného príkazu:
				for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				{
					if (príkaz.startsWith(vlastnýPríkaz.identifikátor))
					{
						nenašielSomVlastný = false;

						// Použitý príkaz znamená rekurziu, čo je považované
						// za chybu, nepoužitý príkaz je označený za použitý
						// a vykonaný:
						if (vlastnýPríkaz.použitý)
						{
							// ++početChýb;
							strop.vypíšRiadok("Chyba! Príkaz: ",
								vlastnýPríkaz.identifikátor,
								" už bol použitý.");
						}
						else
						{
							vlastnýPríkaz.použitý = true;
							vykonajPríkazy(vlastnýPríkaz.príkazy.
								replace("$", pôvodný.trim().substring(
								vlastnýPríkaz.identifikátor.length())));
						}

						break;
					}
				}

				// Ak som nenašiel príkaz ani medzi definíciami vlastných
				// príkazov, tak vypíšem chybu:
				if (nenašielSomVlastný)
				{
					// ++početChýb;

					// Ak sa príkaz nepodarilo rozpoznať, tak je to oznámené
					// používateľovi:
					strop.vypíšRiadok("Chyba! Neznámy príkaz: ", príkaz,
						riadok, "(Zadajte pomoc na zobrazenie zoznamu ",
						"príkazov.)");
				}
			}
		}
	}

	/**
	 * Táto špeciálna definícia skupiny príkazov je automaticky vykonaná
	 * pred každým spracovaním príkazového riadka.
	 */
	private void spustiPred()
	{
		if (null != pred)
		{
			// Zresetuje použitie vlastných príkazov (pozri aj
			// vysvetlenie v rámci reakcie „potvrdenieÚdajov“):
			for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				vlastnýPríkaz.použitý = false;

			// Vykonanie definície „pred“:
			vykonajPríkazy(pred);
		}
	}

	/**
	 * Táto špeciálna definícia skupiny príkazov je automaticky vykonaná
	 * po každom spracovaní príkazového riadka.
	 */
	private void spustiPo()
	{
		if (null != po)
		{
			// Zresetuje použitie vlastných príkazov (pozri aj
			// vysvetlenie v rámci reakcie „potvrdenieÚdajov“):
			for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				vlastnýPríkaz.použitý = false;

			// Vykonanie definície „po“:
			vykonajPríkazy(po);
		}
	}

	/**
	 * Toto je prekrytá metóda rámca, ktorá je spustená automaticky po
	 * potvrdení údajov vo vstupnom riadku. Metóda prevezme potvrdený reťazec
	 * z rámca a podľa neho vykoná prislúchajúci príkaz alebo príkazy.
	 */
	@Override public void potvrdenieÚdajov()
	{
		// Prevzatie hodnoty potvrdeného vstupného riadka:
		String reťazec = Svet.prevezmiReťazec();

		// Prázdny vstupný riadok je ignorovaný:
		if (reťazec.isEmpty()) return;

		// Overí, či sa riadok nezačína rezervovaným slovom „uprav“ a ak
		// áno, vykoná metapríkaz „uprav“:
		if (reťazec.trim().toLowerCase().startsWith("uprav"))
		{
			uprav(reťazec.substring(5));
		}
		else
		{
			// Uchová príkazový riadok v histórii:
			uchovajRiadok(reťazec);

			// Výpis ozveny príkazu (informačne pre používateľa):
			strop.vypíšRiadok();
			strop.vypíšRiadok(">", reťazec);
			strop.vypíšRiadok();

			// Inicializácia atribútov riadiacich vypísanie stavu účtu:
			poslednýStav = null;
			vypíšKontrolu = false;

			// Reset príznaku vykonania príkazu „stop“:
			neboloZastavené = true;

			// Vykonanie príkazov pred spracovaním príkazového riadka:
			spustiPred();

			//##
			// Zresetuje použitie vlastných príkazov (príznak „použitý“ slúži
			// na identifikáciu použitých príkazov a na zabránenie rekurzie,
			// pretože tá by bola v tomto prípade určite nekonečná):
			for (Príkaz vlastnýPríkaz : vlastnéPríkazy)
				vlastnýPríkaz.použitý = false;

			// Spracuje príkazový riadok:
			vykonajPríkazy(reťazec);

			if (neboloZastavené)
			{
				// Vykonanie príkazov po spracovaní príkazového riadka:
				spustiPo();

				// Posledný výpis stavu účtu, ak treba:
				if (vypíšKontrolu) stav(true);
			}
		}
	}

	/**
	 * Toto je prekrytá metóda rámca, ktorá je spustená automaticky po
	 * zvolení definovanej klávesovej skratky. Metóda je použitá pri
	 * implementácii histórie príkazov.
	 */
	@Override public void klávesováSkratka()
	{
		// Pohyb späť v histórii potvrdených riadkov (príkazov):
		if (ÚdajeUdalostí.príkazSkratky().equals("späť"))
		{
			// Pohyb skončí na prvej položke zoznamu:
			if (história.počítadlo() > 0)
			{
				// Ak bola aktuálna pozícia histórie za koncom zoznamu,
				// tak sa uchová do záložnej premennej reťazec aktuálneho
				// riadka:
				if (história.počítadlo() == história.veľkosť())
					aktuálnyRiadok = Svet.textVstupnéhoRiadka();
				Svet.textVstupnéhoRiadka(história.predchádzajúci());
			}
			else Svet.pípni();
		}
		// Pohyb vpred v histórii potvrdených riadkov (príkazov):
		else if (ÚdajeUdalostí.príkazSkratky().equals("vpred"))
		{
			// Pohyb sa končí za poslednou položkou zoznamu:
			if (história.počítadlo() < história.veľkosť())
			{
				// Ak bola aktuálna pozícia na poslednej položke, tak sa
				// aktuálna pozícia nastaví za poslednú položku v zozname
				// a do vstupného riadka sa vráti zálohovaná hodnota
				// aktuálneho riadka:
				if (história.počítadlo() == história.veľkosť() - 1)
				{
					Svet.textVstupnéhoRiadka(aktuálnyRiadok);
					história.počítadlo(história.veľkosť());
				}
				else
					Svet.textVstupnéhoRiadka(história.ďalší());
			}
			else Svet.pípni();
		}
	}

	/**
	 * Toto je prekrytá metóda rámca – overuje, či je potrebné uložiť
	 * konfiguračný súbor.
	 */
	@Override public boolean konfiguráciaZmenená()
	{
		// Nasledujúci riadok kódu sem bol vložený v dôsledku zvolenia
		// položky „Uložiť históriu do konfigurácie“ v generátore projektov.
		// Riadok spôsobí to, že konfigurácia bude ukladaná vždy…
		if (true) return true;

		// Ak sa suma na účte líši od sumy prečítanej z konfigurácie,
		// tak metóda ohlási, že konfiguráciu je potrebné uložiť:
		if (sumaNaÚčte != prečítanáSuma) return true;

		return false;
	}

	/**
	 * Toto je prekrytá metóda rámca – ukladá údaje do konfiguračného súboru.
	 *
	 * @param  súbor  konfiguračný súbor (objekt príde z rámca automaticky)
	 */
	@Override public void zapíšKonfiguráciu(Súbor súbor)
		throws java.io.IOException
	{
		// Zápis hodnoty do konfigurácie:
		súbor.zapíšVlastnosť("sumaNaÚčte", sumaNaÚčte);

		// Zápis histórie príkazov do konfigurácie:
		int dĺžkaHistórie = história.dĺžka();
		súbor.zapíšVlastnosť("dĺžkaHistórie", dĺžkaHistórie);
		for (int i = 0; i < dĺžkaHistórie; ++i)
			súbor.zapíšVlastnosť("história[" + i + "]", história.daj(i));

		//##
		// Zápis definícií vlastných príkazov do konfigurácie:
		int početVlastnýchPríkazov = vlastnéPríkazy.dĺžka();
		súbor.zapíšVlastnosť("početVlastnýchPríkazov",
			početVlastnýchPríkazov);
		for (int i = 0; i < početVlastnýchPríkazov; ++i)
		{
			Príkaz vlastnýPríkaz = vlastnéPríkazy.daj(i);
			súbor.zapíšVlastnosť("vlastnéPríkazy[" + i +
				";'identifikátor']", vlastnýPríkaz.identifikátor);
			súbor.zapíšVlastnosť("vlastnéPríkazy[" + i +
				";'príkazy']", vlastnýPríkaz.príkazy);
			súbor.zapíšVlastnosť("vlastnéPríkazy[" + i +
				";'pomocník']", vlastnýPríkaz.pomocník);
		}

		// Uloženie rezervovaných skupín príkazov (úvod…):
		súbor.zapíšVlastnosť("úvod", úvod);
		súbor.zapíšVlastnosť("pred", pred);
		súbor.zapíšVlastnosť("po", po);
		súbor.zapíšVlastnosť("predVkladom", predVkladom);
		súbor.zapíšVlastnosť("poVklade", poVklade);
		súbor.zapíšVlastnosť("predVýberom", predVýberom);
		súbor.zapíšVlastnosť("poVýbere", poVýbere);

		// Zápis histórie transakcií do konfigurácie:
		int početTransakcií = transakcie.dĺžka();
		súbor.zapíšVlastnosť("početTransakcií", početTransakcií);
		for (int i = 0; i < početTransakcií; ++i)
			transakcie.daj(i).zapíš(súbor, "transakcia[" + i + "]");

	}

	/**
	 * Toto je prekrytá metóda rámca – číta údaje z konfiguračného súboru.
	 *
	 * @param  súbor  konfiguračný súbor (objekt príde z rámca automaticky)
	 */
	@Override public void čítajKonfiguráciu(Súbor súbor)
		throws java.io.IOException
	{
		// Vloženie predvolenej hodnoty:
		sumaNaÚčte = prečítanáSuma = 1_000_000L;

		// Čítanie hodnoty z konfigurácie:
		sumaNaÚčte = prečítanáSuma = súbor.čítajVlastnosť(
			"sumaNaÚčte", sumaNaÚčte);

		// Čítanie histórie príkazov z konfigurácie:

		// Vytvorenie zoznamu histórie príkazov (ak nejestvuje):
		if (null == história) história = new Zoznam<String>();

		// Prečítanie dĺžky histórie:
		int dĺžkaHistórie = súbor.čítajVlastnosť(
			"dĺžkaHistórie", 0L).intValue();

		// Prečítanie a vloženie neprázdnych príkazov histórie:
		for (int i = 0; i < dĺžkaHistórie; ++i)
		{
			String položka = súbor.čítajVlastnosť("história[" + i + "]", "");

			if (null != položka && !položka.isEmpty())
				história.pridaj(položka);
		}

		// Nastavenie počítadla za poslednú položku histórie:
		história.počítadlo(história.dĺžka());

		//##
		// Vytvorenie zoznamu vlastných príkazov (ak nejestvuje):
		if (null == vlastnéPríkazy) vlastnéPríkazy = new Zoznam<Príkaz>();

		// Prečítanie počtu vlastných príkazov:
		int početVlastnýchPríkazov = súbor.čítajVlastnosť(
			"početVlastnýchPríkazov", 0L).intValue();

		// Prečítanie a vloženie neprázdnych definícií do zoznamu:
		for (int i = 0; i < početVlastnýchPríkazov; ++i)
		{
			String identifikátor = súbor.čítajVlastnosť(
				"vlastnéPríkazy[" + i + ";'identifikátor']", "");

			String príkazy = súbor.čítajVlastnosť(
				"vlastnéPríkazy[" + i + ";'príkazy']", "");

			String pomocník = súbor.čítajVlastnosť(
				"vlastnéPríkazy[" + i + ";'pomocník']", (String)null);

			if (null != identifikátor && !identifikátor.isEmpty() &&
				null != príkazy && !príkazy.isEmpty())
			{
				Príkaz vlastnýPríkaz = new Príkaz(identifikátor, príkazy);
				vlastnéPríkazy.pridaj(vlastnýPríkaz);
				vlastnýPríkaz.pomocník = pomocník;
			}
		}

		// Čítanie rezervovaných skupín príkazov (úvod…):
		úvod = súbor.čítajVlastnosť("úvod", úvod);
		pred = súbor.čítajVlastnosť("pred", pred);
		po = súbor.čítajVlastnosť("po", po);
		predVkladom = súbor.čítajVlastnosť("predVkladom", predVkladom);
		poVklade = súbor.čítajVlastnosť("poVklade", poVklade);
		predVýberom = súbor.čítajVlastnosť("predVýberom", predVýberom);
		poVýbere = súbor.čítajVlastnosť("poVýbere", poVýbere);

		// Vytvorenie zoznamu transakcií (ak nejestvuje):
		if (null == transakcie) transakcie = new Zoznam<Transakcia>();

		// Prečítanie počtu transakcií:
		int početTransakcií = súbor.čítajVlastnosť(
			"početTransakcií", 0L).intValue();

		// Prečítanie a vloženie neprázdnych príkazov histórie:
		for (int i = 0; i < početTransakcií; ++i)
		{
			Transakcia transakcia = čítajTransakciu(súbor,
				"transakcia[" + i + "]");

			if (null != transakcia) transakcie.pridaj(transakcia); else
			{
				// ++početChýb;
				String chyba = "Chyba! Transakciu číslo " + i +
					" sa nepodarilo prečítať.";
				Farba záloha = podlaha.farbaTextu();
				podlaha.farbaTextu(červená);
				podlaha.vypíšRiadok(chyba);
				podlaha.farbaTextu(záloha);
				System.err.println(chyba);
			}
		}
	}

	// ----------------------------------------------------------------------
	//  Hlavná metóda
	//

	/**
	 * Metóda {@code main} je vstupným bodom aplikácie (slúži na jej spúšťanie).
	 *
	 * @param  args  parametre prečítané z príkazového riadka
	 */
	public static void main(String[] args)
	{
		Svet.použiKonfiguráciu("KonzolováBanka.cfg");
		new KonzolováBanka();
	}
}