38 Commits

Author SHA1 Message Date
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
c86a93c153 fix: i forgor to add some waiting time to avoid rate limiting 2025-06-05 19:22:05 +02:00
43eb1d421d Merge branch 'ScraperTest' 2025-06-05 19:18:49 +02:00
c2568c86ef fix: scraper fixes, list matches 2025-06-05 19:18:31 +02:00
cf46fdfbb7 data for stats 2025-06-05 18:47:30 +02:00
791d20139d chore: offload some shared functionality to other methods
should also fix unexpected db behavior (hangs and disconnects)
2025-06-05 16:31:45 +02:00
c3a6626d6f fix: display commit info properly 2025-06-05 11:40:56 +02:00
5960e44b17 Merge pull request 'merge new front-end' (#3) from frontend into master
Reviewed-on: #3
2025-06-05 10:30:28 +02:00
919d64ca5e Merge branch 'master' into frontend 2025-06-05 10:30:04 +02:00
2cfa5f1fa4 poland-style changes 2025-06-05 10:27:11 +02:00
9b45a3f26f polandmode statbox color 2025-06-05 00:47:59 +02:00
3dfc40cdb0 trophies update and hamburger fix 2025-06-05 00:40:47 +02:00
Pc
13f6e2e3b9 Added rest of player updating code 2025-06-04 20:34:26 +02:00
Pc
9a007f504c Wins update 2025-06-04 19:56:32 +02:00
Pc
b5fdbb3230 Updating matches
Updating players stats(not finished)
Not tested
2025-06-04 19:50:18 +02:00
be951d296f representation changes 2025-06-04 17:02:57 +02:00
6e1e8ccc7d stats maches club style changes 2025-06-04 16:55:31 +02:00
03463905ef fixing responsive 2025-06-04 15:32:03 +02:00
35db71b8cc feat: get sportsmen full name and birthday from id 2025-06-04 00:19:57 +02:00
f65a174089 skeleton to all sites (i hope) 2025-06-03 23:26:30 +02:00
bdfa31c8ea fix: check for id in simple_insert_one() to avoid breaking autoincrement 2025-06-03 21:46:59 +02:00
19 changed files with 12611 additions and 278 deletions

View File

@@ -1,20 +1,12 @@
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
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"error reading: {' -> '.join(path)} - returning: {default}")
finally:
return result
class scraper: class scraper:
@@ -45,34 +37,65 @@ class scraper:
else: else:
return False return False
def to_iso_compatible_date(self, dmy_date: str):
"""
Zamienia datę z formatu DD.MM.YY na YYYY-MM-DD
:param dmy_date: Data w formacie DD.MM.YY
:type dmy_date: str
"""
day, month, year = dmy_date.split(".")
return f"{2000 + int(year)}-{month}-{day}"
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"):
"""
Scraper z dykty xD
Pobiera imiona, nazwiska i dni urodzin sportowców z zewnętrznego id.
Działa na słowo honoru.
:param zewnetrzne_id_sportowca: Zewnętrzne id sportowca
:type zewnetrzne_id_sportowca: str
"""
if len(zewnetrzne_id_sportowca) != 8:
raise ValueError("Zewnętrzne ID sportowca powinno być długości 8!")
r = requests.get(f'https://www.flashscore.pl/?r=4:{zewnetrzne_id_sportowca}')
page = r.text
name_start_pos = page.find("data-testid=\"wcl-scores-heading-02\">") + 36
name_end_pos = page.find("</", name_start_pos)
name = page[name_start_pos:name_end_pos].strip().split(' ')
# Tak wiem... można by było użyć beautifulsoup4, ale nie ma sensu dodawać nowych zależności dla tylko jednej metody.
birthday_start_pos_1 = page.find("data-testid=\"wcl-scores-simpleText-01\">", name_end_pos) + 39
birthday_start_pos_2 = page.find("data-testid=\"wcl-scores-simpleText-01\">", birthday_start_pos_1) + 39
birthday_start_pos_3 = page.find("data-testid=\"wcl-scores-simpleText-01\">", birthday_start_pos_2) + 39
birthday_start_pos = page.find("data-testid=\"wcl-scores-simpleText-01\">", birthday_start_pos_3) + 39
birthday_end_pos = page.find("</", birthday_start_pos) - 1
birthday = None if birthday_end_pos - birthday_start_pos > 20 else page[birthday_start_pos:birthday_end_pos].strip(" ()")
return name, birthday
def aktualizuj_dane_sportowca(self, zewnetrzne_id_sportowca: str = "MVC8zHZD"): def aktualizuj_dane_sportowca(self, zewnetrzne_id_sportowca: str = "MVC8zHZD"):
stop_scraping = False stop_scraping = False
matches_to_add = [] matches_to_add = []
# TODO: Sprawdź, czy sportowiec istnieje w bazie. # TODO: Sprawdź, czy sportowiec istnieje w bazie.
if not self.__czy_x_istnieje("sportowcy", zewnetrzne_id_sportowca=zewnetrzne_id_sportowca): # Jeśli nie, dodaj go w podobny sposób, jak
print(f"{c.OKCYAN}Dodaję nowego sportowca do bazy danych{c.ENDC}") # w sample_data_init() (w lewy_db.py).
self.db.simple_insert_one("sportowcy", # -- Jednak tego tak nie robimy, ponieważ nie uzyskamy wielu informacji.
zewnetrzne_id_sportowca=zewnetrzne_id_sportowca,
imie="Robert", id_zawodnika = self.db.get_id_zawodnika_by_zewnetrzne_id(zewnetrzne_id_sportowca)
nazwisko="Lewandowski" zawodnik = self.db.simple_select_all("sportowcy", zewnetrzne_id_zawodnika=zewnetrzne_id_sportowca)[0]
)
page = 0 page = 0
match_num = 0 match_num = 0
@@ -88,14 +111,35 @@ class scraper:
retrieved_matches = safe_traverse(retrieved_page, ["lastMatches"], default=[]) retrieved_matches = safe_traverse(retrieved_page, ["lastMatches"], default=[])
for match in retrieved_matches: for match in retrieved_matches:
match_id = safe_traverse(match, ["eventEncodedId"], default="non-existent-match-id") match_id = safe_traverse(match, ["eventEncodedId"], default="non-existent-match-id")
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")
if self.czy_mecz_istnieje(zewnetrzne_id_meczu=match_id): # ~Sprawdź, czy mecz nie znajduje się już w bazie~
#
# 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,
# 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):
print(f"{c.OKCYAN}Nowy klub{c.ENDC}: {home_club_id}") print(f"{c.OKCYAN}Nowy klub{c.ENDC}: {home_club_id}")
self.db.simple_insert_one("kluby", self.db.simple_insert_one("kluby",
@@ -109,40 +153,104 @@ 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: Zamień słownik match na obiekt mecz # TODO: dodaj obiekt mecz do bazy (simple_insert_one(), simple_insert_many())
mecz = { print(f"{c.OKCYAN}Nowy mecz ({match_num}){c.ENDC}: {match}")
"zewnetrzne_id_meczu": match_id,
"data": safe_traverse(match, ["startTimeTimestamp"], default=0), iso_converted_date = self.to_iso_compatible_date(safe_traverse(match, ["eventStartTime"], default="1970-01-01"))
"id_klubu_gospodarzy": home_club_id,
"id_klubu_gosci": away_club_id,
"gole_gospodarzy": safe_traverse(match, ["homeScore", "current"], default=0),
"gole_gosci": safe_traverse(match, ["awayScore", "current"], default=0),
"rozgrywki": safe_traverse(match, ["tournament", "name"], default="Brak"),
"zewnetrzne_id_sportowca": zewnetrzne_id_sportowca
}
# TODO: Dodaj obiekt mecz do bazy self.db.simple_insert_one("mecze",
self.db.simple_insert_one("mecze", **mecz) zewnetrzne_id_meczu = safe_traverse(match, ["eventEncodedId"], default=""),
data = iso_converted_date,
print(f"{c.OKCYAN}Nowy mecz ({match_num}){c.ENDC}: {match_id}") gospodarze_id = home_club_id,
gospodarze = self.db.simple_select_all("kluby", id_klubu=home_club_id)[0],
goscie_id = away_club_id,
goscie = self.db.simple_select_all("kluby", id_klubu=away_club_id)[0],
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 match_num += 1
# TODO: Zaktualizuj statystyki sportowca stats = safe_traverse(match, ["stats"], default="")
# np. zlicz gole RL9 zewnetrzne_id_meczu = safe_traverse(match, ["eventEncodedId"], default="")
strzelcy = safe_traverse(match, ["goals"], default=[])
liczba_goli = 0
for gol in strzelcy:
if gol.get("playerId") == zewnetrzne_id_sportowca:
liczba_goli += 1
if liczba_goli > 0: if stats != False: # gdy sportowiec był aktywny w meczu
# zwiększamy liczbę goli zawodnika # print("todo :)")
print(f"{c.OKBLUE}Zwiększam gole Lewandowskiego o {liczba_goli}{c.ENDC}") self.db.simple_insert_one("sportowcy_w_meczach",
self.db.increment_stat("sportowcy", {"zewnetrzne_id_sportowca": zewnetrzne_id_sportowca}, "gole", liczba_goli) id_zawodnika = id_zawodnika,
zawodnik = zawodnik,
zewnetrzne_id_meczu = zewnetrzne_id_meczu,
# Uwaga! Czasami przygłupy z flashscore zwracają puste pole '' zamiast zera, np. do liczby strzelonych goli.
# Dlatego int("0" + "") = int("0"), co zapobiegnie wysypaniu się przy int("").
czas_gry = int("0" + safe_traverse(stats, ["595", "value"], default="0").rstrip("'?")),
goli = int("0" + safe_traverse(stats, ["596", "value"], default="0")),
asyst = int("0" + safe_traverse(stats, ["541", "value"], default="0")),
interwencje_bramkarza = 0,
suma_interwencji_na_bramke = 0,
zolte_kartki = int("0" + safe_traverse(stats, ["599", "value"], default="0")),
czerwone_kartki = int("0" + safe_traverse(stats, ["600", "value"], default="0")),
wygrana = {"Z": 1, "R": 0, "P": -1}.get(safe_traverse(match, ["winLoseShort"], default=""), 0),
wynik = safe_traverse(match, ["rating"], default=0) or 0
)
# # analogicznie zinkrementuj statystyki_sportowcow:
# # aby to zrobić, najpierw pobierz najnowszą statystykę sportowca
# # ...
#
#
# # 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,
# 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,
# minut_gry = int(safe_traverse(stats, ["595", "value"], default="0").rstrip("'")),
# gier_sum = 1 if int(safe_traverse(stats, ["595", "value"], default="0").rstrip("'")) > 0 else 0,
# goli_sum = int(safe_traverse(stats, ["596", "value"], default="0")),
# asyst_sum = int(safe_traverse(stats, ["541", "value"], default="0")),
# interwencji_sum = 0,
# nieobronionych_interwencji_sum = 0,
# zoltych_kartek_sum = int(safe_traverse(stats, ["599", "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,
# 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
# )
else:
# print("też todo :)")
# # TODO: TU TEŻ TRZEBA POPRAWIĆ ANALOGICZNIE DO TEGO, CO JEST WEWNĄTRZ IF'A
self.db.simple_insert_one("sportowcy_w_meczach",
id_zawodnika = id_zawodnika,
zawodnik = zawodnik,
zewnetrzne_id_meczu = zewnetrzne_id_meczu,
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 = int("0" + safe_traverse(stats, ["596", "value"], default="0")),
asyst = int("0" + safe_traverse(stats, ["541", "value"], default="0")),
interwencje_bramkarza = 0,
suma_interwencji_na_bramke = 0,
zolte_kartki = int("0" + safe_traverse(stats, ["599", "value"], default="0")),
czerwone_kartki = int("0" + safe_traverse(stats, ["600", "value"], default="0")),
wygrana = {"Z": 1, "R": 0, "P": -1}.get(safe_traverse(match, ["winLoseShort"], default=""), 0),
wynik = safe_traverse(match, ["rating"], default=0) or 0
)
# TODO: Zaktualizuj statystyki sportowca
# Opcjonalnie: odczekaj kilka sekund (?)
# Problem w tym, że time.sleep() jest blokujące,
# a asyncio i flask nie idą ze sobą w parze.
# Można to załatwić osobnym skryptem, ale
# martwmy się tym dopiero, gdy dostaniemy
# rate limita. - sherl
page += 1 page += 1
time.sleep(15) #time.sleep(5)
def aktualizuj_dane(self): def aktualizuj_dane(self):
@@ -150,8 +258,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,7 +13,7 @@ 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
@@ -58,23 +58,28 @@ def setup():
sanity_string += f" If you're running a reverse proxy, set {c.OKCYAN}is_proxied{c.ENDC} to true to silence this message.\n" sanity_string += f" If you're running a reverse proxy, set {c.OKCYAN}is_proxied{c.ENDC} to true to silence this message.\n"
print(sanity_string) print(sanity_string)
# Should fix disconnects: https://stackoverflow.com/a/61739721
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {"pool_pre_ping": True}
app.config['SQLALCHEMY_DATABASE_URI'] = f"{config['general']['db_path_url']}" app.config['SQLALCHEMY_DATABASE_URI'] = f"{config['general']['db_path_url']}"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# Widoki widoczne dla "normalnego" użytkownika: # Widoki widoczne dla "normalnego" użytkownika:
app.add_url_rule('/', view_func=lewy_routes.index) app.add_url_rule('/', view_func=lewy_routes.index)
app.add_url_rule('/index.html', view_func=lewy_routes.index) app.add_url_rule('/index.html', view_func=lewy_routes.index)
app.add_url_rule('/mecze', view_func=lewy_routes.mecze) app.add_url_rule('/mecze', view_func=lewy_routes.mecze)
app.add_url_rule('/statystyki', view_func=lewy_routes.statystyki) app.add_url_rule('/statystyki', view_func=lewy_routes.statystyki)
app.add_url_rule('/toggle_dark_mode', view_func=lewy_routes.toggle_dark_mode) app.add_url_rule('/toggle_dark_mode', view_func=lewy_routes.toggle_dark_mode)
app.add_url_rule('/historia', view_func=lewy_routes.historia) app.add_url_rule('/club', view_func=lewy_routes.clubs)
app.add_url_rule('/representation', view_func=lewy_routes.representation)
app.add_url_rule('/compare', view_func=lewy_routes.compare)
app.add_url_rule('/trophies', view_func=lewy_routes.trophies)
# API: # API:
app.add_url_rule('/api/', view_func=lewy_api.api_greeting) app.add_url_rule('/api/', view_func=lewy_api.api_greeting)
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()
@@ -92,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,16 @@ 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)
# GET /api/v1 # GET /api/v1
def stub_hello(): def stub_hello():
""" """
@@ -85,11 +95,43 @@ 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: str | 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
""" """
pass response_json = []
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:
response_json.append(mecz.jsonify())
# print(f"zwracam mecze: {response_json}")
return 200, "ok", response_json
# GET /api/v1/debugger_halt?token=XXX... # GET /api/v1/debugger_halt?token=XXX...
@require_authentication @require_authentication
@@ -142,7 +184,7 @@ def lookup(data, request):
case 'halt': case 'halt':
return debugger_halt(r = request) return debugger_halt(r = request)
case 'matches': case 'matches':
get_matches(r = request) return get_matches(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
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()
@@ -105,7 +107,7 @@ class baza():
wynik: Mapped[ float] = mapped_column() wynik: Mapped[ float] = mapped_column()
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"
@@ -157,6 +159,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 +171,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,
@@ -486,6 +492,67 @@ 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 @exit_gracefully
def sample_data_init(self, override_safety_check=False): def sample_data_init(self, override_safety_check=False):
""" """
@@ -525,7 +592,12 @@ class baza():
flaga=0) flaga=0)
#Robercik # 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=487, ilosc_wystapien=487,
@@ -542,21 +614,21 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych 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="Barcelona", klub_id="barcelona",
narodowosc="PL", narodowosc="PL",
ilosc_trofeow=0, # Brak danych na Flashscore 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=67_000_000 # Wartość rynkowa: €15.3 mln wycena=67_000_000 # Wartość rynkowa: €15.3 mln
) )
trofeum = trofea( trofeum = trofea(
nazwa="Nieznane trofeum", nazwa="Nieznane trofeum",
@@ -605,7 +677,12 @@ class baza():
# statystyki_id=2, # itd... # statystyki_id=2, # itd...
# wycena=...) # w złotówkach # wycena=...) # w złotówkach
#Ronaldo # Ronaldo
self.simple_insert_one(kluby,
id_klubu="al-nassr",
pelna_nazwa="Al Nassr Riyadh",
skrocona_nazwa="ANR" #?
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=702, ilosc_wystapien=702,
@@ -622,22 +699,28 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="WGOY4FSt", zewnetrzne_id_zawodnika="WGOY4FSt",
imie="Cristiano", imie="Cristiano",
nazwisko="Ronaldo", nazwisko="Ronaldo",
data_urodzenia="05.02.1985", data_urodzenia="05.02.1985",
czy_aktywny=True, czy_aktywny=True,
klub_id="Al Nassr Riyadh", klub_id="al-nassr",
narodowosc="PT", narodowosc="PT",
ilosc_trofeow=0, # Brak danych na Flashscore 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=2, statystyki_id=2,
wycena=55_000_000 # Wartość rynkowa: €12.1 mln wycena=55_000_000 # Wartość rynkowa: €12.1 mln
) )
#Messi
# Messi
self.simple_insert_one(kluby,
id_klubu="inter-miami",
pelna_nazwa="Inter Miami",
skrocona_nazwa="INM"
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=619, ilosc_wystapien=619,
@@ -654,22 +737,28 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="vgOOdZbd", zewnetrzne_id_zawodnika="vgOOdZbd",
imie="Lionel", imie="Lionel",
nazwisko="Messi", nazwisko="Messi",
data_urodzenia="24.06.1987", data_urodzenia="24.06.1987",
czy_aktywny=True, czy_aktywny=True,
klub_id="Inter Miami", klub_id="inter-miami",
narodowosc="AR", narodowosc="AR",
ilosc_trofeow=0, # Brak danych na Flashscore 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=3, statystyki_id=3,
wycena=67_000_000 # Wartość rynkowa: €15.3 mln wycena=67_000_000 # Wartość rynkowa: €15.3 mln
) )
#Mbappe
# Mbappe
self.simple_insert_one(kluby,
id_klubu="real-madryt",
pelna_nazwa="Real Madryt",
skrocona_nazwa="RMA"
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=280, ilosc_wystapien=280,
@@ -686,22 +775,23 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="Wn6E2SED", zewnetrzne_id_zawodnika="Wn6E2SED",
imie="Kylian", imie="Kylian",
nazwisko="Mbappé", nazwisko="Mbappé",
data_urodzenia="20.12.1998", data_urodzenia="20.12.1998",
czy_aktywny=True, czy_aktywny=True,
klub_id="Real Madryt", klub_id="real-madryt",
narodowosc="FR", narodowosc="FR",
ilosc_trofeow=0, # Brak danych na Flashscore 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=4, statystyki_id=4,
wycena=185_700_000 # Wartość rynkowa: €185.7 mln wycena=185_700_000 # Wartość rynkowa: €185.7 mln
) )
#Zlatan
# Zlatan
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=519, ilosc_wystapien=519,
@@ -718,8 +808,8 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="AiH2zDve", zewnetrzne_id_zawodnika="AiH2zDve",
imie="Zlatan", imie="Zlatan",
nazwisko="Ibrahimović", nazwisko="Ibrahimović",
@@ -732,8 +822,9 @@ class baza():
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=5, statystyki_id=5,
wycena=0 # Zakończył karierę wycena=0 # Zakończył karierę
) )
#Suarez
# Suarez
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=608, ilosc_wystapien=608,
@@ -750,22 +841,28 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="dUShzrBp", zewnetrzne_id_zawodnika="dUShzrBp",
imie="Luis", imie="Luis",
nazwisko="Suárez", nazwisko="Suárez",
data_urodzenia="24.01.1987", data_urodzenia="24.01.1987",
czy_aktywny=True, czy_aktywny=True,
klub_id="Inter Miami", klub_id="inter-miami",
narodowosc="UY", narodowosc="UY",
ilosc_trofeow=0, # Brak danych na Flashscore 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=6, statystyki_id=6,
wycena=8_800_000 # Wartość rynkowa: €2.0 mln wycena=8_800_000 # Wartość rynkowa: €2.0 mln
) )
#Haaland
# Haaland
self.simple_insert_one(kluby,
id_klubu="manchester-city",
pelna_nazwa="Manchester City",
skrocona_nazwa="MCI"
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=235, ilosc_wystapien=235,
@@ -782,22 +879,28 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="UmV9iQmE", zewnetrzne_id_zawodnika="UmV9iQmE",
imie="Erling", imie="Erling",
nazwisko="Haaland", nazwisko="Haaland",
data_urodzenia="21.07.2000", data_urodzenia="21.07.2000",
czy_aktywny=True, czy_aktywny=True,
klub_id="Manchester City", klub_id="manchester-city",
narodowosc="NO", narodowosc="NO",
ilosc_trofeow=0, # Brak danych ilosc_trofeow=0, # Brak danych
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=7, statystyki_id=7,
wycena=777_500_000 # ~€178.7 mln wycena=777_500_000 # ~€178.7 mln
) )
#Karim Benzema
# 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, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=589, ilosc_wystapien=589,
@@ -814,23 +917,23 @@ class baza():
remisow_sum=0, remisow_sum=0,
wynik_sum=0, wynik_sum=0,
meczow_do_wynikow_sum=0 meczow_do_wynikow_sum=0
) )
self.simple_insert_one(sportowcy,
sportowiec = sportowcy(
zewnetrzne_id_zawodnika="tpV0VX0S", zewnetrzne_id_zawodnika="tpV0VX0S",
imie="Karim", imie="Karim",
nazwisko="Benzema", nazwisko="Benzema",
data_urodzenia="19.12.1987", data_urodzenia="19.12.1987",
czy_aktywny=True, czy_aktywny=True,
klub_id="Al Ittihad", klub_id="al-ittihad",
narodowosc="FR", narodowosc="FR",
ilosc_trofeow=0, # Flashscore nie podaje ilosc_trofeow=0, # Flashscore nie podaje
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=8, statystyki_id=8,
wycena=31_950_000 # €7.1 mln wycena=31_950_000 # €7.1 mln
) )
#Sergio Aguero
# Sergio Aguero
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=443, ilosc_wystapien=443,
@@ -847,23 +950,28 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
self.simple_insert_one(sportowcy,
sportowiec = sportowcy(
zewnetrzne_id_zawodnika="vw8ZV7HC", zewnetrzne_id_zawodnika="vw8ZV7HC",
imie="Sergio", imie="Sergio",
nazwisko="Agüero", nazwisko="Agüero",
data_urodzenia="02.06.1988", data_urodzenia="02.06.1988",
czy_aktywny=False, czy_aktywny=False,
klub_id="retired", klub_id="undefined",
narodowosc="AR", narodowosc="AR",
ilosc_trofeow=0, # Brak danych ilosc_trofeow=0, # Brak danych
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=9, statystyki_id=9,
wycena=0 # Zakończył karierę wycena=0 # Zakończył karierę
) )
#Edinson Cavani
# Edinson Cavani
self.simple_insert_one(kluby,
id_klubu="boca-juniors",
pelna_nazwa="Boca Juniors", #?
skrocona_nazwa="CAB" #?
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=507, ilosc_wystapien=507,
@@ -880,23 +988,28 @@ class baza():
remisow_sum=0, # Brak danych remisow_sum=0, # Brak danych
wynik_sum=0, # Brak danych wynik_sum=0, # Brak danych
meczow_do_wynikow_sum=0 # Brak danych meczow_do_wynikow_sum=0 # Brak danych
) )
self.simple_insert_one(sportowcy,
sportowiec = sportowcy(
zewnetrzne_id_zawodnika="Qgx2trzH", zewnetrzne_id_zawodnika="Qgx2trzH",
imie="Edinson", imie="Edinson",
nazwisko="Cavani", nazwisko="Cavani",
data_urodzenia="14.02.1987", data_urodzenia="14.02.1987",
czy_aktywny=True, czy_aktywny=True,
klub_id="Boca Juniors", klub_id="boca-juniors",
narodowosc="UY", narodowosc="UY",
ilosc_trofeow=0, ilosc_trofeow=0,
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=10, statystyki_id=10,
wycena=4_212_000 # PLN wycena=4_212_000 # PLN
) )
#Radamel Falcao
# Radamel Falcao
self.simple_insert_one(kluby,
id_klubu="millonarios",
pelna_nazwa="Millonarios",
skrocona_nazwa="MLA" #?
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=360, ilosc_wystapien=360,
@@ -913,22 +1026,23 @@ class baza():
remisow_sum=0, remisow_sum=0,
wynik_sum=0, wynik_sum=0,
meczow_do_wynikow_sum=0 meczow_do_wynikow_sum=0
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="2oMimkAU", zewnetrzne_id_zawodnika="2oMimkAU",
imie="Radamel", imie="Radamel",
nazwisko="Falcao", nazwisko="Falcao",
data_urodzenia="10.02.1986", data_urodzenia="10.02.1986",
czy_aktywny=True, czy_aktywny=True,
klub_id="Millonarios", klub_id="millonarios",
narodowosc="CO", narodowosc="CO",
ilosc_trofeow=0, # brak danych ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=11, statystyki_id=11,
wycena=1_084_500 #PLN wycena=1_084_500 #PLN
) )
#Wayne Rooney
# Wayne Rooney
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=568, ilosc_wystapien=568,
@@ -945,8 +1059,8 @@ class baza():
remisow_sum=0, remisow_sum=0,
wynik_sum=0, wynik_sum=0,
meczow_do_wynikow_sum=0 meczow_do_wynikow_sum=0
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="WfXv1DCa", zewnetrzne_id_zawodnika="WfXv1DCa",
imie="Wayne", imie="Wayne",
nazwisko="Rooney", nazwisko="Rooney",
@@ -959,8 +1073,9 @@ class baza():
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=12, statystyki_id=12,
wycena=0 # brak wyceny wycena=0 # brak wyceny
) )
#Robin van Persie
# Robin van Persie
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=374, ilosc_wystapien=374,
@@ -977,8 +1092,8 @@ class baza():
remisow_sum=0, remisow_sum=0,
wynik_sum=0, wynik_sum=0,
meczow_do_wynikow_sum=0 meczow_do_wynikow_sum=0
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="0vgcq6un", zewnetrzne_id_zawodnika="0vgcq6un",
imie="Robin", imie="Robin",
nazwisko="van Persie", nazwisko="van Persie",
@@ -991,8 +1106,14 @@ class baza():
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=13, statystyki_id=13,
wycena=0 # zakończył karierę wycena=0 # zakończył karierę
) )
#Harry Kane
# Harry Kane
self.simple_insert_one(kluby,
id_klubu="bayern",
pelna_nazwa="Bayern Monachium",
skrocona_nazwa="BAY"
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=439, ilosc_wystapien=439,
@@ -1009,22 +1130,28 @@ class baza():
remisow_sum=0, remisow_sum=0,
wynik_sum=0, wynik_sum=0,
meczow_do_wynikow_sum=0 meczow_do_wynikow_sum=0
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="v5HSlEAa", zewnetrzne_id_zawodnika="v5HSlEAa",
imie="Harry", imie="Harry",
nazwisko="Kane", nazwisko="Kane",
data_urodzenia="28.07.1993", data_urodzenia="28.07.1993",
czy_aktywny=True, czy_aktywny=True,
klub_id="Bayern Monachium", klub_id="bayern",
narodowosc="ENG", narodowosc="ENG",
ilosc_trofeow=0, # brak danych ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=14, statystyki_id=14,
wycena=344_700_000 # PLN wycena=344_700_000 # PLN
) )
#Ciro Immobile
# Ciro Immobile
self.simple_insert_one(kluby,
id_klubu="besiktas",
pelna_nazwa="Besiktas",
skrocona_nazwa="BES"
)
self.simple_insert_one(statystyki_sportowcow, self.simple_insert_one(statystyki_sportowcow,
ostatni_mecz=1, ostatni_mecz=1,
ilosc_wystapien=455, ilosc_wystapien=455,
@@ -1041,24 +1168,21 @@ class baza():
remisow_sum=0, remisow_sum=0,
wynik_sum=0, wynik_sum=0,
meczow_do_wynikow_sum=0 meczow_do_wynikow_sum=0
) )
sportowiec = sportowcy( self.simple_insert_one(sportowcy,
zewnetrzne_id_zawodnika="4S9fNUYh", zewnetrzne_id_zawodnika="4S9fNUYh",
imie="Ciro", imie="Ciro",
nazwisko="Immobile", nazwisko="Immobile",
data_urodzenia="20.02.1990", data_urodzenia="20.02.1990",
czy_aktywny=True, czy_aktywny=True,
klub_id="Besiktas", klub_id="besiktas",
narodowosc="IT", narodowosc="IT",
ilosc_trofeow=0, # brak danych ilosc_trofeow=0, # brak danych
pierwszy_mecz_id=1, pierwszy_mecz_id=1,
ostatni_gol_dla_id="undefined", ostatni_gol_dla_id="undefined",
statystyki_id=15, statystyki_id=15,
wycena=12_600_000 # PLN wycena=12_600_000 # PLN
) )
session.commit() session.commit()

View File

@@ -1,4 +1,4 @@
from git import Repo # hash ostatniego commitu #from git import Repo # hash ostatniego commitu
import os import os
import time import time
import toml import toml
@@ -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
@@ -36,11 +36,11 @@ def getCommit() -> str | None:
return None return None
def getCommitInFormattedHTML(): def getCommitInFormattedHTML():
repo = "<p>Brak informacji o wersji skryptu</p>" repo = "<center><p style=\"color: white;\">Brak informacji o wersji skryptu</p></center>"
commit = getCommit() commit = getCommit()
if commit is not None: if commit is not None:
repo = f"<p>Commit: <a href='https://gitea.7o7.cx/roberteam/lewangoalski/commit/{commit}'>{commit[:11]}</a></p>" repo = f"<center><p style=\"color: white;\">Commit: <a href='https://gitea.7o7.cx/roberteam/lewangoalski/commit/{commit}'>{commit[:11]}</a></p></center>"
return repo return repo
@@ -155,4 +155,4 @@ config = {}
configfile = "config.toml" configfile = "config.toml"
version = getCommitWithFailsafe() version = getCommitWithFailsafe()
apiVersion = "1" apiVersion = "1"
randomly_generated_passcode = 0 randomly_generated_passcode = 0

View File

@@ -2,6 +2,40 @@ 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
def get_lewy_stats():
return {
'all_time_stats': {
'goals': 589+85,
'assists':154+35,
'matches': 791+158,
},
'club_stats': {
'goals': 589,
'assists': 154,
'matches': 791,
},
'nation_stats': {
'goals': 85,
'assists': 35,
'matches': 158,
},
'international_cups': {
'goals': 110,
'assists': 19,
'matches': 152,
},
'national_cups': {
'goals': 58,
'assists': 4,
'matches': 74,
},
'cards': {
'yellow': 86,
'red': 2,
}
}
def index(): def index():
dark_mode = request.cookies.get('darkMode', 'disabled') dark_mode = request.cookies.get('darkMode', 'disabled')
@@ -25,27 +59,127 @@ def index():
def mecze(): def mecze():
# Możesz dostarczyć szczegóły dotyczące meczów # Możesz dostarczyć szczegóły dotyczące meczów
matches = [ selected_date = request.args.get("date", '2025')
{'date': '2024-10-12', 'opponent': 'Real Madrid', 'goals': 2, 'assists': 1, 'minutes': 90}, try:
{'date': '2024-10-19', 'opponent': 'Valencia', 'goals': 1, 'assists': 0, 'minutes': 85}, selected_date = int(selected_date)
] except:
return render_template('matches.html', matches=matches) selected_date = 2025
#with open("static/lewandowski_matches.json", "r") as file:
# data = json.load(file)
status, msg, matches = get_matches(None, id_zawodnika=1, rok=selected_date)
return render_template('matches.html', matches=matches, selected_date=selected_date)
def statystyki(): def statystyki():
stats = { dane=get_lewy_stats()
'goals': 38, return render_template('stats.html', **dane)
'assists': 12,
'matches': 45,
}
return render_template('stats.html', stats=stats)
def historia(): def clubs():
selected_club = request.args.get("club","FC Barcelona") selected_club = request.args.get("club","FC Barcelona")
history = [ clubs = [
{'club': 'FC Barcelona', 'goals': 22}, {'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': 132}, {'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': 'Lech Poznan', 'goals': 41,'assist':19,'matches':82,'minutes_played': 6858,'yellow_card':9,'red_card': 0, 'wins':'-', 'draws': '-','lost': '-'},
] ]
return render_template('history.html', history=history, selected_club=selected_club) return render_template('club.html', clubs=clubs, selected_club=selected_club)
def representation():
nation_stats = {
'goals': 85,
'assists': 35,
'matches': 158,
'minutes_played': 12108,
'yellow_card':10,
'red_card': 0,
'wins':75,
'draws': 35,
'lost': 48
}
return render_template('representation.html', nation_stats=nation_stats)
def compare():
selected_player = request.args.get("player","Leo Messi")
lewy=get_lewy_stats()
player2 = [
{'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, )
def trophies():
trophy = [
{'name': 'Piłkarz Roku FIFA', 'year':'2021'},
{'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)
def toggle_dark_mode(): def toggle_dark_mode():
# Przełącz tryb i zapisz w ciasteczku # Przełącz tryb i zapisz w ciasteczku

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

View File

@@ -24,7 +24,7 @@
--polska-red: #E30B17; --polska-red: #E30B17;
--polska-white: #FFFFFF; --polska-white: #FFFFFF;
--polska-section-color: #05204A; --polska-section-color: #121623;
--section-color: #051839; --section-color: #051839;
--pink-highlight: #E1317E; --pink-highlight: #E1317E;
--blue-highlight: #00B9BF; --blue-highlight: #00B9BF;
@@ -61,6 +61,7 @@ body {
font-size: 15px; font-size: 15px;
z-index: -2; z-index: -2;
position: relative; position: relative;
margin-top: 60px;
/* box-shadow: 0px -5px 10px 2px rgba(0, 0, 0, 0.347); */ /* box-shadow: 0px -5px 10px 2px rgba(0, 0, 0, 0.347); */
} }
@@ -82,6 +83,7 @@ body {
width: 40%; width: 40%;
padding: 20px; padding: 20px;
position: relative; position: relative;
} }
.profile-image-cover { .profile-image-cover {
@@ -93,6 +95,7 @@ body {
top: 0; top: 0;
} }
.profile-image img { .profile-image img {
width: 100%; width: 100%;
max-width: 600px; max-width: 600px;
@@ -129,7 +132,7 @@ header button {
padding: 2.3rem 1rem; padding: 2.3rem 1rem;
height: 1.5rem; height: 1.5rem;
position: sticky; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
@@ -181,7 +184,7 @@ header button {
align-items: center; align-items: center;
text-decoration: none; text-decoration: none;
border-radius: var(--border-radius); border-radius: var(--border-radius);
padding: 10px 20px; padding: 10px;
height: 100%; height: 100%;
transition: 100ms ease; transition: 100ms ease;
position: relative; position: relative;
@@ -218,8 +221,17 @@ header button {
} }
.nav-links li:nth-child(4) a::before { .nav-links li:nth-child(4) a::before {
content: "🤝";
}
.nav-links li:nth-child(5) a::before {
content: "⚽";
}
.nav-links li:nth-child(6) a::before {
content: "🏆"; content: "🏆";
} }
.nav-links li:nth-child(7) a::before {
content: "🔎";
}
.nav-links li { .nav-links li {
display: block; display: block;
@@ -292,21 +304,32 @@ header button {
cursor: pointer; cursor: pointer;
} }
@media (max-width: 768px) { @media (max-width: 1090px) {
/* .base-header .navbar:not(:has(.show))
{
margin-bottom: 400px;
} */
.nav-links { .nav-links {
display: none;
flex-direction: column;
background-color: var(--barca-blue);
position: absolute; position: absolute;
top: 2.5rem; flex-direction: column;
right: 0rem; top: 57px;
right: 0px;
padding: 0rem; padding: 0rem;
gap: 0; gap: 0;
width: 200px; height: auto;
backdrop-filter: blur(4px);
width: 30%;
justify-content: center;
box-shadow: 0px 0px 5px 5px rgba(0, 0, 0, 0.105);
} }
.nav-links li { .nav-links li {
width: 100%; width: 100%;
margin: 0;
display: flex;
justify-content: center;
} }
.nav-links li a, .nav-links li a,
@@ -319,16 +342,78 @@ header button {
border-radius: 0; border-radius: 0;
/* brak zaokrągleń w mobilnym menu */ /* brak zaokrągleń w mobilnym menu */
} }
.nav-links li button
{
background-color: none;
width: 45px;
border-radius: 50%;
}
.nav-links li button::before,.nav-links li button::after
{
background-color: none
;
}
.nav-links li button:hover
{
transform: none;
}
.nav-links.show { .nav-links.show {
display: flex; display: none;
} }
.hamburger { .hamburger {
display: block; display: block;
} }
} }
@media (max-width: 1000px)
{
.header-content
{
flex-direction: column;
}
.header-content .profile-image
{
display: flex;
justify-content: center;
width: 100%;
}
.header-content .profile-image img{
width: 100%;
}
.about-section-image
{
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;
}
}
@@ -490,6 +575,7 @@ td {
width: 80%; width: 80%;
border-radius: var(--border-radius); border-radius: var(--border-radius);
max-width: 1000px; max-width: 1000px;
margin-bottom: 50px;
} }
.section__matches h2 .section__matches h2
{ {
@@ -544,7 +630,6 @@ body.poland-mode .nav-links li a {
color: white; color: white;
} }
body.poland-mode .nav-links li a:hover { body.poland-mode .nav-links li a:hover {
color: #220000; color: #220000;
background-color: white; background-color: white;
@@ -607,28 +692,79 @@ body.poland-mode .hamburger {
} }
@media (max-width: 768px) { @media (max-width: 768px) {
body.poland-mode .nav-links { /* body.poland-mode .nav-links {
background-color: var(--polska-red); background-color: var(--polska-red);
/*Ale oczopląs*/ /*Ale oczopląs*/
} }
}
body.poland-mode .section-stats { body.poland-mode .section-stats {
background: linear-gradient(to bottom, #bd4148, #dc1414); background: linear-gradient(to bottom, #bd4148, #dc1414);
} }
body.poland-mode .section-stats h2 { body.poland-mode .section-stats h2 {
color: #220000 color: white;
} }
body.poland-mode .stat-box { body.poland-mode .stat-box {
border-color: white; border-color: white;
background: linear-gradient(to bottom, #ff0000,#231212);
} }
body.poland-mode .stat-box h3 { body.poland-mode .stat-box h3 {
color: white; color: white;
} }
body.poland-mode .club-stats h2{
background: linear-gradient(to bottom, #ff0000,#231212);
border: 4px solid white;
color: white;
}
body.poland-mode .about-section {
background-color: var(--polska-section-color);
color: white;
}
body.poland-mode .about-section article h3 {
background-color: var(--polska-red-dark);
color: white;
}
body.poland-mode .about-section article h4 {
background-color: #ffcaca;
color: black;
border-radius: 5px;
}
body.poland-mode .general-stats-section h2 {
background: var(--polska-section-color);
}
body.poland-mode .general-stats-section .grid article:nth-child(1){background-color: var(--polska-red-dark);}
body.poland-mode .general-stats-section .grid article:nth-child(2){background-color: var(--yellow-highlight);}
body.poland-mode .general-stats-section .grid article:nth-child(3){background-color: var(--barca-blue);}
body.poland-mode .about-section-image::after{
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 */
@@ -641,9 +777,31 @@ body.poland-mode .stat-box h3 {
padding: 2rem 2rem; padding: 2rem 2rem;
max-width: 1000px; max-width: 1000px;
margin: 0 auto; margin: 0 auto;
text-align: center;
margin-bottom: 10px; margin-bottom: 10px;
width: 100%;
}
.section-stats h1{
font-size: 34px;
color: var(--barca-red);
}
body.poland-mode .section-stats h1{
color: white;
}
.section-stats-center
{
display: grid;
grid-template-columns: 1fr 1fr;
gap: 30px;
justify-content: center;
}
@media (max-width: 1400px) {
.section-stats-center
{
grid-template-columns: 1fr !important;
}
} }
.section-stats h2 { .section-stats h2 {
font-size: 2rem; font-size: 2rem;
margin-bottom: 1rem; margin-bottom: 1rem;
@@ -655,7 +813,6 @@ body.poland-mode .stat-box h3 {
justify-content: space-around; justify-content: space-around;
text-align: center; text-align: center;
margin-top: 2rem; margin-top: 2rem;
flex-wrap: wrap;
gap: 2rem; gap: 2rem;
} }
@@ -683,21 +840,98 @@ body.poland-mode .stat-box h3 {
.stat-box p { .stat-box p {
font-size: 1.1rem; font-size: 1.1rem;
} }
.choose-club
{
margin: 10px;
padding: 20px;
display: flex;
gap: 20px;
justify-content: space-around;
}
.choose-club button { .choose-club button {
height: 50px; width: 100px;
width: 50px;
background-color: white;
border: none; border: none;
background-color:transparent;
border-radius: 50%;
} }
.choose-club button img { .choose-club button img {
height: 40px; width: 100%;
width: 40px; height: 100%;
background-color:transparent;
transition: transform 100ms ease;
} }
.choose-club button img:hover { .choose-club button img:hover {
height: 45px; transform: scale(1.3,1.3) translateY(-10px);
width: 45px; }
background-color: #ffffff7e; .club-stats h2{
color: var(--barca-gold);
text-align: center;
border: 5px solid var(--barca-red);
background-color: var(--barca-blue);
padding: 20px;
border-radius: var(--border-radius);
}
.stat-box
{
padding: 20px;
background-color: var(--barca-blue);
display: grid;
grid-template-rows: 1fr 1fr;
text-align: center;
}
.stat-box-special
{text-align: center;
display: block;
font-size: 40px;
color: var(--barca-gold);
}
.club-stats-grid
{
display: grid;
margin-bottom: 50px;
gap: 10px;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
select
{
color: white;
padding: 20px;
margin: 10px;
font-size: 24px;
background-color: var(--barca-blue);
border-radius: 10px;
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

@@ -23,7 +23,10 @@
<li><a href="/">Strona główna</a></li> <li><a href="/">Strona główna</a></li>
<li><a href="/mecze">Mecze</a></li> <li><a href="/mecze">Mecze</a></li>
<li><a href="/statystyki">Statystyki</a></li> <li><a href="/statystyki">Statystyki</a></li>
<li><a href="/historia">Osiągnięcia</a></li> <li><a href="/club">Kluby</a></li>
<li><a href="/representation">Reprezentacja</a></li>
<li><a href="/trophies">Trofea</a></li>
<li><a href="/compare">Porównaj</a></li>
<li><button id="theme-toggle" onclick="toggleTheme()"></button></li> <li><button id="theme-toggle" onclick="toggleTheme()"></button></li>
</ul> </ul>
<div class="hamburger"></div> <div class="hamburger"></div>

View File

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

View File

@@ -0,0 +1,63 @@
{% extends "base.html" %}
{% block title %}Statystyki{% endblock %}
{% block content %}
<select onchange="location = this.value;">
<option disabled selected>Wybierz zawodnika</option>
<option value="{{ url_for('compare', player='Leo Messi') }}">Leo Messi</option>
<option value="{{ url_for('compare', player='Cristiano Ronaldo') }}">Cristiano Ronaldo</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>
{%for player in player2 %}
{% if player.name == selected_player %}
<section class="section-stats">
<h1>Robert Lewandowski VS {{selected_player}}</h1>
<h2>Gole</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ all_time_stats.goals }}</h3>
</div>
<div class="stat-box">
<h3>{{ player.goals}}</h3>
</div>
</div>
<h2>Asysty</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>
<h2>Wystąpienia</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ all_time_stats.matches }}</h3>
</div>
<div class="stat-box">
<h3>{{ player.matches}}</h3>
</div>
</div>
</section>
{% endif %}
{% endfor%}
{% endblock %}

View File

@@ -1,30 +0,0 @@
{% extends "base.html" %}
{% block title %}Strona Główna{% endblock %}
{% block content %}
<section class="choose-club">
<a href="{{ url_for('historia', club='FC Barcelona') }}">
<button><img src="{{ url_for('static', filename='FC_Barcelona.png') }}"></button>
</a>
<a href="{{ url_for('historia', club='Bayern Monachium') }}">
<button><img src="{{ url_for('static', filename='FC_Bayern.png') }}"></button>
</a>
</section>
<!-- Wyświetlanie danych tylko dla wybranego klubu -->
{% for stats in history %}
{% if stats.club == selected_club %}
<section class="club-stats">
<h2>{{ stats.club }} - All time stats</h2>
<div class="stats">
Gole: {{ stats.goals }}
</div>
</section>
{% endif %}
{% endfor %}
{% endblock %}
{% block footer %}
{{ commit_in_html | safe }}
{% endblock %}

View File

@@ -10,30 +10,30 @@
<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="/historia">Zobacz osiągnięcia</a> <a href="/club">Zobacz trofea</a>
</article> </article>
</section> </section>
<!--
<section class="general-stats-section"> <section class="general-stats-section">
<h2>Ogólne statystyki:</h3> <h2>Ogólne statystyki:</h3>
<div class="grid"> <div class="grid">
@@ -52,10 +52,12 @@
</article> </article>
</div> </div>
</section> </section>
-->
</div> </div>
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}
<!--
{{ commit_in_html | safe }} {{ commit_in_html | safe }}
-->
{% endblock %} {% endblock %}

View File

@@ -3,23 +3,50 @@
{% block title %}Lista meczów{% endblock %} {% block title %}Lista meczów{% endblock %}
{% block content %} {% block content %}
<select onchange="location = this.value;">
<option disabled selected>Wybierz rok</option>
<option value="{{ url_for('mecze', date='2025') }}">2025</option>
<option value="{{ url_for('mecze', date='2024') }}">2024</option>
<option value="{{ url_for('mecze', date='2023') }}">2023</option>
<option value="{{ url_for('mecze', date='2022') }}">2022</option>
<option value="{{ url_for('mecze', date='2021') }}">2021</option>
<option value="{{ url_for('mecze', date='2020') }}">2020</option>
<option value="{{ url_for('mecze', date='2019') }}">2019</option>
<option value="{{ url_for('mecze', date='2018') }}">2018</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>
<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

@@ -0,0 +1,39 @@
{% extends "base.html" %}
{% block title %}Statystyki{% endblock %}
{% block content %}
<section class="club-stats club-stats-poland">
<h2>Statystyki w reprezentacji Polski</h2>
<div class="wybrany{{selected_club}}"></div>
<div class="club-stats-grid">
<div class="stat-box">
<p>Gole:</p> <span class="stat-box-special"> {{ nation_stats.goals }} </span>
</div>
<div class="stat-box">
<p>Asysty:</p> <span class="stat-box-special"> {{ nation_stats.assists }} </span>
</div>
<div class="stat-box">
<p>Występy:</p> <span class="stat-box-special"> {{ nation_stats.matches }} </span>
</div>
<div class="stat-box">
<p>Łączny czas gry:</p> <span class="stat-box-special"> {{ nation_stats.minutes_played }}</span>
</div>
<div class="stat-box">
<p>Żółte kartki:</p> <span class="stat-box-special"> {{ nation_stats.yellow_card }}</span>
</div>
<div class="stat-box">
<p>Czerwone kartki:</p> <span class="stat-box-special"> {{ nation_stats.red_card }}</span>
</div>
<div class="stat-box">
<p>Zwycięstwa:</p> <span class="stat-box-special"> {{ nation_stats.wins }}</span>
</div>
<div class="stat-box">
<p>Remisy:</p> <span class="stat-box-special"> {{ nation_stats.draws }}</span>
</div>
<div class="stat-box">
<p>Porażki:</p> <span class="stat-box-special"> {{ nation_stats.lost }}</span>
</div>
</div>
</section>
{% endblock %}

View File

@@ -3,38 +3,104 @@
{% block title %}Statystyki{% endblock %} {% block title %}Statystyki{% endblock %}
{% block content %} {% block content %}
<section class="section-stats"> <div class="section-stats-center">
<h2>All time stats</h2>
<div class="stats"> <section class="section-stats">
<div class="stat-box"> <h2>Ogólne statystyki</h2>
<h3>{{ stats.goals }}</h3> <div class="stats">
<p>Goals</p> <div class="stat-box">
</div> <h3>{{ all_time_stats.goals }}</h3>
<div class="stat-box"> <p>Gole</p>
<h3>{{ stats.assists }}</h3> </div>
<p>Assists</p> <div class="stat-box">
</div> <h3>{{ all_time_stats.assists }}</h3>
<div class="stat-box"> <p>Asysty</p>
<h3>{{ stats.matches }}</h3> </div>
<p>Apps</p> <div class="stat-box">
</div> <h3>{{ all_time_stats.matches }}</h3>
<p>Występy</p>
</div>
</div>
</section>
<section class="section-stats">
<h2>Klubowe statystyki</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ club_stats.goals }}</h3>
<p>Gole</p>
</div>
<div class="stat-box">
<h3>{{ club_stats.assists }}</h3>
<p>Asysty</p>
</div>
<div class="stat-box">
<h3>{{ club_stats.matches }}</h3>
<p>Występy</p>
</div>
</div>
</section>
<section class="section-stats">
<h2>Reprezentacja statystyki</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ nation_stats.goals }}</h3>
<p>Gole</p>
</div>
<div class="stat-box">
<h3>{{ nation_stats.assists }}</h3>
<p>Asysty</p>
</div>
<div class="stat-box">
<h3>{{ nation_stats.matches }}</h3>
<p>Występy</p>
</div>
</section>
<section class="section-stats">
<h2>Puchary międzynarodowe</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ international_cups.goals }}</h3>
<p>Gole</p>
</div>
<div class="stat-box">
<h3>{{ international_cups.assists }}</h3>
<p>Asysty</p>
</div>
<div class="stat-box">
<h3>{{ international_cups.matches }}</h3>
<p>Występy</p>
</div>
</div>
</section>
<section class="section-stats">
<h2>Puchary krajowe</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ national_cups.goals }}</h3>
<p>Gole</p>
</div>
<div class="stat-box">
<h3>{{ national_cups.assists }}</h3>
<p>Asysty</p>
</div>
<div class="stat-box">
<h3>{{ national_cups.matches }}</h3>
<p>Występy</p>
</div>
</div>
</section>
<section class="section-stats">
<h2>Kartki</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ cards.yellow }}</h3>
<p>Żółte</p>
</div>
<div class="stat-box">
<h3>{{ cards.red }}</h3>
<p>Czerwone</p>
</div>
</div>
</div> </div>
</section> </section>
<section class="section-stats"> {% endblock %}
<h2>All time stats</h2>
<div class="stats">
<div class="stat-box">
<h3>{{ stats.goals }}</h3>
<p>Goals</p>
</div>
<div class="stat-box">
<h3>{{ stats.assists }}</h3>
<p>Assists</p>
</div>
<div class="stat-box">
<h3>{{ stats.matches }}</h3>
<p>Apps</p>
</div>
</div>
</section>
{% endblock %}

View File

@@ -0,0 +1,28 @@
{% extends "base.html" %}
{% block title %}Statystyki{% endblock %}
{% block content %}
<section class="section__matches">
<h2>🏆 Trofea</h2>
<table>
<tr>
<th>Nazwa</th>
<th>Data/Sezon</th>
</tr>
{% for trophy in trophy %}
<tr>
<td>{{ trophy.name }}</td>
{% if trophy.year == NULL %}
<td>{{ trophy.sezon }}</td>
{% endif %}
{% if trophy.sezon == NULL %}
<td>{{ trophy.year }}</td>
{% endif %}
</tr>
{% endfor %}
</table>
</section>
{% endblock %}

Binary file not shown.