o
    iڰ                     @   s  d Z ddlZddlZddlZddlZddlmZmZmZ ddlm	Z	 e
dZe	jp/eddZ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-Zd.d/d0d1d2d3d.d4d0d1d5d3d.d6d7d1d8d3d9d:d;d<d=d3d9d>d?d<d@d3d9dAdBd<dCd3dDdEdFd<dGd3dDdHdId<dJd3dKZi dLdMdNd1dOdPdMdQd1dOdRdMdSd1dOdTdMdUd1dOdVdMdWd1dOdXdMdYd1dOdZdMd[d1dOd\dMd]d1dOd^d_d`d<dOdad_dbd<dOdcd_ddd<dOded_dfd<dOdgd_dhd<dOdid_djd<dOdkd_dld<dOdmd_dnd<dOZd0dBdodpdqdrdsdtZdudvdwdxZi dydzd{dzd|dzd}did~diddidd^dd^dd^ddddddddddddaddaddi ddddVddVddddddgddgddeddeddddddLddLddddXddPddPi ddcddcddTddTddddRddRddddmddmddkddkddddddddddi dddd\ddddddZddddÓddœddœddȓddʓddʓdd͓ddϓddѓddѓddԓi ddԓddדddٓddۓddݓddݓddddddddddddddddddddddi ddddddddddddd dddddddddddd	dd
ddddddd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/ZG d0d1 d1Zdad2d3 ZdS (4  u  
Sports Betting Module for Luke.

Bill's Distilled Betting Strategy — "Predictable Tempo" Philosophy
==================================================================
We bet on predictable tempo and structure, NOT outcomes.
Find the most controlled game environments and bet the scoring
range that matches the most common scorelines.

Core Process:
  1. Eliminate chaotic games (high-variance leagues, high-offense matchups)
  2. Find controlled games (defensive teams, low-creation matchups)
  3. Predict the scoring range (goal bands, not exact scores)
  4. Build matching bets (totals, spreads, correlated parlays)

Bill's Profile:
  - Platform: Bet365
  - Sports: NHL, NFL, EPL, Serie A, Ligue 1, La Liga, Liga Portugal, MLS
  - Style: Low-risk parlays, correlated boosts, profit boost optimization
  - Sweet spot: +120 to +220 boost range

Uses The Odds API (free tier: 500 requests/month).
Get a free key at: https://the-odds-api.com
    N)datetimedate	timedelta)Configzsports-bettingODDS_API_KEY zhttps://api.the-odds-api.com/v4nhlicehockey_nhlnflamericanfootball_nflepl
soccer_eplncaafamericanfootball_ncaafnbabasketball_nbamlbbaseball_mlbmlssoccer_usa_mlscflamericanfootball_cflserieasoccer_italy_serie_aserie_aligue1soccer_france_ligue_oneligue_1laligasoccer_spain_la_ligala_liga
bundesligasoccer_germany_bundesligaliga_portugalsoccer_portugal_primeira_liga
eredivisiesoccer_netherlands_eredivisiesoccer_uefa_champs_leaguesoccer_uefa_europa_league$soccer_uefa_europa_conference_leaguesoccer_fa_cupsoccer_spain_copa_del_rey)uclchampions_leagueeuropaeuropa_league
conferenceconference_leaguefa_cupcopa_del_rey   zSerie Ag      @Tz4Most tactically disciplined. Best league for unders.)tierlabel	avg_goals
under_biasnotezLigue 1z6Low-creation outside PSG. Treat PSG games as outliers.zLiga Portugal333333@z<Very predictable. Strong for Under 2.5 in mid-table clashes.   zLa Ligag@Fz2Top 3 inflate goals. Mid-table matchups are solid.EPLgffffff@zKMost variance. Only target 'boring' matchups (e.g., Everton/Palace/Wolves).MLSg      @z/Use Under 3.0 or 3.5 only. No Under 2.5 in MLS.   
Bundesligag	@z:AVOID unders. High-pressing league, goals come in bunches.
Eredivisiegffffff
@z9AVOID. Open, end-to-end play. Not suited to Bill's style.)r   r   r#   r   r   r   r!   r%   zCarolina Hurricaneslowzelite defense)tempor6   under_targetzMinnesota Wildz
grind teamzNashville Predatorszdefensive structurezDallas Starszlow-event hockeyzWinnipeg Jetszstructured playzNew York Islanderszdefensive identityzColumbus Blue Jacketszlow-scoringzLos Angeles Kingszstructured westzToronto Maple Leafshighzhigh-offensezEdmonton Oilerszhigh-firepowerzColorado Avalanchezexplosive offensezFlorida Panthersz
high-eventzTampa Bay Lightningzoffensive upsidezOttawa Senatorszyoung/chaoticzBuffalo Sabreszchaotic/rebuildingzDetroit Red Wingszinconsistent/leakyg      @)primaryr   safeg      @g      @)rE   tight)soccer_under	nhl_underx      z7Sweet spot +120 to +220. Only on legs you'd bet anyway.)min_oddsmax_oddsr9   habszMontreal Canadiens	canadiensmontrealsenssenatorsottawaleafszmaple leafstorontobruinszBoston BruinsbostonrangerszNew York RangerspenguinszPittsburgh PenguinspensoilersedmontonflameszCalgary FlamescalgaryjetswinnipegcanuckszVancouver Canucks	vancouver	lightningtampapanthersfloridacapitalszWashington Capitalscaps
hurricanescarolinadevilszNew Jersey Devils	islanderswild	minnesota	avalancheavsstarsdallasblueszSt. Louis Blues	predatorspreds
blackhawkszChicago Blackhawksz	red wingswingssabresbuffalokrakenzSeattle KrakenseattlecoyoteszUtah Hockey ClubutahduckszAnaheim DuckssharkszSan Jose Sharkskingszgolden knightszVegas Golden Knightsvegaszblue jacketschiefszKansas City ChiefsbillszBuffalo BillseagleszPhiladelphia EaglesphillycowboyszDallas Cowboys49erszSan Francisco 49ersninersravenszBaltimore RavensbengalszCincinnati BengalsdolphinszMiami DolphinsmiamilionszDetroit LionsdetroitpackerszGreen Bay PackersbearszChicago BearsvikingszMinnesota VikingssteelerszPittsburgh Steelers
pittsburghchargerszLos Angeles ChargersbroncoszDenver BroncosraiderszLas Vegas RaiderstexanszHouston TexansjaguarszJacksonville JaguarscoltszIndianapolis ColtstitanszTennessee Titans
commanderszWashington CommandersgiantszNew York GiantssaintszNew Orleans SaintsfalconszAtlanta Falcons
buccaneerszTampa Bay BuccaneersbucsseahawkszSeattle Seahawks	cardinalszArizona CardinalsramszLos Angeles RamsarsenalArsenalgunners	liverpool	Liverpoolredszman cityzManchester Citycityz
man unitedzManchester UnitedunitedchelseaChelsea	tottenhamzTottenham Hotspurspurs	newcastlezNewcastle Unitedmagpieszaston villazAston VillavillabrightonzBrighton and Hove Albionzwest hamzWest Ham Unitedhammerszcrystal palacezCrystal Palacepalace	brentford	BrentfordfulhamFulhamwolveszWolverhampton WandererswolverhamptonbournemouthzAFC Bournemouth
nottinghamzNottingham ForestforestevertonEverton	leicesterzLeicester CityzIpswich TownSouthampton)ipswichsouthamptonc                   @   s   e Zd ZdZdd Zedd Zdd Zdd	 Zd
d Z	dd Z
d(ddZdd Zdd Zd)ddZd(ddZdd Zdd Zdd  Zd*d"d#Zd(d$d%Zd&d' ZdS )+SportsBettingAnalystuK   Luke's sports betting brain — built on Bill's Predictable Tempo strategy.c                 C   s
   d | _ d S N)
_availableself r   I/sessions/festive-kind-sagan/mnt/clawd/whatsapp-agent/./sports_betting.py__init__   s   
zSportsBettingAnalyst.__init__c                 C   s:   | j du rtt| _ | j rtd | j S td | j S )z$Check if the Odds API is configured.NzSports betting module: ACTIVEz:Sports betting module: INACTIVE (set ODDS_API_KEY in .env))r   boolr   loggerinfor   r   r   r   	available   s   



zSportsBettingAnalyst.availablec                 C   sp   t |i }t |i }|dd}|dd}|dkr"|dkr"dS |dkr,|dkr,dS |dks4|dkr6dS dS )zh
        Classify an NHL matchup by tempo.
        Returns: 'controlled', 'chaotic', or 'mixed'
        rB   mediumrA   
controlledrD   chaoticmixedNHL_TEAM_PROFILESget)r   homeawayhome_profileaway_profile
home_tempo
away_tempor   r   r   classify_nhl_matchup   s   z)SportsBettingAnalyst.classify_nhl_matchupc                    s   | dd t  d}|st D ]\}}| v r|} nq|s9ddddddd} |v r9d|  d	d
d
ddS |sBdddddS t|}t fdddD rYd
|d< d|d< |S )z
        Classify a soccer matchup by league tier and expected tempo.
        Returns dict with tier, recommendation, and notes.
        sportr   NzEuropa LeaguezConference LeaguezChampions League)r.   r/   r0   r1   r,   r-   r4   r:   TzOCUP KNOCKOUT: Teams protect leads, first legs are cagey. Prime under territory.)r5   r6   r7   r8   is_cupr9   r;   zUnknown Leaguecautionu(   Unknown league — apply Tier 2 caution.)r5   r6   recommendationr9   c                 3       | ]}| v V  qd S r   r   ).0cup	sport_keyr   r   	<genexpr>1      z?SportsBettingAnalyst.classify_soccer_matchup.<locals>.<genexpr>)r   copar   zwCUP GAME: Unders hit more in knockout rounds (teams protect leads). Group stages are less predictable. Check the stage.r9   )r   SOCCER_LEAGUE_TIERSitemsdictany)r   gameleague_infokeyr   
cup_labelsresultr   r   r   classify_soccer_matchup  sD   	z,SportsBettingAnalyst.classify_soccer_matchupc                 C   s   t |i }|ddS )z$Get the tempo label for an NHL team.r6   	unlabeledr   )r   	team_nameprofiler   r   r   get_nhl_team_label:  s   z'SportsBettingAnalyst.get_nhl_team_labelc                 C   s    t d |  kot d kS   S )zBCheck if a profit boost falls in Bill's sweet spot (+120 to +220).rL   rM   )BOOST_STRATEGY)r   
odds_valuer   r   r   is_boost_worthy?  s    z$SportsBettingAnalyst.is_boost_worthyNc              
   C   s0  | j sdS |du ri }t|d< zmt | }td|  tj||dd}|jdkrG|jdd}|	 }td	t
| d
| d |W S |jdkrTtd W dS |jdkritd|jdd   W dS td|j d|jdd   W dS  ty } ztd|  W Y d}~dS d}~ww )zMake a request to The Odds API.NapiKeyzOdds API calling:    )paramstimeout   zx-requests-remaining?u   Odds API OK — z
 results, z requests remainingi  u1   Odds API auth failed (401) — check your API keyi  u#   Odds API invalid request (422) — zOdds API error:     — zOdds API request failed: )r   r   ODDS_BASE_URLr   r   requestsr   status_codeheadersjsonlenerrortext	Exception)r   endpointr   urlresp	remainingdataer   r   r   _api_getC  s6   



"zSportsBettingAnalyst._api_getc                 C   sJ   |   }|tv rt| S t D ]\}}||v s||v r"|  S qdS )z(Resolve a team name from a casual query.N)lowerstripTEAM_ALIASESr   )r   queryqalias	full_namer   r   r   resolve_teama  s   z!SportsBettingAnalyst.resolve_teamc                    s   |   t fdddD rdS t fdddD rdS t fddd	D r+d
S t fdddD r8dS |  }|r_dd t D }||v rNdS dd t D }||v r]dS d
S dS )z$Detect which sport a query is about.c                 3   r   r   r   r   wr  r   r   r   q  r   z4SportsBettingAnalyst.detect_sport.<locals>.<genexpr>)r   hockeyicer   c                 3   r   r   r   r  r  r   r   r   s  r   )r
   football	touchdownr
   c                 3   r   r   r   r  r  r   r   r   u  r   )r   zpremier leaguesoccerr   r   c                 3   r   r   r   r  r  r   r   r   w  r   )r   
basketballr   c                    *   g | ]\} t  fd ddD r qS )c                 3   r   r   r   r   tvr   r   r   ~      
?SportsBettingAnalyst.detect_sport.<locals>.<listcomp>.<genexpr>)	CanadiensSenatorszMaple LeafsBruinsRangersPenguinsOilersFlamesJetsCanucks	LightningPanthersCapitals
HurricanesDevils	IslandersWild	AvalancheStarsBlues	Predators
Blackhawksz	Red WingsSabresKrakenzHockey ClubDucksSharksKingszGolden KnightszBlue Jacketsr   r   kr   r'  r   
<listcomp>~      z5SportsBettingAnalyst.detect_sport.<locals>.<listcomp>c                    r$  )c                 3   r   r   r   r%  r'  r   r   r     r)  r*  )ChiefsBillsEaglesCowboysr   RavensBengalsDolphinsLionsPackersBearsVikingsSteelersChargersBroncosRaidersTexansJaguarsColtsTitans
CommandersGiantsSaintsFalcons
BuccaneersSeahawks	CardinalsRamsrE  rF  r   r'  r   rH    rI  N)r  r   r  r  r   )r   r  team	nhl_teams	nfl_teamsr   r  r   detect_sportm  s&   
z!SportsBettingAnalyst.detect_sportr   r;   c                 C   s,  t |}|std|  g S | jd| ddddddd	}|s1td
| d| d g S t }|t|d }g }d}|D ]A}	z#t	|	d 
ddj
dd}
|
|krb|| |	| n|d7 }W qB ttfy } ztd|  W Y d}~qBd}~ww t| dt| d| d |S )z)Get upcoming games with odds for a sport.zUnknown sport key: /sports/z/odds/zus,us2,uk,euzh2h,spreads,totalsamericaniso)regionsmarkets
oddsFormat
dateFormatr   zNo data returned for z ()daysr   commence_timeZ+00:00Ntzinfor4   zSkipped game parse error: : z games within window, z beyond cutoff)
SPORT_KEYSr   r   warningr  r   r   utcnowr   fromisoformatreplaceappend_parse_gameKeyError
ValueErrordebugr  )r   r   
days_aheadr   r  nowcutoffgamesskippedr   	game_timer  r   r   r   get_upcoming_games  s>   

 z'SportsBettingAnalyst.get_upcoming_gamesc                 C   s   |  |}|sdd| dfS |s| |}|sMdD ]*}| j|dd}|D ]}| |d  v s;| |d  v rC|df    S q%qdd	| d
fS | j|dd}|D ]}| |d  v sl| |d  v rr|df  S qVdd|  d| dfS )z*Find an upcoming game for a specific team.NzI don't recognize 'z' as a team. Try the full name?)r   r
   r      r  	home_team	away_teamzNo upcoming game found for .zNo upcoming z game found for z in the next 7 days.)r  rh  r  r  upper)r   
team_queryr   r   sr  gr   r   r   get_game_for_team  s(   

((z&SportsBettingAnalyst.get_game_for_teamc              	   C   s  | d|| dd| dd| ddg d}z"t|d dd}|td	d
 }|d|d< |d|d< W n ttfyM   d|d< d|d< Y nw g d}|D ]4}| dg D ]+}|d |kr|d i d}	| dg D ]}
|
d |	d |
d < qq|d |	  nq\qT|S )z/Parse raw API game data into a clean structure.idr  r   r  rt  r  r   r  r  rt  
bookmakersru  rv     hours
%A, %B %-d	game_date%-I:%M %p ETr  )bet365
draftkingsfanduelbovadabetmgmr  r   title)namerm  rm  outcomes)	r   r   r}  r~  r   strftimer  r  r  )r   rawr   r   cteasternpreferred_books	book_namebm	book_datamarketr   r   r   r    s8   



z SportsBettingAnalyst._parse_gamec              
      s  | j sdS | |\}}|r|S |d  |d  d|d  g}||d  d|d    d	krw| |d |d }| |d }| |d }|d
|   |dkre|d|d  d|  |dkrv|d|d  d|  nB tv st fdddD r| |}|d|	d   d|d  d |	dr|d |d dkr|d|d   |d z*ddl
m}	m}
 |	|d |d  }|
||d |d }|r|| |d W n ty } ztd|  W Y d}~nd}~ww |d  |d | |}|D ]}|d|  qz)dd!lm}m} ||d |d  }d"|i}||}|rI|d || W n) tyY   td# Y n tys } ztd$|  W Y d}~nd}~ww |d |d% d&|S )'u   
        Generate a strategy-driven pre-game analysis using Bill's
        Predictable Tempo philosophy.

        No odds displayed — just game environment classification,
        pre-game chatter, and recommended legs that fit the matchup.
        n   Sports betting not configured. Add ODDS_API_KEY to your .env file. Get a free key at the-odds-api.com — Luker   r   @ r  r  u    • r  r   zTempo: r     ry  c                 3   s    | ]}  |V  qd S r   )
startswithrF  r   r   r   r     s    z9SportsBettingAnalyst.generate_analysis.<locals>.<genexpr>)r   serieliguer   liga_zLeague: r6   z (Tier r5   rq  r   u3     CUP GAME — knockout round unders hit more oftenr>   z  CAUTION: r9   r   r   get_pregame_chatterformat_chatter_for_whatsappz%Chatter fetch failed (non-critical): NzSUGGESTED LEGS:)validate_pickformat_validation_for_whatsapp
validationu7   pregame_validator not available — skipping validationz*Pregame validation failed (non-critical): u   — Luke
)r   r  r  r   r   r  r   r   r   r   pregame_chatterr  r  r  r   r  _generate_suggestionspregame_validatorr  r  ImportErrorjoin)r   r  r   r	  linesrB   
home_label
away_labelleague_classr  r  chatterchatter_textr  suggestionsr  r  r  r  pick_with_validationvalidation_textr   r  r   generate_analysis  sz   
(












z&SportsBettingAnalyst.generate_analysisc                 C   s4  g }|d }d}d}|d rJ|d d }|d  dg }|d  dg }|r2t|dd	 d
}	|	d }|r>tdd |D dnd}
|
rH|
 ddnd}|dkr*| |d |d }|dkr|d |d |d |d |d |d |r|d| d |d |d |d| d |d |d nR|dkr|d  |d! |d |d" |d# |d$ n.t |d i }t |d i }| d%d&kr|d n|d }|d' || d( |d |d |d) |r(|d| d* |d |d |d| d |d+ n|d,v s:d-t| d.dv rp| |}| d/d0}|d1kr||d2  d3 || d4d |d |d |d5 |d6 |r|d| d7 |d |d |d| d8 |d9 n|d0kr||d2  d: || d4d |d |d;kr|d |d< |r|d| d7 n7|d=kr|d> |d5 |r|d| d7 |d? n|d@ |d5 |r|d| d7 |r|d |d |d| d8 n3|dAkrP||d2  dB || d4d |d |dC |rP|dD| dE |dF | dGro|d |dH |dI |dJ |dK n|dLkr|d |dMkr|dN |d |dO| dP n,|dQkr|dR |d |dO| dS n|dT |d |dU| dV |r|d| dW |d |d |d| dX|  n|r|d| d7 |dY |dZ |rt|d0kr|d |d[ |d\ |s|d] |S )^u,  
        Generate leg recommendations based on Bill's Predictable Tempo strategy.

        No odds or prices — just the legs that fit the game environment.
        Uses the API data internally to detect the favorite and total line,
        then recommends legs purely on matchup structure.
        r   Nr   r  rm  h2htotalsc                 S      | d S Npricer   xr   r   r   <lambda>V      z<SportsBettingAnalyst._generate_suggestions.<locals>.<lambda>r   r  c                 s   s     | ]}|d  dkr|V  qdS )r  OverNr   r%  r   r   r   r   X  s    z=SportsBettingAnalyst._generate_suggestions.<locals>.<genexpr>pointr   r  r  r   u    CONTROLLED GAME — prime targetz(Two low-event teams = predictable tempo.r   zLegs that fit:z  Under 6.5 goalsz.  5-6 goal band is most likely scoreline ranger  z ML (tight win expected)zPARLAY IDEA:z ML + Under 6.5z*  Favorite wins a tight, low-scoring game.z$  Good candidate for a profit boost.r   u$   CHAOTIC MATCHUP — skip or go lightz0Both teams can score. Hard to predict the range.zIf you must play:z#  Over 6.5 goals (goals are coming)z  Avoid unders in this matchup.rB   rA   u)   MIXED TEMPO — one team anchors the pacez controls the tempo here.z0  Under 6.5 goals (defensive team dictates pace) MLz$  The defensive team keeps it tight.)r   r   r   r   r   r   r    r#   r   r!   r%   r"  r  r5   r;   r4   r6   u    — TIER 1 (best for unders)r9   z  Under 2.5 goalsz#  Most common scoreline: 1-0 or 1-1z to winz ML + Under 2.5 goalsz0  Favorite wins 1-0 or 2-1, controls possession.u    — TIER 2 (filter needed)r   z4  Under 3.0 or Under 3.5 goals (no Under 2.5 in MLS)r   z*Only play if both teams are mid/low-table:z#  Skip if top-6 teams are involved.z(Legs that fit (mid-table matchups only):r>   u    — TIER 3 (AVOID)z)Strategy says skip unders in this league.zIf you must play: z	 ML only.u    No totals — too unpredictable.r   zCUP PATTERN:z5  Knockout rounds favor unders (teams protect leads).u0     First legs especially — both teams cautious.z7  Under 2.5 is playable even in higher-scoring leagues.r
   0   u)   HIGH TOTAL — contrarian under territoryz  Under z# (shootout lines tend to overshoot))   u%   LOW TOTAL — defensive game expectedz (both defenses are legit)u/   STANDARD TOTAL — need to dig into the matchupz  Lean Under z if defenses travel wellz ML or spreadz ML + Under z2  No specific strategy profile for this sport yet.z$  Check Bet365 for what looks right.9Check Bet365 for profit boosts in the +120 to +220 range.z+Only use boosts on legs you'd already play.z7Not enough data to suggest legs. Check Bet365 directly.)	r   minnextr   r  r   strr   r  )r   r   r  r   favorite_name
total_linebookr  r  favoverrB   home_paway_panchorr  r5   r   r   r   r  C  s  







































































z*SportsBettingAnalyst._generate_suggestionsr4   c              
   C   s  t |}|s	g S | jd| dddid}|sg S t }|t|d }g }|D ]T}zGt|d dd	jd
d}	|	|krq|d||dd|dd|ddg d}
|	tdd }|d|
d< |d|
d< |	|
 W q) t
tfy}   Y q)w t| dt| d |S )z
        Fallback: get upcoming events (games) without requiring odds.
        The Odds API /events endpoint returns scheduled games even if
        no bookmaker has posted odds yet.
        ri  z/events/ro  rk  rp  rr  rt  ru  rv  Nrw  r  r  r   r  r  r  r  r  r  r  r  z events fallback: z games found)rz  r   r  r   r|  r   r}  r~  r  r  r  r  r   r   r  )r   r   r  r   r  r  r  r  eventr  r   r  r   r   r   get_upcoming_events  s@   



	
z(SportsBettingAnalyst.get_upcoming_eventsc              
   C   sp  |r|gng d}g }|D ]}| j |dd}|s| j|dd}|D ]}|| q!q|s3| js1dS dS ddg}i }|D ]}|d }||vrIg ||< || | q;| D ]w\}	}|	 }
|	tv rgt|	 d	 }
|d
|
 d |D ]Y}d}|	dkr| |d |d }|dkrd}n!|dkrd}nd}n|	tv rt|	 d }|dkrd}n|dkrd}||d  d|d   |d|d  |  |d qrqUz@ddlm	} |rt
| d nd}||dd}|r|d |D ]}|d|d   |d |d!   q|d W n ty( } ztd"|  W Y d#}~nd#}~ww |d$ |d% d&|S )'z
        Get today's full slate with tempo classification.
        Games are tagged as CONTROLLED / MIXED / CHAOTIC to help
        Bill quickly identify the best betting targets.
        	r   r   r   r   r   r#   r.   r0   r,   r4   r  r  u   Odds API returned no games right now. Could be early — bookmakers may not have posted yet. Check back in a bit or try 'what's good tonight'. — Lukeu   TODAY'S SLATE — Luker   r   r6   u   ── u    ──r   r  r  r   u    ★ CONTROLLEDr   u    ⚡ CHAOTICz ~ MIXEDr5   u    ★ TIER 1r>   u
    ⚠ AVOIDr  r  r  r   )get_general_sport_headlines)	max_itemszTOP HEADLINES:r  u       — sourcez'Headlines fetch failed (non-critical): Nu$   ★ = best targets for your strategyz)Reply 'odds [team]' for a full breakdown.r  )r  r  r  r   r   r  r   r   r  r  listkeysr  r   r  r  )r   r   sports	all_gamesr  r  r  r  by_sportr   sport_label	tempo_tagrB   r5   r  primary_sport	headlineshr  r   r   r   get_todays_slate  s|   




z%SportsBettingAnalyst.get_todays_slatec              	   C   s$  | j sdS g d}g }|D ]}| j|dd}|s| j|dd}|D ]}|dkrn| |d |d }|dkr>|||d	f q!|d
krmt|d i }t|d i }|ddkr]|d n|d }	|||d|	 df q!| |}
|
dd}|dkr|||d|
d  df q!|dkr|dvr||||
d  df q!q|sdS ddg}|t| dt|dkrdnd d |d |D ]\}}}d}|d r|d d d d g }|rt	|d!d" d#}|d$ }||d  d%|d   |d&|d'  d(|  |dkr2d)|v r'd*}|r|d+| d,7 }|d-|  n;d.|v r1|d/ n0| |}
|
dd}|dkrXd0}|rO|d+| d,7 }|d-|  n
|dkrb|d1 zSdd2l
m} ||d |d |}|d3d}|d4d}|d5kr|d6|dd7   n#|d8kr|d9|dd7   n|d:kr|d;|dd7   W n
 ty   Y nw |d qz2dd<lm}m} |d \}}}||d |d |}|||d |d }|r|| |d W n
 ty   Y nw |d= |d> d?|S )@ux  
        'What's good today/tonight' — only returns games that pass
        Bill's strategy filter. No noise, just the plays.

        Filter rules:
          NHL: controlled or mixed tempo only (skip chaotic)
          Soccer: Tier 1 leagues only + Tier 2 with caution note
          NFL: games with total <= 44 (defensive matchups)
          Everything else: skip
        r  r  r4   r  r   r  r  r   u   ★ CONTROLLED — prime targetr   rB   rA   u
   MIXED — z anchors the pacer5   r;   u   ★ r6   z	 (Tier 1))r!   r%   u    (Tier 2 — filter)u:   Nothing jumps out today. Strategy says sit tight. — Lukeu   WHAT'S GOOD TODAY — Luker   z gamer  z passed the filter:Nr  r   rm  r  c                 S   r  r  r   r  r   r   r   r    r  z7SportsBettingAnalyst.get_best_targets.<locals>.<lambda>r  r  r  r  r  r  
CONTROLLEDz	Under 6.5z + r  z  Legs: MIXEDz+  Legs: Under 6.5 (defensive team controls)z	Under 2.5z1  Legs: Under 2.5 (only if mid/low-table matchup))r  verdictreason	VALIDATEDu     ★ PREGAME: VALIDATED — <   CAUTIONu     ⚠️ PREGAME: CAUTION — DROPPEDu     ❌ PREGAME: DROPPED — r  r  z/Reply 'odds [team]' to dive deeper on any game.r  )r   r  r  r   r  r   r   r   r  r  r  r  r  r  r  r  r  )r   r  targetsr  r  r  rB   r  r  r  r  r5   r  r   tagr  r  r  legsr  r(  r  r  r  r  top_game	top_sport_r  r  r   r   r   get_best_targetsi  s   
*
















z%SportsBettingAnalyst.get_best_targetsr   )r   r;   )r   r4   )__name__
__module____qualname____doc__r   propertyr   r   r   r   r   r  r  rh  r  r  r  r  r  r  r  r  r   r   r   r   r      s*    
3

*
%#L 
,
+Pr   c                   C   s   t du rt a t S )z'Get the singleton SportsBettingAnalyst.N)_analystr   r   r   r   r   get_analyst  s   r  )r  osr  loggingr  r   r   r   configr   	getLoggerr   r   getenvr  rz  r   r   
GOAL_BANDSr   r  r   r  r  r   r   r   r   <module>   s   

#			

 "#$$%&&'())**+,-../0123456789::;<=??@@AABBCDDEEFFGHHIIJKLLMNNOPQ
V      