init
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate data/transfers.json from assets/transfers-list.csv.
|
||||
|
||||
CSV columns: Player, Club, Sum, Photo, Logo
|
||||
- Photo: filename of the player photo at project root (e.g. tmp-player.png)
|
||||
- Logo: filename of the club logo in clubs-logo/ (e.g. chelsea.png)
|
||||
|
||||
Team colours are looked up from the CLUBS dict below; unknown clubs
|
||||
get auto-generated colours.
|
||||
|
||||
Run: python3 generate_placeholders.py
|
||||
"""
|
||||
|
||||
import csv
|
||||
import json
|
||||
import os
|
||||
import colorsys
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
DATA_DIR = os.path.join(BASE_DIR, "data")
|
||||
CSV_PATH = os.path.join(BASE_DIR, "assets", "transfers-list.csv")
|
||||
CLUBS_DIR = os.path.join(BASE_DIR, "clubs-logo")
|
||||
|
||||
os.makedirs(DATA_DIR, exist_ok=True)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Russian club name -> colours
|
||||
# ---------------------------------------------------------------------------
|
||||
CLUBS = {
|
||||
"Челси": {"color": "#034694", "accent": "#FFFFFF"},
|
||||
"Барселона": {"color": "#A50044", "accent": "#004D98"},
|
||||
"Реал": {"color": "#FEBE10", "accent": "#00529F"},
|
||||
"Арсенал": {"color": "#EF0107", "accent": "#FFFFFF"},
|
||||
"Бавария": {"color": "#DC052D", "accent": "#0066B2"},
|
||||
"ПСЖ": {"color": "#004170", "accent": "#DA291C"},
|
||||
"Ман Сити": {"color": "#6CABDD", "accent": "#1C2C5B"},
|
||||
"Ливерпуль": {"color": "#C8102E", "accent": "#FFFFFF"},
|
||||
"Ювентус": {"color": "#000000", "accent": "#FFFFFF"},
|
||||
"Интер": {"color": "#0068A8", "accent": "#000000"},
|
||||
"Милан": {"color": "#FB090B", "accent": "#000000"},
|
||||
"Атлетико": {"color": "#CB3524", "accent": "#261E60"},
|
||||
"Тоттенхэм": {"color": "#132257", "accent": "#FFFFFF"},
|
||||
"Ньюкасл": {"color": "#241F20", "accent": "#FFFFFF"},
|
||||
"Вест Хэм": {"color": "#7A263A", "accent": "#1BB1E7"},
|
||||
"Брайтон": {"color": "#0057B8", "accent": "#FFCD00"},
|
||||
"Байер": {"color": "#E32221", "accent": "#000000"},
|
||||
"Айнтрахт": {"color": "#000000", "accent": "#E1000F"},
|
||||
"Олимпиакос": {"color": "#E30613", "accent": "#FFFFFF"},
|
||||
"Галатасарай":{"color": "#A90432", "accent": "#FCB330"},
|
||||
"Аталанта": {"color": "#1E71B8", "accent": "#000000"},
|
||||
"Наполи": {"color": "#12A0E0", "accent": "#FFFFFF"},
|
||||
"Брюгге": {"color": "#0066B2", "accent": "#000000"},
|
||||
"Боде/Глимт": {"color": "#FCD116", "accent": "#000000"},
|
||||
"Унион": {"color": "#EA2127", "accent": "#FFFFFF"},
|
||||
"Копенгаген": {"color": "#000000", "accent": "#FFFFFF"},
|
||||
"Пафос": {"color": "#0033A0", "accent": "#FFFFFF"},
|
||||
"Славия": {"color": "#C8102E", "accent": "#FFFFFF"},
|
||||
"Карабах": {"color": "#000000", "accent": "#FFFFFF"},
|
||||
"Кайрат": {"color": "#000000", "accent": "#FFD700"},
|
||||
"Бенфика": {"color": "#E30613", "accent": "#FFFFFF"},
|
||||
"Вильярреал": {"color": "#FFE667", "accent": "#00529F"},
|
||||
"Аякс": {"color": "#D2122E", "accent": "#FFFFFF"},
|
||||
"Монако": {"color": "#E20E32", "accent": "#FFFFFF"},
|
||||
"ПСВ": {"color": "#ED1C24", "accent": "#FFFFFF"},
|
||||
"Спортинг": {"color": "#008053", "accent": "#FFFFFF"},
|
||||
"Марсель": {"color": "#009DDC", "accent": "#FFFFFF"},
|
||||
"Боруссия": {"color": "#FDE100", "accent": "#000000"},
|
||||
"Атлетик": {"color": "#EE2523", "accent": "#FFFFFF"},
|
||||
"Манчестер Сити": {"color": "#6CABDD", "accent": "#1C2C5B"},
|
||||
"Манчестер Юнайтед": {"color": "#DA291C", "accent": "#FFE500"},
|
||||
"Астон Вилла": {"color": "#95BFE5", "accent": "#670E36"},
|
||||
"Аль-Хилаль": {"color": "#1B458F", "accent": "#FFFFFF"},
|
||||
"Кристал Пэлас": {"color": "#1B458F", "accent": "#C4122E"},
|
||||
"Комо": {"color": "#0033A0", "accent": "#FFFFFF"},
|
||||
}
|
||||
|
||||
FREE_AGENT_KEYWORDS = ("свободн", "free")
|
||||
LOAN_KEYWORDS = ("аренд", "loan")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Colour helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
def _hex_to_rgb(h):
|
||||
h = h.lstrip("#")
|
||||
return tuple(int(h[i:i+2], 16) for i in (0, 2, 4))
|
||||
|
||||
|
||||
def _rgb_to_hex(rgb):
|
||||
return "#{:02X}{:02X}{:02X}".format(*rgb)
|
||||
|
||||
|
||||
def auto_colors(name):
|
||||
h = hash(name) % 360
|
||||
r, g, b = colorsys.hsv_to_rgb(h / 360, 0.65, 0.75)
|
||||
return _rgb_to_hex((int(r * 255), int(g * 255), int(b * 255))), "#FFFFFF"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Parse CSV and build JSON
|
||||
# ---------------------------------------------------------------------------
|
||||
def parse_csv():
|
||||
rows = []
|
||||
with open(CSV_PATH, encoding="utf-8-sig") as f:
|
||||
reader = csv.DictReader(f, skipinitialspace=True)
|
||||
for row in reader:
|
||||
player = (row.get("Player") or "").strip()
|
||||
if not player:
|
||||
continue
|
||||
rows.append({
|
||||
"player": player,
|
||||
"club": (row.get("Club") or "").strip(),
|
||||
"fee": (row.get("Sum") or "").strip(),
|
||||
"photo": (row.get("Photo") or "").strip(),
|
||||
"logo": (row.get("Logo") or "").strip(),
|
||||
})
|
||||
return rows
|
||||
|
||||
|
||||
def main():
|
||||
rows = parse_csv()
|
||||
if not rows:
|
||||
print("ERROR: no data found in", CSV_PATH)
|
||||
return
|
||||
|
||||
transfers_json = []
|
||||
warnings = []
|
||||
|
||||
for i, r in enumerate(rows):
|
||||
club_name = r["club"]
|
||||
if not club_name:
|
||||
warnings.append(f"Row {i+1}: empty club for player '{r['player']}'")
|
||||
continue
|
||||
|
||||
meta = CLUBS.get(club_name)
|
||||
if meta:
|
||||
color = meta["color"]
|
||||
accent = meta["accent"]
|
||||
else:
|
||||
color, accent = auto_colors(club_name)
|
||||
warnings.append(f"Row {i+1}: unknown club '{club_name}' -> auto colours {color}")
|
||||
|
||||
photo = r["photo"] if r["photo"] else "tmp-player.png"
|
||||
photo_path = os.path.join(BASE_DIR, photo)
|
||||
if not os.path.exists(photo_path):
|
||||
warnings.append(f"Row {i+1}: photo '{photo}' not found at project root")
|
||||
|
||||
logo = r["logo"] if r["logo"] else ""
|
||||
logo_path = os.path.join(CLUBS_DIR, logo) if logo else ""
|
||||
if logo and not os.path.exists(logo_path):
|
||||
warnings.append(f"Row {i+1}: logo '{logo}' not found in clubs-logo/")
|
||||
|
||||
is_free = any(kw in r["fee"].lower() for kw in FREE_AGENT_KEYWORDS)
|
||||
is_loan = any(kw in r["fee"].lower() for kw in LOAN_KEYWORDS)
|
||||
price = r["fee"] if r["fee"] else ""
|
||||
|
||||
if is_free:
|
||||
status = "free-agent"
|
||||
elif is_loan:
|
||||
status = "loan"
|
||||
else:
|
||||
status = "fee"
|
||||
|
||||
transfers_json.append({
|
||||
"id": i + 1,
|
||||
"playerName": r["player"],
|
||||
"photo": photo,
|
||||
"team": {
|
||||
"name": club_name,
|
||||
"logo": f"clubs-logo/{logo}" if logo else "",
|
||||
"color": color,
|
||||
"accent": accent,
|
||||
},
|
||||
"price": price,
|
||||
"status": status,
|
||||
})
|
||||
|
||||
json_path = os.path.join(DATA_DIR, "transfers.json")
|
||||
with open(json_path, "w") as f:
|
||||
json.dump({"transfers": transfers_json}, f, indent=2, ensure_ascii=False)
|
||||
f.write("\n")
|
||||
print(f" Data -> {os.path.relpath(json_path, BASE_DIR)}")
|
||||
|
||||
if warnings:
|
||||
print("\n WARNINGS:")
|
||||
for w in warnings:
|
||||
print(f" ! {w}")
|
||||
|
||||
print(f"\nDone! {len(transfers_json)} transfers written to transfers.json")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user