o
    txiK                     @   sJ  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mZm	Z	 zddl
Z
W n ey:   ed ed Y nw zddlmZ eee jd  W n	 eyW   Y nw ejejd	d
d edZeddZdZee jd Zddddddddddd
Zi 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/Zdd0d1dd2d1dd3d1d4d5d1d4d6d1d4d7d1d8d9d1d8d:d1dd;d<d=dd>d<d=dd?d<d=d@ZdAdB ZdCdD ZdEdF Z dGdH Z!dIdJ Z"dKdL Z#dMdN Z$e%dOkr#e$  dS dS )Pu  
Standalone Betting Refresh — Predictable Tempo Strategy
========================================================
Fetches live odds from The Odds API, applies Bill's full strategy
(tempo classification + odds-based intelligence + validation),
and writes picks directly to dashboard-data.json.

Independent of Luke. Can be run manually or on a schedule.

Usage:
  python3 betting_refresh.py              # uses .env for API key
  ODDS_API_KEY=xxx python3 betting_refresh.py  # explicit key
    N)Path)datetime	timedeltadatezpip install requests   )load_dotenvz.envz!%(asctime)s [BETTING] %(message)sz%H:%M:%S)levelformatdatefmtzbetting-refreshODDS_API_KEY zhttps://api.the-odds-api.com/v4zdashboard-data.jsonicehockey_nhl
soccer_eplsoccer_italy_serie_asoccer_france_ligue_onesoccer_spain_la_ligasoccer_portugal_primeira_ligasoccer_usa_mlssoccer_uefa_champs_leaguesoccer_uefa_europa_league$soccer_uefa_europa_conference_league)
nhleplseriealigue1laligaliga_portugalmlsucleuropa
conferencezCarolina HurricaneslowzMinnesota WildzNashville PredatorszDallas StarszWinnipeg JetszNew York IslanderszColumbus Blue JacketszLos Angeles KingszBoston BruinszNew Jersey DevilszVegas Golden KnightszSt Louis BlueszSeattle KrakenzVancouver CanuckszAnaheim DuckszToronto Maple LeafshighzEdmonton Oilers)zColorado AvalanchezFlorida PantherszTampa Bay LightningzOttawa SenatorszBuffalo SabreszDetroit Red WingszPittsburgh PenguinszNew York RangerszWashington CapitalszCalgary FlameszPhiladelphia FlyerszChicago BlackhawkszMontreal CanadienszSan Jose SharkszUtah Hockey ClubzSerie AtierlabelzLigue 1zLiga Portugal   zLa LigaEPLMLS   
Bundesliga
EredivisiezChampions LeagueT)r$   r%   is_cupzEuropa LeaguezConference League)r   r   r   r   r   r   soccer_germany_bundesligasoccer_netherlands_eredivisier   r   r   c                 C   sD   t | d}t |d}|dkr|dkrdS |dkr |dkr dS dS )Nmediumr!   
controlledr"   chaoticmixed)	NHL_TEAMSget)homeawayha r9   ;/sessions/lucid-sleepy-lamport/mnt/clawd/betting_refresh.pyclassify_nhl\   s   r;   c                 C   s   t | d| dS )Nr&   r#   )SOCCER_TIERSr4   )	sport_keyr9   r9   r:   get_soccer_tierf   s   r>   c                    s  |  dg }g d}d}|D ] t fdd|D d}|r  nq|s)|r)|d }|s-i S d| d| d	d
i}tdd | dg D d}|rt| drtt|d dd d}t|d dd d}|d |d< |d |d< |d |d< tdd | dg D d}|r| drtdd |d D d}	tdd |d D d}
|	r|	 dd|d< |	 dd|d< |
r|
 dd|d< tdd | dg D d}|r| drtdd |d D d}|rt|d |d < |S )!z9Extract favorite, total line, spread from bookmaker data.
bookmakers)bet365
draftkingsfanduelbovadabetmgmNc                 3   s     | ]}|d   kr|V  qdS )keyNr9   ).0bbnamer9   r:   	<genexpr>p       z%extract_odds_intel.<locals>.<genexpr>r   booktitlerE   r   c                 s        | ]}|d  dkr|V  qdS )rE   h2hNr9   rF   mr9   r9   r:   rJ   {   rK   marketsoutcomesc                 S      | d S Npricer9   or9   r9   r:   <lambda>}       z$extract_odds_intel.<locals>.<lambda>rE   c                 S   rT   rU   r9   rW   r9   r9   r:   rY   ~   rZ   namefavoriterV   	fav_price	dog_pricec                 s   rN   )rE   totalsNr9   rP   r9   r9   r:   rJ      rK   c                 s   rN   )r\   OverNr9   rF   rX   r9   r9   r:   rJ      rK   c                 s   rN   )r\   UnderNr9   rb   r9   r9   r:   rJ      rK   point
total_line
over_priceunder_pricec                 s   rN   )rE   spreadsNr9   rP   r9   r9   r:   rJ      rK   c                 s   s$    | ]}| d ddk r|V  qdS )rd   r   Nr4   rb   r9   r9   r:   rJ      s   " spread)r4   nextminmaxabs)gamebms	preferredrL   intelrO   favdogr`   overunderrh   
fav_spreadr9   rH   r:   extract_odds_intelj   sF   rx   c                 C   s2  | d }| d }d}zt | d dd}|tdd }|d	}W n ttfy.   Y nw t| }|d
}	|dd}
|dd}|dd}|dd}|rX|rX||k nd}|dd}d|v rt	||}|dkr|
rvd|
 dnd}|g}|	r|
|	 d |r|dkr|
|	 d |
d d}d}|
r|
dkrd}|d 7 }n|
r|
d!krd"}|d#|
 d$7 }n|
r|
d%krd&}d'|
 d(}|rtd)|d* }|||d+d,|d-|dkrd.nd/||dd0 d1d2| d$gd3d4S |d5kr|||d+d6d7gd8d9d:d;d1gd3d4S t|d<kr|n|}||kr|n|}|
r&d|
 dnd}|| d=dg}d>}| d?| }|
rH|
dkrHd}|d@7 }n|
rV|
d!krVd&}|dA7 }|r`td)|d* }|	|krqtd)|d* }| dB}|dkr|dC| dDndE| dD}|dkrd-ndF}|||d+||||dkrd.nd/||dd0 d1d2| d$gd3d4S t|}|dG d*kr@|
r|
dHkrd|
 dIndJ}|g}|	r|
|	 dK |
|	 dL n
|
dM |
dN d}|dO  dP}|dQr |dO  dR}d"}|
r|
dSkrtd)|d* }|dT7 }|rtd)|d* }||||dO dU|d-|dkr-d.nd/||dd0 dVd2| d$gd3d4S |dG d:kr g }|dWkr]|
|
rYd|
 dIndX n|
dJ |	rv|
|	 dK |
|	 dL n
|
dY |
dN d>}|dO  dZ}|
r|
dSkrd}|d[7 }n|
r|
dHkrd&}|d\7 }|rtd)|d* }|r|dkrtd)|d* }d]|dO  }|dkrdC|dO  nd^}|dkrd-ndF}||||dO ||||dkrd.nd/||dd0 dVd2| d$gd3d4S ||||dO d_d`gd8d9d:|dO  dadVgd3d4S )bz:Build a pick with legs, validation, and odds intelligence.	home_team	away_teamr   commence_timeZ+00:00   hoursz%-I:%M %p ETr]   re   r   rj   rf   rg   NrL   market	icehockeyr0   zUnder z total goalszUnder 6.5 total goalsz ML (moneyline)g      ?z +1.5 PL (puckline)z1st period Under 1.5   u-   Both teams are low-event — controlled tempog      @	   u   , total line confirms (≤5.5)g      @   z, total line supports ()g      @   z%Low-event teams but total line high (u   ) — market disagrees
   r   NHLu   ★ CONTROLLEDprime	VALIDATEDCAUTIONP   zTempo ProfilezLive Odds ()verdict
confidencereasonsources)r5   r6   timesporttaglegsrating
validationr1   u   ⚡ CHAOTICu"   Skip unders — high-event matchupavoidDROPPEDr&   u-   Both teams are high-event — chaotic matchupr!   z Under 3.5 team total   z anchors the pace, risk from u    — but total line is tightu    — total line moderatez favored + controls tempou   ★ VALIDATED — z anchorsu
   MIXED — playabler$   g      @z goalszUnder 2.5 goalsz DC (draw no bet)z Over 3 cornerszBTTS No (both teams to score)zUnder 8.5 cornersr%   u    — prime under territoryr,   u!    knockout — teams protect leadsg      @z, line confirmsu
   ★ TIER 1zLeague Tierr   zUnder 3.0 goalszBTTS Nou    — usable with filteringz, line confirms underz, line moderateu'   Heavy favorite → controlled tempo in u   TIER 2 — filteru   TIER 3 — AVOIDu$   Skip unders — high-variance leagueu&    — high-scoring league, avoid unders)r   fromisoformatreplacer   strftime
ValueErrorKeyErrorrx   r4   r;   appendrl   r3   r>   )ro   sport_labelr=   r5   r6   time_strcteasternoddsr]   re   rj   rf   rg   under_favored	book_nametempounder_targetr   confr   anchor
non_anchorr   r   leaguer9   r9   r:   
build_pick   s  







"
 







r   c                     s2  t s	td g S g } t }t }|jdddd}|tdd }|||  }d}t	 D ]\}}zt
 d| d	}	t d
dddd}
tj|	|
dd}|jdkrZt| d W q.|jdkrit| d W q.|jdkr{t| d|j  W q.|jd|}|}| }d}|D ];}z.t|d ddjdd}||k rW q||krW q|d7 }t|||}|r| | W q ttfy   Y qw |rt| dt| d | d! W q. ty } zt| d"|  W Y d}~q.d}~ww td#t|  d$| d% ddd&d'd( | j fd)d*d+ | S ),z;Fetch odds for all sports, build picks, return sorted list.z5No ODDS_API_KEY found. Set it in .env or environment.   ;   )hourminutesecondr   r   ?z/sports/z/odds/zus,us2,uk,euzh2h,totals,spreadsamericaniso)apiKeyregionsrR   
oddsFormat
dateFormat   )paramstimeouti  z: not on plan, skippingi  z: rate limited   z: API error zx-requests-remainingr   r{   r|   r}   N)tzinfor   z: z total, z
 in windowu   : fetch failed — zTotal: z picks, z API requests remainingr&   r)   )r   r   neutralr   c                    s*     |  ddd|  di  dd fS )Nr   r   r&   r   r   r   ri   )prating_orderr9   r:   rY     s   z!fetch_all_picks.<locals>.<lambda>r[   )r   logerrorr   utcnownowr   r   
SPORT_KEYSitems	ODDS_BASErequestsr4   status_codeinfowarningheadersjsonr   r   r   r   r   len	Exceptionsort)	all_picksr   	local_now
end_of_daycutoff
cutoff_utc	remainingr%   r=   urlr   respremgames	in_windowro   	game_timepicker9   r   r:   fetch_all_picksS  s~   




  r   c              
   C   s   t  stdt   dS z	tt  }W n tjtfy5 } ztd|  W Y d}~dS d}~ww | t	
  dd|d< zt tj|dd	 td
t|  dt   W dS  tyw } ztd|  W Y d}~dS d}~ww )z;Write picks to dashboard-data.json under the 'betting' key.zDashboard JSON not found: FzFailed to read dashboard JSON: Nzbetting_refresh.py)r   updatedsourcebettingr&   )indentzWrote z
 picks to Tz Failed to write dashboard JSON: )DASHBOARD_JSONexistsr   r   r   loads	read_textJSONDecodeErrorOSErrorr   r   	isoformat
write_textdumpsr   r   )picksdatar   r9   r9   r:   write_to_dashboard  s.   

r   c                  C   s  t d t d t dt    t d t } | rtdd | D }tdd | D }tdd | D }tdd | D }t d	| d
| d| d| d	 t|  tdd  tdt 	d  td d | D ]u}|d dkrqv|
di }|
dd}|
dd}|dkrdn|dkrdnd}	t|	 d|d  d|d    td!|d"  d#|d$  d#|d%   |
d&g D ]	}
td'|
  q|rtd!|	 d| d(| d)|
d*d  t  qvd S t d+ tg  d S ),Nz2==================================================u.   Betting Refresh — Predictable Tempo StrategyzDate: c                 s        | ]}|d  dkrdV  qdS )r   r   r   Nr9   rF   r   r9   r9   r:   rJ     rK   zmain.<locals>.<genexpr>c                 s   r   )r   r   r   Nr9   r   r9   r9   r:   rJ     rK   c                 s   r   )r   r   r   Nr9   r   r9   r9   r:   rJ     rK   c                 s   s*    | ]}| d i  ddkrdV  qdS )r   r   r   r   Nri   r   r9   r9   r:   rJ     s   ( z	Results: z prime, z playable, z	 avoid | z
 validated
u   TODAY'S PICKS — z
%A, %B %-dr   r   r   r   r   r   r   r   u   ★r   u   ⚠u   ✕ r6   z @ r5   z  r   u    · r   r   r   u       → z (u	   /10) — r   u3   No picks generated — either no games or API issue)r   r   r   todayr   r   sumr   printr   r4   )r   r   r   r   	validatedr   vr   r   iconlegr9   r9   r:   main  s@   


$ &(
r   __main__)&__doc__ossysr   loggingpathlibr   r   r   r   r   ImportErrorr   exitdotenvr   __file__resolveparentbasicConfigINFO	getLoggerr   getenvr   r   r   r   r3   r<   r;   r>   rx   r   r   r   r   __name__r9   r9   r9   r:   <module>   s   




. <M
)
