2026. június 26., péntek

Járványok terjedésének modellezése

A járványok terjedésének modellezésére a legelterjedtebb matematikai eszköz az úgynevezett SIR (Fogékony, Fertőző, Gyógyult) modell. Ezzel a dinamikus rendszerrel szimulálható a betegség terjedése, a csúcspontok elérése és a lefolyás időtartama.A kipusztulás (amikor mindenki megfertőződik és belehal) egy speciális, végzetes forgatókönyv, ami akkor következik be, ha a betegség halálozási rátája \(100\%\)
-----------
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

# 1. A modell paraméterei
N = 8000000000              # Kezdeti összlakosság (pl. 8 milliárd)
I0 = 1                      # Kezdeti fertőzöttek száma
R0 = 0                      # Kezdeti gyógyultak/halottak száma
S0 = N - I0 - R0            # Kezdeti fogékonyak száma

beta = 0.4                  # Fertőzési ráta (kontaktusok száma * fertőzési esély)
gamma = 0.1                 # Átlagos gyógyulási ráta (itt: 1/10 nap)
mortality_rate = 1.0        # Halálozási ráta (1.0 = minden fertőzött meghal)

# 2. A differenciálegyenlet-rendszer (SIR modell)
def sir_model(y, t, N, beta, gamma, mortality):
    S, I, R = y
    
    # Fogékonyak számának változása
    dSdt = -beta * S * I / N
    
    # Fertőzöttek számának változása
    dIdt = (beta * S * I / N) - (gamma * I)
    
    # Gyógyultak és halottak számának változása
    dRdt = gamma * I * mortality
    
    return dSdt, dIdt, dRdt

# 3. Időtartomány meghatározása (pl. 300 nap)
t = np.linspace(0, 300, 301)

# 4. A szimuláció futtatása
y0 = S0, I0, R0
ret = odeint(sir_model, y0, t, args=(N, beta, gamma, mortality_rate))
S, I, R = ret.T

# 5. Eredmények vizualizációja
plt.figure(figsize=(10, 6))
plt.plot(t, S, 'b', alpha=0.7, linewidth=2, label='Fogékony (Susceptible)')
plt.plot(t, I, 'r', alpha=0.7, linewidth=2, label='Fertőzött (Infected)')
plt.plot(t, R, 'k', alpha=0.7, linewidth=2, label='Elhunyt (Dead/Removed)')

plt.title('Járvány terjedése és az emberiség kipusztulása', fontsize=14)
plt.xlabel('Idő (nap)', fontsize=12)
plt.ylabel('Népesség', fontsize=12)
plt.ylim(0, N + N*0.1)
plt.legend(loc='best')
plt.grid(True, linestyle='--', alpha=0.6)
plt.show()

# 6. Mennyi ideig tart?
# Megkeressük azt a napot, amikor a fertőzöttek száma 0 alá csökken
infection_days = np.where(I < 1)[0]
if len(infection_days) > 0:
    end_day = np.max(infection_days)
    print(f"A szimuláció szerint a járvány lefolyása: {end_day} nap.")
else:
    print("A járvány nem ért véget a vizsgált időszakon belül.")
---------
A járvány 5 év alatt teljesen kiírtja az emberi fajt.
------------
Könyvek
https://mek.oszk.hu/08400/08435/08435.pdf
https://mtmi.unideb.hu/pluginfile.php/554/mod_resource/content/3/thinkcspy3.pdf

Atomtámadás hatásának modellezése

Az alábbi Python program a nukleáris fegyverek hatásait (hőhatás, lökéshullám, kezdeti sugárzás) modellezi a  cube-root scalingot  alkalmazva. A program kiszámítja az egyes pusztítási zónák sugarait egy megadott robbanási energia alapján:
---------
import math

class NuclearExplosionModel:
    def __init__(self, yield_ktons):
        """
        :param yield_ktons: A robbanás ereje kilotonnában (pl. 15 = Hiroshima)
        """
        self.yield_ktons = yield_ktons
        # Skálázási tényező (cube-root scaling)
        self.scale_factor = math.pow(self.yield_ktons, 1/3)

    def calculate_fireball_radius(self):
        """Tűzgömb sugara (hőhatás kezdete) méterben."""
        return 670 * self.scale_factor

    def calculate_blast_overpressure_radius(self, psi=5):
        """
        Lökéshullám hatótávolsága méterben.
        Alapértelmezetten az 5 PSI (súlyos épületkárok és emberi sérülések) zónát számolja.
        """
        if psi == 20: # 20 PSI: Vasbeton épületek megsemmisülése
            return 370 * self.scale_factor
        elif psi == 5: # 5 PSI: Átlagos épületek összeomlása
            return 740 * self.scale_factor
        elif psi == 1: # 1 PSI: Ablaküvegek betörése
            return 2130 * self.scale_factor
        return 0

    def calculate_radiation_radius(self, dose_Sv=5):
        """
        Kezdeti ionizáló sugárzás hatótávolsága méterben (5 Sv halálos dózis).
        """
        if dose_Sv == 5:
            return 1100 * self.scale_factor
        return 0

    def print_report(self):
        print(f"--- Atomcsapás Modell: {self.yield_ktons} kt TNT ---")
        print(f"1. Tűzgömb sugara: ~{self.calculate_fireball_radius():.2f} m")
        print(f"2. Lökéshullám (20 PSI - Teljes pusztulás): ~{self.calculate_blast_overpressure_radius(20):.2f} m")
        print(f"3. Lökéshullám (5 PSI - Épületek dőlnek): ~{self.calculate_blast_overpressure_radius(5):.2f} m")
        print(f"4. Lökéshullám (1 PSI - Ablakok törnek): ~{self.calculate_blast_overpressure_radius(1):.2f} m")
        print(f"5. Ionizáló sugárzás (5 Sv - Halálos): ~{self.calculate_radiation_radius(5):.2f} m")

# Modell futtatása példa adattal (pl. 50 kilotonnás robbanás)
if __name__ == "__main__":
    nuke = NuclearExplosionModel(yield_ktons=50)
    nuke.print_report()
------------
--- Atomcsapás Modell: 50 kt TNT ---
1. Tűzgömb sugara: ~2468.30 m
2. Lökéshullám (20 PSI - Teljes pusztulás): ~1363.09 m
3. Lökéshullám (5 PSI - Épületek dőlnek): ~2726.18 m
4. Lökéshullám (1 PSI - Ablakok törnek): ~7846.99 m
5. Ionizáló sugárzás (5 Sv - Halálos): ~4052.43 m
----------

import numpy as np
import matplotlib.pyplot as plt

def nuklearis_modell(hatohato_kt, robbanasi_magassag_m=0):
    """
    Atomeffektusok számítása (egyszerűsített skálázási törvények alapján).
    hatohato_kt: Robbanóerő kilotonnában
    robbanasi_magassag_m: Felszíni robbanás esetén 0
    """
    # Hatósugarak számítása (közelítő empirikus képletek)
    # Tűzgolyó sugara (km)
    tuzgolyo = 0.16 * (hatohato_kt ** 0.38)
    
    # 20 psi (súlyos épületkárok, zóna közepe)
    psi_20 = 0.45 * (hatohato_kt ** 0.33)
    
    # 5 psi (közepes épületkárok, légnyomás)
    psi_5 = 0.98 * (hatohato_kt ** 0.33)
    
    # 1 psi (ablaküveg törések, könnyű sérülések)
    psi_1 = 2.45 * (hatohato_kt ** 0.33)
    
    # Hősugárzás (3. fokozatú égési sérülések)
    ho_sugar = 1.0 * (hatohato_kt ** 0.41)

    return {
        'tuzgolyo': tuzgolyo,
        'psi_20': psi_20,
        'psi_5': psi_5,
        'psi_1': psi_1,
        'ho_sugar': ho_sugar
    }

def szimulacio_megjelenites(hatohato_kt):
    adatok = nuklearis_modell(hatohato_kt)
    
    # Vizuális körök beállítása
    sugarak = [
        ('Tűzgolyó (minden elpárolog)', adatok['tuzgolyo'], 'darkred'),
        ('20 psi Túlnyomás (pusztító)', adatok['psi_20'], 'red'),
        ('5 psi Túlnyomás (súlyos kár)', adatok['psi_5'], 'orange'),
        ('Hősugárzás (3. fokú égés)', adatok['ho_sugar'], 'gold'),
        ('1 psi Túlnyomás (ablakok törnek)', adatok['psi_1'], 'yellow')
    ]

    fig, ax = plt.subplots(figsize=(8, 8))
    ax.set_facecolor('lightgray')

    # Körök rajzolása
    for nev, sugar, szin in reversed(sugarak):
        circle = plt.Circle((0, 0), sugar, color=szin, alpha=0.5, label=f"{nev} ({sugar:.2f} km)")
        ax.add_patch(circle)

    # Célpont (epicentrum)
    ax.plot(0, 0, 'kX', markersize=10, label="Epicentrum (becsapódási pont)")

    # Grafikon beállítások
    max_sugar = adatok['psi_1'] * 1.2
    ax.set_xlim(-max_sugar, max_sugar)
    ax.set_ylim(-max_sugar, max_sugar)
    ax.set_aspect('equal')
    ax.set_title(f"Atomcsapás szimulációja ({hatohato_kt} kt robbanóerő)\n Hatósugarak kilométerben", fontsize=14)
    ax.set_xlabel("X távolság (km)")
    ax.set_ylabel("Y távolság (km)")

    # Jelmagyarázat és rács
    ax.legend(loc='upper right', bbox_to_anchor=(1.35, 1))
    ax.grid(True, linestyle='--', alpha=0.6)
    
    plt.tight_layout()
    plt.show()

# --- Szimuláció futtatása ---
# Példa egy tipikus kisebb taktikai atomfegyverre (pl. 15 kilotonna - Hirosima méret)
valasztott_kt = 15 
print(f"{valasztott_kt} kilotonnás nukleáris robbanás hatásainak vizualizációja...")
szimulacio_megjelenites(valasztott_kt)
---------------
15 kilotonnás nukleáris robbanás hatásainak vizualizációja...
------------------
Könyvek
https://mek.oszk.hu/08400/08435/08435.pdf
https://mtmi.unideb.hu/pluginfile.php/554/mod_resource/content/3/thinkcspy3.pdf

A mohácsi csata sztochasztikus determinisztikus harcászati szimulációja

A mohácsi csata (1526. augusztus 29.) modellezése kiváló példa a sztochasztikus (véletlen faktorokat is tartalmazó) események és a determinisztikus harcászati szabályok kombinálására objektumorientált (OOP) Python programozásban. Az alábbi komplex, mégis átlátható mintakód a csata főbb fázisait (tüzérségi támadás, lovasroham, gyalogsági harc) szimulálja le, figyelembe véve a létszámot, a terepviszonyokat és a véletlenszerű harci eseményeket (morál, taktikai döntések). A szimuláció főbb lépései (OOP megközelítésben):Egység (Unit): Osztály a seregek (magyar és oszmán) csapatainak (gyalogság, lovasság, tüzérség) reprezentálására.Hadsereg (Army): Kezeli az egységeket, összesíti a morált és a létszámot.Csata (Battle): Szimulálja a fázisokat (köröket), ahol a sebzés a létszám, a fegyverzet és a szerencsefaktor alapján kerül kiszámításra. A mohácsi csata taktikai modellezését Pythonban legkönnyebben egy objektumorientált szimulációval (OOP) vagy egy ügynökalapú modellező keretrendszerrel (pl. Mesa) valósíthatjuk meg. Az alábbiakban egy olyan leegyszerűsített, de harcászatilag szemléletes Python-példát mutatok be, amely az alapvető tényezőket (létszám, fegyverzet, terep, morál) veszi alapul.Koncepcionális modell. A harcászati szimuláció az alábbi főbb paramétereket veszi figyelembe:Egységek (Units): Név, létszám, morál, sebzés (tűzerő/közelharc) és védelem.Interakció: A csata körökre (turn) van osztva. Minden körben a szembenálló felek támadást indítanak egymás ellen, figyelembe véve a veszteségeket és a morál csökkenését.A csata legfőbb taktikai elemei – mint a magyar lovasság elsöprő erejű rohama vagy a török janicsárok tűzfegyvereinek hatékonysága és a tüzérség – a megfelelő statisztikai értékekkel modellezhetők .
------------
import random

class Egyseg:
    def __init__(self, nev, letszam, tamadas_ero, vedelem, tipus):
        self.nev = nev
        self.letszam = letszam
        self.alap_letszam = letszam
        self.tamadas_ero = tamadas_ero
        self.vedelem = vedelem
        self.tipus = tipus # 'gyalogsag', 'lovas', 'tuzerseg'
        self.moral = 1.0 # 0.0 és 1.0 között

    def tamad(self, celpont):
        if self.letszam <= 0:
            return 0
        
        # Alapsebzés
        sebzes = int(self.letszam * self.tamadas_ero * random.uniform(0.8, 1.2))
        
        # Taktikai módosítók (pl. lovasroham gyalogság ellen)
        if self.tipus == 'lovas' and celpont.tipus == 'gyalogsag':
            sebzes = int(sebzes * 1.5)
        elif self.tipus == 'tuzerseg':
            sebzes = int(sebzes * 1.8)

        # Védelem és morál levonása
        elszivott_sebzes = max(0, sebzes - int(celpont.vedelem * 0.5))
        elszivott_sebzes = int(elszivott_sebzes * self.moral)
        
        # Sebzés alkalmazása a célponton
        celpont.letszam = max(0, celpont.letszam - elszivott_sebzes)
        return elszivott_sebzes

    def serules(self, mertek):
        self.letszam = max(0, self.letszam - mertek)
        # Morál csökkenése a veszteségek arányában
        self.moral = max(0.2, self.letszam / self.alap_letszam)


class Hadsereg:
    def __init__(self, nev):
        self.nev = nev
        self.egysegek = []

    def hozzaad_egyseg(self, egyseg):
        self.egysegek.append(egyseg)

    def elo_egysegek(self):
        return [e for e in self.egysegek if e.letszam > 0]

    def ossz_letszam(self):
        return sum(e.letszam for e in self.egysegek)

class MohacsiCsataSzimulacio:
    def __init__(self):
        # Magyar sereg adatai (becslések alapján)
        self.magyarok = Hadsereg("Magyar Királyi Sereg")
        self.magyarok.hozzaad_egyseg(Egyseg("Könnyűlovasság", 4000, 1.2, 10, 'lovas'))
        self.magyarok.hozzaad_egyseg(Egyseg("Nehézlovasság", 5000, 2.0, 30, 'lovas'))
        self.magyarok.hozzaad_egyseg(Egyseg("Gyalogság", 15000, 0.8, 15, 'gyalogsag'))
        self.magyarok.hozzaad_egyseg(Egyseg("Tüzérség (Ágyúk)", 85, 3.0, 5, 'tuzerseg'))

        # Oszmán sereg adatai (becslések alapján)
        self.torokok = Hadsereg("Oszmán Birodalmi Sereg")
        self.torokok.hozzaad_egyseg(Egyseg("Akıncı (Könnyűlovasság)", 7000, 1.1, 12, 'lovas'))
        self.torokok.hozzaad_egyseg(Egyseg("Szpáhi (Nehézlovasság)", 8000, 2.2, 35, 'lovas'))
        self.torokok.hozzaad_egyseg(Egyseg("Janicsárok (Gyalogság)", 12000, 1.6, 25, 'gyalogsag'))
        self.torokok.hozzaad_egyseg(Egyseg("Szultáni Gárda és Tüzérség", 8000, 2.5, 40, 'tuzerseg'))

    def inditas(self):
        print("=== A MOHÁCSI CSATA (1526. augusztus 29.) MODELLEZÉSE ===\n")
        
        # 1. Fázis: Tüzérségi párbaj
        print("--- 1. FÁZIS: Tüzérségi tűzváltás ---")
        self.csata_faze("Tüzérség")

        # 2. Fázis: Lovasrohamok
        print("\n--- 2. FÁZIS: Lovasroham és összecsapás ---")
        self.csata_faze("lovas")

        # 3. Fázis: Általános gyalogsági harc és visszavonulás
        print("\n--- 3. FÁZIS: Gyalogsági harc és a csata vége ---")
        self.csata_faze("gyalogsag")

        # Eredmény hirdetése
        self.eredmeny_hirdetes()

    def csata_faze(self, fegyvernem_szures):
        for m_egyseg in self.magyarok.elo_egysegek():
            if fegyvernem_szures == "Tüzérség" and m_egyseg.tipus != "tuzerseg": continue
            if fegyvernem_szures == "lovas" and m_egyseg.tipus != "lovas": continue
            if fegyvernem_szures == "gyalogsag" and m_egyseg.tipus != "gyalogsag": continue

            for t_egyseg in self.torokok.elo_egysegek():
                if fegyvernem_szures == "Tüzérség" and t_egyseg.tipus != "tuzerseg": continue
                if fegyvernem_szures == "lovas" and t_egyseg.tipus != "lovas": continue
                
                sebzes = m_egyseg.tamad(t_egyseg)
                print(f"{m_egyseg.nev} támadja a(z) {t_egyseg.nev} egységet. Oszmán veszteség: {sebzes} fő.")

        # Visszacsapás
        for t_egyseg in self.torokok.elo_egysegek():
            for m_egyseg in self.magyarok.elo_egysegek():
                sebzes = t_egyseg.tamad(m_egyseg)
                print(f"{t_egyseg.nev} támadja a(z) {m_egyseg.nev} egységet. Magyar veszteség: {sebzes} fő.")

        print(f"Állás - Magyarok: {self.magyarok.ossz_letszam()} fő | Oszmánok: {self.torokok.ossz_letszam()} fő")

    def eredmeny_hirdetes(self):
        print("\n=== CSATA VÉGE ===")
        m_maradek = self.magyarok.ossz_letszam()
        t_maradek = self.torokok.ossz_letszam()

        print(f"Magyar seregek túlélői: {m_maradek} harcos.")
        print(f"Oszmán seregek túlélői: {t_maradek} harcos.")

        if m_maradek > t_maradek:
            print("GYŐZELEM: A magyar sereg nyerte a csatát!")
        elif m_maradek < t_maradek:
            print("VERESÉG: Az oszmán sereg győzedelmeskedett (történelmi hűség).")
        else:
            print("Döntetlen! A csatatér vértől ázva elhagyatott.")

# A szimuláció futtatása
if __name__ == "__main__":
    szim = MohacsiCsataSzimulacio()
    szim.inditas()
-------------------
=== A MOHÁCSI CSATA (1526. augusztus 29.) MODELLEZÉSE ===

--- 1. FÁZIS: Tüzérségi tűzváltás ---
Tüzérség (Ágyúk) támadja a(z) Szultáni Gárda és Tüzérség egységet. Oszmán veszteség: 469 fő.
Akıncı (Könnyűlovasság) támadja a(z) Könnyűlovasság egységet. Magyar veszteség: 8324 fő.
Akıncı (Könnyűlovasság) támadja a(z) Nehézlovasság egységet. Magyar veszteség: 6282 fő.
Akıncı (Könnyűlovasság) támadja a(z) Gyalogság egységet. Magyar veszteség: 10298 fő.
Akıncı (Könnyűlovasság) támadja a(z) Tüzérség (Ágyúk) egységet. Magyar veszteség: 7419 fő.
Szpáhi (Nehézlovasság) támadja a(z) Gyalogság egységet. Magyar veszteség: 22574 fő.
Állás - Magyarok: 0 fő | Oszmánok: 34531 fő

--- 2. FÁZIS: Lovasroham és összecsapás ---
Állás - Magyarok: 0 fő | Oszmánok: 34531 fő

--- 3. FÁZIS: Gyalogsági harc és a csata vége ---
Állás - Magyarok: 0 fő | Oszmánok: 34531 fő

=== CSATA VÉGE ===
Magyar seregek túlélői: 0 harcos.
Oszmán seregek túlélői: 34531 harcos.
VERESÉG: Az oszmán sereg győzedelmeskedett (történelmi hűség).
------------------
import random

class Hadsereg:
    def __init__(self, nev, gyalogsag, lovassag, agyuk):
        self.nev = nev
        self.gyalogsag = gyalogsag
        self.lovassag = lovassag
        self.agyuk = agyuk
        self.moral = 1.0 # Kezdeti morál

    @property
    def ossz_ero(self):
        return self.gyalogsag + (self.lovassag * 1.5) + (self.agyuk * 10)

    def veszteseg(self, szazalek):
        self.gyalogsag = int(self.gyalogsag * (1 - szazalek))
        self.lovassag = int(self.lovassag * (1 - szazalek))
        self.agyuk = int(self.agyuk * (1 - szazalek))

class MohacsiCsataSzimulacio:
    def __init__(self):
        # Történelmi adatok alapján meghatározott kezdeti létszámok
        self.magyarok = Hadsereg("Magyar Királyság", 13000, 13000, 85)
        self.torokok = Hadsereg("Oszmán Birodalom", 45000, 20000, 300)

    def csata_inditasa(self):
        print("--- MOHÁCSI CSATA SZIMULÁCIÓ (1526. AUGUSZTUS 29.) ---")
        
        # 1. FÁZIS: Tomori taktikája - Magyar lovasroham a ruméliai hadtest ellen
        self.fzis_1_tamadas()
        
        # 2. FÁZIS: Janicsárok puskatüze és török ellentámadás
        self.fzis_2_janicsar_vedelem()
        
        # 3. FÁZIS: Végső felmorzsolódás
        self.fzis_3_befejezes()

    def fzis_1_tamadas(self):
        print("\n[1. Fázis] A magyar hadsereg (Tomori Pál) támadást indít a ruméliai seregek ellen.")
        # A magyarok kezdeményeznek, előnyben a lovasság
        esely = min(0.85, self.magyarok.ossz_ero / self.torokok.ossz_ero)
        if random.random() < esely:
            print("-> A magyar lovasroham áttöri a ruméliaiak első vonalát!")
            self.torokok.veszteseg(0.15)
        else:
            print("-> A török védvonalak tartanak.")

    def fzis_2_janicsar_vedelem(self):
        print("\n[2. Fázis] Az oszmán janicsárok megkezdik a puskatüzet, az anatóliai erők bekerítenek.")
        # A török tüzérség és a janicsárok túlereje érvényesül
        esely = min(0.9, self.torokok.ossz_ero / self.magyarok.ossz_ero)
        if random.random() < esely:
            print("-> A janicsárok puskatüze megakasztja a magyar rohamot, a törökök ellentámadásba lendülnek.")
            self.magyarok.veszteseg(0.40)
        else:
            print("-> A magyarok hősiesen tartják pozícióikat.")

    def fzis_3_befejezes(self):
        print("\n[3. Fázis] A csata lezárása és a menekülés.")
        self.magyarok.veszteseg(0.60) # Történelmi megsemmisülés
        self.torokok.veszteseg(0.10)
        
        print("\n--- CSATA VÉGE ---")
        print(f"Magyar seregek megmaradt harcosai: {self.magyarok.gyalogsag + self.magyarok.lovassag} fő.")
        print(f"Oszmán seregek megmaradt harcosai: {self.torokok.gyalogsag + self.torokok.lovassag} fő.")
        print("\nEredmény: Döntő oszmán győzelem. Magyarország hadereje megsemmisült, II. Lajos király a Csele-patakba fulladt.")

# A szimulacio futtatasa
szim = MohacsiCsataSzimulacio()
szim.csata_inditasa()
-----------------
--- MOHÁCSI CSATA SZIMULÁCIÓ (1526. AUGUSZTUS 29.) ---

[1. Fázis] A magyar hadsereg (Tomori Pál) támadást indít a ruméliai seregek ellen.
-> A magyar lovasroham áttöri a ruméliaiak első vonalát!

[2. Fázis] Az oszmán janicsárok megkezdik a puskatüzet, az anatóliai erők bekerítenek.
-> A magyarok hősiesen tartják pozícióikat.

[3. Fázis] A csata lezárása és a menekülés.

--- CSATA VÉGE ---
Magyar seregek megmaradt harcosai: 10400 fő.
Oszmán seregek megmaradt harcosai: 49725 fő.

Eredmény: Döntő oszmán győzelem. Magyarország hadereje megsemmisült, II. Lajos király a Csele-patakba fulladt.
-----------
import random

class Egyseg:
    def __init__(self, nev, letszam, tamadas, vedelem, moral):
        self.nev = nev
        self.letszam = letszam
        self.alap_letszam = letszam
        self.tamadas = tamadas
        self.vedelem = vedelem
        self.moral = moral
        self.allapot = "Harcol"

    def tamad(self, celpont):
        if self.allapot == "Futás" or self.allapot == "Megsemmisült":
            return 0

        sebzes = int(self.tamadas * self.letszam * (self.moral / 100))
        elszenvedett_sebzes = max(0, sebzes - celpont.vedelem)
        celpont.veszit(elszenvedett_sebzes)
        return elszenvedett_sebzes

    def veszit(self, veszteseg):
        if veszteseg > 0:
            self.letszam = max(0, self.letszam - veszteseg)
            veszteseg_szazalek = (veszteseg / self.alap_letszam) * 100
            self.moral = max(10, self.moral - veszteseg_szazalek)

            if self.letszam == 0:
                self.allapot = "Megsemmisült"
            elif self.moral < 30:
                self.allapot = "Futás"

    @property
    def veszteseg(self):
        return self.alap_letszam - self.letszam

magyar_tuzerseg = Egyseg("Magyar tüzérség és gyalogság", 4000, tamadas=120, vedelem=20, moral=80)
magyar_lovas = Egyseg("Magyar nehézlovasság", 10000, tamadas=250, vedelem=50, moral=90)
magyar_zaszlok = [magyar_tuzerseg, magyar_lovas]

torok_elcsapat = Egyseg("Török előhad (Ruméliaiak)", 15000, tamadas=100, vedelem=30, moral=70)
torok_janicsar = Egyseg("Janicsárok (Tűzfegyverek)", 12000, tamadas=220, vedelem=40, moral=95)
torok_szuzerseg = Egyseg("Oszmán tüzérség", 3000, tamadas=150, vedelem=10, moral=85)
torok_zaszlok = [torok_elcsapat, torok_janicsar, torok_szuzerseg]

print("--- A mohácsi csata szimulációja indul ---\n")

for kor in range(1, 10):
    print(f"--- {kor}. Kör ---")

    for mg_egyseg in magyar_zaszlok:
        for tr_egyseg in torok_zaszlok:
            sebzes = mg_egyseg.tamad(tr_egyseg)
            print(f"{mg_egyseg.nev} támadja a következőt: {tr_egyseg.nev}. Okozat: {sebzes} veszteség.")

    for tr_egyseg in torok_zaszlok:
        for mg_egyseg in magyar_zaszlok:
            sebzes = tr_egyseg.tamad(mg_egyseg)
            print(f"{tr_egyseg.nev} támadja a következőt: {mg_egyseg.nev}. Okozat: {sebzes} veszteség.")

    print("\n--- Állapotok a kör végén ---")
    for egyseg in magyar_zaszlok + torok_zaszlok:
        print(f"{egyseg.nev} | Létszám: {egyseg.letszam} | Morál: {int(egyseg.moral)} | Státusz: {egyseg.allapot}")
    print("\n")

print("--- Szimuláció vége ---")
------------
--- A mohácsi csata szimulációja indul ---

--- 1. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 2. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 3. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 4. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 5. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 6. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 7. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 8. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült


--- 9. Kör ---
Magyar tüzérség és gyalogság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 383970 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 383960 veszteség.
Magyar tüzérség és gyalogság támadja a következőt: Oszmán tüzérség. Okozat: 383990 veszteség.
Magyar nehézlovasság támadja a következőt: Török előhad (Ruméliaiak). Okozat: 2249970 veszteség.
Magyar nehézlovasság támadja a következőt: Janicsárok (Tűzfegyverek). Okozat: 2249960 veszteség.
Magyar nehézlovasság támadja a következőt: Oszmán tüzérség. Okozat: 2249990 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Török előhad (Ruméliaiak) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Janicsárok (Tűzfegyverek) támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar tüzérség és gyalogság. Okozat: 0 veszteség.
Oszmán tüzérség támadja a következőt: Magyar nehézlovasság. Okozat: 0 veszteség.

--- Állapotok a kör végén ---
Magyar tüzérség és gyalogság | Létszám: 4000 | Morál: 80 | Státusz: Harcol
Magyar nehézlovasság | Létszám: 10000 | Morál: 90 | Státusz: Harcol
Török előhad (Ruméliaiak) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Janicsárok (Tűzfegyverek) | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült
Oszmán tüzérség | Létszám: 0 | Morál: 10 | Státusz: Megsemmisült

--- Szimuláció vége ---
-----------
Könyvek
https://mek.oszk.hu/08400/08435/08435.pdf
https://mtmi.unideb.hu/pluginfile.php/554/mod_resource/content/3/thinkcspy3.pdf

Valószínűség-számítás

Íme egy komplex, valós szimulációt megvalósító Python-kód, amely a véletlenszám-generálást (random modul), a véletlenszerű eseményeket (valószínűség-számítás) és a vizuális állapotkövetést kombinálja.Ez a program egy egyszerűsített szerencsejáték-szimulátor, amely modellezi a játékos egyenlegének változását, a nyerési esélyeket, és statisztikát készít a folyamatról.
---------------
import random
import time

def jatszma_szimulacio(Kezdo_egyenleg, Tet, Jatszmaksz_szam):
    """
    Komplex véletlenszám-alapú szimuláció:
    - Véletlen események modellezése (pl. veszteség, kis nyerés, jackpot).
    - Statisztikák és trendek számolása.
    """
    egyenleg = Kezdo_egyenleg
    nyeremenyek_szama = 0
    vesztesegek_szama = 0
    osszes_tet = 0
    legmagasabb_egyenleg = Kezdo_egyenleg
    
    print("--- Szimuláció indítása ---\n")
    
    for kor in range(1, Jatszmaksz_szam + 1):
        if egyenleg < Tet:
            print(f"{kor}. kör: Nincs elég egyenleg a játékhoz. A szimuláció véget ért.")
            break
            
        egyenleg -= Tet
        osszes_tet += Tet
        
        # Véletlen esemény generálása (0 és 1 közötti valószínűség)
        esemeny = random.random()
        
        # Események logikája súlyozott valószínűségek alapján
        if esemeny < 0.01:  # 1% esély a Jackpotra
            nyeremeny = Tet * 50
            egyenleg += nyeremeny
            nyeremenyek_szama += 1
            print(f"🌟 {kor}. kör: JACKPOT! Nyertél: {nyeremeny} Ft!")
        elif esemeny < 0.45:  # 44% esély sima nyereményre
            nyeremeny = Tet * 2
            egyenleg += nyeremeny
            nyeremenyek_szama += 1
            print(f"💰 {kor}. kör: Nyertél! Új egyenleg: {egyenleg} Ft")
        else:  # 55% esély a veszteségre
            vesztesegek_szama += 1
            print(f"❌ {kor}. kör: Nem nyertél. Egyenleg: {egyenleg} Ft")
            
        if egyenleg > legmagasabb_egyenleg:
            legmagasabb_egyenleg = egyenleg
            
        time.sleep(0.05)  # Késleltetés a valós idejű szimuláció érzetéhez

    # Eredmények összegzése
    print("\n" + "="*40)
    print("SZIMULÁCIÓ VÉGEREDMÉNYE")
    print("="*40)
    print(f"Kezdeti egyenleg: {Kezdo_egyenleg} Ft")
    print(f"Végső egyenleg: {egyenleg} Ft")
    print(f"Legmagasabb elért egyenleg: {legmagasabb_egyenleg} Ft")
    print(f"Összes megjátszott tét: {osszes_tet} Ft")
    
    # Nyerési arány számítása és nullával osztás kezelése
    nyeremeny_arany = (nyeremenyek_szama / (nyeremenyek_szama + vesztesegek_szama)) * 100
    print(f"Nyerési arány: {nyeremeny_arany:.2f}%")
    print("="*40)

# A program futtatása
if __name__ == "__main__":
    # Paraméterek beállítása
    Kezdo_egyenleg = 100000
    Tet_ertek = 1000
    Kori_szam = 50
    
    jatszma_szimulacio(Kezdo_egyenleg, Tet_ertek, Kori_szam)
------------
--- Szimuláció indítása ---

❌ 1. kör: Nem nyertél. Egyenleg: 99000 Ft
❌ 2. kör: Nem nyertél. Egyenleg: 98000 Ft
❌ 3. kör: Nem nyertél. Egyenleg: 97000 Ft
❌ 4. kör: Nem nyertél. Egyenleg: 96000 Ft
❌ 5. kör: Nem nyertél. Egyenleg: 95000 Ft
❌ 6. kör: Nem nyertél. Egyenleg: 94000 Ft
💰 7. kör: Nyertél! Új egyenleg: 95000 Ft
❌ 8. kör: Nem nyertél. Egyenleg: 94000 Ft
💰 9. kör: Nyertél! Új egyenleg: 95000 Ft
💰 10. kör: Nyertél! Új egyenleg: 96000 Ft
❌ 11. kör: Nem nyertél. Egyenleg: 95000 Ft
❌ 12. kör: Nem nyertél. Egyenleg: 94000 Ft
💰 13. kör: Nyertél! Új egyenleg: 95000 Ft
❌ 14. kör: Nem nyertél. Egyenleg: 94000 Ft
💰 15. kör: Nyertél! Új egyenleg: 95000 Ft
❌ 16. kör: Nem nyertél. Egyenleg: 94000 Ft
💰 17. kör: Nyertél! Új egyenleg: 95000 Ft
❌ 18. kör: Nem nyertél. Egyenleg: 94000 Ft
❌ 19. kör: Nem nyertél. Egyenleg: 93000 Ft
💰 20. kör: Nyertél! Új egyenleg: 94000 Ft
💰 21. kör: Nyertél! Új egyenleg: 95000 Ft
💰 22. kör: Nyertél! Új egyenleg: 96000 Ft
❌ 23. kör: Nem nyertél. Egyenleg: 95000 Ft
💰 24. kör: Nyertél! Új egyenleg: 96000 Ft
❌ 25. kör: Nem nyertél. Egyenleg: 95000 Ft
❌ 26. kör: Nem nyertél. Egyenleg: 94000 Ft
❌ 27. kör: Nem nyertél. Egyenleg: 93000 Ft
💰 28. kör: Nyertél! Új egyenleg: 94000 Ft
❌ 29. kör: Nem nyertél. Egyenleg: 93000 Ft
💰 30. kör: Nyertél! Új egyenleg: 94000 Ft
❌ 31. kör: Nem nyertél. Egyenleg: 93000 Ft
❌ 32. kör: Nem nyertél. Egyenleg: 92000 Ft
❌ 33. kör: Nem nyertél. Egyenleg: 91000 Ft
❌ 34. kör: Nem nyertél. Egyenleg: 90000 Ft
💰 35. kör: Nyertél! Új egyenleg: 91000 Ft
💰 36. kör: Nyertél! Új egyenleg: 92000 Ft
💰 37. kör: Nyertél! Új egyenleg: 93000 Ft
❌ 38. kör: Nem nyertél. Egyenleg: 92000 Ft
❌ 39. kör: Nem nyertél. Egyenleg: 91000 Ft
💰 40. kör: Nyertél! Új egyenleg: 92000 Ft
💰 41. kör: Nyertél! Új egyenleg: 93000 Ft
❌ 42. kör: Nem nyertél. Egyenleg: 92000 Ft
💰 43. kör: Nyertél! Új egyenleg: 93000 Ft
💰 44. kör: Nyertél! Új egyenleg: 94000 Ft
💰 45. kör: Nyertél! Új egyenleg: 95000 Ft
💰 46. kör: Nyertél! Új egyenleg: 96000 Ft
💰 47. kör: Nyertél! Új egyenleg: 97000 Ft
💰 48. kör: Nyertél! Új egyenleg: 98000 Ft
❌ 49. kör: Nem nyertél. Egyenleg: 97000 Ft
❌ 50. kör: Nem nyertél. Egyenleg: 96000 Ft

========================================
SZIMULÁCIÓ VÉGEREDMÉNYE
========================================
Kezdeti egyenleg: 100000 Ft
Végső egyenleg: 96000 Ft
Legmagasabb elért egyenleg: 100000 Ft
Összes megjátszott tét: 50000 Ft
Nyerési arány: 46.00%
========================================

Szerepjáték

 Ez a program egy interaktív RPG (szerepjáték) harc szimulátort valósít meg, amely a beépített random modullal vezérli a kritikus találatokat, a véletlen sebzéseket és az ellenfél akcióit.
--------------
import random

class Karakter:
    def __init__(self, nev, hp, alapsebzes):
        self.nev = nev
        self.hp = hp
        self.alapsebzes = alapsebzes

    def tamad(self, cel):
        # 10% esély a kritikus csapásra (dupla sebzés)
        kritikus = random.random() < 0.10
        sebzes = self.alapsebzes + random.randint(-5, 5) # Véletlen szórás
        
        if kritikus:
            sebzes *= 2
            print(f"⚔️ {self.nev} KRITIKUS CSAPÁST mér {cel.nev}-re! {sebzes} sebzés.")
        else:
            print(f"⚔️ {self.nev} megtámadja {cel.nev}-t. {sebzes} sebzés.")
            
        cel.hp = max(0, cel.hp - sebzes)
        print(f"   {cel.nev} hátralévő életereje: {cel.hp} HP\n")

    is_alive = property(lambda self: self.hp > 0)


def jatek_inditas():
    hos = Karakter(nev="Hős", hp=100, alapsebzes=20)
    szorny = Karakter(nev="Goblin", hp=80, alapsebzes=15)
    
    print("A csata elkezdődik!\n")

    while hos.is_alive and szorny.is_alive:
        # Hős köre
        hos.tamad(szorny)
        if not szorny.is_alive:
            print(f"🏆 {szorny.nev} elesett. Te nyertél!")
            break

        # Szörny köre
        szorny.tamad(hos)
        if not hos.is_alive:
            print(f"💀 A {szorny.nev} legyőzött. GAME OVER.")
            break

        # Kényszerített várakozás a fordulatok között a jobb olvashatóságért
        import time
        time.sleep(1)

if __name__ == "__main__":
    jatek_inditas()
------------
A csata elkezdődik!

⚔️ Hős megtámadja Goblin-t. 23 sebzés.
   Goblin hátralévő életereje: 57 HP

⚔️ Goblin megtámadja Hős-t. 15 sebzés.
   Hős hátralévő életereje: 85 HP

⚔️ Hős megtámadja Goblin-t. 23 sebzés.
   Goblin hátralévő életereje: 34 HP

⚔️ Goblin megtámadja Hős-t. 19 sebzés.
   Hős hátralévő életereje: 66 HP

⚔️ Hős megtámadja Goblin-t. 16 sebzés.
   Goblin hátralévő életereje: 18 HP

⚔️ Goblin megtámadja Hős-t. 11 sebzés.
   Hős hátralévő életereje: 55 HP

⚔️ Hős megtámadja Goblin-t. 20 sebzés.
   Goblin hátralévő életereje: 0 HP

🏆 Goblin elesett. Te nyertél!

Valutaárfolyam-lekérdező és -átváltó alkalmazás

Egy komplex Python program több programozási koncepció (objektum-orientáltság, fájlkezelés, API integráció és hibakezelés) kombinációja.Az alábbi példa egy valós idejű valutaárfolyam-lekérdező és -átváltó alkalmazás, amely egy külső webszervertől (pl. ExchangeRate-API) kéri le az adatokat, kezeli az esetleges hálózati hibákat, és logolja a tranzakciókat egy szöveges fájlba.
---------
from datetime import datetime
import os
import requests


class ValutaKalkulator:

    def __init__(self, api_key):
        self.api_key = api_key
        self.base_url = (
            f"https://exchangerate-api.com{self.api_key}/latest/"
        )

    def arfolyam_lekeres(self, valuta):
        """Lekérdezi az aktuális árfolyamokat a megadott alapvalutához."""
        try:
            url = f"{self.base_url}{valuta}"
            valasz = requests.get(url)
            valasz.raise_for_status()  # Hibakezelés (pl. 404 vagy 500 esetén)
            adat = valasz.json()
            return adat["conversion_rates"]
        except requests.exceptions.RequestException as e:
            print(f"\nHiba történt a hálózati kapcsolat során: {e}")
            return None
        except KeyError:
            print("\nHiba: Az API válasz nem tartalmazza az árfolyamokat.")
            return None

    def penzvaltas(self, osszeg, honnan, hova):
        """Kiszámolja az átváltott összeget és logolja azt."""
        print(f"Adatok lekérése a(z) {honnan} valutáról...")
        arfolyamok = self.arfolyam_lekeres(honnan)

        if arfolyamok and hova in arfolyamok:
            arfolyam = arfolyamok[hova]
            valtott_osszeg = osszeg * arfolyam

            # Eredmény formázása matematikailag megfelelő kerekítéssel ($2$ tizedesjegyre)
            eredmeny = round(valtott_osszeg, 2)

            # Tranzakció logolása fájlba
            self.tranzakcio_mentese(osszeg, honnan, eredmeny, hova, arfolyam)
            return eredmeny
        else:
            print(f"A(z) {hova} valuta nem található az árfolyamlistában.")
            return None

    def tranzakcio_mentese(
        self, osszeg, honnan, valtott_osszeg, hova, arfolyam
    ):
        """Privát metódus a tranzakciók fájlba írásához."""
        fajl_nev = "tranzakciok.txt"
        idopont = datetime.now().strftime("%Y-%m-%d %H:%M:%S")

        with open(fajl_nev, "a", encoding="utf-8") as f:
            f.write(
                f"{idopont} - {osszeg} {honnan} átváltva {valtott_osszeg} {hova} értékre (Árfolyam: {arfolyam})\n"
            )


# Főprogram
if __name__ == "__main__":
    API_KULCS = "IDE_IRJA_AZ_API_KULCSAT"  # Helyettesítse be a saját kulcsával

    # Példa futtatás
    kalkulator = ValutaKalkulator(api_key=API_KULCS)

    try:
        osszeg_input = float(input("Kérem adja meg az átváltani kívánt összeget: "))
        honnan_input = input("Melyik valutából vált (pl. EUR): ").upper()
        hova_input = input("Melyik valutába vált (pl. HUF): ").upper()

        eredmeny = kalkulator.penzvaltas(
            osszeg_input, honnan_input, hova_input
        )

        if eredmeny is not None:
            print(
                f"\nEredmény: {osszeg_input} {honnan_input} = {eredmeny} {hova_input}"
            )
            print("A tranzakció sikeresen mentve a 'tranzakciok.txt' fájlba.")
    except ValueError:
        print("Hiba: Kérjük, hogy az összegnél számot adjon meg.")
--------------
Kérem adja meg az átváltani kívánt összeget: 100
Melyik valutából vált (pl. EUR): EUR
Melyik valutába vált (pl. HUF): HUF
Adatok lekérése a(z) EUR valutáról...
Eredmény: 100.0 EUR = 38975.0 HUF
A tranzakció sikeresen mentve a 'tranzakciok.txt' fájlba.

Könyvtárkezelő alkalmazás

Ez a komplex példaprogram egy olyan parancssoros könyvtárkezelő alkalmazást mutat be, amely ötvözi az objektumorientált programozást (OOP), a fájlkezelést (JSON formátum) és a modern típusannotációkat.A kód tartalmazza a hibakezelést, a dinamikus keresést, a szűrést és az objektumok kezelését.

------------
import json
import os
from typing import List, Optional

# 1. Osztály (OOP)
class Konyv:
    def __init__(self, cim: str, szerzo: str, ev: int, mufaj: str):
        self.cim = cim
        self.szerzo = szerzo
        self.ev = ev
        self.mufaj = mufaj
        self.kolcsonozve = False

    def __str__(self) -> str:
        allapot = "Kölcsönözhető" if not self.kolcsonozve else "Kölcsönzés alatt"
        return f"{self.cim} - {self.szerzo} ({self.ev}) [{self.mufaj}] | Státusz: {allapot}"

    def to_dict(self) -> dict:
        return self.__dict__

# 2. Üzleti logika osztály
class Konyvtar:
    def __init__(self, fajl_nev: str = "konyvtar.json"):
        self.fajl_nev = fajl_nev
        self.konyvek: List[Konyv] = []
        self.betoltes()

    def hozzaad(self, konyv: Konyv) -> None:
        self.konyvek.append(konyv)
        self.mentes()
        print(f"'{konyv.cim}' sikeresen hozzáadva a könyvtárhoz.")

    def kereses(self, kulcsszo: str) -> List[Konyv]:
        kulcsszo = kulcsszo.lower()
        talalatok = []
        for k in self.konyvek:
            if kulcsszo in k.cim.lower() or kulcsszo in k.szerzo.lower():
                talalatok.append(k)
        return talalatok

    def kolcsonzes(self, cim: str) -> None:
        for k in self.konyvek:
            if k.cim.lower() == cim.lower():
                if k.kolcsonozve:
                    print(f"Hiba: A(z) '{cim}' már ki van kölcsönözve.")
                else:
                    k.kolcsonozve = True
                    self.mentes()
                    print(f"Sikeres kölcsönzés: '{cim}'.")
                return
        print("Hiba: A könyv nem található.")

    def mentes(self) -> None:
        with open(self.fajl_nev, 'w', encoding='utf-8') as f:
            json.dump([k.to_dict() for k in self.konyvek], f, ensure_ascii=False, indent=4)

    def betoltes(self) -> None:
        if os.path.exists(self.fajl_nev):
            try:
                with open(self.fajl_nev, 'r', encoding='utf-8') as f:
                    adatok = json.load(f)
                    self.konyvek = [Konyv(**k) for k in adatok]
            except json.JSONDecodeError:
                print("Hiba a mentett fájl olvasásakor, új lista létrehozva.")
                self.konyvek = []

# 3. Főprogram (CLI)
def main():
    konyvtar = Konyvtar()
    
    while True:
        print("\n--- KÖNYVTÁR MENÜ ---")
        print("1. Új könyv hozzáadása")
        print("2. Összes könyv listázása")
        print("3. Keresés (cím vagy szerző alapján)")
        print("4. Könyv kölcsönzése")
        print("5. Kilépés")
        
        valasztas = input("Válasszon egy opciót (1-5): ").strip()
        
        if valasztas == '1':
            cim = input("Cím: ")
            szerzo = input("Szerző: ")
            try:
                ev = int(input("Kiadási év: "))
                mufaj = input("Műfaj: ")
                uj_konyv = Konyv(cim, szerzo, ev, mufaj)
                konyvtar.hozzaad(uj_konyv)
            except ValueError:
                print("Hiba: Az évszámnak számnak kell lennie!")
                
        elif valasztas == '2':
            if not konyvtar.konyvek:
                print("A könyvtár üres.")
            else:
                for idx, konyv in enumerate(konyvtar.konyvek, 1):
                    print(f"{idx}. {konyv}")
                    
        elif valasztas == '3':
            kulcsszo = input("Keresőkifejezés: ")
            talalatok = konyvtar.kereses(kulcsszo)
            if talalatok:
                for konyv in talalatok:
                    print(konyv)
            else:
                print("Nincs találat.")
                
        elif valasztas == '4':
            cim = input("A kikölcsönözni kívánt könyv címe: ")
            konyvtar.kolcsonzes(cim)
            
        elif valasztas == '5':
            print("Viszontlátás!")
            break
        else:
            print("Érvénytelen választás. Kérjük, adjon meg egy számot 1 és 5 között.")

if __name__ == "__main__":
    main()
-------------------
--- KÖNYVTÁR MENÜ ---
1. Új könyv hozzáadása
2. Összes könyv listázása
3. Keresés (cím vagy szerző alapján)
4. Könyv kölcsönzése
5. Kilépés
Válasszon egy opciót (1-5): 

Banki Rendszer

Íme egy komplex, objektumorientált Python-példa egy egyszerűsített Banki Rendszerre, amely bemutatja az osztályok, a kompozíció (összetett objektumok), a hibakezelés és az adatvédelmi elvek (tokozás) gyakorlati használatát.A kód kezeli a számlanyitást, a befizetést, a tranzakciókat, azonosítja a felhasználókat, és a tranzakciós díjakat \(O(\log n)\) matematikai és logikai lépésekkel számítja ki (ha összetett kamatos kamatról vagy növekményről lenne szó).
-------------
import datetime

class Tranzakcio:
    """Egyedi tranzakciókat leíró osztály."""
    def __init__(self, tipus: str, osszeg: float):
        self.tipus = tipus
        self.osszeg = osszeg
        self.datum = datetime.datetime.now()

    def __str__(self):
        return f"{self.datum.strftime('%Y-%m-%d %H:%M:%S')} - {self.tipus}: {self.osszeg} Ft"


class Bankszla:
    """Banki számlát kezelő osztály (tokozás: a _egyenleg védett)."""
    def __init__(self, szamlaszam: str, tulajdonos: str, kezdo_egyenleg: float = 0.0):
        self.szamlaszam = szamlaszam
        self.tulajdonos = tulajdonos
        self._egyenleg = kezdo_egyenleg
        self.tranzakciok = []

    def penz_befizetes(self, osszeg: float):
        if osszeg <= 0:
            raise ValueError("A befizetett összegnek pozitívnak kell lennie!")
        self._egyenleg += osszeg
        self.tranzakciok.append(Tranzakcio("Befizetés", osszeg))

    def penz_felvetel(self, osszeg: float):
        if osszeg <= 0:
            raise ValueError("A felvett összegnek pozitívnak kell lennie!")
        if osszeg > self._egyenleg:
            raise ValueError("Nincs fedezet a tranzakcióhoz!")
        self._egyenleg -= osszeg
        self.tranzakciok.append(Tranzakcio("Kifizetés", osszeg))

    def egyenleg_lekerdezes(self) -> float:
        return self._egyenleg

    def tranzakcio_elozmeny(self):
        print(f"\n--- Tranzakciós előzmény: {self.szamlaszam} ---")
        for tranzakcio in self.tranzakciok:
            print(tranzakcio)


class Bank:
    """Több számlát összefogó komplex rendszer."""
    def __init__(self, nev: str):
        self.nev = nev
        self.szamlak = {}

    def uj_szamla(self, szamla: Bankszla):
        self.szamlak[szamla.szamlaszam] = szamla
        print(f"Új számla létrehozva: {szamla.szamlaszam} ({szamla.tulajdonos})")

    def utalas(self, honnan_szamla: str, hova_szamla: str, osszeg: float):
        if honnan_szamla not in self.szamlak or hova_szamla not in self.szamlak:
            raise ValueError("Érvénytelen számlaszám!")
        
        # A Bank osztály hozzáfér a számlák műveleteihez
        forrás = self.szamlak[honnan_szamla]
        cél = self.szamlak[hova_szamla]

        try:
            forrás.penz_felvetel(osszeg)
            cél.penz_befizetes(osszeg)
            print(f"\nSikeres utalás: {osszeg} Ft -> {honnan_szamla} számláról {hova_szamla} számlára.")
        except ValueError as e:
            print(f"Utalás sikertelen: {e}")


# --- A program futtatása ---
if __name__ == "__main__":
    # 1. Bank létrehozása
    my_bank = Bank("MegaBank")

    # 2. Számlák nyitása
    szamla1 = Bankszla("1111-2222", "Kovács Anna", 50000.0)
    szamla2 = Bankszla("3333-4444", "Szabó Béla", 20000.0)

    my_bank.uj_szamla(szamla1)
    my_bank.uj_szamla(szamla2)

    # 3. Tranzakciók végrehajtása
    try:
        szamla1.penz_befizetes(15000)
        my_bank.utalas("1111-2222", "3333-4444", 25000)
    except ValueError as error:
        print(f"Hiba történt: {error}")

    # 4. Egyenlegek lekérdezése és történet
    print(f"\nKovács Anna egyenlege: {szamla1.egyenleg_lekerdezes()} Ft")
    szamla1.tranzakcio_elozmeny()
-----------------------
Új számla létrehozva: 1111-2222 (Kovács Anna)
Új számla létrehozva: 3333-4444 (Szabó Béla)

Sikeres utalás: 25000 Ft -> 1111-2222 számláról 3333-4444 számlára.

Kovács Anna egyenlege: 40000.0 Ft

--- Tranzakciós előzmény: 1111-2222 ---
2026-06-26 14:39:46 - Befizetés: 15000 Ft
2026-06-26 14:39:46 - Kifizetés: 25000 Ft

Receptkönyv

Az alábbiakban egy olyan recept- és hozzávalókezelő rendszert láthatsz, amely objektumokat használ, kezeli az adatok mentését (JSON formátumban), és szűri a recepteket.
--------------
import json
import os

class Hozzavalo:
    """Egyetlen hozzávalót reprezentáló osztály."""
    def __init__(self, nev: str, mennyiseg: str):
        self.nev = nev
        self.mennyiseg = mennyiseg

    def __str__(self):
        return f"{self.nev} - {self.mennyiseg}"


class Recept:
    """Egy receptet és a hozzá tartozó logikát leíró osztály."""
    def __init__(self, nev: str, elkeszitesi_ido: int):
        self.nev = nev
        self.elkeszitesi_ido = elkeszitesi_ido # percben
        self.hozzavalok = []

    def hozzaad_hozzavalo(self, hozavalo: Hozzavalo):
        self.hozzavalok.append(hozavalo)

    def __str__(self):
        hozzavalok_lista = "\n  ".join(str(h) for h in self.hozzavalok)
        return f"Recept: {self.nev} ({self.elkeszitesi_ido} perc)\nHozzávalók:\n  {hozzavalok_lista}"


class ReceptKonyv:
    """A recepteket kezelő és fájlba mentő/betöltő osztály."""
    def __init__(self, fajl_nev: str = "receptek.json"):
        self.fajl_nev = fajl_nev
        self.receptek = []

    def hozzaad_recept(self, recept: Recept):
        self.receptek.append(recept)

    def kereses_ido_alapjan(self, max_perc: int) -> list:
        """Visszaadja azokat a recepteket, amelyek elkészítése nem vesz igénybe több időt."""
        return [r for r in self.receptek if r.elkeszitesi_ido <= max_perc]

    def mentes_json(self):
        """Elmenti a recepteket egy JSON fájlba."""
        adatok = []
        for r in self.receptek:
            hozzavalok_dict = [{"nev": h.nev, "mennyiseg": h.mennyiseg} for h in r.hozzavalok]
            adatok.append({
                "nev": r.nev,
                "elkeszitesi_ido": r.elkeszitesi_ido,
                "hozzavalok": hozzavalok_dict
            })
        
        with open(self.fajl_nev, "w", encoding="utf-8") as f:
            json.dump(adatok, f, ensure_ascii=False, indent=4)
        print("Receptek sikeresen mentve!")

    def betoltes_json(self):
        """Betölti a recepteket a JSON fájlból."""
        if not os.path.exists(self.fajl_nev):
            print("A mentési fájl nem található.")
            return

        try:
            with open(self.fajl_nev, "r", encoding="utf-8") as f:
                adatok = json.load(f)
                self.receptek = []
                for elem in adatok:
                    recept = Recept(elem["nev"], elem["elkeszitesi_ido"])
                    for h in elem["hozzavalok"]:
                        recept.hozzaad_hozzavalo(Hozzavalo(h["nev"], h["mennyiseg"]))
                    self.receptek.append(recept)
            print("Receptek sikeresen betöltve!")
        except json.JSONDecodeError:
            print("Hiba történt: A mentési fájl sérült.")


# --- A program futtatása ---
if __name__ == "__main__":
    konyv = ReceptKonyv()

    # Új recept létrehozása és feltöltése
    recept1 = Recept("Paradicsomleves", 25)
    recept1.hozzaad_hozzavalo(Hozzavalo("Paradicsomlé", "1 liter"))
    recept1.hozzaad_hozzavalo(Hozzavalo("Cukor", "2 evőkanál"))
    recept1.hozzaad_hozzavalo(Hozzavalo("Só", "1 csipet"))

    recept2 = Recept("Rántotta", 10)
    recept2.hozzaad_hozzavalo(Hozzavalo("Tojás", "3 db"))
    recept2.hozzaad_hozzavalo(Hozzavalo("Vaj", "1 dkg"))

    konyv.hozzaad_recept(recept1)
    konyv.hozzaad_recept(recept2)

    # Receptek mentése
    konyv.mentes_json()

    # Keresés 15 percnél rövidebb receptekre
    print("\nGyors receptek (max 15 perc):")
    gyors_receptek = konyv.kereses_ido_alapjan(15)
    for r in gyors_receptek:
        print("-", r.nev)
--------------
Receptek sikeresen mentve!

Gyors receptek (max 15 perc):
- Rántotta

Aszinkron vagy párhuzamos feladatvégzés

Egy komplexebb Python program tipikusan több egymással együttműködő modulból (objektum-orientált tervezés), hibakezelésből, külső könyvtárak használatából és aszinkron vagy párhuzamos feladatvégzésből épül fel.Íme egy gyakorlati példa egy többszálú (multithreading) webes adatgyűjtő (crawler) és adatfeldolgozó alkalmazásra, amely objektum-orientált felépítést alkalmaz:
---------------
import requests
import concurrent.futures
import logging
from urllib.parse import urlparse
from html.parser import HTMLParser
import time

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class SimpleHTMLParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.in_title = False
        self.title = ""
        self.paragraphs = []
        self.current_p = []
        self.in_p = False

    def handle_starttag(self, tag, attrs):
        if tag == "title":
            self.in_title = True
        if tag == "p":
            self.in_p = True
            self.current_p = []

    def handle_endtag(self, tag):
        if tag == "title":
            self.in_title = False
        if tag == "p":
            self.in_p = False
            text = "".join(self.current_p).strip()
            if text:
                self.paragraphs.append(text)

    def handle_data(self, data):
        if self.in_title:
            self.title += data
        if self.in_p:
            self.current_p.append(data)

class WebCrawler:
    def __init__(self, max_threads=5):
        self.max_threads = max_threads
        self.visited_urls = set()
        self.results = []

    def is_valid(self, url):
        parsed = urlparse(url)
        return bool(parsed.netloc) and bool(parsed.scheme)

    def scrape_page(self, url):
        logging.info(f"Oldal feldolgozása: {url}")
        try:
            response = requests.get(url, timeout=10)
            response.raise_for_status()

            parser = SimpleHTMLParser()
            parser.feed(response.text)

            title = parser.title.strip() if parser.title.strip() else "Nincs cím"
            paragraphs = parser.paragraphs

            return {
                "url": url,
                "title": title,
                "content_length": len(" ".join(paragraphs))
            }

        except requests.RequestException as e:
            logging.error(f"Hiba a(z) {url} letöltésekor: {e}")
            return None

    def crawl_site(self, start_urls):
        with concurrent.futures.ThreadPoolExecutor(max_workers=self.max_threads) as executor:
            future_to_url = {
                executor.submit(self.scrape_page, url): url
                for url in start_urls
                if url not in self.visited_urls
            }

            for future in concurrent.futures.as_completed(future_to_url):
                url = future_to_url[future]
                self.visited_urls.add(url)
                data = future.result()
                if data:
                    self.results.append(data)

if __name__ == "__main__":
    start_time = time.time()

    urls_to_crawl = [
        "https://python.org",
        "https://wikipedia.org",
        "https://github.com"
    ]

    crawler = WebCrawler(max_threads=3)
    crawler.crawl_site(urls_to_crawl)

    logging.info(f"Bejárt oldalak száma: {len(crawler.visited_urls)}")
    logging.info(f"Teljes futási idő: {time.time() - start_time:.2f} másodperc")

    for res in crawler.results:
        print(f"\nSikeres találat: {res['title']}\nURL: {res['url']}\nKarakterszám: {res['content_length']}")
----------------

2026-06-26 14:34:24,589 - INFO - Oldal feldolgozása: https://python.org
2026-06-26 14:34:24,589 - INFO - Oldal feldolgozása: https://wikipedia.org
2026-06-26 14:34:24,589 - INFO - Oldal feldolgozása: https://github.com
HTTPSConnectionPool(host='python.org', port=443): Max retries exceeded with url: / (Caused by NameResolutionError("HTTPSConnection(host='python.org', port=443): Failed to resolve 'python.org' ([Errno -3] Temporary failure in name resolution)"))
 HTTPSConnectionPool(host='wikipedia.org', port=443): Max retries exceeded with url: / (Caused by NameResolutionError("HTTPSConnection(host='wikipedia.org', port=443): Failed to resolve 'wikipedia.org' ([Errno -3] Temporary failure in name resolution)"))
 HTTPSConnectionPool(host='github.com', port=443): Max retries exceeded with url: / (Caused by NameResolutionError("HTTPSConnection(host='github.com', port=443): Failed to resolve 'github.com' ([Errno -3] Temporary failure in name resolution)"))
2026-06-26 14:34:24,592 - INFO - Bejárt oldalak száma: 3
2026-06-26 14:34:24,592 - INFO - Teljes futási idő: 0.00 másodperc