Népesedési világnap

Népesedési világnap logó

Népesedési világnap logóAz ENSZ 1987-ben július 11-ét a népesedési világnappá (World Population Day) nyilvánította. Bolygónk lakossága aznap érte el az 5 milliárdot. További kerek számok voltak: 1999. október 12-én 6 milliárd, 2011. október 30-án 7 milliárd. További kerek számok várhatóak: 2023 – 8 milliárd, 2037 – 9 milliárd, 2057 – 10 milliárd. A KSH elemzése részletes elemzéseket közöl évről-évre a témában, például: 2019-ben, 2018-ban. A worldometer.info weboldalon folyamatosan frissülő kimutatások érhetők el a népességhez globálisan, valamint országonként is: például Magyarország aktuális népesedési adatai.

A népesedési világnap inspirált egy Java program megtervezésére és megírására. A swing GUI-s program megjeleníti a worldometer.info weboldalról kinyerhető adatok alapján régiónként (kontinensenként) az elérhető adatokat 1950-től 2020-ig az alábbiak szerint egy világtérképen.

Az elkészült program

Népesedési világnap Java program

Tervezés

Objektumorientált szemlélettel, MVC architekturális tervezési mintát követünk, angol nyelvű interfész, osztály, változó, objektum, metódus nevekkel. A projekt neve: WorldPopulation, a csomag neve: worldpopulation. Amit lehet, konstansként interfészbe (szeparálva) teszünk és az MVC rétegekhez kötődő osztályok implementálják. A modell minden évszámhoz tárolja a szükséges adatokat, mindezt egyetlen betöltéssel/letöltéssel éri el. A program kliensként hat régióra vonatkozó adatot gyűjt össze, alkalmazkodva a szerver adatforráshoz. A címsorban lévő összesített adat is elérhető közvetlenül a weboldalon, de a kisebb adatforgalom érdekében hasznos inkább a kliensben összesíteni. Mindössze egyetlen eseménykezelés szükséges: a csúszka beállításával megadott évszám alapján frissíteni kell a régiók címkéit és az ablak címsorát. Öröklődés hasznos a feladat megoldása során: egyrészt interfészek, másrészt osztályok között.

Interfészek

Az ősinterfész a WorldPopulationConstants, benne az évszám intervallum MIN_YEAR és MAX_YEAR határaival, valamint a megjeleníthető régiók neveivel tömbben: REGION_NAME_ARRAY. Két utódinterfész épül az ősre: ModelConstants és ViewConstants. Előbbi interfész az adatforráshoz kapcsolódik: URL_COMMON az URL eleje, URL_ARRAY az URL végei régiónként tömbben. Utóbbi interfész a megjelenítéshez kapcsolódik: WORLD_MAP_IMAGE a háttérkép annak WORLD_MAP_RECT méretével együtt, valamint a régiónkénti REGION_RECT_ARRAY téglalapok tömbje a kezdeti pozíciókkal/méretekkel, TITLE a sablon a program címsorához (frissítendő az évszámmal és az összesített népességgel). A megfelelő utódinterfészt mindig implementálja az MVC szerint hozzá illeszkedő osztály.

Osztályok

A belépési pont a WorldPopulation.java fájlban található.

Három összetartozó elemi adatot fog össze egybe a RegionData POJO, ezek name, year, population nevű rendre String, int, long típusú adatok. Például: Európa, 2020, 747643253. Tartalmaz két függvényt: getPopulation(), valamint toString(). Utóbbi HTML formátumban adja vissza a megjelenítendő adatokat.

A JLabel-ből származik az igényekhez alakított RegionLabel osztály. Ennek van előre megadott pozíciója, mérete, betűtípusa, betűmérete, sárga háttérszíne, piros kerete. Ezenkívül a téglalap átlátszó, valamint a benne megjelenő HTML tartalom vízszintesen középre igazított. Némi extra funkció, hogy egérrel megfogva – drag and drop – áthelyezhető, ami a MouseMotionListener egérmozgást figyelő interfész mouseDragged() metódusának felülírásával válik lehetővé. A mozgathatóságáért saját maga felel. Példaként közöljük az osztály teljes forráskódját:

A webről adatokat szerez és tárolja a Model osztály, a java.io és java.net csomagokra építve. Egy példa: a https://www.worldometers.info/world-population/europe-population/ oldal forrásából nyeri ki az osztály az alábbi adatokat:

Ezek parszolását követően elkészül egy optimálisnak tekinthető, generikus listákból álló regionListArray tömb adatszerkezet. A parszolás történhet egyszerű szövegkezeléssel vagy JSON feldolgozással is. Erre épülnek a konstruktorral és vezérlővel összehangoltan működő getter metódusok: getHTML(), getRegionList(), getRegionData(), getPopulation(). A JSON adatforrás feldolgozását most nem részletezzük, de hasonlóról blogoltunk már: Időjárás Budapesten.

A grafikus felhasználói felületet adja a JFrame utód View osztály. Három GUI komponensből áll: pnWorldMap – háttérkép JPanel, lbYear – kiválasztott/aktuális év JLabel, slYear – kiválasztható/görgethető aktuális év JSlider. Izgalmas megoldani egymásra/egymáson elhelyezni a komponenseket. Egy JLayeredPane komponens  DEFAULT_LAYER rétegére kerül a térképet tartalmazó háttérkép, majd a  PALETTE_LAYER rétegére kerül dinamikusan a hat  RegionLabel osztályú/típusú objektum. A csúszka komponens slYearStateChanged() eseménykezelő metódusa vezérlőként megszólítja a modell réteget és a visszakapott adatokkal frissíti a nézet réteget (a címsorban lévő összesítéssel együtt, ezres szeparátorokkal).

Ötlet továbbfejlesztésre

Hat különböző weboldal forráskódjából kell összegyűjteni a megjelenítendő adatokat. Ez 2020-ban régiónként 71 számot jelent és hat régió van. Érdemes lehet olyan adattárolást megvalósítani, amely csökkenti a szerverhez fordulások számát, illetve a letöltendő adatok mennyiségét. Hiszen a múltbeli évekhez kötődő historikus adatok nem változnak. Ha ezekre valamilyen formában a program emlékszik, akkor elegendő az utolsó tárolt évből kiindulva az aktuális évig évenként, régiónként lekérni mindössze 6, 12, 18… számot, a program utolsó futtatásának évéből kiindulva. Ez lényegesen kevesebb lenne, mint a jelenlegi 6*71 lekért szám. A koncepció kulcsszava: inkrementális adatfrissítés. Ha megvalósítjuk az ötletet, akkor figyelni kell arra, hogy az aktuális/utolsó évben az adatok akár másodpercenként is változhatnak.

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 tematikájához kötődik (ha a swing GUI-ra koncentrálunk és az adatok helyi fájlrendszerből elérhetők), és a Java EE szoftverfejlesztő tanfolyam tematikájához kapcsolódik (ha az adatokat közvetlenül a webről olvassuk).

Letöltés szimuláció

letöltés logó

letöltés logóLetöltési folyamatot szimulálunk. A paraméterek rugalmasan beállíthatóak. Előre beállított mennyiségű adatot, párhuzamos szálakon/folyamatokon keresztül töltünk le, miközben mérjük az eltelt időt. A folyamatok állapota lehet inaktív, aktív és befejezett. Az aktív folyamatok esetében megjelenő százalék fejezi ki, hogy a folyamat hol tart a rá jutó részfeladat végrehajtásával. Összesített formában követhetjük a hiányzó és a letöltött adat mennyiségét MB-onként és százalékosan is. A folyamat szimulációjához grafikus felületű Java kliensprogram készült, egyszerű GUI komponensekkel (nyomógomb, címke, folyamatindikátor, másképpen JButton, JLabel, JProgressBar swing komponensek).

Az alábbi animáció bemutatja a letöltés szimulációját:

letölés szimuláció

A konkrét paraméterek: 128 MB-nyi adatot töltünk le 256 párhuzamos szálon/folyamaton keresztül, így egy-egy részfeladat 0,5 MB-nyi adat letöltését jelenti. Minden értéket/mérőszámot egész számként ábrázolunk, akár százalékhoz tartozik, akár mértékegységként MB vagy s. A változások – és egyben a frissítés is – 5 ezredmásodpercként történnek a GUI-n.

A Java SE szoftverfejlesztő tanfolyamunkon, a szakmai modul Objektumorientált programozás témakörét követő 29-36. óra Grafikus felhasználói felület alkalmain már tudunk egyszerűbb szimulációs programot tervezni, kódolni, tesztelni. A Java EE szoftverfejlesztő tanfolyamunkon, a szakmai modul 5-8. óra Szálkezelés, párhuzamosság alkalommal többféle elosztott stratégiát ismertetünk, és a 17-24. óra Socket és RMI alapú kommunikáció alkalommal pedig megvalósíthatjuk többféle protokoll szerint a hálózati kapcsolatot, letöltést/feltöltést.

Elosztott alkalmazások esetén többféleképpen is modellezhető és kialakítható a rendszer architektúrája. Elosztott lehet maga a hálózat, a számítási folyamat, az algoritmus. Elosztott objektumok kommunikálhatnak egyenrangúnak tekinthető P2P szerepkörben vagy szerver/kliens oldalon, és több dolog/elem/hardver/szoftver/komponens együttműködéseként is megvalósulhat elosztott alkalmazás. A hálózati kommunikáció folyamatát valamilyen protokoll határozza meg, amit minden komponens ismer és így meghatározott szabályrendszer szerint működik.

Hardver szinten elosztottak a többprocesszoros rendszerek. Szoftveresen elosztott például egy moduláris vállalatirányítási rendszer, illetve a mobilalkalmazások többsége. Tipikus háromrétegű webalkalmazás esetén külön szerver nyújtja az adatbázishoz kapcsolódó szolgáltatásokat, a felhasználó számítógépén található a böngészőben futó/megjelenő kliensprogram/weboldal és a kettő között a felhő rétegben lehet a funkcionálisan elosztott alkalmazáslogika (például validálás, titkosítás, tömörítés, autentikáció, autorizáció).

A feladat könnyen általánosítható, például:

  • Egy keresési feladatot oldjunk meg az állományrendszerben! Kereshetünk egy konkrét nevű fájlt, adott kiterjesztésű fájlt, joker karakterekkel paraméterezett nevű fájlt/mappát, adott méretű állományt, adott dátum előtt létrehozott fájlt… Az állományrendszer bejárása rekurzív módon történik. A gyökérben lévő mappánként külön, esetleg második szinten lévő mappánként külön indíthatók szálak, párhuzamos folyamatok. Ha egyetlen találat elegendő, akkor bármelyik szál pozitív visszajelzésére minden szál leállítható. A feladatnál nagy eséllyel nagyon különböző méretű mappákon és eltérő mélységű mappaszerkezeteken kell végighaladni, így erre érdemes lehet optimalizálni, de ez már nagyon más szintje ennek a problémának.
  • Active Directory szerkezetben keressünk elérhető nyomtatókat a hálózaton!
  • Elosztott számítási hálózatként működik/működött a SETI@home. Koncepciójának lényege, hogy egy hatalmas feladatot nem nagyon drága szuperszámítógépeken, hanem olcsó gépek ezrein, százezrein, vagy akár millióin végeztetjük el, amelyek jelentős szabad kapacitással (pl. processzoridővel, átmeneti tárhellyel) rendelkeznek és egyébként is csatlakoznak a világhálóra.
  • Hasonlóan elosztott működésű a torrent protokoll. A kliensek/szálak az állományokat több kisebb darabban/szeletben töltik le, természetesen párhuzamosítva. Minden csomópont megkeresi a hiányzó részhez a lehető leggyorsabb kapcsolatot, miközben saját maga is letöltésre kínálja fel a már letöltött fájldarabokat. A módszer nagyon jól beválik nagyméretű fájloknál, például videók esetében. Minél népszerűbb/keresettebb egy fájl, annál többen vesznek részt az elosztásában, ezáltal a letöltési folyamat gyorsabb, mintha mindenki egy központi szerverről töltené le ugyanazt (hiszen az informatikában minden korlátos, a sávszélesség is).
  • A képtömörítést végző algoritmusok is lehetnek elosztottak, ezáltal párhuzamosíthatóak. Például ha felosztjuk a képet 16*16-os méretű egymást nem átfedő részekre, akkor ezek egymástól függetlenül tömöríthetők.
  • A merevlemezek esetén korábban használatos defragmentáló szoftverek felhasználói felülete emlékeztet a mintafeladat ablakára.

Fontos szem előtt tartani, hogy a grafikus megjelenítés csupán a szimulációhoz tartozó – annak megértéséhez szükséges – reprezentáció, így teljesen független lehet a folyamatok valós működésétől.

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

Denevérek a barlangban

DenevérekÉvekkel ezelőtt hálózatos Java EE esettanulmányt akartunk készíteni Lengyel Borisz kollégával. Ötleteltünk: milyen technológiával és hogyan kommunikáljon egymással a szerver és a kliens(ek). A távoli metódushívás (Remote Method Invocation) mellett döntöttünk és elkészült a denevérek a barlangban projekt, amely evolúciós projektként azóta több változatot is megélt. A felhasználói felület (barlang) betölt néhány képet (denevér kliensek), amelyek a szerver segítségével mozognak.

Ismertetjük a tervezés folyamatát, a kliens és szerver funkcióit részletesen, végül ötleteket adunk a továbbfejlesztésre.

A főbb feladatokat így határoztuk meg:

  • az RMI kommunikációs módszer megismertetése,
  • az RMI szolgáltatás reprezentálása látványos grafikus/swinges klienssel,
  • alternatíva nyújtása a TCP protokoll közvetlenül csatlakozó socket-jére.

Elkészítettük az alábbi osztálydiagramot (persze ez nem az első változat):

Denevérek a barlangban - Osztálydiagram

A szerver és kliens funkcióit megvalósító osztályok/interfészek feladatait így határoztuk meg:

BarlangDenevérInterfész interfész:

  • véletlen 5 és 10 közötti a denevérek száma,
  • méretek a GUI-hoz.

Denevér osztály:

  • megvalósítja az RMI kliens funkciót,
  • JLabel leszármazott, külső képfájlt tölt be ( bat.jpg),
  • egyedi azonosítója van,
  • eldönti mozgásának irányát (4) és léptékét (3), mintha ultrahangot adna,
  • a szerver megadja neki, hogy az új helyre elmozdulhat-e,
  • saját magát képes mozgatni.

Pozíció interfész:

  • öröklődik a java.rmi.Remote interfészből,
  • két távolról hívható metódus fejét tartalmazza.

BarlangSzerver osztály:

  • megvalósítja az RMI szerver funkciót,
  • implementálja a Pozíció interfészt,
  • JFrame leszármazott,
  • figyel arra, hogy a denevérek ne mozogjanak ki a barlangból.

BarlangFelület osztály:

  • JFrame leszármazott,
  • GUI az RMI kliensek megjelenítéséhez.

BarlangSzerverTérkép osztály:

  • JPanel leszármazott,
  • GUI a szerveren a kliensek mozgásának követésére.

Ha futtatjuk az elkészült szerver és kliens programot, akkor ezt láthatjuk:

Denevérek a barlangban - animáció

A fejlesztés és tesztelés közben sok-sok továbbfejlesztési ötletet/javaslatot fogalmaztunk meg:

  • háttérkép a barlangról,
  • a háttérkép megvalósíthat labirintust, koordináta-rendszert,
  • átlátszó illetve egyedi képfájlok a denevéreknek,
  • a denevérek mozgásának tetszőleges iránya (360°),
  • a denevérek mozgásának egyedi léptéke,
  • a denevérek figyeljenek egymásra (ne ütközzenek össze),
  • a denevérek figyeljenek a környezetükre (ne ütközzenek bele sziklákba, cseppkövekbe),
  • a szerver követheti a denevérek útvonalát,
  • a szerver archiválhat, szerializálhat, készíthet statisztikát.

A bejegyzéshez tartozó – több lépésben továbbfejlesztett – forráskódot ILIAS e-learning tananyagban tesszük elérhetővé tanfolyamaink résztvevői számára.

A feladat a Java EE szoftverfejlesztő tanfolyam 21-24. óra: RMI alapú kommunikáció alkalmához kapcsolódik.

Koch-görbe rajzolása

Koch-görbe

Koch-görbeA Koch-görbe egyike a legrégebben ismert egyszerű fraktáloknak. Mint ilyen, önhasonlóan rekurzív. Az önhasonlóság azt jelenti, hogy az ábra tetszőleges részét felnagyítva mindig hasonló/ugyanolyan részek jelennek meg (a méretaránytól függetlenül). Az n=1 szinten a Koch-görbe kiindulópontja egy szabályos háromszög. A n+1-edik szinten az n-edik szinten található szakaszokat harmadoljuk, és a középső szakasz helyére egy harmad akkora háromszög két szárát illesztjük (az alapját kihagyjuk). Ezt rekurzívan folytatva kapjuk meg a Koch-görbét, másképpen Koch-féle hópelyhet.

Írtam egy egyszerű Java programot, amely n=1-től 9-ig paraméterezhetően kirajzolja a Koch-görbét egy grafikus felületre. Így működik:

Koch-görbe rajzolását bemutató program működése

A program elkészítéséhez néhány alapvető dolgot kell csupán tudni:

  • Vászontechnikával tudunk swing GUI felületre ( Graphics osztályú g objektum) rajzolni, ahol a koordináta-rendszer origója egy téglalap alakú terület bal felső csúcsa, X jobbra növekszik, Y pedig lefelé növekszik.
  • Kétféle szín áll rendelkezésre: háttérszín (most Color.WHITE), illetve rajzolószín (most Color.BLUE).
  • A rajzoláshoz grafikai primitíveket használhatunk, például pont, szakasz, téglalap, ellipszis. Szakaszt két végpontjának koordinátáival tudunk rajzolni a drawLine() metódussal.
  • Be kell állítani a vászon méreteit, azaz annak a komponensnek ( JPanel-ből öröklött KochPanel osztályú pnKoch objektum) a méreteit, amelyre ráfeszül a vászon.
  • Egy Slider osztályú sSzint nevű vezérlőobjektum ChangeListener figyelőinterfész stateChanged() eseménykezelő metódust implementáló objektumával paraméterezzük a rajzolást 1-től 9-ig.
  • A pnKoch objektumnak küldött repaint() üzenet/metódushívás meghívja a felüldefiniált paintComponent() metódust.

A szakasz négy darab harmad akkora szakaszra osztását a megfelelően paraméterezett rekurzív metódushívások oldják meg az alábbi lépéseket követve:

Koch-görbe rajzolásának fázisai

A rekurzív rajzolást a koch() metódus végzi el, ahol a fraktál szabályának megfelelően szakaszharmadolás és a szükséges pontok koordinátáinak (szakaszok végpontjai) kiszámítása történik:

A Koch-görbének van néhány érdekes tulajdonsága:

  • kerülete minden rekurzív lépésben minden határon túl növekszik, azaz a végtelenhez tart,
  • területe véges, hiszen minden rekurzív lépésben belefér a háromszög köré írható körbe,
  • dimenziója tört, ~ 1,261859.

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 szakmai moduljának 9-12. óra: Metódusok, rekurzió alkalomra építő 29-36. Grafikus felhasználói felület alkalomhoz kötődik.

Kockadobás kliens-szerver alkalmazás

Fejlesszünk elosztott, hálózatos, datagram alapú üzenetküldéssel megvalósított Java alkalmazást!

A kockadobás kliens egyszerre két szabályos dobókockával dob, amit ezerszer megismétel és a dobott számok összegét datagram típusú üzenetküldéssel folyamatosan elküldi a szervernek. A szerver localhost-on fut és egy megadott porton keresztül várja a klienstől. A szerver és a kliens egyaránt szálkezelést alkalmazó konzolos alkalmazás.

A projektben van egy swing GUI-s alkalmazás, amely JFreeChart oszlopdiagramon – folyamatosan frissítve – megjeleníti az összesített adatokat, mindez a szerver üzenetküldésével irányítva (amint beérkezik egy dobott (2-12-ig) összeg).

A kommunikációnak – a lehetőségekhez képes – biztonságosnak és – a hálózati adatforgalmat tekintve – takarékosnak kell lennie! Ennek részeként szükséges egy azonosító és egy egyszerű szabály (protokoll).

Tekintsük át mondatszerűen a szálkezelést használó kliens és szerver kommunikációhoz kötődő feladatait:

Ezek működését összefogja egy központi vezérlőosztály és a programok az alábbiak szerint működnek együtt:

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

A feladat a Java EE szoftverfejlesztő tanfolyam 1-8. óra: Elosztott alkalmazások, webszolgáltatások, szálkezelés, párhuzamosság alkalmához kapcsolódik.