33 Commits

Author SHA1 Message Date
afa666d2fd fix: scraper fix, add club info 2025-06-20 03:50:07 +02:00
b0ea0a836b scraper fix attempt 2025-06-20 01:19:48 +02:00
327aabde78 fix for goals 2025-06-16 23:21:34 +02:00
7ed241bc00 deleting some sections 2025-06-16 23:07:40 +02:00
ac2335a3bc one more 2025-06-16 23:00:38 +02:00
45dfd38f9a one fix for club stats 2025-06-16 22:57:19 +02:00
04b12d4657 fix: readd missing imports and funcs II 2025-06-15 04:59:37 +02:00
687bdedf88 fix: readd missing import 2025-06-15 04:52:37 +02:00
323a8b4973 Merge branch 'routes_using_api' 2025-06-15 04:50:27 +02:00
8bc1dcb876 feat: general improvements, show wins, losses, draws (broken for clubs) 2025-06-15 04:47:24 +02:00
fc5acd28f7 Revert "chore: prepare for rescraping"
This reverts commit fce1b69893.
this time it works
2025-06-13 12:32:38 +02:00
19e100b4b2 fix 2025-06-13 12:15:04 +02:00
fcf11d4a0d Revert "chore: prepare for rescraping"
This reverts commit fce1b69893.
2025-06-13 12:12:10 +02:00
fc1e636cfd feat: use api for matches 2025-06-13 12:04:25 +02:00
fce1b69893 chore: prepare for rescraping 2025-06-13 11:09:18 +02:00
7b457475b4 Merge branch 'frontend-fix' 2025-06-13 00:34:11 +02:00
8fb2a22c2a another one 2025-06-13 00:32:13 +02:00
d1f5f8f3f4 Merge branch 'frontend' 2025-06-13 00:31:57 +02:00
56e68ed751 fix: show only relevant matches for a given year 2025-06-13 00:31:19 +02:00
f96a3ed1f1 fix 2025-06-12 23:42:55 +02:00
416b2ccfe0 changing responsive design 2025-06-12 23:08:58 +02:00
00bbe05b1c feat: include club's full name in matches view 2025-06-12 22:35:04 +02:00
e373c6b274 hotfix: fixes /mecze endpoint not working (cause of a wrong API call) 2025-06-12 20:43:22 +02:00
e80ee6bf8f feat: return matches with respect to received sportsman id
also include a comment in the database model to include a relation
2025-06-12 20:36:10 +02:00
a25be482b0 matches from DB 2025-06-12 16:23:14 +02:00
4e8cb48c82 fix: safe_traverse renaming issue 2025-06-11 00:38:55 +02:00
bc82fcd6b8 chore: depend on safe_traverse from lewy_globals, add scraper cron job 2025-06-11 00:35:48 +02:00
5d238cb6b8 fix: general fixes to scraper, and db model
Co-authored-by: Noicei <kuba.baj@interia.pl>
2025-06-11 00:15:30 +02:00
fe4c9aab3d Merge branch 'ScraperV2' 2025-06-06 00:50:21 +02:00
9e8a60dfa1 chore: simplify expression, add an important todo note 2025-06-06 00:50:05 +02:00
7fe4e03945 fix: matches deafult data set to 2025 2025-06-05 22:12:48 +02:00
ffcfa12d4c static data for page 2025-06-05 22:07:29 +02:00
Pc
f7e80811a0 Updated Scraper 2025-06-05 21:41:31 +02:00
15 changed files with 12794 additions and 255 deletions

View File

@@ -1,23 +1,13 @@
from flask import session from flask import session
from lewy_db import baza as ldb from lewy_db import baza as ldb
from lewy_globals import colors as c from lewy_globals import colors as c
from lewy_globals import safeTraverse as safe_traverse
import json import json
import lewy_globals import lewy_globals
import requests import requests
import time import time
from sqlalchemy import func from sqlalchemy import func
def safe_traverse(obj: dict, path: list, default=None):
result = obj
try:
for x in path:
result = result[x]
except KeyError:
result = default
print(f"safe_traverse: error reading {' -> '.join(path)} - returning: {default}")
finally:
return result
class scraper: class scraper:
headers = { headers = {
@@ -59,21 +49,14 @@ class scraper:
def czy_mecz_istnieje(self, zewnetrzne_id_meczu: str): def czy_mecz_istnieje(self, zewnetrzne_id_meczu: str):
# mecz = db.simple_select_all(ldb.mecze, zewnetrzne_id_meczu=zewnetrzne_id_meczu)
# if mecz is not None and mecz != []:
# return True
# else:
# return False
return self.__czy_x_istnieje("mecze", zewnetrzne_id_meczu=zewnetrzne_id_meczu) return self.__czy_x_istnieje("mecze", zewnetrzne_id_meczu=zewnetrzne_id_meczu)
def czy_klub_istnieje(self, id_klubu: str): def czy_klub_istnieje(self, id_klubu: str):
# mecz = db.simple_select_all(ldb.mecze, zewnetrzne_id_meczu=zewnetrzne_id_meczu)
# if mecz is not None and mecz != []:
# return True
# else:
# return False
return self.__czy_x_istnieje("kluby", id_klubu=id_klubu) return self.__czy_x_istnieje("kluby", id_klubu=id_klubu)
def czy_nie_trzeba_pobierac_nowych_meczy_zawodnika(self, id_zawodnika: int, zewnetrzne_id_meczu: str):
return self.__czy_x_istnieje("sportowcy_w_meczach", id_zawodnika=id_zawodnika, zewnetrzne_id_meczu=zewnetrzne_id_meczu)
def id_na_imie_nazwisko_urodziny(self, zewnetrzne_id_sportowca: str = "MVC8zHZD"): def id_na_imie_nazwisko_urodziny(self, zewnetrzne_id_sportowca: str = "MVC8zHZD"):
""" """
Scraper z dykty xD Scraper z dykty xD
@@ -109,6 +92,7 @@ class scraper:
# TODO: Sprawdź, czy sportowiec istnieje w bazie. # TODO: Sprawdź, czy sportowiec istnieje w bazie.
# Jeśli nie, dodaj go w podobny sposób, jak # Jeśli nie, dodaj go w podobny sposób, jak
# w sample_data_init() (w lewy_db.py). # w sample_data_init() (w lewy_db.py).
# -- Jednak tego tak nie robimy, ponieważ nie uzyskamy wielu informacji.
id_zawodnika = self.db.get_id_zawodnika_by_zewnetrzne_id(zewnetrzne_id_sportowca) id_zawodnika = self.db.get_id_zawodnika_by_zewnetrzne_id(zewnetrzne_id_sportowca)
zawodnik = self.db.simple_select_all("sportowcy", zewnetrzne_id_zawodnika=zewnetrzne_id_sportowca)[0] zawodnik = self.db.simple_select_all("sportowcy", zewnetrzne_id_zawodnika=zewnetrzne_id_sportowca)[0]
@@ -131,11 +115,29 @@ class scraper:
home_club_id = safe_traverse(match, ["homeParticipantUrl"], default="non-existent-club-id") home_club_id = safe_traverse(match, ["homeParticipantUrl"], default="non-existent-club-id")
away_club_id = safe_traverse(match, ["awayParticipantUrl"], default="non-existent-club-id") away_club_id = safe_traverse(match, ["awayParticipantUrl"], default="non-existent-club-id")
# Sprawdź, czy mecz nie znajduje się już w bazie # ~Sprawdź, czy mecz nie znajduje się już w bazie~
if self.czy_mecz_istnieje(zewnetrzne_id_meczu=match_id): #
# UWAGA! Nie powinniśmy tego sprawdzać jak w komentarzu poniżej!
# To sprawdzenie powinno jedynie służyć zapobieganiu dodania istniejących meczy,
# natomiast istniejący mecz nie oznacza, że sportowiec ma już statystykę z niego!
# Przerwać scrapowanie należy wtedy, gdy znajdzie się statystykę sportowca
# z bieżącego meczu, a nie kiedy znajdzie się bieżący mecz w bazie!
#
# if self.czy_mecz_istnieje(zewnetrzne_id_meczu=match_id):
# stop_scraping = True
# break
#
# Rozwiązanie jest mocno nieefektywne przy scrapowaniu całej bazy od zera,
# ale rozwiąże przypadki, w których zawodnicy, których śledzimy, grali przeciwko sobie.
if self.czy_nie_trzeba_pobierac_nowych_meczy_zawodnika(id_zawodnika=id_zawodnika, zewnetrzne_id_meczu=match_id):
stop_scraping = True stop_scraping = True
break break
if self.czy_mecz_istnieje(zewnetrzne_id_meczu=match_id):
# Nie scrapuj istniejących meczy.
# Naturalnie, istniejący mecz nie musi oznaczać potrzeby zakończenia scrapowania.
continue
# Sprawdź, czy klub znajduje się już w bazie. Jeśli nie, # Sprawdź, czy klub znajduje się już w bazie. Jeśli nie,
# trzeba go dodać przed meczem. # trzeba go dodać przed meczem.
if not self.czy_klub_istnieje(id_klubu=home_club_id): if not self.czy_klub_istnieje(id_klubu=home_club_id):
@@ -151,10 +153,6 @@ class scraper:
pelna_nazwa=safe_traverse(match, ["awayParticipantName"]), pelna_nazwa=safe_traverse(match, ["awayParticipantName"]),
skrocona_nazwa=safe_traverse(match, ["awayParticipant3CharName"])) skrocona_nazwa=safe_traverse(match, ["awayParticipant3CharName"]))
# TODO: (opcjonalnie) zamień *słownik match* na *obiekt mecz*
# TODO: dodaj obiekt mecz do bazy (simple_insert_one(), simple_insert_many()) # TODO: dodaj obiekt mecz do bazy (simple_insert_one(), simple_insert_many())
print(f"{c.OKCYAN}Nowy mecz ({match_num}){c.ENDC}: {match}") print(f"{c.OKCYAN}Nowy mecz ({match_num}){c.ENDC}: {match}")
@@ -179,32 +177,50 @@ class scraper:
stats = safe_traverse(match, ["stats"], default="") stats = safe_traverse(match, ["stats"], default="")
zewnetrzne_id_meczu = safe_traverse(match, ["eventEncodedId"], default="") zewnetrzne_id_meczu = safe_traverse(match, ["eventEncodedId"], default="")
wygrana_str = safe_traverse(match, ["winLoseShort"], default="R").upper()
klub_zawodnika = "undefined"
# Zwycięstwo klubu zawodnika
if wygrana_str == "Z":
if safe_traverse(match, ["homeScore"], default=0) > safe_traverse(match, ["awayScore"], default=0):
klub_zawodnika = home_club_id
else:
klub_zawodnika = away_club_id
# Przegrana klubu zawodnika
elif wygrana_str == "P":
if safe_traverse(match, ["homeScore"], default=0) > safe_traverse(match, ["awayScore"], default=0):
klub_zawodnika = away_club_id
else:
klub_zawodnika = home_club_id
if stats != False: # gdy sportowiec był aktywny w meczu if stats != False: # gdy sportowiec był aktywny w meczu
print("todo :)") # print("todo :)")
# # TODO: self.db.simple_insert_one("sportowcy_w_meczach",
# self.db.simple_insert_one("sportowcy_w_meczach", id_zawodnika = id_zawodnika,
# id_zawodnika = id_zawodnika, zawodnik = zawodnik,
# zawodnik = zawodnik, zewnetrzne_id_meczu = zewnetrzne_id_meczu,
# zewnetrzne_id_meczu = zewnetrzne_id_meczu, # Uwaga! Czasami przygłupy z flashscore zwracają puste pole '' zamiast zera, np. do liczby strzelonych goli.
# # ODTĄD SIĘ NIE POKRYWA!!! POLA POWINNY SIĘ ZGADZAĆ Z TYM, CO JEST W LEWY_DB (konkretnie klasie sportowcy_w_meczach) # Dlatego int("0" + "") = int("0"), co zapobiegnie wysypaniu się przy int("").
# ostatni_mecz = self.db.get_id_meczu_by_zewnetrzne_id(zewnetrzne_id_meczu), czas_gry = int("0" + safe_traverse(stats, ["595", "value"], default="0").rstrip("'?")),
# ilosc_wystapien = 1 if int(safe_traverse(stats, ["595", "value"], default="0").rstrip("'")) > 0 else 0, goli = int("0" + safe_traverse(stats, ["596", "value"], default="0")),
# minut_gry = int(safe_traverse(stats, ["595", "value"], default="0").rstrip("'")), asyst = int("0" + safe_traverse(stats, ["541", "value"], default="0")),
# gier_sum = 1 if int(safe_traverse(stats, ["595", "value"], default="0").rstrip("'")) > 0 else 0, interwencje_bramkarza = 0,
# goli_sum = int(safe_traverse(stats, ["596", "value"], default="0")), suma_interwencji_na_bramke = 0,
# asyst_sum = int(safe_traverse(stats, ["541", "value"], default="0")), zolte_kartki = int("0" + safe_traverse(stats, ["599", "value"], default="0")),
# interwencji_sum = 0, czerwone_kartki = int("0" + safe_traverse(stats, ["600", "value"], default="0")),
# nieobronionych_interwencji_sum = 0, wygrana = {"Z": 1, "R": 0, "P": -1}.get(safe_traverse(match, ["winLoseShort"], default=""), 0),
# zoltych_kartek_sum = int(safe_traverse(stats, ["599", "value"], default="0")), wynik = safe_traverse(match, ["rating"], default=0) or 0,
# czerwonych_kartek_sum = int(safe_traverse(stats, ["600", "value"], default="0")), klub_id = klub_zawodnika
# wygranych_sum = 1 if safe_traverse(match, ["winLoseShort"], default="") == "Z" else 0, )
# wynik_sum = safe_traverse(match, ["rating"], default=0),
# meczow_do_wynikow_sum = 1 if safe_traverse(match, ["rating"], default=0) not in (0, None) else None
# )
# # analogicznie zinkrementuj statystyki_sportowcow: # # analogicznie zinkrementuj statystyki_sportowcow:
# # UWAGA! NIE ZADZIAŁA DLA NIKOGO INNEGO, NIŻ ROBERCIKA (bo nie mamy innych sportowców w bazie, trzeba dodać ich ręcznie w lewy_db sample_data_init()) # # aby to zrobić, najpierw pobierz najnowszą statystykę sportowca
# self.db.simple_insert_one("statystyki_sportowcow", # # ...
#
#
# # a następnie użyj funkcji w lewy_db do inkrementowania danych
# # (póki co jeszcze takiej nie ma)
# self.db.simple_increment_data("statystyki_sportowcow",
# id = ... # pewnie id się przyda
# sportowiec = zawodnik, # sportowiec = zawodnik,
# ostatni_mecz = self.db.get_id_meczu_by_zewnetrzne_id(zewnetrzne_id_meczu), # ostatni_mecz = self.db.get_id_meczu_by_zewnetrzne_id(zewnetrzne_id_meczu),
# ilosc_wystapien = 1 if int(safe_traverse(stats, ["595", "value"], default="0").rstrip("'")) > 0 else 0, # ilosc_wystapien = 1 if int(safe_traverse(stats, ["595", "value"], default="0").rstrip("'")) > 0 else 0,
@@ -216,29 +232,29 @@ class scraper:
# nieobronionych_interwencji_sum = 0, # nieobronionych_interwencji_sum = 0,
# zoltych_kartek_sum = int(safe_traverse(stats, ["599", "value"], default="0")), # zoltych_kartek_sum = int(safe_traverse(stats, ["599", "value"], default="0")),
# czerwonych_kartek_sum = int(safe_traverse(stats, ["600", "value"], default="0")), # czerwonych_kartek_sum = int(safe_traverse(stats, ["600", "value"], default="0")),
# wygranych_sum = 1 if safe_traverse(match, ["winLoseShort"], default="") == "Z" else 0, # wygranych_sum = 1 if safe_traverse(match, ["winloseshort"], default="") == "z" else 0,
# wynik_sum = safe_traverse(match, ["rating"], default=0), # wynik_sum = safe_traverse(match, ["rating"], default=0),
# meczow_do_wynikow_sum = 1 if safe_traverse(match, ["rating"], default=0) not in (0, None) else None # meczow_do_wynikow_sum = 1 if safe_traverse(match, ["rating"], default=0) not in (0, none) else none
# ) # )
else: else:
print("też todo :)") # print("też todo :)")
# # TODO: TU TEŻ TRZEBA POPRAWIĆ ANALOGICZNIE DO TEGO, CO JEST WEWNĄTRZ IF'A # # TODO: TU TEŻ TRZEBA POPRAWIĆ ANALOGICZNIE DO TEGO, CO JEST WEWNĄTRZ IF'A
# self.db.simple_insert_one("sportowcy_w_meczach", id_zawodnika, self.db.simple_insert_one("sportowcy_w_meczach",
# ostatni_mecz = self.db.get_id_meczu_by_zewnetrzne_id(zewnetrzne_id_meczu), id_zawodnika = id_zawodnika,
# ilosc_wystapien = 0, zawodnik = zawodnik,
# minut_gry = 0, zewnetrzne_id_meczu = zewnetrzne_id_meczu,
# gier_sum = 0, czas_gry = 0, #(lambda v: int(str(v).rstrip("'")) if isinstance(v, (str, int, float)) and str(v).rstrip("'").lstrip("-").isdigit() else 0)(safe_traverse(stats if isinstance(stats, dict) else {}, ["595", "value"], default="0")),
# goli_sum = 0, goli = int("0" + safe_traverse(stats, ["596", "value"], default="0")),
# asyst_sum = 0, asyst = int("0" + safe_traverse(stats, ["541", "value"], default="0")),
# interwencji_sum = 0, interwencje_bramkarza = 0,
# nieobronionych_interwencji_sum = 0, suma_interwencji_na_bramke = 0,
# zoltych_kartek_sum = 0, zolte_kartki = int("0" + safe_traverse(stats, ["599", "value"], default="0")),
# czerwonych_kartek_sum = 0, czerwone_kartki = int("0" + safe_traverse(stats, ["600", "value"], default="0")),
# wygranych_sum = 1 if safe_traverse(match, ["winLoseShort"], default="") == "Z" else 0, wygrana = {"Z": 1, "R": 0, "P": -1}.get(safe_traverse(match, ["winLoseShort"], default=""), 0),
# wynik_sum = safe_traverse(match, ["rating"], default=0), wynik = safe_traverse(match, ["rating"], default=0) or 0,
# meczow_do_wynikow_sum = 1 if safe_traverse(match, ["rating"], default=0) not in (0, None) else None klub_id = klub_zawodnika
# ) )
# TODO: Zaktualizuj statystyki sportowca # TODO: Zaktualizuj statystyki sportowca
@@ -251,7 +267,7 @@ class scraper:
# rate limita. - sherl # rate limita. - sherl
page += 1 page += 1
time.sleep(5) #time.sleep(5)
def aktualizuj_dane(self): def aktualizuj_dane(self):
@@ -259,8 +275,12 @@ class scraper:
Pobiera mecze dla każdego sportowca wymienionego Pobiera mecze dla każdego sportowca wymienionego
w pliku konfiguracyjnym. w pliku konfiguracyjnym.
""" """
start_time = time.time()
for id_sportowca in lewy_globals.config['sportsmen']['tracked_ids']: for id_sportowca in lewy_globals.config['sportsmen']['tracked_ids']:
self.aktualizuj_dane_sportowca(zewnetrzne_id_sportowca=id_sportowca) self.aktualizuj_dane_sportowca(zewnetrzne_id_sportowca=id_sportowca)
time.sleep(15) time.sleep(5)
end_time = time.time()
print(f"Scrapowanie trwało {end_time - start_time}s.")

View File

@@ -1,7 +1,7 @@
from argparse import ArgumentParser from argparse import ArgumentParser
from flask import Flask, Response, render_template from flask import Flask, Response, render_template
from flask_apscheduler import APScheduler from flask_apscheduler import APScheduler
from fs_scraper import scraper as scr from fs_scraper import scraper
from lewy_globals import colors as c from lewy_globals import colors as c
import lewy_api import lewy_api
import lewy_db import lewy_db
@@ -13,12 +13,12 @@ import time
app = Flask(__name__) app = Flask(__name__)
app_host = "None" app_host = "None"
app_port = "None" app_port = "None"
scrape = None scr = None
def setup(): def setup():
# sanity check: make sure config is set # sanity check: make sure config is set
# required to make `flask --app lewy run --debug` work # required to make `flask --app lewy run --debug` work
global config, app_host, app_port, scrape global config, app_host, app_port, scr
try: try:
if not config['general']: if not config['general']:
lewy_globals.setConfig(lewy_globals.configfile) lewy_globals.setConfig(lewy_globals.configfile)
@@ -79,7 +79,7 @@ def setup():
app.add_url_rule('/api/<path:received_request>', view_func=lewy_api.api_global_catchall) app.add_url_rule('/api/<path:received_request>', view_func=lewy_api.api_global_catchall)
db = lewy_globals.setupDb(app, config) db = lewy_globals.setupDb(app, config)
scraper = scr() scr = scraper()
with app.app_context(): with app.app_context():
db.create_all() db.create_all()
@@ -97,8 +97,7 @@ def every5seconds():
def every2hours(): def every2hours():
# zaktualizuj bazę danych scrapując FS # zaktualizuj bazę danych scrapując FS
# ... scr.aktualizuj_dane()
# scraper.aktualizuj_dane()
return return
@app.route('/<string:val>', methods=['GET']) @app.route('/<string:val>', methods=['GET'])

View File

@@ -50,6 +50,19 @@ def not_implemented(data):
# TODO: change list to string -> data, not data[0] # TODO: change list to string -> data, not data[0]
return 501, f"not recognised/implemented: {data[0]}", [] return 501, f"not recognised/implemented: {data[0]}", []
def __czy_x_istnieje(typ, **id):
rekord = getDb().simple_select_all(typ, **id)
if rekord is not None and rekord != []:
return True
else:
return False
def czy_sportowiec_istnieje(id_zawodnika: str):
return __czy_x_istnieje("sportowcy", id_zawodnika=id_zawodnika)
def czy_klub_istnieje(id_klubu: str):
return __czy_x_istnieje("kluby", id_klubu=id_klubu)
# GET /api/v1 # GET /api/v1
def stub_hello(): def stub_hello():
""" """
@@ -85,15 +98,152 @@ def stats():
return 200, "ok", data_to_send return 200, "ok", data_to_send
# GET /api/v1/matches # GET /api/v1/matches
def get_matches(r): def get_matches(r = None, id_zawodnika: int | None = None, rok: int | None = None):
""" """
TODO: Zwraca mecze. Zwraca mecze.
Przykład wywołania:
get_matches(r, id_zawodnika=1), tożsame z GET /api/v1/matches?id_zawodnika=1
get_matches(r, rok=2024), tożsame z GET /api/v1/matches?rok=2024
get_matches(r), tożsame z GET /api/v1/matches
""" """
response_json = [] response_json = []
mecze = getDb().simple_select_all("mecze") mecze = None
if id_zawodnika is None:
# Gdy nie podano id wprost, sprawdź, czy podano je przez parametr.
id_zawodnika = r.args.get('id_zawodnika', -1)
if rok is None:
# Gdy nie podano roku wprost, sprawdź, czy podano je przez parametr.
# Jeśli nie, przyjmij None (2025).
rok = r.args.get('rok', None)
# Sprawdź, czy podano jakiekolwiek ID sportowca. Jeżeli nie, wypisz wszystkie mecze.
if id_zawodnika == -1:
mecze = getDb().get_sportsman_matches(year=rok)
# Sprawdź, czy sportowiec o podanym (lub niepodanym) id istnieje.
# Jeśli nie istnieje, wypisz wszystkie mecze.
elif not czy_sportowiec_istnieje(id_zawodnika=id_zawodnika):
return 404, "error", {"error_msg": "This sportsman has not been found in the database. Try: id_zawodnika=1"}
# Gdy sportowiec istnieje, wypisz jego mecze.
else:
mecze = getDb().get_sportsman_matches(id_zawodnika=id_zawodnika, year=rok)
for mecz in mecze: for mecz in mecze:
response_json.append(mecz.jsonify()) response_json.append(mecz.jsonify())
print(response_json) # print(f"zwracam mecze: {response_json}")
return 200, "ok", response_json
# GET /api/v1/player_stats
def player_stats(r = None, id_zawodnika: int | None = None):
"""
Zwraca statystyki gracza.
Przykład wywołania:
player_stats(r, id_zawodnika=1), tożsame z GET /api/v1/player_stats?id_zawodnika=1
player_stats(r), tożsame z GET /api/v1/player_stats
"""
response_json = []
if id_zawodnika is None:
# Gdy nie podano id wprost, sprawdź, czy podano je przez parametr.
id_zawodnika = r.args.get('id_zawodnika', 0)
# Sprawdź, czy sportowiec o podanym (lub niepodanym) id istnieje.
if not czy_sportowiec_istnieje(id_zawodnika=id_zawodnika):
return 404, "error", {"error_msg": "This sportsman has not been found in the database. Try: id_zawodnika=1"}
# Gdy sportowiec istnieje, wypisz jego statystyki.
else:
staty = getDb().get_basic_stats(id_zawodnika=id_zawodnika)
# for stat in staty:
response_json.append({
'unique_items': staty[0],
'time_played': staty[1],
'goals': staty[2],
'assists': staty[3],
'yellow_cards': staty[4],
'red_cards': staty[5],
'avg_score': staty[6],
'wins': staty[7],
'draws': staty[8],
'losses': staty[9]
}
)
print(f"zwracam staty: {response_json}")
return 200, "ok", response_json
# GET /api/v1/robert_stats
def robert_stats(r = None, id_klubu: str | None = None):
"""
Zwraca statystyki Roberta w danym klubie.
Przykład wywołania:
robert_stats(r, id_klubu="barcelona"), tożsame z GET /api/v1/robert_stats?id_klubu=barcelona
"""
response_json = []
if id_klubu is None:
# Gdy nie podano id wprost, sprawdź, czy podano je przez parametr.
id_klubu = r.args.get('id_klubu', "non-existent-club-id")
# Sprawdź, czy klub o podanym (lub niepodanym) id istnieje.
if not czy_klub_istnieje(id_klubu=id_klubu):
return 404, "error", {"error_msg": "This club has not been found in the database. Try: id_klubu=barcelona"}
# Gdy klub istnieje, wypisz statystyki z tego klubu.
else:
staty = getDb().get_sportsman_club_stats(id_zawodnika=1, id_klubu=id_klubu)
# for stat in staty:
print(staty)
response_json.append({
'unique_items': staty[0],
'time_played': staty[1],
'goals': staty[2],
'assists': staty[3],
'yellow_cards': staty[4],
'red_cards': staty[5],
'avg_score': staty[6],
'wins': staty[7],
'draws': staty[8],
'losses': staty[9]
}
)
print(f"zwracam staty roberta: {response_json}")
return 200, "ok", response_json
# GET /api/v1/clubs
def clubs(r, id_klubu: str = None):
"""
Zwraca informacje o klubach.
Przykład wywołania:
clubs(r, id_klubu="barcelona"), tożsame z GET /api/v1/clubs?id_klubu=barcelona
clubs(r), tożsame z GET /api/v1/clubs
"""
response_json = []
if id_klubu is None:
# Gdy nie podano id wprost, sprawdź, czy podano je przez parametr.
id_klubu = r.args.get('id_klubu', -1)
if id_klubu == -1:
kluby = getDb().simple_select_all("kluby")
# Sprawdź, czy sportowiec o podanym (lub niepodanym) id istnieje.
# Jeśli nie istnieje, wypisz wszystkie mecze.
elif not czy_klub_istnieje(id_klubu=id_klubu):
return 404, "error", {"error_msg": "This club has not been found in the database. Try: id_klubu=barcelona"}
# Gdy sportowiec istnieje, wypisz jego mecze.
else:
kluby = getDb().simple_select_all("kluby", id_klubu=id_klubu)
for klub in kluby:
response_json.append(klub.jsonify())
print(f"zwracam kluby: {response_json}")
return 200, "ok", response_json return 200, "ok", response_json
# GET /api/v1/debugger_halt?token=XXX... # GET /api/v1/debugger_halt?token=XXX...
@@ -148,6 +298,12 @@ def lookup(data, request):
return debugger_halt(r = request) return debugger_halt(r = request)
case 'matches': case 'matches':
return get_matches(r = request) return get_matches(r = request)
case 'player_stats':
return player_stats(r = request)
case 'robert_stats':
return robert_stats(r = request)
case 'clubs':
return clubs(r = request)
case _: case _:
increment_bad_requests() increment_bad_requests()
return not_implemented(data) return not_implemented(data)

View File

@@ -1,7 +1,7 @@
from datetime import datetime from datetime import datetime
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
from functools import wraps from functools import wraps
from sqlalchemy import ForeignKey, select, insert, update from sqlalchemy import ForeignKey, select, insert, update, extract, func, case
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, Session, relationship from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase, Session, relationship
from typing import List from typing import List
import time import time
@@ -70,6 +70,7 @@ class baza():
statystyki_id: Mapped[ List[int]] = mapped_column(ForeignKey(f"{tnp}statystyki_sportowcow.id_statystyki"), nullable=True) statystyki_id: Mapped[ List[int]] = mapped_column(ForeignKey(f"{tnp}statystyki_sportowcow.id_statystyki"), nullable=True)
statystyki: Mapped[List["statystyki_sportowcow"]] = relationship(back_populates="sportowiec") statystyki: Mapped[List["statystyki_sportowcow"]] = relationship(back_populates="sportowiec")
trofea: Mapped[ List["trofea"]] = relationship(back_populates="zawodnik", foreign_keys="[trofea.id_zawodnika]") trofea: Mapped[ List["trofea"]] = relationship(back_populates="zawodnik", foreign_keys="[trofea.id_zawodnika]")
mecze_zawodnika: Mapped[ List["sportowcy_w_meczach"]] = relationship(back_populates="zawodnik")
def __repr__(self): def __repr__(self):
return f"<Sportowiec #{self.id_zawodnika} ({self.imie} {self.nazwisko})>" return f"<Sportowiec #{self.id_zawodnika} ({self.imie} {self.nazwisko})>"
@@ -92,8 +93,9 @@ class baza():
__tablename__ = tnp + "sportowcy_w_meczach" __tablename__ = tnp + "sportowcy_w_meczach"
id_rekordu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True) id_rekordu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
id_zawodnika: Mapped[ int] = mapped_column(ForeignKey(f"{tnp}sportowcy.id_zawodnika")) id_zawodnika: Mapped[ int] = mapped_column(ForeignKey(f"{tnp}sportowcy.id_zawodnika"))
zawodnik: Mapped[ "sportowcy"] = relationship() zawodnik: Mapped[ "sportowcy"] = relationship(back_populates="mecze_zawodnika")
zewnetrzne_id_meczu: Mapped[ str] = mapped_column(ForeignKey(f"{tnp}mecze.zewnetrzne_id_meczu")) zewnetrzne_id_meczu: Mapped[ str] = mapped_column(ForeignKey(f"{tnp}mecze.zewnetrzne_id_meczu"))
mecz: Mapped[ "mecze"] = relationship() # back_populates="zawodnicy_w_meczu", foreign_keys=[zewnetrzne_id_meczu])
czas_gry: Mapped[ int] = mapped_column() czas_gry: Mapped[ int] = mapped_column()
goli: Mapped[ int] = mapped_column() goli: Mapped[ int] = mapped_column()
asyst: Mapped[ int] = mapped_column() asyst: Mapped[ int] = mapped_column()
@@ -103,9 +105,11 @@ class baza():
czerwone_kartki: Mapped[ int] = mapped_column() czerwone_kartki: Mapped[ int] = mapped_column()
wygrana: Mapped[ int] = mapped_column() wygrana: Mapped[ int] = mapped_column()
wynik: Mapped[ float] = mapped_column() wynik: Mapped[ float] = mapped_column()
klub_id: Mapped[ int] = mapped_column(ForeignKey(f"{tnp}kluby.id_klubu"))
klub: Mapped[ "kluby"] = relationship()
def __repr__(self): def __repr__(self):
return f"<Sportowiec #{self.id_zawodnika} ({self.imie} {self.nazwisko})>" return f"<{self.zawodnik.imie} {self.zawodnik.nazwisko} w meczu {self.mecz.gospodarze.skrocona_nazwa} vs. {self.mecz.goscie.skrocona_nazwa}>"
class statystyki_sportowcow(Base): class statystyki_sportowcow(Base):
__tablename__ = tnp + "statystyki_sportowcow" __tablename__ = tnp + "statystyki_sportowcow"
@@ -141,6 +145,13 @@ class baza():
def __repr__(self): def __repr__(self):
return f"<Klub #{self.id_klubu} ({self.skrocona_nazwa})>" return f"<Klub #{self.id_klubu} ({self.skrocona_nazwa})>"
def jsonify(self):
return {
"id_klubu": self.id_klubu,
"pelna_nazwa": self.pelna_nazwa,
"skrocona_nazwa": self.skrocona_nazwa
}
class mecze(Base): class mecze(Base):
__tablename__ = tnp + "mecze" __tablename__ = tnp + "mecze"
id_meczu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True) id_meczu: Mapped[ int] = mapped_column(primary_key=True, autoincrement=True)
@@ -157,6 +168,8 @@ class baza():
skrocona_nazwa_turnieju: Mapped[ str] = mapped_column() skrocona_nazwa_turnieju: Mapped[ str] = mapped_column()
flaga: Mapped[ int] = mapped_column() flaga: Mapped[ int] = mapped_column()
# zawodnicy_w_meczu: Mapped[ List["sportowcy_w_meczach"]] = relationship(back_populates="mecz")
def __repr__(self): def __repr__(self):
return f"<Mecz #{self.id_meczu} ({self.zewnetrzne_id_meczu}, {self.gospodarze.skrocona_nazwa} vs. {self.goscie.skrocona_nazwa})>" return f"<Mecz #{self.id_meczu} ({self.zewnetrzne_id_meczu}, {self.gospodarze.skrocona_nazwa} vs. {self.goscie.skrocona_nazwa})>"
@@ -167,8 +180,10 @@ class baza():
"data": self.data.strftime("%Y-%m-%d"), "data": self.data.strftime("%Y-%m-%d"),
"gospodarze_id": self.gospodarze_id, "gospodarze_id": self.gospodarze_id,
"gospodarze": self.gospodarze.skrocona_nazwa, "gospodarze": self.gospodarze.skrocona_nazwa,
"gospodarze_pelna_nazwa": self.gospodarze.pelna_nazwa,
"goscie_id": self.goscie_id, "goscie_id": self.goscie_id,
"goscie": self.goscie.skrocona_nazwa, "goscie": self.goscie.skrocona_nazwa,
"goscie_pelna_nazwa": self.goscie.pelna_nazwa,
"gosp_wynik": self.gosp_wynik, "gosp_wynik": self.gosp_wynik,
"gosc_wynik": self.gosc_wynik, "gosc_wynik": self.gosc_wynik,
"sezon": self.sezon, "sezon": self.sezon,
@@ -195,12 +210,12 @@ class baza():
with self.app.app_context(): with self.app.app_context():
self.session = Session(self.db.engine) self.session = Session(self.db.engine)
def exit_gracefully(func): def exit_gracefully(fun):
@wraps(func) @wraps(fun)
def wrapper(self, *args, **kwargs): def wrapper(self, *args, **kwargs):
return_val = None return_val = None
try: try:
return_val = func(self, *args, **kwargs) return_val = fun(self, *args, **kwargs)
except: except:
print(f"{c.FAIL}" print(f"{c.FAIL}"
f"Wystąpił błąd podczas wykonywania zapytania SQL:" f"Wystąpił błąd podczas wykonywania zapytania SQL:"
@@ -486,6 +501,194 @@ class baza():
self.session.commit() self.session.commit()
return 0 return 0
@exit_gracefully
def get_sportowcy_w_meczach_by_sportsman_id(self, id_zawodnika = None, zewnetrzne_id_zawodnika = None, order = "DESC"):
if zewnetrzne_id_zawodnika is not None:
id_zawodnika = self.get_id_zawodnika_by_zewnetrzne_id(zewnetrzne_id_zawodnika)
# Aliasy (dla czytelności)
SportowcyWMeczach = self.entities["sportowcy_w_meczach"]
Sportowcy = self.entities["sportowcy"]
query = self.session.query(
SportowcyWMeczach
).join(
SportowcyWMeczach.zawodnik
).filter(
Sportowcy.id_zawodnika == id_zawodnika
)
# print(f"get_sportowcy_w_meczach_by_sportsman_id: {query}")
if order.lower() == "desc":
query = query.order_by(SportowcyWMeczach.id_rekordu.desc())
return query.all()
@exit_gracefully
def get_sportsman_matches(self, id_zawodnika = None, zewnetrzne_id_zawodnika = None, order = "DESC", year = None):
# Spróbuj otrzymać id zawodnika z zewnętrznego id.
if zewnetrzne_id_zawodnika is not None:
id_zawodnika = self.get_id_zawodnika_by_zewnetrzne_id(zewnetrzne_id_zawodnika)
# Aliasy
Mecze = self.entities["mecze"]
SportowcyWMeczach = self.entities["sportowcy_w_meczach"]
Sportowcy = self.entities["sportowcy"]
query = self.session.query(
Mecze
).join(
SportowcyWMeczach, Mecze.zewnetrzne_id_meczu == SportowcyWMeczach.zewnetrzne_id_meczu
)
if id_zawodnika is not None:
query = query.join(
Sportowcy, SportowcyWMeczach.id_zawodnika == Sportowcy.id_zawodnika
).filter(
Sportowcy.id_zawodnika == id_zawodnika
)
if year is not None:
query = query.filter(
extract("year", Mecze.data) == year
)
if order.lower() == "desc":
query = query.order_by(Mecze.data.desc())
# print(f"get_sportsman_matches: {query}")
return query.all()
@exit_gracefully
def get_basic_stats(self, id_zawodnika = None, zewnetrzne_id_zawodnika = None):
# Spróbuj otrzymać id zawodnika z zewnętrznego id.
if zewnetrzne_id_zawodnika is not None:
id_zawodnika = self.get_id_zawodnika_by_zewnetrzne_id(zewnetrzne_id_zawodnika)
if id_zawodnika is None:
return []
# Aliasy
SportowcyWMeczach = self.entities["sportowcy_w_meczach"]
# Zlicz liczbę zwycięstw, remisów i przegranych.
# https://stackoverflow.com/a/3975328
# https://stackoverflow.com/a/49064561
# Czy da się to zrobić prościej? Nie wiem. ~ sherl
query = self.session.query(
func.count(SportowcyWMeczach.id_rekordu ).label('unique_items'),
func.sum( SportowcyWMeczach.czas_gry ).label('time_played'),
func.sum( SportowcyWMeczach.goli ).label('goals'),
func.sum( SportowcyWMeczach.asyst ).label('assists'),
func.sum( SportowcyWMeczach.zolte_kartki ).label('yellow_cards'),
func.sum( SportowcyWMeczach.czerwone_kartki).label('red_cards'),
func.avg( SportowcyWMeczach.wynik ).label('avg_score'),
# Kompatybilne z każdą bazą.
# https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.case
# https://modern-sql.com/feature/filter
func.sum(
case(
(SportowcyWMeczach.wygrana == 1, 1),
else_ = 0
)
).label('wins'),
func.sum(
case(
(SportowcyWMeczach.wygrana == 0, 1),
else_ = 0
)
).label('draws'),
func.sum(
case(
(SportowcyWMeczach.wygrana == -1, 1),
else_ = 0
)
).label('losses'),
).where(
SportowcyWMeczach.czas_gry > 0
).where(
SportowcyWMeczach.id_zawodnika == id_zawodnika
)
return query.all()[0]
@exit_gracefully
def get_sportsman_club_stats(self, id_zawodnika = None, zewnetrzne_id_zawodnika = None, id_klubu = None):
# Spróbuj otrzymać id zawodnika z zewnętrznego id.
if zewnetrzne_id_zawodnika is not None:
id_zawodnika = self.get_id_zawodnika_by_zewnetrzne_id(zewnetrzne_id_zawodnika)
if id_zawodnika is None:
return []
if id_klubu is None:
return self.get_basic_stats(id_zawodnika=id_zawodnika)
else:
if self.simple_select_all("kluby", id_klubu=id_klubu) == []:
return []
# Aliasy
SportowcyWMeczach = self.entities["sportowcy_w_meczach"]
# Zlicz liczbę zwycięstw, remisów i przegranych.
# https://stackoverflow.com/a/3975328
# https://stackoverflow.com/a/49064561
# Czy da się to zrobić prościej? Nie wiem. ~ sherl
query = self.session.query(
func.count(SportowcyWMeczach.id_rekordu ).label('unique_items'),
func.sum( SportowcyWMeczach.czas_gry ).label('time_played'),
func.sum( SportowcyWMeczach.goli ).label('goals'),
func.sum( SportowcyWMeczach.asyst ).label('assists'),
func.sum( SportowcyWMeczach.zolte_kartki ).label('yellow_cards'),
func.sum( SportowcyWMeczach.czerwone_kartki).label('red_cards'),
func.avg( SportowcyWMeczach.wynik ).label('avg_score'),
# Kompatybilne z każdą bazą.
# https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.case
# https://modern-sql.com/feature/filter
func.sum(
case(
(SportowcyWMeczach.wygrana == 1, 1),
else_ = 0
)
).label('wins'),
# UWAGA! Jeśli jest remis, to nie wiemy dla którego klubu grał sportowiec!
# Poniższe wyrażenie jest poprawne, to dane zwracane przez flashscore są
# niewystarczające, aby stwierdzić w którym klubie grał sportowiec!
func.sum(
case(
(SportowcyWMeczach.wygrana == 0, 1),
else_ = 0
)
).label('draws'),
func.sum(
case(
(SportowcyWMeczach.wygrana == -1, 1),
else_ = 0
)
).label('losses'),
).where(
SportowcyWMeczach.czas_gry > 0
).where(
SportowcyWMeczach.id_zawodnika == id_zawodnika
).where(
SportowcyWMeczach.klub_id == id_klubu
)
return query.all()[0]
@exit_gracefully @exit_gracefully
def sample_data_init(self, override_safety_check=False): def sample_data_init(self, override_safety_check=False):
""" """
@@ -523,36 +726,46 @@ class baza():
nazwa_turnieju="Nieznany turniej", nazwa_turnieju="Nieznany turniej",
skrocona_nazwa_turnieju="N/A", skrocona_nazwa_turnieju="N/A",
flaga=0) flaga=0)
# Robercik
self.simple_insert_one(kluby,
id_klubu="barcelona",
pelna_nazwa="Barcelona",
skrocona_nazwa="BAR"
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=0, ilosc_wystapien=487,
minut_gry=0, minut_gry=0, # Brak danych
gier_sum=0, gier_sum=487,
goli_sum=0, goli_sum=381,
asyst_sum=0, asyst_sum=44,
interwencji_sum=0, interwencji_sum=0,
nieobronionych_interwencji_sum=0, nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=0, zoltych_kartek_sum=2,
czerwonych_kartek_sum=0, czerwonych_kartek_sum=0,
wygranych_sum=0, wygranych_sum=0, # Brak danych
przegranych_sum=0, przegranych_sum=0, # Brak danych
remisow_sum=0, remisow_sum=0, # Brak danych
wynik_sum=0, wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0) meczow_do_wynikow_sum=0 # Brak danych
)
sportowiec = sportowcy( sportowiec = sportowcy(
zewnetrzne_id_zawodnika="MVC8zHZD", zewnetrzne_id_zawodnika="MVC8zHZD",
imie="Robert", imie="Robert",
nazwisko="Lewandowski", nazwisko="Lewandowski",
data_urodzenia="21.08.1988", data_urodzenia="21.08.1988",
czy_aktywny=True, czy_aktywny=True,
klub_id="undefined", klub_id="barcelona",
narodowosc="PL", narodowosc="PL",
ilosc_trofeow=0, ilosc_trofeow=0, # Brak danych na Flashscore
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=1, statystyki_id=1,
wycena=64_940_000) wycena=67_000_000 # Wartość rynkowa: €15.3 mln
)
trofeum = trofea( trofeum = trofea(
nazwa="Nieznane trofeum", nazwa="Nieznane trofeum",
sezon="0000-0000", sezon="0000-0000",
@@ -600,6 +813,514 @@ class baza():
# statystyki_id=2, # itd... # statystyki_id=2, # itd...
# wycena=...) # w złotówkach # wycena=...) # w złotówkach
# Ronaldo
self.simple_insert_one(kluby,
id_klubu="al-nassr",
pelna_nazwa="Al Nassr Riyadh",
skrocona_nazwa="ANR" #?
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=702,
minut_gry=0, # Brak danych
gier_sum=702,
goli_sum=569,
asyst_sum=81,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=92,
czerwonych_kartek_sum=8,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="WGOY4FSt",
imie="Cristiano",
nazwisko="Ronaldo",
data_urodzenia="05.02.1985",
czy_aktywny=True,
klub_id="al-nassr",
narodowosc="PT",
ilosc_trofeow=0, # Brak danych na Flashscore
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=2,
wycena=55_000_000 # Wartość rynkowa: €12.1 mln
)
# Messi
self.simple_insert_one(kluby,
id_klubu="inter-miami",
pelna_nazwa="Inter Miami",
skrocona_nazwa="INM"
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=619,
minut_gry=0, # Brak danych o łącznym czasie gry
gier_sum=619,
goli_sum=528,
asyst_sum=53,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=0,
czerwonych_kartek_sum=0,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="vgOOdZbd",
imie="Lionel",
nazwisko="Messi",
data_urodzenia="24.06.1987",
czy_aktywny=True,
klub_id="inter-miami",
narodowosc="AR",
ilosc_trofeow=0, # Brak danych na Flashscore
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=3,
wycena=67_000_000 # Wartość rynkowa: €15.3 mln
)
# Mbappe
self.simple_insert_one(kluby,
id_klubu="real-madryt",
pelna_nazwa="Real Madryt",
skrocona_nazwa="RMA"
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=280,
minut_gry=0, # Brak danych o łącznym czasie gry
gier_sum=280,
goli_sum=222,
asyst_sum=67,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=38,
czerwonych_kartek_sum=2,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="Wn6E2SED",
imie="Kylian",
nazwisko="Mbappé",
data_urodzenia="20.12.1998",
czy_aktywny=True,
klub_id="real-madryt",
narodowosc="FR",
ilosc_trofeow=0, # Brak danych na Flashscore
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=4,
wycena=185_700_000 # Wartość rynkowa: €185.7 mln
)
# Zlatan
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=519,
minut_gry=0, # Brak danych o łącznym czasie gry
gier_sum=519,
goli_sum=355,
asyst_sum=63,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=87,
czerwonych_kartek_sum=9,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="AiH2zDve",
imie="Zlatan",
nazwisko="Ibrahimović",
data_urodzenia="03.10.1981",
czy_aktywny=False,
klub_id="undefined",
narodowosc="SE",
ilosc_trofeow=0, # Brak danych na Flashscore
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=5,
wycena=0 # Zakończył karierę
)
# Suarez
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=608,
minut_gry=0, # Brak danych o łącznym czasie gry
gier_sum=608,
goli_sum=399,
asyst_sum=122,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=0,
czerwonych_kartek_sum=0,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="dUShzrBp",
imie="Luis",
nazwisko="Suárez",
data_urodzenia="24.01.1987",
czy_aktywny=True,
klub_id="inter-miami",
narodowosc="UY",
ilosc_trofeow=0, # Brak danych na Flashscore
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=6,
wycena=8_800_000 # Wartość rynkowa: €2.0 mln
)
# Haaland
self.simple_insert_one(kluby,
id_klubu="manchester-city",
pelna_nazwa="Manchester City",
skrocona_nazwa="MCI"
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=235,
minut_gry=0, # Brak danych o łącznym czasie gry
gier_sum=235,
goli_sum=178,
asyst_sum=41,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=18,
czerwonych_kartek_sum=0,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="UmV9iQmE",
imie="Erling",
nazwisko="Haaland",
data_urodzenia="21.07.2000",
czy_aktywny=True,
klub_id="manchester-city",
narodowosc="NO",
ilosc_trofeow=0, # Brak danych
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=7,
wycena=777_500_000 # ~€178.7 mln
)
# Karim Benzema
self.simple_insert_one(kluby,
id_klubu="al-ittihad",
pelna_nazwa="Al-Ittihad FC", #?
skrocona_nazwa="RMA" #?
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=589,
minut_gry=0, # Brak danych
gier_sum=589,
goli_sum=305,
asyst_sum=0,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=14,
czerwonych_kartek_sum=0,
wygranych_sum=0, # Brak danych
przegranych_sum=0,
remisow_sum=0,
wynik_sum=0,
meczow_do_wynikow_sum=0
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="tpV0VX0S",
imie="Karim",
nazwisko="Benzema",
data_urodzenia="19.12.1987",
czy_aktywny=True,
klub_id="al-ittihad",
narodowosc="FR",
ilosc_trofeow=0, # Flashscore nie podaje
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=8,
wycena=31_950_000 # €7.1 mln
)
# Sergio Aguero
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=443,
minut_gry=0, # Brak danych o czasie gry
gier_sum=443,
goli_sum=254,
asyst_sum=38,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=47,
czerwonych_kartek_sum=2,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="vw8ZV7HC",
imie="Sergio",
nazwisko="Agüero",
data_urodzenia="02.06.1988",
czy_aktywny=False,
klub_id="undefined",
narodowosc="AR",
ilosc_trofeow=0, # Brak danych
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=9,
wycena=0 # Zakończył karierę
)
# Edinson Cavani
self.simple_insert_one(kluby,
id_klubu="boca-juniors",
pelna_nazwa="Boca Juniors", #?
skrocona_nazwa="CAB" #?
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=507,
minut_gry=0, # Brak danych o czasie gry
gier_sum=507,
goli_sum=273,
asyst_sum=62,
interwencji_sum=0,
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=3,
czerwonych_kartek_sum=0,
wygranych_sum=0, # Brak danych
przegranych_sum=0, # Brak danych
remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="Qgx2trzH",
imie="Edinson",
nazwisko="Cavani",
data_urodzenia="14.02.1987",
czy_aktywny=True,
klub_id="boca-juniors",
narodowosc="UY",
ilosc_trofeow=0,
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=10,
wycena=4_212_000 # PLN
)
# Radamel Falcao
self.simple_insert_one(kluby,
id_klubu="millonarios",
pelna_nazwa="Millonarios",
skrocona_nazwa="MLA" #?
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=360,
minut_gry=0, # brak danych o czasie gry
gier_sum=360,
goli_sum=170,
asyst_sum=17,
interwencji_sum=54,
nieobronionych_interwencji_sum=1,
zoltych_kartek_sum=0, # brak danych
czerwonych_kartek_sum=0,
wygranych_sum=0,
przegranych_sum=0,
remisow_sum=0,
wynik_sum=0,
meczow_do_wynikow_sum=0
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="2oMimkAU",
imie="Radamel",
nazwisko="Falcao",
data_urodzenia="10.02.1986",
czy_aktywny=True,
klub_id="millonarios",
narodowosc="CO",
ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=11,
wycena=1_084_500 #PLN
)
# Wayne Rooney
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=568,
minut_gry=0, # brak danych o czasie gry
gier_sum=568,
goli_sum=234,
asyst_sum=47,
interwencji_sum=0, # brak danych
nieobronionych_interwencji_sum=0, # brak danych
zoltych_kartek_sum=105,
czerwonych_kartek_sum=4,
wygranych_sum=0, # brak danych
przegranych_sum=0,
remisow_sum=0,
wynik_sum=0,
meczow_do_wynikow_sum=0
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="WfXv1DCa",
imie="Wayne",
nazwisko="Rooney",
data_urodzenia="24.10.1985",
czy_aktywny=False, # zakończył karierę
klub_id="undefined",
narodowosc="ENG",
ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=12,
wycena=0 # brak wyceny
)
# Robin van Persie
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=374,
minut_gry=0, # brak danych o czasie gry
gier_sum=374,
goli_sum=190,
asyst_sum=16,
interwencji_sum=0, # brak danych
nieobronionych_interwencji_sum=0, # brak danych
zoltych_kartek_sum=54,
czerwonych_kartek_sum=3,
wygranych_sum=0, # brak danych
przegranych_sum=0,
remisow_sum=0,
wynik_sum=0,
meczow_do_wynikow_sum=0
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="0vgcq6un",
imie="Robin",
nazwisko="van Persie",
data_urodzenia="06.08.1983",
czy_aktywny=False,
klub_id="undefined", # zakończył karierę
narodowosc="NED",
ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=13,
wycena=0 # zakończył karierę
)
# Harry Kane
self.simple_insert_one(kluby,
id_klubu="bayern",
pelna_nazwa="Bayern Monachium",
skrocona_nazwa="BAY"
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=439,
minut_gry=0, # brak danych o czasie gry
gier_sum=439,
goli_sum=295,
asyst_sum=64,
interwencji_sum=0, # brak danych
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=48,
czerwonych_kartek_sum=1,
wygranych_sum=0, # brak danych
przegranych_sum=0,
remisow_sum=0,
wynik_sum=0,
meczow_do_wynikow_sum=0
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="v5HSlEAa",
imie="Harry",
nazwisko="Kane",
data_urodzenia="28.07.1993",
czy_aktywny=True,
klub_id="bayern",
narodowosc="ENG",
ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=14,
wycena=344_700_000 # PLN
)
# Ciro Immobile
self.simple_insert_one(kluby,
id_klubu="besiktas",
pelna_nazwa="Besiktas",
skrocona_nazwa="BES"
)
self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1,
ilosc_wystapien=455,
minut_gry=0, # brak danych o czasie gry
gier_sum=455,
goli_sum=250,
asyst_sum=51,
interwencji_sum=0, # brak danych
nieobronionych_interwencji_sum=0,
zoltych_kartek_sum=71,
czerwonych_kartek_sum=3,
wygranych_sum=0,
przegranych_sum=0,
remisow_sum=0,
wynik_sum=0,
meczow_do_wynikow_sum=0
)
self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="4S9fNUYh",
imie="Ciro",
nazwisko="Immobile",
data_urodzenia="20.02.1990",
czy_aktywny=True,
klub_id="besiktas",
narodowosc="IT",
ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined",
statystyki_id=15,
wycena=12_600_000 # PLN
)
session.commit() session.commit()
return 0 return 0

View File

@@ -23,9 +23,9 @@ def safeTraverse(obj: dict, path: list, default=None):
try: try:
for x in path: for x in path:
result = result[x] result = result[x]
except KeyError: except (KeyError, TypeError):
result = default result = default
# print(f"error reading: {' -> '.join(path)} - returning: {default}") print(f"error reading: {' -> '.join(path)} - returning: {default}")
finally: finally:
return result return result

View File

@@ -2,23 +2,30 @@ from flask import render_template, request, make_response
import lewy_api_v1 import lewy_api_v1
import lewy_db import lewy_db
import lewy_globals import lewy_globals
import json
from lewy_api_v1 import get_matches, player_stats, robert_stats, clubs as get_clubs
def get_lewy_stats(): def get_lewy_stats():
stats = player_stats(id_zawodnika=1)[2][0]
polska = robert_stats(id_klubu="polska")[2][0]
barcelona = robert_stats(id_klubu="barcelona")[2][0]
borussia = robert_stats(id_klubu="dortmund")[2][0]
bayern = robert_stats(id_klubu="bayern")[2][0]
und = robert_stats(id_klubu="undefined")[2][0]
return { return {
'all_time_stats': { 'all_time_stats': {
'goals': 589+78, 'goals': stats["goals"], # 589+85
'assists':154+21, 'assists': stats["assists"], # 154+35
'matches': 791+136, 'matches': stats["unique_items"] # 791+158
}, },
'club_stats': { 'club_stats': {
'goals': 589, 'goals': barcelona["goals"] + borussia["goals"] + bayern["goals"]+ und["goals"], # 589
'assists': 154, 'assists': barcelona["assists"] + borussia["assists"] + bayern["assists"]+ und["assists"], # 154
'matches': 791, 'matches': barcelona["unique_items"] + borussia["unique_items"] + bayern["unique_items"]+ und["unique_items"] # 791 # to trochę na wyrost, bo w części meczy był kontuzjowany
}, },
'nation_stats': { 'nation_stats': {
'goals': 78, 'goals': polska["goals"], # 85
'assists': 21, 'assists': polska["assists"], # 35
'matches': 136, 'matches': polska["unique_items"] # 158
}, },
'international_cups': { 'international_cups': {
'goals': 110, 'goals': 110,
@@ -31,8 +38,13 @@ def get_lewy_stats():
'matches': 74, 'matches': 74,
}, },
'cards': { 'cards': {
'yellow': 86, 'yellow': stats["yellow_cards"], # 86
'red': 2, 'red': stats["red_cards"], # 2
},
'wins_losses': {
'wins': stats["wins"],
'draws': stats["draws"],
'losses': stats["losses"]
} }
} }
@@ -58,69 +70,165 @@ def index():
def mecze(): def mecze():
# Możesz dostarczyć szczegóły dotyczące meczów # Możesz dostarczyć szczegóły dotyczące meczów
selected_date = request.args.get("date", 2024) selected_date = request.args.get("date", '2025')
matches = [ try:
{'date': '2024-10-12', 'opponent': 'Real Madrid', 'goals': 2, 'assists': 1, 'minutes': 90}, selected_date = int(selected_date)
{'date': '2024-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, except:
{'date': '2023-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, selected_date = 2025
{'date': '2023-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, #with open("static/lewandowski_matches.json", "r") as file:
{'date': '2023-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, # data = json.load(file)
{'date': '2022-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, status, msg, matches = get_matches(None, id_zawodnika=1, rok=selected_date)
{'date': '2022-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2022-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2022-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2021-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2021-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2021-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2021-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2020-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2020-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2020-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2019-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2019-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
{'date': '2019-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85},
] return render_template('matches.html', matches=matches, selected_date=selected_date)
return render_template('matches.html', matches=matches)
def statystyki(): def statystyki():
dane=get_lewy_stats() dane=get_lewy_stats()
return render_template('stats.html', **dane) return render_template('stats.html', **dane)
def clubs(): def clubs():
selected_club = request.args.get("club","FC Barcelona") selected_club = request.args.get("club", "barcelona")
clubs = [ #clubs = [
{'club': 'FC Barcelona', 'goals': 101,'assist':20, 'matches':147,'minutes_played': 11684,'yellow_card':12,'red_card': 1, 'wins':101, 'draws': 14,'lost': 32}, # {'club': 'FC Barcelona', 'goals': 101,'assist':20, 'matches':147,'minutes_played': 11684,'yellow_card':12,'red_card': 1, 'wins':101, 'draws': 14,'lost': 32},
{'club': 'Bayern Monachium', 'goals': 344,'assist':73,'matches':375,'minutes_played': 31759,'yellow_card':36,'red_card': 0, 'wins':307, 'draws': 35,'lost': 33}, # {'club': 'Bayern Monachium', 'goals': 344,'assist':73,'matches':375,'minutes_played': 31759,'yellow_card':36,'red_card': 0, 'wins':307, 'draws': 35,'lost': 33},
{'club': 'Borussia Dortmund', 'goals': 103,'assist':42,'matches':187,'minutes_played': 14374,'yellow_card':19,'red_card': 1, 'wins':120, 'draws': 40,'lost': 27}, # {'club': 'Borussia Dortmund', 'goals': 103,'assist':42,'matches':187,'minutes_played': 14374,'yellow_card':19,'red_card': 1, 'wins':120, 'draws': 40,'lost': 27},
{'club': 'Lech Poznan', 'goals': 41,'assist':19,'matches':82,'minutes_played': 6858,'yellow_card':9,'red_card': 0, 'wins':'-', 'draws': '-','lost': '-'}, # {'club': 'Lech Poznan', 'goals': 41,'assist':19,'matches':82,'minutes_played': 6858,'yellow_card':9,'red_card': 0, 'wins':'-', 'draws': '-','lost': '-'},
] #]
return render_template('club.html', clubs=clubs, selected_club=selected_club) response_json = {
"club": "Błędny klub",
"goals": 0,
"assist": 0,
"matches": 0,
"minutes_played": 0,
"yellow_card": 0,
"red_card": 0,
"wins": 0,
"draws": 0,
"lost": 0
}
club = get_clubs(request, id_klubu=selected_club)
if club[1] == "ok": # gdy nie wystąpił bład, bo jest taki klub
club = club[2][0]
staty = robert_stats(id_klubu=club["id_klubu"])[2][0]
response_json["club"] = club["pelna_nazwa"]
response_json["goals"] = staty["goals"]
response_json["assist"] = staty["assists"]
response_json["matches"] = staty["unique_items"]
response_json["minutes_played"] = staty["time_played"]
response_json["yellow_card"] = staty["yellow_cards"]
response_json["red_card"] = staty["red_cards"]
response_json["wins"] = staty["wins"]
response_json["draws"] = staty["draws"]
response_json["lost"] = staty["losses"]
return render_template('club.html', clubs=clubs, selected_club=selected_club, resp_json=response_json)
def representation(): def representation():
nation_stats = { # nation_stats = {
'goals': 85, # 'goals': 85,
'assists': 35, # 'assists': 35,
'matches': 158, # 'matches': 158,
'minutes_played': 12108, # 'minutes_played': 12108,
'yellow_card':10, # 'yellow_card':10,
'red_card': 0, # 'red_card': 0,
'wins':75, # 'wins':75,
'draws': 35, # 'draws': 35,
'lost': 48 # 'lost': 48
} # }
return render_template('representation.html', nation_stats=nation_stats) response_json = {}
staty = robert_stats(id_klubu="polska")[2][0]
response_json["goals"] = staty["goals"]
response_json["assist"] = staty["assists"]
response_json["matches"] = staty["unique_items"]
response_json["minutes_played"] = staty["time_played"]
response_json["yellow_card"] = staty["yellow_cards"]
response_json["red_card"] = staty["red_cards"]
response_json["wins"] = staty["wins"]
response_json["draws"] = staty["draws"]
response_json["lost"] = staty["losses"]
return render_template('representation.html', nation_stats=response_json)
def compare(): def compare():
selected_player = request.args.get("player","Leo Messi") selected_player = request.args.get("player","Leo Messi")
lewy=get_lewy_stats() lewy=get_lewy_stats()
player2 = [ player2 = [
{'name':'Leo Messi','goals': 34,'assists': 12}, {'name':'Leo Messi','goals': 865,'assists': 384,'matches':1103},
{'name':'Cristiano Ronaldo','goals': 937,'assists': 257,'matches':1280},
{'name':'Kylian Mbappé','goals': 330,'assists': 187,'matches':436},
{'name':'Zlatan Ibrahimović','goals': 573,'assists': 200,'matches':988},
{'name':'Luis Suárez','goals': 511,'assists': 277,'matches':858},
{'name':'Erling Haaland','goals': 276,'assists': 49,'matches':342},
{'name':'Karim Benzema','goals': 438,'assists': 160,'matches':820},
{'name':'Sergio Agüero','goals': 385,'assists': 118,'matches':685},
] ]
return render_template('compare.html',player2=player2, selected_player=selected_player,**lewy, ) return render_template('compare.html',player2=player2, selected_player=selected_player,**lewy, )
def trophies(): def trophies():
trophy = [ trophy = [
{'name': 'asdasd', 'year': 2023}, {'name': 'Piłkarz Roku FIFA', 'year':'2021'},
{'name': 'ssss', 'sezon': '2022/2023'}, {'name': 'Piłkarz Roku FIFA', 'year':'2020'},
{'name': 'UEFA Best Player in Europe', 'year':'2020'},
{'name': 'Zdobywca Złotego Buta (Europe)', 'sezon':'2021/2022'},
{'name': 'Zdobywca Złotego Buta (Europe)', 'sezon':'2020/2021'},
{'name': 'Piłkarz roku', 'sezon':'2021'},
{'name': 'Piłkarz roku', 'sezon':'2021'},
{'name': 'Piłkarz roku', 'sezon':'2020'},
{'name': 'Piłkarz roku', 'sezon':'2020'},
{'name': 'Piłkarz roku', 'sezon':'2019'},
{'name': 'Piłkarz roku', 'sezon':'2017'},
{'name': 'Piłkarz roku', 'sezon':'2016'},
{'name': 'Piłkarz roku', 'sezon':'2015'},
{'name': 'Piłkarz roku', 'sezon':'2014'},
{'name': 'Piłkarz roku', 'sezon':'2013'},
{'name': 'Piłkarz roku', 'sezon':'2012'},
{'name': 'Piłkarz roku', 'sezon':'2011'},
{'name': 'Król strzelców', 'sezon':'2022/2023'},
{'name': 'Król strzelców', 'sezon':'2021/2022'},
{'name': 'Król strzelców', 'sezon':'2020/2021'},
{'name': 'Król strzelców', 'sezon':'2019/2020'},
{'name': 'Król strzelców', 'sezon':'2019/2020'},
{'name': 'Król strzelców', 'sezon':'2018/2019'},
{'name': 'Król strzelców', 'sezon':'2018/2019'},
{'name': 'Król strzelców', 'sezon':'2017/2018'},
{'name': 'Król strzelców', 'sezon':'2017/2018'},
{'name': 'Król strzelców', 'sezon':'2016/2017'},
{'name': 'Król strzelców', 'sezon':'2016/2017'},
{'name': 'Król strzelców', 'sezon':'2015/2016'},
{'name': 'Król strzelców', 'sezon':'2015/2016'},
{'name': 'Król strzelców', 'sezon':'2013/2014'},
{'name': 'Król strzelców', 'sezon':'2011/2012'},
{'name': 'Król strzelców', 'sezon':'2009/2010'},
{'name': 'Zdobywca Ligi Mistrzów', 'sezon':'2019/2020'},
{'name': 'Zdobywca Klubowych Mistrzostw Świata', 'sezon':'2021'},
{'name': 'Mistrz Hiszpanii', 'sezon':'2024/2025'},
{'name': 'Mistrz Hiszpanii', 'sezon':'2022/2023'},
{'name': 'Mistrz Niemiec', 'sezon':'2021/2022'},
{'name': 'Mistrz Niemiec', 'sezon':'2020/2021'},
{'name': 'Mistrz Niemiec', 'sezon':'2019/2020'},
{'name': 'Mistrz Niemiec', 'sezon':'2018/2019'},
{'name': 'Mistrz Niemiec', 'sezon':'2017/2018'},
{'name': 'Mistrz Niemiec', 'sezon':'2016/2017'},
{'name': 'Mistrz Niemiec', 'sezon':'2015/2016'},
{'name': 'Mistrz Niemiec', 'sezon':'2014/2015'},
{'name': 'Mistrz Niemiec', 'sezon':'2011/2012'},
{'name': 'Mistrz Niemiec', 'sezon':'2010/2011'},
{'name': 'Mistrz Niemiec', 'sezon':'2020/2021'},
{'name': 'Zdobywca Superpucharu UEFA', 'sezon':'2020/2021'},
{'name': 'Zdobywca Pucharu Niemiec', 'sezon':'2019/2020'},
{'name': 'Zdobywca Pucharu Niemiec', 'sezon':'2018/2019'},
{'name': 'Zdobywca Pucharu Niemiec', 'sezon':'2015/2016'},
{'name': 'Zdobywca Pucharu Niemiec', 'sezon':'2011/2012'},
{'name': 'Zdobywca Pucharu Hiszpanii', 'sezon':'2024/2025'},
{'name': 'Zdobywca Superpucharu Niemiec', 'sezon':'2021/2022'},
{'name': 'Zdobywca Superpucharu Niemiec', 'sezon':'2020/2021'},
{'name': 'Zdobywca Superpucharu Niemiec', 'sezon':'2018/2019'},
{'name': 'Zdobywca Superpucharu Niemiec', 'sezon':'2017/2018'},
{'name': 'Zdobywca Superpucharu Niemiec', 'sezon':'2016/2017'},
{'name': 'Zdobywca Superpucharu Niemiec', 'sezon':'2013/2014'},
{'name': 'Zdobywca Superpucharu Hiszpanii', 'sezon':'2024/2025'},
{'name': 'Zdobywca Superpucharu Hiszpanii', 'sezon':'2022/2023'},
{'name': 'Mistrz Polski', 'sezon':'2009/2010'},
{'name': 'Zdobywca Superpucharu Polski', 'sezon': '2009/2010'},
{'name': 'Zdobywca Pucharu Polski', 'sezon': '2008/2009'},
] ]
return render_template('trophies.html',trophy=trophy) return render_template('trophies.html',trophy=trophy)

File diff suppressed because it is too large Load Diff

View File

@@ -386,6 +386,34 @@ header button {
display: none; display: none;
} }
} }
@media (max-width: 600px){
.section__matches
{
font-size: 10px;
}
.section__matches th{
padding: 3px;
}
.club-stats-grid
{
grid-template-columns: 1fr 1fr !important;
}
.club-stats-grid .stat-box
{
width: 100%;
}
.section-stats-center .section-stats .stats
{
display: flex;
flex-direction: column;
align-items: center;
}
.section-stats-center .section-stats .stats .stat-box
{
width: 100%;
padding: 0;
}
}
@@ -717,6 +745,26 @@ body.poland-mode .general-stats-section .grid article:nth-child(3){background-co
body.poland-mode .about-section-image::after{ body.poland-mode .about-section-image::after{
background:var(--polska-red-dark); background:var(--polska-red-dark);
} }
body.poland-mode .section__matches
{
background-color: white;
}
body.poland-mode .section__matches h2
{
background-color: var(--polska-red);
color: white;
}
body.poland-mode .section__matches th
{
color: var(--barca-red)
}
body.poland-mode .section__matches tr:hover:has(:not(th))
{
background-color: #ff5959;
}
body.poland-mode select{
background:var(--section-color);
}
/* Przyciski i elementy */ /* Przyciski i elementy */
@@ -733,6 +781,13 @@ body.poland-mode .about-section-image::after{
margin-bottom: 10px; margin-bottom: 10px;
width: 100%; width: 100%;
} }
.section-stats h1{
font-size: 34px;
color: var(--barca-red);
}
body.poland-mode .section-stats h1{
color: white;
}
.section-stats-center .section-stats-center
{ {
display: grid; display: grid;
@@ -852,3 +907,31 @@ select
border-radius: 10px; border-radius: 10px;
border: 2px solid white; border: 2px solid white;
} }
@media (max-width: 600px){
.sectionmatches
{
font-size: 10px;
}
.sectionmatches th{
padding: 3px;
}
.club-stats-grid
{
grid-template-columns: 1fr 1fr !important;
}
.club-stats-grid .stat-box
{
width: 100%;
}
.section-stats-center .section-stats .stats
{
display: flex;
flex-direction: column;
align-items: center;
}
.section-stats-center .section-stats .stats .stat-box
{
width: 100%;
padding: 0;
}
}

View File

@@ -4,59 +4,59 @@
{% block content %} {% block content %}
<section class="choose-club"> <section class="choose-club">
<a href="{{ url_for('clubs', club='FC Barcelona') }}"> <a href="{{ url_for('clubs', club='barcelona') }}">
<button><img src="{{ url_for('static', filename='FC_Barcelona.png') }}"></button> <button><img src="{{ url_for('static', filename='FC_Barcelona.png') }}"></button>
</a> </a>
<a href="{{ url_for('clubs', club='Bayern Monachium') }}"> <a href="{{ url_for('clubs', club='bayern') }}">
<button><img src="{{ url_for('static', filename='FC_Bayern.png') }}"></button> <button><img src="{{ url_for('static', filename='FC_Bayern.png') }}"></button>
</a> </a>
<a href="{{ url_for('clubs', club='Borussia Dortmund') }}"> <a href="{{ url_for('clubs', club='dortmund') }}">
<button><img src="{{ url_for('static', filename='Borussia_Dortmund.png') }}"></button> <button><img src="{{ url_for('static', filename='Borussia_Dortmund.png') }}"></button>
</a> </a>
<!--Jak nie będzie statysytk dla lecha to usunać--> <!--Jak nie będzie statysytk dla lecha to usunać-->
<a href="{{ url_for('clubs', club='Lech Poznan') }}"> <!-- <a href="{{ url_for('clubs', club='Lech Poznan') }}">
<button><img src="{{ url_for('static', filename='Lech_Poznan.png') }}"></button> <button><img src="{{ url_for('static', filename='Lech_Poznan.png') }}"></button>
</a> </a> -->
</section> </section>
<!-- Wyświetlanie danych tylko dla wybranego klubu --> <!-- Wyświetlanie danych tylko dla wybranego klubu -->
{% for stats in clubs %} {#{% for stats in clubs %}#}
{% if stats.club == selected_club %} {#{% if stats.club == selected_club %}#}
<section class="club-stats"> <section class="club-stats">
<h2>Statystyki dla {{selected_club}}</h2> <h2>Statystyki dla {{resp_json.club}}</h2>
<div class="wybrany{{selected_club}}"></div> <div class="wybrany{{resp_json.club}}"></div>
<div class="club-stats-grid"> <div class="club-stats-grid">
<div class="stat-box"> <div class="stat-box">
<p>Gole:</p> <span class="stat-box-special"> {{ stats.goals }} </span> <p>Gole:</p> <span class="stat-box-special"> {{ resp_json.goals }} </span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Asysty:</p> <span class="stat-box-special"> {{ stats.assist }} </span> <p>Asysty:</p> <span class="stat-box-special"> {{ resp_json.assist }} </span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Występy:</p> <span class="stat-box-special"> {{ stats.matches }} </span> <p>Występy:</p> <span class="stat-box-special"> {{ resp_json.matches }} </span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Łączny czas gry:</p> <span class="stat-box-special"> {{ stats.minutes_played }}</span> <p>Łączny czas gry:</p> <span class="stat-box-special"> {{ resp_json.minutes_played }}</span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Żółte kartki:</p> <span class="stat-box-special"> {{ stats.yellow_card }}</span> <p>Żółte kartki:</p> <span class="stat-box-special"> {{ resp_json.yellow_card }}</span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Czerwone kartki:</p> <span class="stat-box-special"> {{ stats.red_card }}</span> <p>Czerwone kartki:</p> <span class="stat-box-special"> {{ resp_json.red_card }}</span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Zwycięstwa:</p> <span class="stat-box-special"> {{ stats.wins }}</span> <p>Zwycięstwa:</p> <span class="stat-box-special"> {{ resp_json.wins }}</span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Remisy:</p> <span class="stat-box-special"> {{ stats.draws }}</span> <p>Remisy:</p> <span class="stat-box-special"> {{ resp_json.draws }}</span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Porażki:</p> <span class="stat-box-special"> {{ stats.lost }}</span> <p>Porażki:</p> <span class="stat-box-special"> {{ resp_json.lost }}</span>
</div> </div>
</div> </div>
</section> </section>
{% endif %} {#{% endif %}#}
{% endfor %} {#{% endfor %}#}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

View File

@@ -6,13 +6,19 @@
<select onchange="location = this.value;"> <select onchange="location = this.value;">
<option disabled selected>Wybierz zawodnika</option> <option disabled selected>Wybierz zawodnika</option>
<option value="{{ url_for('compare', player='Leo Messi') }}">Leo Messi</option> <option value="{{ url_for('compare', player='Leo Messi') }}">Leo Messi</option>
<option value="{{ url_for('compare', player='Ronaldo') }}">Cristiano Ronaldo</option> <option value="{{ url_for('compare', player='Cristiano Ronaldo') }}">Cristiano Ronaldo</option>
<option value="{{ url_for('compare', player='Neymar') }}">Neymar</option> <option value="{{ url_for('compare', player='Kylian Mbappé') }}">Kylian Mbappé</option>
<option value="{{ url_for('compare', player='Zlatan Ibrahimović') }}">Zlatan Ibrahimović</option>
<option value="{{ url_for('compare', player='Luis Suárez') }}">Luis Suárez</option>
<option value="{{ url_for('compare', player='Erling Haaland') }}">Erling Haaland</option>
<option value="{{ url_for('compare', player='Karim Benzema') }}">Karim Benzema</option>
<option value="{{ url_for('compare', player='Sergio Agüero') }}">Sergio Agüero</option>
</select> </select>
{%for player in player2 %} {%for player in player2 %}
{% if player.name == selected_player %} {% if player.name == selected_player %}
<section class="section-stats"> <section class="section-stats">
<h1>Robert Lewandowski VS {{selected_player}}</h1>
<h2>Gole</h2> <h2>Gole</h2>
<div class="stats"> <div class="stats">
<div class="stat-box"> <div class="stat-box">
@@ -41,26 +47,15 @@
<h2>Wystąpienia</h2> <h2>Wystąpienia</h2>
<div class="stats"> <div class="stats">
<div class="stat-box"> <div class="stat-box">
<h3>{{ all_time_stats.assists }}</h3> <h3>{{ all_time_stats.matches }}</h3>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<h3>{{ player.assists}}</h3> <h3>{{ player.matches}}</h3>
</div> </div>
</div> </div>
<h2>Minuty zagrane</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ all_time_stats.assists }}</h3>
</div>
<div class="stat-box">
<h3>{{ player.assists}}</h3>
</div>
</div>
</section> </section>
{% endif %} {% endif %}
{% endfor%} {% endfor%}

View File

@@ -10,27 +10,27 @@
<article class="article__how-it-works"> <article class="article__how-it-works">
<h3>Jak to działa?</h3> <h3>Jak to działa?</h3>
<h4>Pobieranie statystyk</h4> <h4>Pobieranie statystyk</h4>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Ratione harum minus hic, voluptate perspiciatis laborum? Alias maxime, voluptate reprehenderit iusto dolorem officiis porro voluptatibus repellat dicta doloribus, blanditiis similique accusantium.</p> <p>Tu znajdziesz najświeższe statystyki, aktualizowane zaraz po zakończeniu meczu Lewego</p>
<h4>Porównywanie zawodników</h4> <h4>Porównywanie zawodników</h4>
<p>Lorem, ipsum dolor sit amet consectetur adipisicing elit. Fuga, in perspiciatis. Sequi laborum et animi quas sit voluptatibus alias sed ad molestias nulla vel cum, consectetur commodi odio aliquam officia.</p> <p>Robert Lewandowski jest uznawany za jednego z najlepszych zawodników na świecie, zobacz jak wypada w porównaniu do innych czołowych zawodników i sprawdź czy zasługuje na miano jednego z najlepszych napastników świata.</p>
</article> </article>
<div class="about-section-image"> <div class="about-section-image">
<img src="{{ url_for('static', filename='gigabuła.png') }}"> <img src="{{ url_for('static', filename='gigabuła.png') }}">
</div> </div>
<article> <article>
<h3>Mecze</h3> <h3>Mecze</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Soluta ullam iusto ex? Quo amet officia aliquam odio sint harum nam eaque nihil ipsa quos aliquid, illum voluptatum, numquam, magnam omnis?</p> <p>Nie oglądałeś ostatniego meczu Barcelony? Wypadło Ci coś i nie widziałeś najnowszego spotkania reprezentacji Polski? Wejdź i sprawdź jak poradził sobie Robert.</p>
<a href="/mecze">Zobacz mecze</a> <a href="/mecze">Zobacz mecze</a>
</article> </article>
<article> <article>
<h3>Statystyki</h3> <h3>Statystyki</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Temporibus dolore tenetur nulla sint recusandae illo dolores aspernatur ducimus, omnis vitae ipsam neque animi voluptates eos porro, nihil iusto veniam commodi!</p> <p>Jesteś zainteresowany jak Robert radzi sobie na przestrzeni tylu lat gry? Jesteś ciekaw czy napastnik oprócz strzelania bramek lubi kolekcjonować kartki? Sprawdź u nas jak wygląda kariera Roberta Lewandowskiego na podstawie jego gry w kadrze Polski, klubach oraz Pucharach ligowych i międzynarodowych.</p>
<a href="/statystyki">Zobacz statystyki</a> <a href="/statystyki">Zobacz statystyki</a>
</article> </article>
<article> <article>
<h3>Osiągnięcia</h3> <h3>Trofea</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quod dicta veritatis quibusdam eligendi corrupti. Expedita delectus assumenda ipsum illum molestias a voluptates, voluptas quia reprehenderit, quod non, eum veritatis tenetur!</p> <p>Zastanawia Cie jakie było ostatnie trofeum Roberta? A może z kolegami sprawdzacie, który lepiej pamięta złote chwile w karierze naszego idola? Rozwiejcie wasze wątpliwości i zobaczcie wielką kolekcji zdobyczy pucharowych najlepszego polskiego zawodnika.</p>
<a href="/club">Zobacz osiągnięcia</a> <a href="/club">Zobacz trofea</a>
</article> </article>
</section> </section>
<!-- <!--
@@ -57,5 +57,7 @@
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}
<!--
{{ commit_in_html | safe }} {{ commit_in_html | safe }}
-->
{% endblock %} {% endblock %}

View File

@@ -3,35 +3,50 @@
{% block title %}Lista meczów{% endblock %} {% block title %}Lista meczów{% endblock %}
{% block content %} {% block content %}
<select> <select onchange="location = this.value;">
<option disabled selected>Wybierz rok</option> <option disabled selected>Wybierz rok</option>
<option value="{{ url_for('compare', player='Leo Messi') }}">2024/2025</option> <option value="{{ url_for('mecze', date='2025') }}">2025</option>
<option value="{{ url_for('compare', player='Ronaldo') }}">2023/2024</option> <option value="{{ url_for('mecze', date='2024') }}">2024</option>
<option value="{{ url_for('compare', player='Neymar') }}">2022/2023</option> <option value="{{ url_for('mecze', date='2023') }}">2023</option>
<option value="{{ url_for('compare', player='Neymar') }}">2021/2022</option> <option value="{{ url_for('mecze', date='2022') }}">2022</option>
<option value="{{ url_for('compare', player='Neymar') }}">2020/2021</option> <option value="{{ url_for('mecze', date='2021') }}">2021</option>
<option value="{{ url_for('compare', player='Neymar') }}">2019/2020</option> <option value="{{ url_for('mecze', date='2020') }}">2020</option>
<option value="{{ url_for('compare', player='Neymar') }}">2018/2019</option> <option value="{{ url_for('mecze', date='2019') }}">2019</option>
<option value="{{ url_for('compare', player='Neymar') }}">2017/2018</option> <option value="{{ url_for('mecze', date='2018') }}">2018</option>
<option value="{{ url_for('compare', player='Neymar') }}">2016/2017</option> <option value="{{ url_for('mecze', date='2017') }}">2017</option>
<option value="{{ url_for('mecze', date='2016') }}">2016</option>
<option value="{{ url_for('mecze', date='2015') }}">2015</option>
<option value="{{ url_for('mecze', date='2014') }}">2014</option>
</select> </select>
<section class="section__matches"> <section class="section__matches">
<h2>📅 Mecze Roberta</h2> <h2>📅 Mecze Roberta</h2>
<table> <table>
<tr> <tr>
<th>Data</th> <th>Data</th>
<!--
<th>Przeciwnik</th> <th>Przeciwnik</th>
<th>Gole</th> <th>Gole</th>
<th>Asysty</th> <th>Asysty</th>
<th>Minuty</th> <th>Minuty</th>
-->
<th>Gospodarze</th>
<th>Wynik</th>
<th>Goście</th>
<th></th>
</tr> </tr>
{% for match in matches %} {% for match in matches %}
<tr> <tr>
<td>{{ match.date }}</td> <td>{{ match.data }}</td>
<td>{{ match.opponent }}</td>
<td>{{ match.gospodarze_pelna_nazwa }}</td>
<td>{{ match.gosp_wynik }} : {{ match.gosc_wynik }}</td>
<td>{{ match.goscie_pelna_nazwa }}</td>
<!--
<td>{{ match.goals }}</td> <td>{{ match.goals }}</td>
<td>{{ match.assists }}</td> <td>{{ match.assists }}</td>
<td>{{ match.minutes }}</td> <td>{{ match.minutes }}</td>
-->
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View File

@@ -11,10 +11,10 @@
<p>Gole:</p> <span class="stat-box-special"> {{ nation_stats.goals }} </span> <p>Gole:</p> <span class="stat-box-special"> {{ nation_stats.goals }} </span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Asysty:</p> <span class="stat-box-special"> {{ nation_stats.assists }} </span> <p>Asysty:</p> <span class="stat-box-special"> {{ nation_stats.assist }} </span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Występy:</p> <span class="stat-box-special"> {{ nation_stats.goals }} </span> <p>Występy:</p> <span class="stat-box-special"> {{ nation_stats.matches }} </span>
</div> </div>
<div class="stat-box"> <div class="stat-box">
<p>Łączny czas gry:</p> <span class="stat-box-special"> {{ nation_stats.minutes_played }}</span> <p>Łączny czas gry:</p> <span class="stat-box-special"> {{ nation_stats.minutes_played }}</span>

View File

@@ -55,8 +55,9 @@
<p>Występy</p> <p>Występy</p>
</div> </div>
</section> </section>
<!--
<section class="section-stats"> <section class="section-stats">
<h2>Puchary międzynarodowe</h2> <h2>(!) Puchary międzynarodowe</h2>
<div class="stats"> <div class="stats">
<div class="stat-box"> <div class="stat-box">
<h3>{{ international_cups.goals }}</h3> <h3>{{ international_cups.goals }}</h3>
@@ -73,7 +74,7 @@
</div> </div>
</section> </section>
<section class="section-stats"> <section class="section-stats">
<h2>Puchary krajowe</h2> <h2>(!) Puchary krajowe</h2>
<div class="stats"> <div class="stats">
<div class="stat-box"> <div class="stat-box">
<h3>{{ national_cups.goals }}</h3> <h3>{{ national_cups.goals }}</h3>
@@ -89,6 +90,7 @@
</div> </div>
</div> </div>
</section> </section>
-->
<section class="section-stats"> <section class="section-stats">
<h2>Kartki</h2> <h2>Kartki</h2>
<div class="stats"> <div class="stats">
@@ -103,4 +105,21 @@
</div> </div>
</div> </div>
</section> </section>
<section class="section-stats">
<h2>Wygrane, remisy i przegrane</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ wins_losses.wins }}</h3>
<p>Wygrane</p>
</div>
<div class="stat-box">
<h3>{{ wins_losses.draws }}</h3>
<p>Remisy</p>
</div>
<div class="stat-box">
<h3>{{ wins_losses.losses }}</h3>
<p>Przegrane</p>
</div>
</div>
</section>
{% endblock %} {% endblock %}

View File

@@ -4,7 +4,7 @@
{% block content %} {% block content %}
<section class="section__matches"> <section class="section__matches">
<h2>📅 Trofea</h2> <h2>🏆 Trofea</h2>
<table> <table>
<tr> <tr>
<th>Nazwa</th> <th>Nazwa</th>