From b5fdbb32302055f28a6ba55d85442be58bb1906e Mon Sep 17 00:00:00 2001 From: Pc Date: Wed, 4 Jun 2025 19:50:18 +0200 Subject: [PATCH] Updating matches Updating players stats(not finished) Not tested --- FlaskWebProject/FlaskWebProject/fs_scraper.py | 51 +++++++++++++ FlaskWebProject/FlaskWebProject/lewy_db.py | 69 +++++++++++++++++- .../FlaskWebProject/lewy_globals.py | 4 +- FlaskWebProject/instance/lewangoalski.sqlite | Bin 0 -> 49152 bytes 4 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 FlaskWebProject/instance/lewangoalski.sqlite diff --git a/FlaskWebProject/FlaskWebProject/fs_scraper.py b/FlaskWebProject/FlaskWebProject/fs_scraper.py index f7b9178..070e247 100644 --- a/FlaskWebProject/FlaskWebProject/fs_scraper.py +++ b/FlaskWebProject/FlaskWebProject/fs_scraper.py @@ -4,6 +4,7 @@ import json import lewy_globals import requests import time +from sqlalchemy import func def safe_traverse(obj: dict, path: list, default=None): result = obj @@ -16,6 +17,21 @@ def safe_traverse(obj: dict, path: list, default=None): finally: return result +def get_stat_value(stats: dict, stat_id: str, field: str = "value", default=None): + """ + Bezpiecznie pobiera wartość z pola 'value' lub 'type' dla danego stat_id w strukturze 'stats'. + + :param stats: słownik ze statystykami + :param stat_id: ID statystyki jako string, np. "595" + :param field: 'value' lub 'type' + :param default: wartość domyślna zwracana, jeśli coś pójdzie nie tak + :return: wartość z pola lub default + """ + try: + return stats[stat_id][field] + except (KeyError, TypeError): + return default + class scraper: headers = { @@ -97,6 +113,7 @@ class scraper: # Jeśli nie, dodaj go w podobny sposób, jak # w sample_data_init() (w lewy_db.py). + page = 0 match_num = 0 while not stop_scraping: @@ -141,8 +158,42 @@ class scraper: # TODO: dodaj obiekt mecz do bazy (simple_insert_one(), simple_insert_many()) print(f"{c.OKCYAN}Nowy mecz ({match_num}){c.ENDC}: {match}") + + self.db.simple_insert_one("mecze", + zewnetrzne_id_meczu= safe_traverse(match, ["eventId"], default=""), + data= safe_traverse(match, ["eventStartTime"], default=func.now()), + gospodarze_id= safe_traverse(match, ["homeParticipant3CharName"], default=0), + gospodarze= safe_traverse(match, ["homeParticipantName"], default=""), + goscie_id= safe_traverse(match, ["awayParticipant3CharName"], default=0), + goscie= safe_traverse(match, ["awayParticipantName"], default=""), + gosp_wynik= safe_traverse(match, ["homeScore"], default=0), + gosc_wynik= safe_traverse(match, ["awayScore"], default=0), + sezon= safe_traverse(match, ["tournamentSeason"], default=""), + nazwa_turnieju= safe_traverse(match, ["tournamentTitle"], default=""), + skrocona_nazwa_turnieju=safe_traverse(match, ["tournamentTemplateShortCode"], default=""), + flaga= safe_traverse(match, ["flagId"], default=0), + + ) match_num += 1 + stats=safe_traverse(match, ["stats"], default=""), + + + self.db.increment_fields("sportowcy",zewnetrzne_id_sportowca, + ostatni_mecz= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca + ilosc_wystapien= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca + minut_gry= get_stat_value(stats, "595"), + gier_sum= 1 if get_stat_value(stats, "595") > 0 else 0 , + goli_sum= get_stat_value(stats, "596"), + asyst_sum= get_stat_value(stats, "541"), + interwencji_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca + nieobronionych_interwencji_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca + zoltych_kartek_sum= get_stat_value(stats, "599"), + czerwonych_kartek_sum= get_stat_value(stats, "600"), + wygranych_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca + wynik_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca + meczow_do_wynikow_sum= safe_traverse(match, ["eventId"], default=0), #TODO: Zaktualizuj statystyki sportowca + ) # TODO: Zaktualizuj statystyki sportowca diff --git a/FlaskWebProject/FlaskWebProject/lewy_db.py b/FlaskWebProject/FlaskWebProject/lewy_db.py index 2bf2ee9..96a60f8 100644 --- a/FlaskWebProject/FlaskWebProject/lewy_db.py +++ b/FlaskWebProject/FlaskWebProject/lewy_db.py @@ -307,6 +307,72 @@ class baza(): return 0 #return 1 + @exit_gracefully + def increment_fields(self, entity_type, record_id, **increments): + """ + Dodaje wartości do istniejących pól (np. goli_sum += 2). + + Użycie: + increment_fields(ldb.statystyki_sportowcow, 123, goli_sum=2, asyst_sum=1) + """ + if not isinstance(entity_type, str): + entity_type = entity_type.__name__ + + if entity_type not in self.entities: + print(f"Nieznany typ encji: {entity_type}") + return -1 + + model_class = self.entities[entity_type] + + print(f"[{round(time.time())}] INCREMENT") + + record = self.session.get(model_class, record_id) + if not record: + print(f"Rekord z ID {record_id} nie istnieje w tabeli {entity_type}") + return -1 + + for key, increment_value in increments.items(): + if hasattr(record, key): + current_value = getattr(record, key, 0) + setattr(record, key, current_value + increment_value) + else: + print(f"⚠️ Pole '{key}' nie istnieje w modelu '{entity_type}' – pomijam.") + + self.session.commit() + return 0 + @exit_gracefully + def simple_update_one(self, entity_type, record_id, **kwargs): + """ + Użycie: + simple_update_one(ldb.kluby, "polska", pelna_nazwa="Nowa Nazwa", skrocona_nazwa="NN") + + Aktualizuje pojedynczy rekord w bazie danych na podstawie ID. + """ + if not isinstance(entity_type, str): + entity_type = entity_type.__name__ + + if entity_type not in self.entities: + print(f"Nieznany typ encji: {entity_type}") + return -1 + + model_class = self.entities[entity_type] + + print(f"[{round(time.time())}] UPDATE") + + record = self.session.get(model_class, record_id) + if not record: + print(f"Rekord z ID {record_id} nie istnieje w tabeli {entity_type}") + return -1 + + for key, value in kwargs.items(): + if hasattr(record, key): + setattr(record, key, value) + else: + print(f"⚠️ Pole '{key}' nie istnieje w modelu '{entity_type}' – pomijam.") + + self.session.commit() + return 0 + @exit_gracefully def sample_data_init(self, override_safety_check=False): """ @@ -388,4 +454,5 @@ class baza(): session.commit() return 0 - return 1 \ No newline at end of file + + return 1 diff --git a/FlaskWebProject/FlaskWebProject/lewy_globals.py b/FlaskWebProject/FlaskWebProject/lewy_globals.py index 855f869..a4ad172 100644 --- a/FlaskWebProject/FlaskWebProject/lewy_globals.py +++ b/FlaskWebProject/FlaskWebProject/lewy_globals.py @@ -1,4 +1,4 @@ -from git import Repo # hash ostatniego commitu +#from git import Repo # hash ostatniego commitu import os import time import toml @@ -155,4 +155,4 @@ config = {} configfile = "config.toml" version = getCommitWithFailsafe() apiVersion = "1" -randomly_generated_passcode = 0 \ No newline at end of file +randomly_generated_passcode = 0 diff --git a/FlaskWebProject/instance/lewangoalski.sqlite b/FlaskWebProject/instance/lewangoalski.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..8814ee63890b82443ba4e9828cf80fa432abce4f GIT binary patch literal 49152 zcmeI2&2Qs27QpR%_^VT-H(z;-i_QY={sCQ2s-#9dcH=k&2El@0WX7YBEPC`&MFM(g ziy5@(p@&|3+y83+k^;RfNlUV%P+BFx?7{m21d--FK9axp9v?}~<;B?WD7t0Nig@Vn zjZYfQX5$|SH5!c;|9!@PlOOSZki77}&CGMzW2^DE?|wZL%13_*oo7dXb?&?0AKrDI z@4Y?xv#c5X`_2-0f6!_7DQ(`Ld*sHV77aq|zO{G|V*X6*B_oz=8rWSk$76vW;sCFx z9ufWZV|2SGGi^B6(0uq}tf9xWM900ZvA_;BnX~ZGXfoH%v>BRA=V)>@9)E_UI3fXC z*oH}z3K0!#>N$~3F*hZK@1t*rvy-ofc|&|!E?zpJ(#VoohEhP>(DjrO!}h2XP+NaP z@r^@PCUGM52wi_g@K)WxHrceGO2ZMexP!Pk&s2{|k9fz7&$mJ+2$v4A)#C|54ilY@ zr$df8gZi7<=;d(s3Y}}O(DBwS1L20#=}a4)O@vH{QkM+SOgq(P+T=vLtl@fTciXsV zS>eli9SFBmbgXLM8@&6X)$Wf*&0lbJ8b~9h;VY%>dZ8WXF?6#TZ=5!pY36!^ z>vpTpM$Lv{FX&yoXcOOK@?9+7>ZM#p9{#*q-uYpDAT#2}>*|b6J0-1iN@V%ff2*t7yBI5jDm^89 zXt*X*3Ps((zQYy~wGE^=eb|Np!1W0)Zj00KY&2mk>f00e*l5C8%|00;m9`2G(u z00e*l5C8%|00;m9AOHk_01yBIKw$R?!1w>%_c6>62mk>f00e*l5C8%|00;m9AOHk_ z0DS+47ytr500;m9AOHk_01yBIKmZ5;0U)sZ1mOI?`#y#l0s$ZZ1b_e#00KY&2mk>f z00e*l5cs(BywN(mYkYKj^n3T;o%`U4BXhv|%GLJi$pi!9ZlTnt$WTL$daWOQ+* zsY9X|b~%jo0?xGjn@~oxc=8|QNXq?b=6VCZDflNFH5-P#pm*`2O?;2Zcd>k{mvR|- z`15Lc=ZE!y%!nVat208*vecH89@fil^0T+U}hzQCYcGp!ux!&H>s;O9@9?f%6@^S3XneUWZ@ zO5Kra?A7x~svkQgt#e9b`PF}`tJ=F5D}yRMC46YOCQ}MU-N3%X77?`#qEykN5EIi2 z13N@7rqi)DoaFo}!aGx1HetgpvVfNcrA5OMMML_Z1zhXCG5x5N7!E* ze0SsWafzj@APYjBmTYQbtC;WP@WSHzt+XBrqoPZ`kqh}|H{V+^a8o~26p_46HjZOl zPh0cFIJ3qSoaz})RtBE<**whJE<&znSQZyq^tN?2YxSWI>e-cxXhkv2d9R+yOp_!n zc{qx#>sG?6g1*=42N#d7vWdyCqB5j9`}}0r5vM!x{eQpvd*kR|&;H)@?{ri=$n^&BsVMUy1U?ldU*G=UJ{4WJpL9zs^Qq!4K*~G+0hkV9asU7T literal 0 HcmV?d00001