
    )\j*                        S r SSKrSSKrSSKrSSKrSSKJr  SSKJr  SSKrSSK	r	SSK
r
SSKrSSKr\" \5      R                  5       R                   R                   rSrSr1 SkrSrS	\S-  4S
 jrS\R0                  S\S\S\S\S\S\S	\\\4   4S jrS\S	\4S jrS	\4S jr\S:X  a  \R@                  " \" 5       5        gg)ub  
Agente 01 "Formazioni & Assenze" — raccolta fatti via LLM + web search.

L'LLM (API Claude con ricerca web) raccoglie SOLO FATTI con fonte: assenze,
dubbi, rientri, turnover. Nessun numero di probabilità esce dall'LLM: la
conversione in probabilità è del layer deterministico (impact.py).

Il segnale viene salvato in agent_signals + predictions se la partita esiste
nel DB (shadow mode: si logga, non si pubblica). Se la partita non è a DB,
l'esito viene solo stampato.

Uso:
    python scripts/agent_formazioni.py --league I1 --home Inter --away Torino         --kickoff "2026-08-23 20:45" --stage S1
    N)datetime)Pathzformazioni-v1zclaude-opus-4-8>   resteddoubtful	suspendedconfirmed_outuL  Sei l'agente "Formazioni & Assenze" di un sistema di previsione calcio.
Il tuo UNICO compito è raccogliere FATTI verificabili sulle disponibilità dei
giocatori per una specifica partita, tramite ricerche web su fonti affidabili
(Sky Sport, Gazzetta, Corriere dello Sport, Tuttosport, siti/canali ufficiali
dei club, Sos Fanta, Fantacalcio.it).

REGOLE FERREE:
1. Solo fatti, mai valutazioni numeriche di probabilità dell'esito.
2. Ogni giocatore citato deve avere una fonte (URL reale trovato in ricerca).
3. Se non trovi notizie rilevanti, restituisci liste vuote: è un esito
   perfettamente valido. NON inventare mai nulla.
4. status ammessi: "confirmed_out" (infortunio/assenza certa),
   "suspended" (squalificato), "rested" (riposo/turnover annunciato),
   "doubtful" (in dubbio, con prob_out tra 0 e 1).
5. turnover_risk (0-1) per squadra: alto solo con segnali concreti
   (coppa imminente, dichiarazioni dell'allenatore).
6. Considera solo notizie recenti e riferite a QUESTA partita o al periodo
   immediatamente precedente. Ignora infortuni già rientrati.

La tua risposta finale deve essere SOLO un blocco JSON (```json ... ```), con
questo schema esatto:
{
  "home": {"absent": [{"player": "...", "status": "confirmed_out", "reason": "...", "source_url": "..."}],
            "doubtful": [{"player": "...", "prob_out": 0.5, "reason": "...", "source_url": "..."}],
            "returning": [{"player": "...", "source_url": "..."}]},
  "away": { come home },
  "turnover_risk": {"home": 0.0, "away": 0.0, "reason": "..."},
  "confidence": 0.8,
  "notes": "sintesi in una riga per il log umano"
}returnc                  f   SS K n U R                  R                  S5      (       a  U R                  S   $ [        S-  nUR	                  5       (       a`  UR                  5       R                  5        H>  nUR                  S5      (       d  M  UR                  SS5      S   R                  5       s  $    g )Nr   ANTHROPIC_API_KEYz.envzANTHROPIC_API_KEY==   )
osenvirongetPROJECT_ROOTexists	read_text
splitlines
startswithsplitstrip)r   env_filelines      C/var/www/tigertips.talkandprofit.net/ai/scripts/agent_formazioni.pyload_api_keyr   F   s    	zz~~)**zz-..f$H&&(335D344zz#q)!,2244 6     clientmodelleaguehomeawaykickoffstagec                 P   US:X  a  SOSnSU SU SU SU SU S	U 3nS
SSS.n	SU;   a  SU	S'   [        US[        U	/SUS./S9n
SU;   d  SU;   a  SS0U
S'   U
S   n[        S5       HI  nU R                  R                  " S&0 U
D6nUR
                  S:X  a  SUS.SUR                  S./nXS'   MI    O   WR
                  S:X  a  [        S5      eSR                  S  UR                   5       5      nUR                  R                  UR                  R                  UR
                  S!.n[        R                  " S"U[        R                  5      nU(       a  UR                  S#5      O$XR!                  S$5      UR#                  S%5      S#-    n[$        R&                  " U5      nUU4$ )'zCInterroga l'LLM con web search e restituisce (payload, usage_info).S1zSiamo a circa 24 ore dal calcio d'inizio: cerca formazioni probabili, infortunati, squalificati, dichiarazioni dell'allenatore, turnover.zSiamo a meno di 75 minuti dal calcio d'inizio: cerca la FORMAZIONE UFFICIALE appena pubblicata e confrontala con le attese; segnala SOLO le sorprese (titolari attesi che mancano, rientri imprevisti).z	Partita: z - z (z), calcio d'inizio z. Stage z. web_search_20260209
web_search   )typenamemax_useshaikuweb_search_20250305r)   i>  user)rolecontent)r   
max_tokenssystemtoolsmessagesopussonnetadaptivethinkingr4      
pause_turn	assistantrefusalu+   La richiesta è stata rifiutata dal modello c              3   \   #    U  H"  oR                   S :X  d  M  UR                  v   M$     g7f)textN)r)   r?   ).0bs     r   	<genexpr>gather_facts.<locals>.<genexpr>w   s!     H#3avv7G6166#3s   ,,)input_tokensoutput_tokensstop_reasonz```json\s*(\{.*?\})\s*```r   {} )dictSYSTEM_PROMPTranger4   createrF   r0   RuntimeErrorjoinusagerD   rE   researchDOTALLgroupfindrfindjsonloads)r   r   r   r    r!   r"   r#   
stage_hintuser_msgr'   kwargsr4   _responser?   rP   mrawpayloads                      r   gather_factsra   R   s    D=	N	N	  D6TF"VH4Gy Qr*/H 0STUJ%2
6%#%+ABDF (e+$j1zj!H1X??))3F3</!'H=!,9I9IJLH!):  y(HII77H8#3#3HHD%^^88&nn::$002E 			.bii@A!''!*tIIcN4::c?Q3FGCjjoGE>r   r`   c                    0 0 U R                  S5      =(       d    0 [        U R                  S5      =(       d    S5      [        U R                  S5      =(       d    S5      SS S.nS	 GH  nU R                  U5      =(       d    0 nUR                  S
5      =(       d    /  Vs/ s H8  nUR                  S5      (       d  M  UR                  S5      [        ;   d  M6  UPM:     nnUR                  S5      =(       d    /  Vs/ s H  oDR                  S5      (       d  M  UPM     nnU H=  n[	        [        [        UR                  S5      =(       d    S5      S5      S5      US'   M?     XVUR                  S5      =(       d    / S.X'   GM!     S	 HE  nUS   R                  U5      =(       d    Sn[	        [        [        U5      S5      S5      US   U'   MG     U$ s  snf s  snf )z*Normalizza e sanifica il payload dell'LLM.turnover_risk
confidenceg      ?notesr=   Ni  )r    r!   rc   rd   re   )r    r!   absentplayerstatusr   prob_outg        g      ?	returning)rf   r   rj   )r   floatstrALLOWED_STATUSminmax)r`   outsidesrcerf   r   risks           r   validateru      s   r#KK8>Bw{{<8?C@G,23DS9;C !kk$%2!ggh/525 L5UU8_ )*xN)J 5 L #
 3 9r 9N 9!eeHoA 9NAE!%%
*;*Bs$CS I3OAjM %"%''+"6"<">	 ! !?#''-4%(U4[#)>%DOT" ! JLNs   "G GG?GGc                  <
   [         R                  " SS9n U R                  SSS9  U R                  SSS9  U R                  SSS9  U R                  SSS	S
9  U R                  SSS/SS9  U R                  S[        S9  [        R
                  " U 5        U R                  5       n[        5       nU(       d  [        S5        g[        R                  " US9n[        SUR                   S35        [        X1R                  UR                  UR                  UR                  UR                   UR"                  5      u  pE[%        U5      n[        SUS    SUS    S35        [        SUS   =(       d    S 35        [        S5        [&        R(                  " UR*                  UR,                  UR.                  UR0                  SS 9n0 nS!UR                  4S"UR                  44 Hj  u  p[2        R4                  " Xi5      n
[7        XH   5      nUS#   U   US#'   [2        R8                  " X5      Xx'   Xx   S$    H  n[        S%U S&U 35        M     Ml     US!   S$   (       d  US"   S$   (       d  [        S'5        [        S(5        [2        R:                  " XaR                  5      n[2        R<                  " XR                  UR                  US!   US"   S).5      nUS*   US+   nn[        S,S-S. S/S0 S1S0 S2S0 35        [        S3S*S. US4   S5 US   S5 US$   S5 35        [        S3S6S. US4   S5 US   S5 US$   S5 35        [        S75        [>        R@                  " UR                   S85      RC                  5       nURE                  5       nURG                  S9UUR                  UR                  45        URI                  5       nUc  [        S:5        GO<US4   nURG                  S;UUR"                  [J        RL                  " US<S=9[O        US!   S4   US!   S   -   S>5      [O        US"   S4   US"   S   -   S>5      US?   [P         S@UR                   345        SAU4SBU44 H  u  nnURG                  SCUUR"                  U[O        US4   S>5      [O        US   S>5      [O        US$   S>5      [J        RL                  " SDURS                  5        VVs0 s H  u  nnUUS S$ _M     snn05      45        M     URU                  5         [        SEU SF35        URW                  5         g4s  snnf )GNu0   Agente formazioni: fatti via LLM -> probabilità)descriptionz--leagueT)requiredz--homez--awayz	--kickoffzes. "2026-08-23 20:45")rx   helpz--stager%   S2)choicesdefaultz--model)r|   z)Manca ANTHROPIC_API_KEY (env o file .env)r   )api_keyz[1/4] Raccolta fatti via z + web search...z      tokens: rD   z in / rE   z outz      note agente: re   z	(nessuna)z2[2/4] Conversione deterministica fatti -> delta...	tigertips)hostportr.   passworddatabaser    r!   rc      z      [z] z,      nessun impatto rilevato (esito valido)u/   [3/4] Probabilità col modello DC aggiornato...)_deltas_home_deltas_awaybaselineadjustedz
      r=   z<121z>8X2z      r   z>8.1%
aggiustataz
[4/4] Salvataggio nel DB...z%Y-%m-%d %H:%Mz
        SELECT m.id FROM matches m
        JOIN teams h ON h.id = m.home_team_id
        JOIN teams a ON a.id = m.away_team_id
        WHERE m.match_date = %s AND h.name = %s AND a.name = %s
    zp      partita non presente in matches: segnale NON salvato (esegui prima sync_fixtures.py). Output solo a video.a1  
            INSERT INTO agent_signals (match_id, agent, stage, checked_at, payload,
                                       delta_lambda_home, delta_lambda_away,
                                       confidence, model_version)
            VALUES (%s, 'formazioni', %s, NOW(), %s, %s, %s, %s, %s)
        F)ensure_asciir9   rd   -r   	agent_adjz
                INSERT INTO predictions (match_id, made_at, stage, source,
                                         prob_home, prob_draw, prob_away, details)
                VALUES (%s, NOW(), %s, %s, %s, %s, %s, %s)
            deltasz      salvato: match_id=z, segnale + 2 predizioni),argparseArgumentParseradd_argumentDEFAULT_MODELconfigadd_db_args
parse_argsr   print	anthropic	Anthropicr   ra   r   r    r!   r"   r#   ru   pymysqlconnectr   r   r.   r   impact
load_squadrJ   side_deltasfit_currentadjusted_predictionr   strptimedatecursorexecutefetchonerW   dumpsroundMODEL_VERSIONitemscommitclose)parserargsr}   r   r`   rP   connr   rq   teamsquadfactsr   r   
predictionrA   akickoff_datecurrowmatch_idsourceprobskvs                            r   mainr      s   $$1cdF

T2
40
40
d9QR
	D$<F
	=9
vDnG9:  1F	%djj\1A
BC!&**dkk"&))TYYdjjRNGwG	N501o8N7Ot
TU	 0 ?K@
AB	
>???						$(MMKIDF		*VTYY,?@
!!$-W]#!(!9$!?o))%7LODGD6D6*+ $ A &>!VF^A%6<=	
;<t[[1E++yy$))HJJ j!:j#9qA	HRHSHSHSH
56	F:c"1Q4,qtEl1Q4,
GH	F<$QqT%L1eQqT%L
IJ	
)*$$T\\3CDIIKL
++-CKK 
 		499	-/ ,,.C
{ F 	G q6 
 

DJJwU$KF6N1%vq(991=F6N1%vq(991=l#a

|%DF	G  'l[!,<=MFEKK  DJJa!$eE!Ha&8%a!:L**hflln(MndaAbqEn(MNOQ	R > 	(
2JKLJJL )Ns   T __main__)!__doc__r   rW   rQ   sysr   pathlibr   r   r   r   dixon_colesdcr   __file__resolveparentr   r   r   rm   rK   rl   r   r   tuplerJ   ra   ru   intr   __name__exitrI   r   r   <module>r      s      	 
       H~%%'..55!E@	cDj 	-,, -S -# --"%-03-<?-DI$PT*DU-`d t *Tc Tn zHHTV r   