a
    „i$jÐ;  ã                |   @   s¦  d Z ddlZddlZddlZddlZddlmZ ddlmZ edƒZ	edƒZ
ej dd¡ ddlmZ d	d
ddddddddddddddddddddddddddddd d!d!d"d"d#d$d%d&d'd(d(d(d)d*d*d+d,d-d.d/d/d0d1d1d2d2d3d3d4d5d5d6d6d7d8d9d:d;d<d=d>d?d@d@dAdAdBdCdCdDdEdFdFdFdGdGdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZd[d\d]d^d_d`dadbdcdddedfdgdhdidjdkœ{Zdldm„ Zdndo„ Zdpdq„ Zdrds„ Zdtdu„ Zdvdw„ Zedxk�r¢eƒ  dS )ya  
Backfill missing ftr / result_home / result_away in live_data CSVs
using results from league_data (football-data.co.uk) CSVs.

Usage:  python _backfill_ftr.py          (dry-run, prints what would change)
        python _backfill_ftr.py --write   (actually writes updated CSVs)
é    N)ÚPath)ÚdatetimezE:\soccer\live_datazE:\soccer\league_dataz	E:\soccer)Úmapsz
Man UnitedzMan CityzNott'm ForestZ	NewcastleZWolvesZLeedszWest HamzSheffield WedsZOxfordz	West BromZ	PeterborozAFC WimbledonzEin FrankfurtzFC KolnZDortmundz
M'gladbachzSt PauliúFortuna Dusseldorfú
Schalke 04ZNurnbergZKaiserslauternúHolstein KielZ	KarlsruheZ
Elversbergz
Ath Bilbaoz
Ath MadridZBetisZCeltaZ	VallecanoZSociedadZEspanolz	La Corunaz
Sociedad BzSp GijonZMilanZVeronaZSudtirolzJuve StabiazParis SGZBrestZRennesZ
Strasbourgz
St EtiennezFor SittardúPSV Eindhovenú
AZ AlkmaarúGo Ahead Eaglesú	NAC BredaZUtrechtZ	GroningenZNijmegenZTwenteúSparta RotterdamZHeraclesz	Sp LisbonzSp BragaúGil VicenteZEstrelaúSanta ClaraZPortoZBenficaZGoztepZ
BuyuksehyrZKocaelisporZ
OlympiakosZArisZAEKZPanetolikosZLevadeiakosú	OFI CreteZHeartsz	St MirrenZDundeezParis FCZ	AtromitosúGreuther FurthZBochumZBraunschweigZ	BielefeldZDresdenzSheffield Unitedz	LA GalaxyúSeattle SoundersúSan Jose EarthquakesúPortland TimbersúSporting Kansas CityúVancouver WhitecapsúHouston DynamoZ
LinlithgowZBroraú	Den BoschúDe GraafschapzAlmere CityúLas Vegas LightsúColorado SpringsúPhoenix RisingúSacramento RepublicúFC Tulsa){zManchester UnitedzManchester CityzNottingham ForestzNewcastle UnitedzWolverhampton WanderersZWolverhamptonzLeeds UnitedzWest Ham UnitedzSheffield WednesdayzOxford UnitedzWest Bromwich AlbionzWest BromwichzPeterborough UnitedZPeterboroughZ	WimbledonzEintracht Frankfurtu   FC KÃ¶lnzBorussia Dortmundu   Borussia MÃ¶nchengladbachu   MÃ¶nchengladbachzFC St. Pauliz	St. Pauliu   Fortuna DÃ¼sseldorfr   r   u   1. FC NÃ¼rnbergu	   NÃ¼rnbergz1. FC Kaiserslauternr   zKarlsruher SCzSV ElversbergzAthletic ClubzAthletic Bilbaou   AtlÃ©tico MadridzAtletico Madridz
Real Betisz
Celta VigozRayo VallecanozReal SociedadZEspanyolu   Deportivo de La CoruÃ±azDeportivo de la CorunazDeportivo La CorunazReal Sociedad Bu   Sporting GijÃ³nzSporting GijonzAC MilanzHellas Veronau	   SÃ¼dtirolzSS Juve StabiazParis Saint-GermainZPSGzStade BrestzStade Rennais FCzStade RennaiszRC StrasbourgzStrasbourg Alsaceu   Saint-Ã‰tienneu   AS Saint-Ã‰tiennezFortuna Sittardr   ZPSVr	   ZAZr
   r   z
FC UtrechtzFC GroningenzNEC Nijmegenz	FC Twenter   zHeracles AlmelozSporting CPzSC BragaZBragar   zVicente BarceloszEstrela Amadorar   zSanta Clara AzoreszFC Portoz
SL Benficau   GÃ¶ztepeZGoztepezGoztepe Izmiru   Ä°stanbul BaÅŸakÅŸehirzIstanbul BasaksehirZ
BasaksehirZKocaeliZ
OlympiacoszAris Thessalonikiz
AEK AthensZPanaitolikosZ
Levadiakosr   zHeart of Midlothianz
St. Mirrenz	Dundee FCZPariszAtromitos Athinonr   z
VfL BochumzEintracht BraunschweigzArminia BielefeldzDynamo DresdenzSheffield UtdzLos Angeles Galaxyr   r   r   r   r   r   zLinlithgow RosezBrora Rangersr   r   zAlmere City FCr   r   r   r   r   c                 C   s*   | t v rt |  S t | ¡}|| kr&|S | S )zŒTranslate API-Football name to football-data.co.uk name.
    Checks local FDCO_MAP first (has specific overrides), then maps.py, then as-is.)ÚFDCO_MAPr   Ú	fdco_name)Zapi_nameZmapped© r    úE:\soccer\_backfill_ftr.pyr   –   s    
r   c                 C   s6   t | tƒsdS t d| ¡}d dd„ |D ƒ¡ ¡  ¡ S )z-Lowercase + strip accents for fuzzy matching.Ú ZNFKDc                 s   s   | ]}t  |¡s|V  qd S ©N)ÚunicodedataZ	combining©Ú.0Úcr    r    r!   Ú	<genexpr>¦   ó    z_fold.<locals>.<genexpr>)Ú
isinstanceÚstrr$   Z	normalizeÚjoinÚlowerÚstrip)ÚsZnfkdr    r    r!   Ú_fold¡   s    
r0   c                  C   sž  i } t t d¡ƒD �]„}|j dd¡d }ztj|dd�}W nF ty‚ } z.td|j	› d|› �ƒ W Y d	}~qW Y d	}~n
d	}~0 0 d
|j
vsd|j
vršq| ¡ D ]ô\}}t | d
¡¡s¢t | d¡¡rÌq¢z&t t|d ƒ ¡ d¡}| d¡}W n t�y
   Y q¢Y n0 tt|d ƒƒ}	tt|d ƒƒ}
t | d¡¡�rJt|d ƒnd	}t | d¡¡�rlt|d ƒnd	}t|d
 ƒ ¡ }|||f| |||	|
f< q¢q| S )z€Load all league_data CSVs into a dict keyed by (div, date_str, home_folded, away_folded).
    Returns dict -> (FTHG, FTAG, FTR).z
*_2526.csvÚ_é   r   z	utf-8-sig©Úencodingz  Warning: could not read ú: NZFTRZDatez%d/%m/%Yz%Y-%m-%dZHomeTeamZAwayTeamZFTHGZFTAG)ÚsortedÚ
LEAGUE_DIRZglobÚstemÚrsplitÚpdÚread_csvÚ	ExceptionÚprintÚnameÚcolumnsÚiterrowsÚisnaÚgetr   Ústrptimer+   r.   Ústrftimer0   ZnotnaÚint)ZresultsÚcsv_pathÚdivÚdfÚer1   ÚrowÚdtZdate_strÚhÚaÚfthgÚftagÚftrr    r    r!   Úload_league_resultsª   s2    " 
""rQ   c                 C   sè   t t|ƒƒ}t t|ƒƒ}||||f}|| v r4| | S d dd„ |D ƒ¡}|  ¡ D ]:\\}	}
}}}|
|krP|	 |¡rP||krP||krP|  S qP|  ¡ D ]N\\}	}
}}}|
|kr®q”|	 |¡sºq”||v sÊ||v r”||v sÚ||v r”|  S q”dS )zsTry to find the game result in league_data.
    Tries exact div match first, then all divs for that country prefix.r"   c                 s   s   | ]}|  ¡ r|V  qd S r#   )Úisalphar%   r    r    r!   r(   Ö   r)   zfind_result.<locals>.<genexpr>N)r0   r   r,   ÚitemsÚ
startswith)Úleague_resultsrG   Ú	game_dateZhome_apiZaway_apiZ	home_fdcoZ	away_fdcoÚkeyÚprefixÚdrK   rL   rM   Úvalr    r    r!   Úfind_resultÉ   s"    "

 
r[   c                 C   s  t j| dd�}| j}| j}dD ]}||jvrd||< qt|ƒ}|d  ¡ |d  t¡j 	¡ dkB }dd„ }	|d  
|	¡}
|
 ¡ }|d	krš||
  jd
d�}|d  ¡ }| ¡ sÂ|d	krÂd	g d	dfS |j|g d¢f  ddg¡}d	}g }| ¡ D ]ì\}}|d }|d }|d }t|||||ƒ}|du�r¾|\}}}|d |k|d |k@ }||j|df< |du�rp||j|df< |du�rˆ||j|df< |d7 }td|› d|› d|› d|› d|› d|› �ƒ qî| |› d|› d|› d�¡ qî|d	k�pì|d	k}|�r
|�r
|j| ddd� ||||fS )zRProcess one live_data CSV. Returns (filled_count, unfilled_list, corrupt_removed).zutf-8r3   )rP   Úresult_homeÚresult_awayNÚhomer"   c                 S   sN   t  | ¡rdS t| ƒ ¡ }|dkr&dS zt|ƒ W dS  tyH   Y dS 0 d S )NTr"   F)r:   rA   r+   r.   ÚfloatÚ
ValueError)rZ   r/   r    r    r!   Úis_bogus_nameø   s    
z#process_file.<locals>.is_bogus_namer   T)ZdroprP   F)r^   ÚawayÚleaguerb   rc   r\   r]   r2   z  [filled] z vs z (z) -> ú ú-ú))Úindexr4   )r:   r;   r8   r>   r?   ÚlenrA   Zastyper+   r.   ZapplyÚsumZreset_indexÚanyZlocZdrop_duplicatesr@   r[   r=   ÚappendZto_csv)rF   rU   Ú
write_moderH   rV   ÚfnameÚcolZorig_lenZ
blank_maskra   Z
bogus_maskZcorrupt_countZmissing_maskZmissing_gamesÚfilledÚunfilledr1   rJ   r^   rb   rc   ÚresultrN   rO   rP   Z	game_maskÚchangedr    r    r!   Úprocess_fileè   sN    

$



.rs   c                     s´  dt jv } | rtdƒ ntdƒ tdƒ tƒ }tdt|ƒ› d�ƒ g d¢}d}g }d}d}|D ]¸‰ tˆ › d	� }| ¡ sŠtd
ˆ › d�ƒ q^td
ˆ › d�ƒ t||| ƒ\}}	}
}||7 }| ‡ fdd„|	D ƒ¡ ||
7 }|râ|d7 }|
rötd|
› d�ƒ |	�s|�s|
�stdƒ tƒ  q^tdƒ td|› �ƒ td|› �ƒ td|› �ƒ tdt|ƒ› �ƒ |�rŽtdƒ |D ]\‰ }tdˆ › d|› �ƒ �qn| �s°|dk�s¨|dk�r°tdƒ d S )Nz--writeu-   === WRITE MODE â€” files will be updated ===
u:   === DRY RUN â€” pass --write to actually update files ===
zLoading league_data results...z	  Loaded z  game results from league_data/
)	z
2026-04-26z
2026-05-02z
2026-05-09z
2026-05-10z
2026-05-12z
2026-05-16z
2026-05-17z
2026-05-23z
2026-05-30r   z.csvú[u"   .csv] â€” file not found, skippingz.csv]c                    s   g | ]}ˆ |f‘qS r    r    )r&   Úu©rK   r    r!   Ú
<listcomp>J  r)   zmain.<locals>.<listcomp>r2   z  [corrupt] removed z blank/bogus rowsz  (no missing ftr)z<============================================================zGames filled:        zCorrupt rows removed:zFiles changed:       zStill unfilled:      z*
Unfilled games (no match in league_data):z  r5   z&
Re-run with --write to apply changes.)	ÚsysÚargvr=   rQ   rh   ÚLIVE_DIRÚexistsrs   Úextend)rl   rU   Ztarget_datesZtotal_filledZtotal_unfilledZtotal_corruptZfiles_changedrF   ro   rp   Zcorruptrr   Zdescr    rv   r!   Úmain,  sP    

r}   Ú__main__)Ú__doc__rx   Úosr$   Zpandasr:   Úpathlibr   r   rz   r7   ÚpathÚinsertr}   r   r   r   r0   rQ   r[   rs   Ú__name__r    r    r    r!   Ú<module>   s  „ 	D6
