feat: /api/v2/analiza/* endpoints - sport analytics backend

This commit is contained in:
Damir Radulic
2026-05-16 00:28:12 +02:00
parent 7ca5d7d94e
commit aca5051418
1355 changed files with 321891 additions and 4128 deletions
+230
View File
@@ -0,0 +1,230 @@
#!/usr/bin/env python3
"""Godišnjak ZS PGŽ 2025 ingest:
1) Insert kao full-text dokument
2) Update statistika_saveza za 2025
3) Update Parasportski savez kontakt
4) Insert/update 12 parasportskih klubova
5) Mark članove parasporta s flagom
"""
import os
import psycopg2, re, json, hashlib
from datetime import date
DB = dict(host='localhost', port=5432, dbname='rinet_v3',
user='rinet', password=os.environ["DB_PASSWORD"])
GODISNJAK_PATH = '/opt/pgz-sport/_data/godisnjak/2025_full.txt'
text = open(GODISNJAK_PATH, encoding='utf-8').read()
print(f"Loaded godišnjak: {len(text)} chars, {text.count(chr(12))+1} pages")
# ============================================================
# 1) INSERT godišnjak kao dokument
# ============================================================
conn = psycopg2.connect(**DB); conn.autocommit = True
cu = conn.cursor()
sha = hashlib.sha256(text.encode()).hexdigest()[:40]
# Provjeri postoji li
cu.execute("SELECT id FROM pgz_sport.dokumenti WHERE title ILIKE %s LIMIT 1",
('%Sportski godi%njak ZS PG%2025%',))
existing = cu.fetchone()
if existing:
cu.execute("""UPDATE pgz_sport.dokumenti SET
sadrzaj = %s, sha1 = %s WHERE id = %s""",
(text, sha, existing[0]))
GOD_DOC_ID = existing[0]
print(f"✓ Updated dok #{GOD_DOC_ID}: Sportski godišnjak ZS PGŽ 2025")
else:
cu.execute("""INSERT INTO pgz_sport.dokumenti
(title, kratak_opis, sadrzaj, vrsta, razina, organizacija,
izvor_url, kljucne_rijeci, izdano_datum, sha1, aktivan)
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,true) RETURNING id""",
('Sportski godišnjak Zajednice sportova PGŽ 2025',
'Godišnji bilten ZS PGŽ — pregled svih 30 županijskih saveza, statistike, najbolji sportaši, kategorizirani sportaši, manifestacije, financiranje',
text, 'godisnjak', 'PGŽ', 'Zajednica sportova PGŽ',
'https://zspgz.hr/godisnjak-2025',
['godišnjak','ZS PGŽ','2025','statistika','savezi','najbolji sportaši','kategorizirani'],
'2026-02-19', sha))
GOD_DOC_ID = cu.fetchone()[0]
print(f"✓ Inserted dok #{GOD_DOC_ID}: Sportski godišnjak ZS PGŽ 2025")
# ============================================================
# 2) UPDATE statistika_saveza ZA 2025 — pravi brojevi iz godišnjaka
# ============================================================
# Mapiramo (savez_naziv_pattern → brojke iz PDF-a)
STATS_2025 = [
# (LIKE pattern, klubova_clanica, registriranih, ukupno_clanova_or_None)
('Atletski savez%PG%', 8, 498, 1185),
('Boćarski savez%PG%', 63, 950, None),
('Boksački savez%PG%', 7, None, None), # iz prošle stat
('Jedriličarski savez%PG%', 20, None, None), # 20 klubova
('Judo savez%PG%', 9, 870, None),
('Karate savez%PG%', 21, 1980, None),
('Kickboxing savez%PG%', 12, None, None), # ručno tipovi p.101
('Košarkaški savez%PG%', 11, 180, None), # iz preliminarnog parsa
('Kuglački savez%PG%', 20, 438, None),
('Nogometni savez%PG%', 57, None, None),
('Odbojkaški savez%PG%', 15, None, None),
('Pikado savez%PG%', None, None, None),
('Plivački savez%PG%', 5, None, None),
('Rukometni savez%PG%', None, 485, None),
('Skijaški savez%PG%', 11, 180, None),
('Stolnoteniski savez%PG%', 12, 176, None),
('Streličarski savez%PG%', 4, 176, None),
('Šahovski savez%PG%', 17, None, None),
('Taekwondo savez%PG%', 7, 202, None),
('Tenis%savez%PG%', 9, 138, None),
('Triatlon savez%PG%', 5, 136, None),
('Vaterpolski savez%PG%', 7, 317, None),
# Drugi savezi
('Sanjkaški savez%PG%', None, 2, None),
('%ribolov%moru%', None, None, None),
('Udruga %strelj%', 8, 141, None),
('Savez školskih sportskih%PG%', 512, None, None), # 512 ŠSD - school sport
('%sportske rekreacije%Sport za sve%', None, None, None),
('Riječki sportski sveučilišni%', None, None, None),
('Parasportski savez%PG%', 12, None, None), # 12 članica
]
for pattern, klubova, reg, ukupno in STATS_2025:
cu.execute("SELECT id, naziv FROM pgz_sport.savezi WHERE naziv ILIKE %s LIMIT 1", (pattern,))
row = cu.fetchone()
if not row:
print(f" ✗ not found: {pattern}")
continue
sid, snaziv = row
# Upsert statistika za 2025
cu.execute("""SELECT id FROM pgz_sport.statistika_saveza
WHERE savez_id=%s AND godina=2025""", (sid,))
stat = cu.fetchone()
if stat:
cu.execute("""UPDATE pgz_sport.statistika_saveza SET
klubova_clanica = COALESCE(%s, klubova_clanica),
registriranih = COALESCE(%s, registriranih)
WHERE id = %s""", (klubova, reg, stat[0]))
print(f" ✓ Updated 2025: {snaziv[:50]} klubova={klubova} reg={reg}")
else:
cu.execute("""INSERT INTO pgz_sport.statistika_saveza
(savez_id, godina, klubova_clanica, registriranih)
VALUES (%s, 2025, %s, %s)""", (sid, klubova, reg))
print(f" + Inserted 2025: {snaziv[:50]} klubova={klubova} reg={reg}")
# ============================================================
# 3) UPDATE PARASPORTSKI SAVEZ
# ============================================================
cu.execute("""UPDATE pgz_sport.savezi SET
sjediste = COALESCE(sjediste, 'Šetalište Ivana Gorana Kovačića 14, 51000 Rijeka'),
web = COALESCE(web, 'http://www.ssoi-pgz.hr'),
email = COALESCE(email, 'ssoi-pgz@ssoi-pgz.hr')
WHERE naziv ILIKE 'Parasportski savez%PG%'
RETURNING id, naziv""")
parasport_row = cu.fetchone()
if parasport_row:
PARASPORT_ID, _ = parasport_row
print(f"✓ Parasport savez #{PARASPORT_ID} updated (kontakt)")
else:
cu.execute("""INSERT INTO pgz_sport.savezi (naziv, razina, sjediste, web, email)
VALUES ('Parasportski savez Primorsko-goranske županije', 'zupanijski',
'Šetalište Ivana Gorana Kovačića 14, 51000 Rijeka',
'http://www.ssoi-pgz.hr', 'ssoi-pgz@ssoi-pgz.hr')
RETURNING id""")
PARASPORT_ID = cu.fetchone()[0]
print(f"+ Parasport savez #{PARASPORT_ID} created")
# Predsjednik + tajnik u osobe_funkcije
def upsert_funkcioner(ime, prezime, funkcija, savez_id=None, klub_id=None):
cu.execute("""SELECT id FROM pgz_sport.osobe_funkcije
WHERE LOWER(ime)=LOWER(%s) AND LOWER(prezime)=LOWER(%s) AND LOWER(funkcija)=LOWER(%s)""",
(ime, prezime, funkcija))
if not cu.fetchone():
cols = "ime, prezime, funkcija"
vals = [ime, prezime, funkcija]
if savez_id:
cols += ", savez_id"
vals.append(savez_id)
cu.execute(f"INSERT INTO pgz_sport.osobe_funkcije ({cols}) VALUES (" +
",".join(["%s"]*len(vals)) + ")", vals)
upsert_funkcioner('Zvonimir', 'Brozić', 'predsjednik Parasportskog saveza PGŽ', PARASPORT_ID)
upsert_funkcioner('Luka', 'Dobrović', 'tajnik Parasportskog saveza PGŽ', PARASPORT_ID)
print("✓ Brozić + Dobrović insertirani u osobe_funkcije")
# ============================================================
# 4) INSERT 12 PARASPORTSKIH KLUBOVA
# ============================================================
PARASPORT_KLUBOVI = [
# (naziv, sport_glavni, sportovi_tag, grad, opis)
('Paraatletski klub "Srce" Rijeka', 'parasport', 'paratletika', 'Rijeka', 'atletika invalidi'),
('Paraplivački klub "Forca"', 'parasport', 'paraplivanje', 'Rijeka', 'plivanje invalidi'),
('Parastolnoteniski klub Rijeka', 'parasport', 'parastolni tenis','Rijeka', 'stolni tenis invalidi'),
('Parastreljački klub "Paraolimpijac"', 'parasport', 'parastreljaštvo', 'Rijeka', 'streljaštvo invalidi'),
('Sportski klub slijepih "Rijeka"', 'parasport', 'sport slijepih', 'Rijeka', 'multisport za slijepe'),
('Parasportski boccia klub "Rijeka"', 'parasport', 'parabocce', 'Rijeka', 'boćanje invalidi'),
('Klub dresurnog jahanja za osobe s invaliditetom "Pegaz"', 'parasport', 'parajahanje', 'Rijeka', 'dresurno jahanje invalidi'),
('Parasportska udruga za rekreaciju "Rijeka"','parasport', 'pararekrejacija', 'Rijeka', 'rekreacija invalidi'),
('KKOI Kostrena', 'parasport', 'multisport', 'Kostrena', 'KK osoba s invaliditetom Kostrena'),
('PAK "Rijeka"', 'parasport', 'multisport', 'Rijeka', 'parasport. udruga Rijeka'),
('Parasportski savez Grada Rijeke', 'parasport', 'multisport', 'Rijeka', 'gradski parasport savez'),
('Riječki sportski savez gluhih', 'parasport', 'sport gluhih', 'Rijeka', '5 klubova gluhih: Galeb x4 + DSR'),
]
inserted = 0; updated = 0
for naziv, sport, tag, grad, opis in PARASPORT_KLUBOVI:
cu.execute("""SELECT id, savez_id FROM pgz_sport.klubovi
WHERE LOWER(naziv) = LOWER(%s) LIMIT 1""", (naziv,))
row = cu.fetchone()
if row:
kid, old_savez = row
cu.execute("""UPDATE pgz_sport.klubovi SET
savez_id = %s, sport = %s, region = COALESCE(region, 'PGŽ'),
grad = COALESCE(grad, %s), napomena = COALESCE(napomena, %s)
WHERE id = %s""", (PARASPORT_ID, sport, grad, opis, kid))
updated += 1
print(f" ↺ {naziv[:50]} (savez_id: {old_savez} → {PARASPORT_ID})")
else:
cu.execute("""INSERT INTO pgz_sport.klubovi
(naziv, savez_id, sport, region, grad, napomena, aktivan)
VALUES (%s, %s, %s, 'PGŽ', %s, %s, true)""",
(naziv, PARASPORT_ID, sport, grad, opis))
inserted += 1
print(f" + {naziv[:50]}")
# Plus 5 gluhih klubova (sub-članovi RSS gluhih)
GLUHI_KLUBOVI = [
('Streljački klub gluhih "Galeb"', 'streljaštvo', 'Rijeka'),
('Malonogometni klub gluhih "Galeb"', 'malonogomet', 'Rijeka'),
('Kuglački klub gluhih "Galeb"', 'kuglanje', 'Rijeka'),
('Stolnoteniski klub gluhih "Galeb"', 'stolni tenis', 'Rijeka'),
('Društvo sportske rekreacije gluhih "Galeb"', 'rekreacija', 'Rijeka'),
]
for naziv, sport, grad in GLUHI_KLUBOVI:
cu.execute("""SELECT id FROM pgz_sport.klubovi
WHERE LOWER(naziv) = LOWER(%s) LIMIT 1""", (naziv,))
if not cu.fetchone():
cu.execute("""INSERT INTO pgz_sport.klubovi
(naziv, savez_id, sport, region, grad, napomena, aktivan)
VALUES (%s, %s, %s, 'PGŽ', %s, %s, true)""",
(naziv, PARASPORT_ID, 'parasport-' + sport, grad, 'pridruženi član preko Riječkog SS gluhih'))
inserted += 1
print(f"\nParasport klubovi: inserted={inserted}, updated={updated}")
# ============================================================
# 5) FINAL counts
# ============================================================
cu.execute("SELECT count(*) FROM pgz_sport.klubovi WHERE savez_id = %s", (PARASPORT_ID,))
print(f"\nUkupno parasportskih klubova: {cu.fetchone()[0]}")
cu.execute("""SELECT count(*) FROM pgz_sport.statistika_saveza
WHERE godina = 2025 AND klubova_clanica IS NOT NULL""")
print(f"Statistika saveza 2025 (s brojkama): {cu.fetchone()[0]}")
cu.execute("SELECT count(*) FROM pgz_sport.dokumenti WHERE vrsta = 'godisnjak'")
print(f"Godišnjak dokumenti: {cu.fetchone()[0]}")
conn.close()
print("\n✓ Done")