Dr. Sheldon Cooper szólánc játéka

Szólánc - Sheldon - Bazinga!

Szólánc - Sheldon - Bazinga!Dr. Sheldon Cooper karakterét nem kell bemutatni. Az Agymenők (The Big Bang Theory) című sorozat 2. évad 5. epizódjának címe A vitatkozás nagymestere (The Euclid Alternative). Nagyon találó az epizód címe magyarul. Miközben Penny reggel Sheldont munkába viszi, Sheldon az autóban kémiai elemek nevéből álló szólánc játékával különösen Penny agyára megy (pedig a játékot Penny nyeri 😀):

A játék során Sheldon az alábbi kémiai elemeket mondja:

  • magyar nyelven: Hélium ↦ Mangán ↦ Neptúnium ↦ Magnézium ↦ Molibdén ↦ Nitrogén ↦ Nobélium ↦ Mendelévium
  • angol nyelven: Helium ↦ Mercury ↦ Ytterbium ↦ Molybdenum ↦ Magnesium ↦ Manganese ↦ Europium ↦ Mendelevium

Támogassuk meg ezt a játékot! Készítsünk olyan programot Java nyelven, ami segít(ene) felkészülni Sheldon szólánc játékára!

A szükséges lépések áttekintése

  • Gyűjtsük össze a kémiai elemek nevét magyar nyelven a Wikipédia – Kémiai elemek listája szócikkéből és rendezzük ábécé sorrendbe!
  • Építsük be az elemlistát a program adatmodelljébe!
  • Indítsuk el a lépésszámláló nulláról! Ha a lépésszámláló páros, akkor az ’A’ játékos, egyébként a ’B’ játékos lép.
  • Készítsük elő a játékmenet tárolására alkalmas adatszerkezetet, szöveget, listát!
  • Kezdetben kínáljuk fel a teljes elemlistát úgy, hogy mindig egy és csak egy legyen belőle kiválasztható!
  • A kiválasztást követően tároljuk el a játékmenetben az elemet, töröljük ezt az elemlistából, majd kínáljuk fel azoknak az elemeknek a listáját, amelyek kezdőbetűje megegyezik az előzőleg kiválasztott elem utolsó betűjével és növeljük meg a lépésszámlálót!
  • Amíg a felkínálható elemek listája nem üres, addig az előző lépést ismételjük meg!
  • A játék végén az nyert, aki a játékmenet utolsó elemét választotta ki. Írjuk ki a nevét és a lépésszámot!

A grafikus felületű megvalósítás képernyőképe rövid játékmenettel

Szólánc képernyőkép

Ötletek a megvalósításra és a továbbfejlesztésre

  • A program Java nyelven konzolos menükezeléssel, asztali alkalmazásként swing-esen többféle GUI komponens használatával és eseménykezeléssel, böngészőben futó JSP webalkalmazásként többféle űrlapmezővel, illetve HTML+CSS+JavaScript alapon is implementálható.
  • A kémiai elemek listája lecserélhető az angol nevekre. Ekkor figyeljünk arra, hogy a kis- és nagybetűket ne különböztessük meg az utolsó-első betű párosítása során.
  • Lehet a játék bármikor megszakítható, illetve a vége után újrakezdhető.
  • A program mérhetné a játék során az eltelt időt.
  • A program lehetne peer-to-peer vagy szerver-kliens elosztott és megvalósíthatna hálózatos kommunikációt.
  • A program mobil alkalmazásként is implementálható.

A bejegyzéshez tartozó teljes forráskódot – többféle változatban is – ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Többféleképpen is hozzájuthatunk az adatokhoz attól függően, hogy milyen előismeretekkel rendelkezünk a különböző tanfolyamainkon:

  • A Java SE szoftverfejlesztő tanfolyamon dolgozhatunk szövegtömbbel, generikus kollekcióval (listával/halmazzal), konzolos és swing-es változatot is készíthetünk. Ehhez a feladathoz objektumorientált alapok mindenképpen szükségesek. Kézzel előállított szövegfájlból olvasva (mentve a Wikipédia oldaláról a táblázatot) hozzájuthatunk a kémiai elemek nevéhez, amihez kivételkezelés is szükséges.
  • A Java EE szoftverfejlesztő tanfolyamon megvalósítható, hogy a program kivételkezeléssel hálózati kapcsolatot épít, majd közvetlenül olvassa és/vagy menti a Wikipédia HTML tartalmából a kémiai elemek nevét szövegfájlba vagy generikus kollekcióba, amivel a feladat visszavezethető az SE szemléletű megközelítésre. Böngészőben futó JSP és/vagy Servlet technológiára építő webalkalmazásként is megvalósítható a feladat.

Sankey-diagramot készítünk

Sankey-diagram-logo

Sankey-diagram-logoA Sankey-diagram alkalmas kétféle adatsor közötti N:M fokszámú kapcsolat, összefüggés és a köztes átmenet ábrázolására. Hangsúlyozza a fő átvitelt vagy áramlatokat egy rendszeren belül. Az áramlás irányát nyíllal szemlélteti és az áramlatok szélessége arányos az áramlási mennyiségekkel.

Feladat

Jelenítsük meg HTML formátumú weboldalként a magyarországi régiókban a foglalkoztatottak számát nemzetgazdasági szektorok szerint a KSH 2018-as adatsora alapján! Automatizáljuk egy Java programmal úgy a feladatot, hogy az év paraméterként megadható legyen!

Tervezés

A KSH témastruktúrában a táblázat elérési útja:

  • 5. Területi adatok,
  • 5.1. A munkaerő-piaci tendenciák Magyarország régióiban,
  • 5.1.3. A foglalkoztatottak száma nemzetgazdasági szektorok szerint, nemenként (2008–)

Online böngészhető táblázat:
http://www.ksh.hu/docs/hun/xstadat/xstadat_hosszu/h_qlf017.html.

Letölthető táblázat (XLS formátumban): http://www.ksh.hu/docs/hun/xstadat/xstadat_hosszu/xls/h5_1_3.xls.

A táblázatban lévő adatforrás szükséges része látható az ábrán:

KSH adatforrás Sankey-diagramhoz

A táblázatban a régiók az A105:A112 cellatartományban találhatók. A hozzájuk tartozó 3 nemzetgazdasági szektor a B-C-D oszlopok azonos soraiból olvashatók ki. POJO-k létrehozása mindenképpen hasznos a megvalósításhoz, például new SankeyData("Közép-Dunántúl", "Szolgáltatás", 253.89). Ezekből generikus listát is célszerű építeni: List<SankeyData> sankeyDataList.

Többféleképpen is hozzájuthatunk az adatokhoz attól függően, hogy milyen előismeretekkel rendelkezünk a különböző tanfolyamainkon:

  • A Java SE szoftverfejlesztő tanfolyamon „kézzel” letölthetjük a projekt files mappájába az XLS fájlt. Ezután akár manuálisan is összeállítható a POJO lista, vagy a JExcel API-val is hatékonyan feldolgozható a XLS fájl aktuális munkalapja. Fájlkezelés előtt az összeállított HTML fájlt kiírathatjuk a konzolra, ahonnan „kézzel” vágólapozva létrehozhatjuk belőle a szükséges HTML fájlt. Fájlkezeléssel persze adott mappába, adott fájlnévvel, kivételkezeléssel a java.io vagy java.nio csomagot használva a HTML fájl generálása is automatizálható.
  • A Java EE szoftverfejlesztő tanfolyamon megvalósítható, hogy a program kivételkezeléssel hálózati kapcsolatot épít, majd letölti az XLS fájlt és ezzel a feladat visszavezethető az előző esetekre. Azt is megtehetjük, hogy az XLS fájlt nem töltjük le, hanem olvasunk belőle közvetlenül a webről. Ekkor is rendelkezésünkre áll a POJO lista. Itt már tudunk HTML fájlt is automatikusan generálni.

Tanulmányoznunk kell a Google Charts galériában a Sankey diagram dokumentációját! Meg kell ismernünk a paraméterezési lehetőségeit és JavaScript forráskódját!

Megvalósítás

A createSankeyDiagram() függvény létrehozza a HTML fájl szöveges tartalmát. Átveszi adatforrásként a sankeyDataList generikus POJO listát. A String típusú sankeyData objektum tartalmazza a Stream API-val hatékonyan összefűzött – POJO-któl elkért – toString() szövegeket. Ezek a diagramhoz szükséges adatok ( addRows …). Például: "['Közép-Dunántúl', 'Szolgáltatás', 253.89]". A  String típusú  html objektum kezdetben tartalmazza a diagramhoz nem szükséges fix részeket, a diagram alapbeállításait, valamint a diagram fejlécéhez szükséges metaadatokat ( addColumnRégió, Nemzetgazdasági szektor, Foglalkoztatottak száma (ezer fő)). A függvény végül a html objektum #SankeyData# részét cseréli a sankeyData-val és az adatfüggő résszel frissített HTML tartalommal tér vissza.

Eredmény

Az egyik eredmény a generált HTML fájl (benne a grafikonhoz tartozó JavaScript) forráskódját tartalmazza:

A másik eredmény a Sankey-diagram képernyőképe, amelyről kiválóan leolvashatók az értékek:

Sankey-diagram

A böngészőben megjelenő HTML oldalon a Sankey-diagram dinamikusan – az egérkurzor pozíciójától függően – képes az aktuális adatok megjelenítésére, mintegy lebegő jelmagyarázatként.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

Dátumtartományok kezelése

dátumintervallumok logó

dátumintervallumok logóAki webáruházat üzemeltet és raktároz, befektet áruk raktározásába, biztosan folyamatosan követi a raktárkészlet (és egyúttal pénzügyei) alakulását különböző lekérdezésekkel. Aki online marketinggel foglalkozik, szintén mérheti/követheti/összevetheti egy-egy reklámkampány eszközeinek (Facebook hirdetés, Google Ads hirdetés, e-mail marketing, Instagram hirdetés, blog) eredményességét, hatékonyságát. Az adatok elemzése mindenképpen része a tervezésnek és folyamatosnak/periodikusnak kell lennie.

Tipikus felmerülő kérdések/problémák

  • Hány offline és/vagy online vásárlás/tranzakció volt eddig az aktuális hónapban?
  • Hogyan változott a raktárkészlet az előző hónapban? Miből kell utánrendelni? Mik a kifutó termékek?
  • A bevétel milyen arányban érkezett offline vagy online vásárlásból az aktuális hónapban?
  • Kik vásároltak az előző negyedévben nyomtatót? Küldjünk nekik e-mailt arról, most 10%-kal olcsóbban rendelhetnek tonert, ha kettőt vesznek!
  • Milyen értékben adtak le rendelést a webáruházban két adott dátum által megadott napon? Például hogyan alakult az utóbbi két Black Friday? Esetleg GLAMOUR-napok, húsvét, hosszú hétvége…
  • Kik azok a rendszeres visszatérő vásárlóink, akik nem vásároltak az előző hónapban?
  • Hogyan alakultak „a számok” az előző két év 3. negyedévében!

Egy webáruház raktárkészletének és számláinak nyilvántartása biztosan adatbázisban tárolódik, így könnyen megfogalmazható SQL lekérdező parancsok segíthetik a fenti kérdésekre/problémákra való válaszadást. Természetesen ezeket a műveleteket okosan ki kell vezetni a felhasználói felületre, hogy könnyen paraméterezhetők legyenek.

Lássunk néhány megoldást! A Java forráskódokból azokat a részeket mutatjuk be, amelyek egy lekérdező parancsba beágyazható dátumokra vonatkozó feltételeket kiírják. A dátumok megjelenítésére rövid formátumot használunk konstansként: SimpleDateFormat SHORT_DATE=new SimpleDateFormat("yyyy-MM-dd");.

Aktuális hónap

Érdemes készíteni két túlterhelt metódust. A paraméter nélküli változat az aktuális napot, a paraméteres változat a megadott napot tekinti maximálisnak és ehhez adja meg az adott hónap első/minimális napját. A két dátumnál az év és hónap megegyezik, a nap többnyire különbözik (ritkán megegyezik). A maxDate nem lehet jövőbeli és teljesül a minDate<=maxDate feltétel.

Előző hónap

Itt is érdemes készíteni két túlterhelt metódust. A paraméter nélküli változat az aktuális napot, a paraméteres változat a megadott napot tekinti kiinduló napnak, és ehhez adja meg az előző hónap első és utolsó napját. A két dátumnál az év és hónap megegyezik, a nap mindig különbözik. Mindkét dátum múltbeli és teljesül a minDate<maxDate feltétel. A megvalósítás kezeli az eltérő hosszúságú hónapokat és a szökőévet is. Ha a kiinduló dátum az adott év első hónapjába esik, akkor az előző hónap az előző év utolsó hónapja (ez most automatikusan teljesül, külön nem kell rá figyelni). Hasznos a dátumobjektum add() metódusa, ami az első paraméterében megadott dátummező alapján a második paraméterében megadott értékkel tudja változtatni a dátumot.

Előző negyedév

Itt is hasznos lehet a két túlterhelt metódus. A paraméter nélküli változat az aktuális napot, a paraméteres változat a megadott napot tekinti kiinduló napnak, és ehhez adja meg az előző negyedév első hónapjának első napját és az előző negyedév utolsó hónapjának utolsó napját. A két dátumnál az év megegyezik, a hónap és a nap mindig különbözik. Mindkét dátum múltbeli és teljesül a minDate<maxDate feltétel. A megvalósítás kezeli az eltérő hosszúságú hónapokat. A szökőév most nem számít. Ha a kiinduló dátum az adott év első negyedévébe esik, akkor az előző negyedév az előző év utolsó negyedéve (erre most külön figyelni kell). A negyedév ( quarter) képletén látszik, hogy épít arra, hogy a dátumobjektumtól elkért hónap ( month) 0 bázisú.

Eredmény

dátumintervallumok eredmény

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java SE szoftverfejlesztő tanfolyam 21-24. óra: Objektumorientált programozás, 2. rész kapcsolódik alapvetően, de a két visszakapott dátum használható több programozási tétellel (kiválogatás, szétválogatás) tömbbel, lambda kifejezésekkel kollekciókkal, SQL lekérdező parancsban adatbázis-kezeléshez kötődően.

Táblázatos komponens testreszabása

táblázat logo

táblázat logoA Java programozási nyelv egyik ismert GUI csomagja a swing. Ennek népszerű grafikus komponense az adatok táblázatos megjelenítését biztosító JTable komponens. A táblázatos megjelenítéshez több beállítás is szükséges. A JTable egy MVC komponens, így külön kezelendők a modell, nézet és a vezérlő funkcióihoz kötődő beállítások. A modell tárolja az adatokat például DefaultTableModel típusú objektumban, amiben szétválaszthatók a fejlécben és a többi cellákban található adatok. A nézethez tartozik a betűméret, a cellák színezése, az adatok igazítása, megjelenítése, a gördítősáv. A viselkedést, a felhasználói reakciót a vezérlő határozza meg, például rendezés, görgetés, fókusz, kijelölés, oszlopok sorrendjének cseréje.

Feladat

Készítsünk olyan Java swing-es kliensprogramot, amely tetszőleges adatforrásból (XML vagy JSON a hálózatról, JDBC adatbázis kapcsolatból, ORM leképzésből származó objektumokból) képes az átvett adatok grafikus felületen való táblázatos megjelenítésére JTable komponenssel! Építsünk arra, hogy az adatokon kívül metaadatok is rendelkezésünkre állnak! A megoldás legyen univerzális!

Képernyőkép

OracleHR képernyőkép

Modell

A táblázatos GUI komponenst kezdetben inicializálni kell, illetve a benne tárolt adatok is törölhetők, ha újrahasznosításra kerül a sor:

Ki kell nyerni a tároláshoz és a megjelenítéshez kötődő adatokat (1. lépés). A metaadatokból a for() ciklus előállítja az oszlopTomb-öt, és az oszlopTipusTomb-be kerülnek az Oracle adattípusból Java objektumtípusként megfeleltetett adatok. Előbbi a fejléc feliratainak szövegeit tartalmazza, és az utóbbi befolyásolja az egyes cellákban az igazítást, illetve hatással van adott oszlop rendezésére is:

Ki kell nyerni a tároláshoz és a megjelenítéshez kötődő adatokat (2. lépés). A while() ciklus végigjárja az eredménytábla sorait és Object típusú tömböt állít elő az összetartozó rekord mezőiből. Ezek először generikus listába kerülnek, majd onnan kétdimenziós Object típusú tömbbe:

Mi indokolja a tömbökből álló generikus lista ( adatLista) alkalmazását?

A while() ciklus végrehajtása előtt nem tudjuk lekérdezni, hogy mennyi rekordot kaptunk vissza, így nem tudjuk rögtön az adatTomb-be tenni az adatokat. A Java nyelvben a tömbök mérete fix, és a deklaráció során meg kell adni. Az eredménytábla metaadatai között megtalálható a mezők száma, ami felhasználható a kétdimenziós tömb oszlopszámaként. A generikus lista dinamikus, annyi elemből fog állni, ahány lépésben végrehajtódik a while() ciklus. Ezután a listától lekérdezhető az elemszáma ( adatLista.size()), és ezzel megvan a kétdimenziós tömb sorainak száma, ami eddig hiányzott. Persze használhatnánk Vector-t is a tömbökből álló generikus lista helyett (mert a DefaultTableModel-nek van olyan túlterhelt konstruktora, ami átvenné paraméterként), de ezt inkább nem tesszük, hiszen a Vector már régóta obsolete kollekció.

Előállítjuk a vizuális komponens mögötti adatmodellt. Öröklődéssel kiegészítjük két hasznos függvénnyel, így cellák rajzolása/renderelése és rendezése megkaphatja a szükséges adattípust ( getColumnClass()), valamint letiltható a cellák szerkeszthetősége ( isCellEditable()). Utóbbiak inkább a vezérléshez kötődnek, de modellen keresztül itt és így kell beállítani:

Végül a vizuális komponens mögötti adatmodellt kell átadni:

Nézet

Adott betűtípus, betűstílus és betűméret használható a táblázat fejlécében, celláiban, illetve a betűmérettől függhet a sorok magassága:

Hasznos ha JScrollPane típusú gördítősáv tartozik a táblázathoz, így dinamikusan megjeleníthető/elrejthető a függőleges/vízszintes gördítősáv:

Vezérlés

Az adatokhoz valahogyan hozzá kell jutni. Most JDBC kapcsolatot használunk és az Oracle HR sémából kérdezünk le adatokat, de a forráskód-részlet univerzális. A folyamat a következő:

  • A driver osztályt betöltjük.
  • Autentikációval c kapcsolatot nyitunk az adatbázis-szerver felé.
  • Végrehajtjuk a lekérdező SQL parancsot.
  • Feldolgozzuk az eredményül kapott ResultSet típusú rs objektumot.
  • Végül lezárjuk a c hálózati kapcsolatot.

Ha engedélyezzük, akkor a megjelenő táblázat fejlécében az egyes oszlopok felirataira kattintva elérhetjük, hogy az adott oszlop típusának megfelelően növekvő vagy csökkenő sorrendbe átrendeződjenek az adatok:

A kivételkezelést nem részleteztük a fenti forráskódoknál, de természetesen kötelezően adott.

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java SE szoftverfejlesztő tanfolyam 45-52. óra: Adatbázis-kezelés JDBC alapon, illetve Java adatbázis-kezelő tanfolyam 9-12. óra: Oracle HR séma elemzése, 33-36. óra: Grafikus kliensalkalmazás fejlesztése JDBC alapon, 2. rész alkalmaihoz kapcsolódik.

A képernyőkép animáció a Animated GIF Maker-rel online készült.

 

Stream API lambda kifejezésekkel

lambda kifejezés logo

lambda kifejezés logoKorábban blogoltunk már a Stream API-ról és a lambda kifejezésekről: Ismerkedjünk lambda kifejezésekkel! Most másképpen közelítve újra foglalkozunk a témával.

Tanfolyamainkon szinte minden adatszerkezethez, tömbhöz, kollekcióhoz, fájlkezeléshez kötődő témakörben használjuk mindkettőt. Áttekintjük az ezekhez szükséges minimális verziószámot, a szintaktika fejlődését, az együttes használat elvi és gyakorlati lehetőségeit. A szükséges alapfogalmakat definiáljuk: hozzárendelési szabály, funkcionális interfész, metódus referencia, alapértelmezett metódusok, típus kikövetkeztetés képessége, generikus és funkcionális programozás. párhuzamos adatfeldolgozás lehetőségei.

Összehasonlításokat is végzünk: a lambda előtti verziók lehetőségei, korlátai, tipikus lambda hibák, mikor mit érdemes és mit nem érdemes használni, paraméterek típusait megadjuk vagy elhagyjuk, hagyományos kollekciós műveletek (azért a generikusság előtti időkre már nem térünk ki) és folyam feldolgozás (adatforrás meghatározása, közbenső és végső műveletek).

Most azokat a Stream API-hoz és lambda kifejezésekhez kötődő bevezető mintapéldákat ismertetjük, amiket részletesen elemzünk tanfolyamaink szakmai moduljának kontakt óráin. Ezek közül közösen meg is írunk néhányat, kombinálunk is néhányat egy-egy összetett adatfeldolgozó művelet megvalósítása során. Programozási tételenként specifikáljuk a feladatokat és megmutatunk néhány megoldást.

1. Adatforrás

100 db olyan véletlen kétjegyű számot állítunk elő generikus listában, amelyek között biztosan előfordul legalább egyszer a 80.

2. Elemi programozási tételek

2.1. Sorozatszámítás

Kiírjuk, hogy mennyi a listában lévő számok összege:

2.2. Eldöntés

Két kérdésre adunk választ. Van-e a listába lévő számok között 35 (konkrét elem), illetve páros (adott tulajdonságú elem)?

2.3. Kiválasztás

Kiírjuk, hogy a biztosan előforduló (legalább 1 db közül balról az első) 80, hányadik helyen (index) található meg:

2.4. Keresés

Keressük a 35-öt az eldöntés és a kiválasztás összeépítésével:

2.5. Megszámolás

Kiírjuk, hogy hány db öttel osztható szám (adott tulajdonságú elem) található a listában:

2.6. Szélsőérték-kiválasztás

Kiírjuk a listában lévő legkisebb számot (értéket, nem indexet):

3. Összetett programozási tételek

3.1. Másolás

Készítünk egy másolatot a lista elemeiről (közben esetleg mindegyiket meg is változtathatjuk):

3.2. Kiválogatás

A listában lévő számok közül kiválogatjuk az öttel osztható számokat:

3.3. Szétválogatás

Külön-külön szétválogatjuk a listában lévő páros és páratlan számokat:

3.4. Unió

A korábban szétválogatott páros és páratlan számokat tartalmazó halmazok unióját állítjuk elő:

3.5. Metszet

A korábban szétválogatott páros és páratlan számokat tartalmazó halmazok metszetét állítjuk elő:

3.6. Összefésülés

A korábban szétválogatott páros és páratlan számokat összefésüljük:

4. A program eredménye a konzolon

A bejegyzéshez tartozó teljes forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java SE szoftverfejlesztő tanfolyam, a Java EE szoftverfejlesztő tanfolyam és a Java adatbázis-kezelő tanfolyam szakmai moduljának több alkalmához és az orientáló moduljának 1-4. óra: Programozási tételek alkalmához is kötődik. A Stream API-val és a lambda kifejezésekkel sokszor foglalkozunk.

Korábban is blogoltunk már a Stream API-ról és a lambda kifejezésekről: Ismerkedjünk lambda kifejezésekkel!