
    ANiv                        d Z ddlZddlZddlZddlZddlZddlmZmZ ddlm	Z	m
Z
mZmZ ddlZddlmZ ddlmZ ej$                  j'                  dej$                  j)                  ej$                  j+                  e                   ddlmZ  ed        ej2                  d	d
      Z ej2                  dd      Z ej2                  dd      Z ej2                  dd      Zdddddddddd	Zdddddd d!d"d#d$d%d&Z G d' d(      Z d) Z!d* Z"d+e d,e#d-e$fd.Z%d+e d,e#d-e$fd/Z&d+e d,e#d-e$fd0Z'd+e d,e#d-e$fd1Z(d+e fd2Z)d3 Z*e+d4k(  r e*        yy)5aZ  
SportsGameOdds API Comprehensive Fetcher
Fills data gaps for half-lines, live odds, player props, and multi-bookmaker comparison
Uses the full-access API key for complete coverage

API: https://sportsgameodds.com
Endpoints used:
  - GET /events - Event data with odds
  - GET /markets - Available markets
  - GET /account/usage - Quota tracking
    N)datetimetimezone)DictListOptionalAny)execute_values)load_dotenv)normalize_to_fullz/var/www/html/eventheodds/.envSPORTSGAMEODDS_API_KEY 47d6ce020d896ece307a284e8c78ff7fSPORTSGAMEODDS_BASE_URLz!https://api.sportsgameodds.com/v2SPORTSGAMEODDS_HEADERz	x-api-keySPORTS_DATABASE_URLzSpostgresql://eventheodds:eventheodds_dev_password@127.0.0.1:5433/eventheodds_sportsNBANFLNHLMLBNCAABNCAAFEPLUCLUFC)	nbanflnhlmlbncaabncaafepluclufcz	Full Gamez1st Halfz2nd Halfz1st Quarterz2nd Quarterz3rd Quarterz4th Quarterz
1st Periodz
2nd Periodz
3rd PeriodOvertime)game1h2h1q2q3q4q1p2p3potc                       e Zd ZdZefdefdZddedee   defdZ		 	 	 	 dd	ed
e
dedee   dee   dee   fdZd	edee   fdZdd	ed
e
dee   fdZdefdZdee   dee
   fdZy)SportsGameOddsFetcherzClient for SportsGameOdds APIapi_keyc                     || _         t        j                         | _        | j                  j                  j                  t        |i       d| _        d| _        y )Nr   )	r1   requestsSessionsessionheadersupdateHEADER_NAMEcredits_usedcredits_remaining)selfr1   s     !scripts/sportsgameodds_fetcher.py__init__zSportsGameOddsFetcher.__init__E   sF    '')##['$:;!"    Nendpointparamsreturnc                    t          d| }	 | j                  j                  ||d      }|j                          |j	                         }d|v r|j                  dd      | _        d|v r|j                  dd      | _        |S # t        j                  j                  $ r'}t        d|        dg t        |      d	cY d
}~S d
}~ww xY w)z$Make API request with error handling/   )r@   timeoutcreditsUsedr   creditsRemainingzAPI Error: F)successdataerrorN)BASE_URLr5   getraise_for_statusjsonr9   r:   r3   
exceptionsRequestExceptionprintstr)r;   r?   r@   urlresprI   es          r<   _requestzSportsGameOddsFetcher._requestL   s    
!H:&	C<<##C#CD!!#99;D $$(HH]A$>!!T))-2Da)H&K""33 	CKs#$$b3q6BB	Cs   A5B C C<CCleaguelimitodds_availablestarted	completedc                 \   t         j                  |j                         |j                               |t	        |      j                         d}|t	        |      j                         |d<   |t	        |      j                         |d<   | j                  d|      }|j                  dg       S )z!Get events with odds for a league)leagueIDrX   oddsAvailablerZ   r[   eventsrI   )
LEAGUE_IDSrL   lowerupperrR   rV   )r;   rW   rX   rY   rZ   r[   r@   rI   s           r<   
get_eventsz SportsGameOddsFetcher.get_events_   s     #v||~v||~F 0668

  #G 2 2 4F9 "%i."6"6"8F;}}Xv.xx##r>   c                 *    | j                  |dd      S )zGet currently live eventsTF)rZ   r[   rc   )r;   rW   s     r<   get_live_eventsz%SportsGameOddsFetcher.get_live_eventsq   s    vtuEEr>   c                 *    | j                  ||d      S )zGet upcoming eventsF)rX   rZ   re   )r;   rW   rX   s      r<   get_upcoming_eventsz)SportsGameOddsFetcher.get_upcoming_eventsu   s    vUEBBr>   c                     | j                  d      }|j                  dd      |j                  dd      |j                  dd      dS )zCheck API quota usagezaccount/usagerF   r   rG   creditsLimit)used	remainingrX   )rV   rL   )r;   rI   s     r<   check_quotaz!SportsGameOddsFetcher.check_quotay   sE    }}_-HH]A."4a8XXna0
 	
r>   odds_strc                 j    |sy	 t        |j                  dd            S # t        t        f$ r Y yw xY w)z%Parse American odds string to integerN+ )intreplace
ValueError	TypeError)r;   rn   s     r<   parse_american_oddsz)SportsGameOddsFetcher.parse_american_odds   s<    	x''R011I& 		s     22)N)2   TNN)   )__name__
__module____qualname____doc__API_KEYrR   r=   r   r   rV   rr   boolr   rc   rf   rh   rm   rv    r>   r<   r0   r0   B   s    '&- # #C Chtn C C& 46*.-1/3$ $S $#'$$TN$ 'tn$ 9=T
$$Fc Fd4j FC# Cc C4: C
T 
HSM hsm r>   r0   c                  x    dt         v rt         j                  d      d   nt         } t        j                  |       S )zGet database connection?r   )DB_URLsplitpsycopg2connect)db_urls    r<   get_db_connectionr      s0     &)F]V\\#q!FF##r>   c                 t   | j                         }|j                  d       |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       |j                  d       | j                          |j                          y	)
zEnsure required tables existzh
        ALTER TABLE "GameHalfLine"
        ADD COLUMN IF NOT EXISTS "externalEventId" VARCHAR(100)
    zu
        ALTER TABLE "GameHalfLine"
        ADD COLUMN IF NOT EXISTS source VARCHAR(50) DEFAULT 'sportsgameodds'
    zn
        ALTER TABLE "GameHalfLine"
        ADD COLUMN IF NOT EXISTS "capturedAt" TIMESTAMP DEFAULT NOW()
    z
        CREATE INDEX IF NOT EXISTS "idx_gamehalfline_external"
        ON "GameHalfLine"(league, "externalEventId", period)
    a
  
        CREATE TABLE IF NOT EXISTS "BookmakerOddsSnapshot" (
            id BIGSERIAL PRIMARY KEY,
            league VARCHAR(20),
            "externalEventId" VARCHAR(100),
            "gameDate" TIMESTAMP,
            "homeTeam" VARCHAR(100),
            "awayTeam" VARCHAR(100),
            bookmaker VARCHAR(50),
            "moneylineHome" INTEGER,
            "moneylineAway" INTEGER,
            "spreadHome" NUMERIC,
            "spreadHomeOdds" INTEGER,
            "spreadAway" NUMERIC,
            "spreadAwayOdds" INTEGER,
            total NUMERIC,
            "totalOverOdds" INTEGER,
            "totalUnderOdds" INTEGER,
            deeplink TEXT,
            "capturedAt" TIMESTAMP DEFAULT NOW(),
            "createdAt" TIMESTAMP DEFAULT NOW()
        )
    z
        CREATE UNIQUE INDEX IF NOT EXISTS "BookmakerOddsSnapshot_unique_idx"
        ON "BookmakerOddsSnapshot"(league, "externalEventId", bookmaker, date_trunc('minute', "capturedAt"))
    ay  
        CREATE TABLE IF NOT EXISTS "LiveOddsSnapshot" (
            id BIGSERIAL PRIMARY KEY,
            league VARCHAR(20),
            "externalEventId" VARCHAR(100),
            "gameDate" TIMESTAMP,
            "homeTeam" VARCHAR(100),
            "awayTeam" VARCHAR(100),
            "gameStatus" VARCHAR(50),
            "currentPeriod" VARCHAR(20),
            "homeScore" INTEGER,
            "awayScore" INTEGER,
            "moneylineHome" INTEGER,
            "moneylineAway" INTEGER,
            "spreadHome" NUMERIC,
            "spreadHomeOdds" INTEGER,
            total NUMERIC,
            "totalOverOdds" INTEGER,
            "fairMoneylineHome" INTEGER,
            "fairSpread" NUMERIC,
            "fairTotal" NUMERIC,
            bookmaker VARCHAR(50),
            "capturedAt" TIMESTAMP DEFAULT NOW(),
            "createdAt" TIMESTAMP DEFAULT NOW()
        )
    z
        CREATE INDEX IF NOT EXISTS "idx_liveodds_lookup"
        ON "LiveOddsSnapshot"(league, "externalEventId", "capturedAt")
    N)cursorexecutecommitclose)conncurs     r<   ensure_tables_existr      s    
++-C KK  	
 KK  	
 KK  	 KK  	 KK  	0 KK  	 KK  	6 KK  	
 	KKMIIKr>   fetcherrW   rA   c                 	   t        dd        t        d|j                                 t        d        | j                  |d      }|st        d       y|j                         }d}|D ]  }|j	                  dd	      }t        |j	                  d
i       j	                  di       j	                  di       j	                  dd	      |      }t        |j	                  d
i       j	                  di       j	                  di       j	                  dd	      |      }	|j	                  di       j	                  dd	      }
|r|	s|
r%t        j                  |
j                  dd            nd}|j	                  di       }i }|j                         D ]  \  }}|j                  d      }t        |      dk  r'|d   }|d   }|d   }|d   }|d   }|dk(  rF|dvrK||vri ||<   | j                  |j	                  d            }|j	                  d      xs |j	                  d      }|r	 t        |      }|d k(  r|dk(  r||d!||   d"<   |d#k(  r|d$k(  r|d%k(  r||d!||   d&<   |d'k(  r|dk(  rd|d!||   d(<   |d'k(  s|dk(  sd|d!||   d)<    |j                         D ]  \  }}|j                         D ]  \  }}|j	                  d*      |j	                  d      )|j                  d+d	      j                  d,d	      }	 |j!                  d-|j#                         ||||	|||j	                  d*      |j	                  d      d.f
       |dz  }  |st        d/|	dd0  d1|dd0         t'        |j                               D ]  \  }}g }d"|v r?|d"   j	                  d*      }|d"   j	                  d      }|r|j)                  d2|d3       d&|v r+|d&   j	                  d*      }|r|j)                  d4|d5       d(|v r+|d(   j	                  d      }|r|j)                  d6|d7       |st        d8t*        j	                  ||      d9d:d;j-                  |                |j/                          |j1                          t        dd        t        d<| d=       t        d        |S # t        t        f$ r d}Y w xY w# t$        $ r}Y d}~)d}~ww xY w)>zb
    Fetch half-time and quarter lines
    Fills data gap Q4: Half spread efficiency analysis
    
<============================================================zFETCHING HALF/QUARTER LINES - rD   rX   No events foundr   eventIDrq   teamshomenameslongawaystatusstartsAtZ+00:00Nodds-               r$   )	r%   r&   r'   r(   r)   r*   r+   r,   r-   bookOddsbookOverUnderfairOverUndersp)valuer   spreadouallovertotalmlmoneyline_homemoneyline_awayr   _home_awaya  
                        INSERT INTO "GameHalfLine" (
                            league, "externalEventId", "gameDate", "homeTeam", "awayTeam",
                            period, market, "lineValue", "bookOdds", bookmaker, "capturedAt"
                        ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                        ON CONFLICT DO NOTHING
                    	consensus
      @ zSpread: z+.1fzTotal: z.1fzML: z+d    12  | STORED: z half/quarter line records)rQ   rb   rh   r   rL   r   r   fromisoformatrs   itemsr   lenrv   floatrt   ru   r   ra   	ExceptionsortedappendPERIODSjoinr   r   ) r   rW   r   r_   r   storedeventevent_id	home_team	away_team	starts_at	game_dater   
half_linesodd_keyodd_datapartsstatsideperiodbet_typeoutcome	book_odds
line_valuemarketsmarketrI   market_namerU   market_strsvos                                    r<   fetch_half_linesr      sT   
 
Bvh-	*6<<>*:
;<	VH((r(:F 
++-CF b]99Y+%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	IIh+//
B?		PYH**9+<+<S(+KL_c	yy$ 
!% )	ZGX
 MM#&E5zA~8D8D1XFQxHAhG SSZ'%'
6"33HLL4LMI!o6W(,,:WJ&!&z!2J
 4DFN9CY/W
6"8,T!dem68I8BI.V
6"7+T!dfnAEy7Y
6"#34T!dfnAEy7Y
6"#34S)	ZX  *//1 	OFG ' 88G$,&1A1I$nnWb9AA'2NKK ! )Y	TXXg->@PR]	 aKF#	. D3B(IcrN+;<=#)**:*:*<#= ] w&)--g6A)--f5A+,,x$x-@Ag%(,,W5A+,,wqg->?#w. 0155f=A+,,tAb6];DVV!<R @%**[BYAZ[\]kb]H 	KKMIIK	Bvh-	HVH6
78	VHM{ #I. &!%J&B ! s%   )R=AS=SS	S)	$S)	c                 
   t        dd        t        d|j                                 t        d        | j                  |      }|st        d       y|j                         }d}|D ]  }|j	                  dd      }t        |j	                  di       j	                  d	i       j	                  d
i       j	                  dd      |      }t        |j	                  di       j	                  di       j	                  d
i       j	                  dd      |      }	|j	                  di       j	                  dd      }
|j	                  di       }|j	                  dd      }|j	                  dd      }|j	                  di       }|j	                  d	i       j	                  d      }|j	                  di       j	                  d      }|
r%t        j                  |
j                  dd            nd}|j	                  di       }|j	                  di       }|j	                  di       }|j	                  di       }|j	                  di       }| j                  |j	                  d            }| j                  |j	                  d            }d}d}|j	                  d      r;	 t        |j	                  d            }| j                  |j	                  d            }d}d}|j	                  d      r;	 t        |j	                  d            }| j                  |j	                  d            }| j                  |j	                  d            }d}d}|j	                  d      r	 t        |j	                  d            }|j	                  d      r	 t        |j	                  d            }t        d |	dd!  d"|xs d d#|dd!  d"|xs d d$| 
       t        d%|xs d& d'|xs d&        t        d(|xs d& d"|xs d& d)       t        d*|xs d& d+|xs d&        	 |j                  d,|j                         ||||	|||||||||||||d-f       |d.z  } |j!                          |j#                          t        dd        t        d/| d0       t        d        |S # t        t        f$ r Y w xY w# t        t        f$ r Y w xY w# t        t        f$ r Y ew xY w# t        t        f$ r Y Ow xY w# t        $ r} Y d} ~ d} ~ ww xY w)1zQ
    Fetch live in-game odds
    Fills data gaps Q8, Q12: Live odds analysis
    r   r   zFETCHING LIVE ODDS - zNo live eventsr   r   rq   r   r   r   r   r   r   r   displayLongLivecurrentPeriodIDscoresr   r   r   Nr   zpoints-home-game-ml-homezpoints-away-game-ml-awayzpoints-home-game-sp-homezpoints-all-game-ou-overr   r   fairOddsr   r   rx    (z) @ z) - z    ML: r   z / z    Spread: )z    Total: z oaf  
                INSERT INTO "LiveOddsSnapshot" (
                    league, "externalEventId", "gameDate", "homeTeam", "awayTeam",
                    "gameStatus", "currentPeriod", "homeScore", "awayScore",
                    "moneylineHome", "moneylineAway", "spreadHome", "spreadHomeOdds",
                    total, "totalOverOdds", "fairMoneylineHome", "fairSpread", "fairTotal",
                    bookmaker, "capturedAt"
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                ON CONFLICT DO NOTHING
            r   r   z
CAPTURED: z live odds snapshots)rQ   rb   rf   r   rL   r   r   r   rs   rv   r   rt   ru   r   ra   r   r   r   )!r   rW   r   r_   r   r   r   r   r   r   r   r   game_statuscurrent_periodr   
home_score
away_scorer   r   ml_homeml_awaysp_home
total_overr   r   spread_homespread_oddsr   total_over_oddsfair_ml_homefair_spread
fair_totalrU   s!                                    r<   fetch_live_oddsr   o  s   
 
Bvh-	!&,,.!1
23	VH$$V,F
++-CF U99Y+%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	IIh+//
B?	8R(jj7$5r: 8R(ZZ+//8
ZZ+//8
PYH**9+<+<S(+KL_c	yy$ ((5r:((5r:((5r:XX7<
 44W[[5LM 44W[[5LM;;'#GKK$@A%99'++j:QR >>/*jnn_=>")"="=jnnZ>X"Y
 227;;z3JK
;;'#GKK$@A >>/*":>>/#BC
 	Ys^$BzQ&7tIcrN;K2jo\]M^^bcnbopq.3/s>3HS2IJK[/C0;3E#2FaHIELS>O,Bs+CDE	KK 	 )Y	^Z[k:  aKFgUn 	KKMIIK	Bvh-	Jvh2
34	VHMy 	*  	*  	* 
 	* 4  		sZ   :R-:R4S
	S 8S6R10R14SS
SS S32S36	T
T
c                 P   t        dd        t        d|j                                 t        d        | j                  |d      }|st        d       y|j                         }d}|D ]  }|j	                  dd	      }t        |j	                  d
i       j	                  di       j	                  di       j	                  dd	      |      }t        |j	                  d
i       j	                  di       j	                  di       j	                  dd	      |      }	|j	                  di       j	                  dd	      }
|j	                  di       j	                  di       }|
r%t        j                  |
j                  dd            nd}|j	                  di       }i }|j                         D ]  \  }}|j	                  di       }|s|j                         D ]  \  }}||vrd|j	                  |      i||<   |}d|v r'| j                  |j	                  d            ||   d<   Nd|v r'| j                  |j	                  d            ||   d<   yd|v rL	 t        |j	                  d      xs d      ||   d<   | j                  |j	                  d            ||   d <   d!|v rM	 t        |j	                  d      xs d      ||   d"<   | j                  |j	                  d            ||   d#<   d$|v rQd%|v rM	 t        |j	                  d      xs d      ||   d&<   | j                  |j	                  d            ||   d'<   od(|v sud%|v s{| j                  |j	                  d            ||   d)<     |j                         D ci c];  \  }}|j	                  d      s"|j	                  d      s|j	                  d&      r||= }}}|rt        d*|	dd+  d,|dd+  d-t        |       d.       t        |j                               dd/ D ]U  \  }}|j	                  dd0      }|j	                  dd0      }|j	                  d&d0      }t        d1|d2d3|d4d5|d4d6|        W t        |      d/kD  rt        d7t        |      d/z
   d8       |j                         D ]  \  }}	 |j!                  d9|j#                         ||||	||j	                  d      |j	                  d      |j	                  d      |j	                  d       |j	                  d"      |j	                  d#      |j	                  d&      |j	                  d'      |j	                  d)      |j	                  d      f       |d:z  }  |j'                          |j)                          t        dd        t        d;| d<       t        d        |S # t        t        f$ r Y w xY w# t        t        f$ r Y w xY w# t        t        f$ r Y 0w xY wc c}}w # t$        $ r}Y d}~yd}~ww xY w)=z~
    Fetch odds from multiple bookmakers for comparison
    Fills data gaps Q16, Q18: Book efficiency and sharp detection
    r   r   z FETCHING MULTI-BOOKMAKER ODDS - rx   r   r   r   r   rq   r   r   r   r   r   r   r   links
bookmakersr   r   Nr   byBookmakerdeeplinkzgame-ml-homer   zgame-ml-awayr   zgame-sp-home	overUnderr   spread_home_oddszgame-sp-awayspread_awayspread_away_oddszgame-ou-overr   r   r   zgame-ou-undertotal_under_oddsr   r   r   r   z books)r   r   r   15z ML: z>5z | Spread: z
 | Total: z    ... and z more booksa>  
                    INSERT INTO "BookmakerOddsSnapshot" (
                        league, "externalEventId", "gameDate", "homeTeam", "awayTeam",
                        bookmaker, "moneylineHome", "moneylineAway",
                        "spreadHome", "spreadHomeOdds", "spreadAway", "spreadAwayOdds",
                        total, "totalOverOdds", "totalUnderOdds", deeplink, "capturedAt"
                    ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                    ON CONFLICT DO NOTHING
                r   r   z bookmaker odds records)rQ   rb   rh   r   rL   r   r   r   rs   r   rv   r   rt   ru   r   listr   ra   r   r   r   )r   rW   r   r_   r   r   r   r   r   r   r   r   r   r   bookmaker_datar   r   by_bookmakerbookbook_oddbokr   active_booksrI   r   r   totrU   s                                r<   fetch_bookmaker_comparisonr    sb   
 
Bvh-	,V\\^,<
=>	VH((r(:F 
++-CF [99Y+%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	IIh+//
B?			'2&**<<PYH**9+<+<S(+KL_c	yy$  "& %	kGX#<<r:L"."4"4"6  kh~-"EIIdO,N4(  "W,=D=X=XY[Y_Y_`fYg=hN4()9:#w.=D=X=XY[Y_Y_`fYg=hN4()9:#w.>CBFF;DWD\[\>]t,];CJC^C^_a_e_efl_mCnt,-?@ $w.>CBFF;DWD\[\>]t,];CJC^C^_a_e_efl_mCnt,-?@ $w.5G3C8=bff[>Q>VUV8Wt,W5BIB]B]^`^d^dek^lBmt,->? %/EW4D?F?Z?Z[][a[abh[i?jN4();<A k%	kP *8)=)=)? ]A%% 01QUU=5IQUUSZ^ 1 ] ] D3B(IcrN+;2c,>O=PPWXY #<#5#5#78!< U
dXX.4XXmS1hhw,T"IU2b'RG:cUST	U
 < 1$S%6%:$;;GH ',,. 	JD$  LLNHiI$((#34dhh?O6PHH]+TXX6H-IHH]+TXX6H-IHHW%txx0A'BDHHM_D`HHZ(  !%	O[z 	KKMIIK	Bvh-	HVH3
45	VHM '	2  '	2  '	2 ]F  sS   A
W	%A
W:A
W5A X.CX	W	W	W2	1W2	5X	X		X% X%c                 *	   t        dd        t        d|j                                 t        d        | j                  |d      }|st        d       y|j                         }d}|D ]  }|j	                  dd	      }t        |j	                  d
i       j	                  di       j	                  di       j	                  dd	      |      }t        |j	                  d
i       j	                  di       j	                  di       j	                  dd	      |      }	|j	                  di       j	                  dd	      }
|
r%t        j                  |
j                  dd            nd}|j	                  di       }i }|j                         D ]]  \  }}|j                  d      t              dk  r'd   }t        fddD              sAd   }d   }d   }d   }|dk7  r[|dk7  ra|j                  dd	      j                  d d	      j                  d!d	      j                  d"d	      }|j                  d#d$      j                         }||vrd%|i||<   |j	                  d&      xs |j	                  d'      }|r	 t        |      }| j#                  |j	                  d(            }|||   vri ||   |<   |d)k(  r|||   |   d*<   |||   |   d+<   L|d,k(  sS|||   |   d-<   ` |st        d.|	dd/  d0|dd/         t%        |j                               dd1 D ]  \  }}|j	                  d%|      }g }d2D ]  }||v s||   j	                  d*      }||   j	                  d+      }|r4|dd3 j                         }|rd4| nd	}|j'                  | d$| |        	 |j)                  d5|j+                         ||||	d6d7| |||||   j	                  d-      f       |dz  } |st        d8|dd/ d9d$d:j/                  |dd                 |j1                          |j3                          t        dd        t        d;| d<       t        d        |S # t        t         f$ r d}Y w xY w# t,        $ r}Y d}~Od}~ww xY w)=zd
    Fetch player props with line movement tracking
    Fills data gap Q6: Prop softness timing
    r   r   zFETCHING PLAYER PROPS -    r   r   r   r   rq   r   r   r   r   r   r   r   r   r   Nr   r   r   c              3   L   K   | ]  }d    j                  d|         yw)r   _N)endswith).0lr   s     r<   	<genexpr>z%fetch_player_props.<locals>.<genexpr>  s&     XauQx((1QC1Xs   !$)r   r   r   r   r   r   r   r   r$   r   _1_NBA_1_NFL_1_NHL_1_MLBr  r   namer   r   r   r   line	over_oddsunder
under_oddsr   r   r   
   )pointsassistsreboundsthreePointersMade   r   a  
                                INSERT INTO "PropSnapshot" (
                                    league, "theoddsapiEventId", "gameDate", "homeTeam", "awayTeam",
                                    bookmaker, "marketType", "playerName", "propLine",
                                    "overPrice", "underPrice", "capturedAt"
                                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, date_trunc('minute', NOW()))
                                ON CONFLICT DO NOTHING
                            sportsgameoddsplayer_r   25r   r   z player prop records)rQ   rb   rh   r   rL   r   r   r   rs   r   r   r   anytitler   rt   ru   rv   r  r   r   ra   r   r   r   r   ) r   rW   r   r_   r   r   r   r   r   r   r   r   r   propsr   r   r   	player_idr   r   r   player_namer   r   player_props	prop_strsr  r   
stat_shortover_strrU   r   s                                   @r<   fetch_player_propsr0  Y  s   
 
Bvh-	$V\\^$4
56	VH((r(:F 
++-CF cT99Y+%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	%eii&<&@&@&L&P&PQXZ\&]&a&abhjl&mouv	IIh+//
B?	PYH**9+<+<S(+KL_c	yy$ !% 0	AGX MM#&E5zA~8D X;WXXaI1XFQxH8D 4 $++Hb9AA(BOWWX`bdemmnvxz{K%--c37==?K%$*K#8i !o6W(,,:WJ&!&z!2J  33HLL4LMI5++)+i &v~1;i &v.6?i &{37@i &|4a0	Af D3B(IcrN+;<=+/+>s+C  T'	<*..vyA	R !D|++D155f=+D155kB)-bq)9J594&zrH%,,
|1TF8*-MN!KK )  !')YPY 0GD62BKQU $l4&8&<&<\&J" #aKF/!6 DSb!1" 5Quzz)BQ-7P6QRSA TGcTJ 	KKMIIK	Bvh-	HVH0
12	VHMw #I. &!%J&\  ) ! !s%   ?Q&%AQ>&Q;:Q;>	R	R	c                 @   | j                         }t        dd        t        d       t        d        t        d|j                  dd      d       t        d|j                  d	d      d       t        d
|j                  dd      d       t        d        y)zDisplay API quota statusr   r   zSPORTSGAMEODDS API QUOTAzCredits Used:      rk   r   ,zCredits Remaining: rl   zCredits Limit:     rX   N)rm   rQ   rL   )r   quotas     r<   
show_quotar4    s    !E	Bvh-	
$%	VH			&! 4Q7
89			+q 9!<
=>			'1 5a8
9:	VHr>   c                  n   t        j                  d      } | j                  dg dd       | j                  ddd	d
       | j                  ddd       | j                         }t	               }|j
                  dk(  rt        |       y |j                  g}|j                  rD|j                  j                  d      D cg c]   }|j                         j                         " }}t               }t        |       d}	 |D ]  }|j
                  dk(  r|t        |||      z  }#|j
                  dk(  r|t        |||      z  }C|j
                  dk(  r|t!        |||      z  }c|j
                  dk(  r|t#        |||      z  }|j
                  dk(  s|t        |||      z  }|t!        |||      z  }|t#        |||      z  }t        |||      }||z  } t        |       t%        dd        t%        d|        t%        d        |j'                          y c c}w # |j'                          w xY w)NzSportsGameOdds Data Fetcher)descriptioncommand)halflivebooksr)  r   r3  zWhat to fetch: half (half-lines), live (in-game), books (multi-bookmaker), props (player props), all (everything), quota (check usage))choiceshelpz--leaguez-lr   z2League to fetch (nba, nfl, nhl, mlb, ncaab, ncaaf))defaultr<  z	--leaguesz-LzComma-separated list of leagues)r<  r3  r2  r   r8  r9  r:  r)  r   r   r   zTOTAL RECORDS STORED: )argparseArgumentParseradd_argument
parse_argsr0   r7  r4  rW   leaguesr   stripra   r   r   r   r   r  r0  rQ   r   )	parserargsr   rB  r  r   total_recordsrW   live_recordss	            r<   mainrH    s9   $$1NOF
	+] e  f

D%P  R
T=  ? D $%G||w7 {{mG||.2ll.@.@.EF1779??$FF DM 	.F||v%!1'64!HH'&$!GG(!;GVT!RR(!3GVT!JJ&!1'64!HH!;GVT!RR!3GVT!JJ.wE-	.$ 	76(m&}o67 	

E GD 	

s   %H BH" A7H" "H4__main__),r|   ossysrN   r>  r3   r   r   typingr   r   r   r   r   psycopg2.extrasr	   dotenvr
   pathinsertdirnameabspath__file__
team_namesr   getenvr}   rK   r8   r   r`   r   r0   r   r   rR   rr   r   r   r  r0  r4  rH  ry   r   r>   r<   <module>rV     s  
 
 
    ' , ,  *  277??277??8#<= > ( , - ")),.P
Q299.0STbii/= 
(*  
A 

 









G GT$Zz|3 |S |3 |~o2 oC o# odu(= us uUX up} 5 }s }S }@
- 
7t zF r>   