
    +i                    p   d dl Z d dlmZmZ d dlmZ d dlmZ d dlZd dl	m	Z	 d dl
Z
d dlZd dlZd dlZd dlZd dlZ e        e j                   j#                  e j                   j%                  e            Z eee j                   j-                  ed      d      Z ee        e j0                  d	d      Z ej4                  e
      Z ej8                  e      ZdZ e	j>                         j@                  Z!dZ"ddgZ#dZ$ddgZ%dddddddddZ&da'd Z(dddddddd d d!d"d#Z)	 d d$l*m+Z+ dd d%a-d&Z.d' Z/dd d%a0d(Z1d) Z2dd d%a0d(Z1d* Z2d+ Z3da4d a5d,Z6d- Z7d. Z8d/ Z9d;d0Z:ejw                  d1d2g3      d4        Z<ejw                  d5d2g3      d6        Z=ed7k(  rej}                  d8d9:       yy# e,$ r i Z+Y w xY w)<    N)Flaskjsonify)CORS)load_dotenv)datetimestatic )static_folderstatic_url_pathCFBD_API_KEY)access_tokenR   zMissouri StateDelawareArmyAkronz
Akron ZipszAppalachian StateUSFWKUFIUFAUECUUMassULM)z	App StatezSouth FloridazWestern KentuckyzFlorida InternationalzFlorida AtlanticzEast CarolinaMassachusettsz	UL Monroec                 V   t         i a ddl}	 t        j                  j	                  t
        d      }t        |dd      5 }|j                  |      }|D ]  }|j                  d      dk(  s|j                  d	d
      j                         }|j                  dd
      j                         }|s[|s^|t         |<   t        j                  ||      }|t         |<    	 ddd       t         j                  | |       S # 1 sw Y   xY w# t        $ r}	t        d|	        Y d}	~	>d}	~	ww xY w)z7Convert display name to APR data key (abbreviated name)Nr   cfb_mastersheet.csvrutf-8encodingfamily_nameFBS
flair_namer	   flair_abbreviatedzError building APR cache: )_display_to_apr_cachecsvospathjoin
NEEDLE_DIRopen
DictReadergetstripTEAM_NAME_MAPPING	Exceptionprint)
display_namer%   csv_pathfreaderrowr"   abbrevdisplay_name_mappedes
             /app/needle/app.pyget_apr_keyr:   6   s   
 $ "	4ww||J0EFHhg6!*!Cww}-6%(WW\2%>%D%D%F
!$)<b!A!G!G!I%&@F1*=2C2G2G
T^2_/IO12EF " 7  !$$\<@@! 76  	4.qc233	4sB   2D  +C;,AC;/C;2*C;D ;D D 	D(D##D(
   	                     )SECzBig TenzBig 12ACCzPac-12AmericanzMountain WestMACzSun BeltzC-USAIndependents)APR_RANKINGSvalue	timestampi,  c                     t        j                          } t        d   | t        d   z
  t        k  r	t        d   S t        j                  t
              }	 d}t        dd      D ]   }	 |j                  t        |dd      }|r|}" |dkD  r|nd	}|| d
a|S #  Y 7xY w# t        $ r/}t        d|        t        d   t        d   cY d}~S Y d}~y	d}~ww xY w)z1Determine the current week of the season (cached)rJ   NrK   rB      regularfbsyearweekseason_typeclassification   rI   zError determining week: )time_current_week_cache_current_week_cache_ttlcfbdGamesApi
api_clientrange	get_gamesCURRENT_YEARr/   r0   )current_time	games_apilatest_weekrR   gamesresultr8   s          r9   get_current_weekrd   l   s    
 99;L7#/\DWXcDd5dh4"7++ j)I0!RLD!++DV_pu+v"&K	 ! !,aR )/\J  0(,-w'3&w// 40s6   B &BB BB 	C%CCCi  c                      t        j                          } t        d   | t        d   z
  t        k  r	t        d   S t        j                  t
              }|j                         }|| da|S zGet FBS teams list (cached)rJ   rK   rI   rV   _fbs_teams_cache_fbs_teams_cache_ttlrY   TeamsApir[   get_fbs_teamsr_   	teams_api	fbs_teamss      r9   get_fbs_teams_cachedro      f     99;L ,,AQR]A^2^bv1v((j)I'')I!*F    c                      t        j                          } t        d   | t        d   z
  t        k  r	t        d   S t        j                  t
              }|j                         }|| da|S rf   rg   rl   s      r9   ro   ro      rp   rq   c            
         	 t               } t               }i }i }| D ]c  }t        |dd      xs t        |dd      }t        |dd      xs d}|s3|j                  |       |||<   t        j                  ||      }|||<   e t        j                  t              }t               }	g }
t        j                  j                  t        d      }i }t        j                  j                  |      r	 t        |d      5 }t!        j"                  |j%                         t         j&                         	 t)        j*                  |      }t!        j"                  |j%                         t         j,                         	 ddd       |j=                         D ]  \  }}|
j?                  |        tA        d|	dz
        }i }t        tC        |tE        d|	dz                     }|D ]4  }	 |jG                  tH        |dd      }|r|
j?                  |       |||<   6 |
}i }|D ]-  }|j                  ||      }dd|j                  |d      d||<   / i }|D ]  }t        |dd      }t        |dd      }| d| dt        |dd       }||vr|||<   <t        |dd      duxr t        |dd      du}t        ||   dd      duxr t        ||   dd      du}|s|r|||<    t               }|jK                         D ]8  }t        |dd      }t        |dd      } t        |dd      }!|s| 0|!3t        |dd      }t        |dd      }t        |dd      }"| d| dt        |dd       }|r|r||v r||v r||vr|j                  |       |j                  ||      }#|j                  ||      }$|#|vrdd|j                  |d      d||#<   |$|vrdd|j                  |d      d||$<   | |!kD  r"||#   d xx   dz  cc<   ||$   d!xx   dz  cc<   |!| kD  s||$   d xx   dz  cc<   ||#   d!xx   dz  cc<   >|sB|sF||vsL||v }%||v }&|%r|&r|&s\|%r`|j                  |       |%ra|&s_|j                  ||      }#|#|vrdd|j                  |d      d||#<   | |!kD  r||#   d xx   dz  cc<   |!| kD  s||#   d!xx   dz  cc<   |&s|%r|j                  ||      }$|$|vrdd|j                  |d      d||$<   |!| kD  r||$   d xx   dz  cc<   "| |!kD  s)||$   d!xx   dz  cc<   ; |S # t!        j"                  |j%                         t         j,                         w xY w# 1 sw Y   xY w# t(        j.                  t0        t2        f$ rM}t5        d|        |d	z   }	 t7        j8                  ||       t5        d
|        n#  Y nxY wi }Y d}~`d}~wt:        $ r}t5        d|        i }Y d}~d}~ww xY w# t:        $ r}t5        d| d|        Y d}~Ld}~ww xY w# t:        $ r.}t5        d"|        ddl&}'|'jO                          i cY d}~S d}~ww xY w)#z3Get current team records from CFBD - FBS teams onlyschoolNteam
conferencerG   zgames_cache.pklrbz"Error loading cache (corrupted?): z
.corruptedzBacked up corrupted cache to zError loading cache: rB   rA   rM   rN   rO   rP   zError fetching week z games: r   Unknown)winslossesrv   	home_team	away_team_rR   home_pointsaway_points	completedFidry   rz   zError fetching team records: )(ro   setgetattraddr.   r,   rY   rZ   r[   rd   r&   r'   r(   r)   existsr*   fcntlflockfilenoLOCK_SHpickleloadLOCK_UNUnpicklingErrorEOFErrorIOErrorr0   shutilcopy2r/   itemsextendmaxr\   minr]   r^   values	traceback	print_exc)(rn   fbs_team_setteam_conferencescfbd_to_displayru   	team_namerv   r1   r`   current_week	all_games
cache_filecached_gamesr3   r8   backup_filerR   rb   
start_weekrecent_games_by_weekweeks_to_fetch
week_games
team_stats	game_dictgamer{   r|   game_keycurrent_pointsstored_pointsprocessed_gamesr   r~   r   game_idhome_displayaway_displayhome_is_fbsaway_is_fbsr   s(                                           r9   get_team_recordsr      s*   L(*	 uDh5Tvt9TI |T:LnJ  +.8 +044Y	J-9	*  MM*-	')	 WW\\*.?@
77>>*%"*d+qKK
EMM:?'-{{1~AHHJ> ,, (--/KD%U# 0
 L1,-
!U:s2|a7G/HIJ"D
&00l[duz0{
 $$Z01;(. #"  
%I*..y)DL.229iH(J|$ & 	Dk48Ik48I#Ai['$2J1KLH y(&*	(# ")}d!C4!O  "CT[\`boquTv  C  UC '	((;]D QY] ]  !`bijst|j}  @M  OS  cT  \`  c`!-*.Ih'  %$$&Dk59I!$t<K!$t<K [49P#D+t<	#D+t<	!$d3 ([)AgdFA6N5OP yL/HYZfMfks  |K  lK#''1#2#6#6y)#LL#2#6#6y)#LL $:5$%&'*:*>*>y)*T4
<0
 $:5$%&'*:*>*>y)*T4
<0 #[0"<08A=8"<0:a?:${2"<08A=8"<0:a?: 91P"+|";K"+|";K $K[Q\'++H5 '{+:+>+>y)+TL+:=,-./2B2F2FyR[2\<"
< 8  +[8 *< 8 @A E @!,{!: *< 8 Ba G B )+:+>+>y)+TL+:=,-./2B2F2FyR[2\<"
< 8  +[8 *< 8 @A E @!,{!: *< 8 Ba G Be 'h A AHHJ> ,+ **Hg> 	":1#>?(<7LL[99+GH! "-aS12!"0  ,TF(1#>?~  -aS12		s-  AX/ BX/ -U7 93U*-T32U*5U7 =A!X/ 1XC X/ X/ AX/ %X/ (C'X/ $X/ 7X/ ;X/ X/ X/ A X/ 7X/ X/ AX/ X/ 34U''U**U4/U7 7XW)$WWWWX/ X)W?9X/ ?XX/ 	X,X'!X/ 'X,,X/ /	Y&8#Y!Y&!Y&   c                  d   t        j                          } t        | t        z
  t        k  rt        S t	        j
                  t              }t               }t               }t               }i }|D ]M  }t        |dd      xs t        |dd      }|s"|j                  |       t        j                  ||      }|||<   O i }		 ddl}
t        j                   j#                  t$        d      }t'        |dd      5 }|
j)                  |      }|D ]  }|j                  d	      d
k(  s|j                  dd      j+                         }|j                  dd      j+                         }|s\d}||v r||   }n9|r7|j-                         D ]  \  }}||k(  s|} n |s||j/                         v r|}|sr|j1                         }t3        |      dk\  rTdj#                  |dd       }||v r||   }n6||j/                         v r|}n!|j-                         D ]  \  }}||k(  s|} n |s||	|<     	 ddd       i }i }	 |j=                  d      }t7        dt3        |       d       |D ]  }t        |dd      }|st        |dd      }t        |dd      }|s1|s4t        |dd      }t        |dd      }t        |dd      } t        |dd      }!t        |dd      }"t        |dd      }#d}$t?        |d      rt        |dd      }%|%|%}$|$t?        |d      rt        |dd      }%|%|%}$|$At?        |d      r5	 |jA                         }&|&j                  d      xs |&j                  d      }$|$E	 t?        |d       r8|jB                  j                  d      xs |jB                  j                  d      }$|d!k(  sd"tE        |      v rd#tE        |      v rt7        d$| d%| d&| d'       t?        |d      r	 |jA                         }&t7        d(tG        |&jI                                       t7        d)d|&v         t7        d*d|&v         d|&v rt7        d+|&d           d|&v rt7        d,|&d           t7        d.|$        |	j                  ||j                  ||            }'|	j                  ||j                  ||            }(| |!|"r|"jK                  d/      r|"d0d n|"|#t        |d1d2      |$|'|(d3||<   |r|r| d4| })|' d4|( }*|||)<   |||*<   |d!k(  sd"tE        |      v sd#tE        |      v st7        d5| d%|( d&|' d6|$ d7|" d8|# d9| d:|'         	 g }+tM        d<|d0z
        },tO        |,d=      D ]i  }-	 |jQ                  tR        |-d>d?      }.|.D ]F  }/t        |/dd      }t        |/dd      }0t        |/dd      }1|0r|0|v nd2}2|1r|1|v nd2}3|r|j                  |      nd}4|d!k(  sd"tE        |0      v r\d#tE        |1      v rOt7        d@| dA|0 dB|1        t7        dCt3        |       dD       |r||v rt7        dE||           nt7        dF       |4s|0r|1r|j-                         D ]  \  }5}6|6j                  dd      }7|6j                  dd      }8|0|7k(  rE|1|8k(  r@|6}4|d!k(  sd"tE        |0      v r*d#tE        |1      v rt7        dG| dH|5 dA|0 dI|7 dB|1 dI|8         nA|0|8k(  sz|1|7k(  s|6}4|d!k(  sd"tE        |0      v rd#tE        |1      v rt7        dJ| dH|5         n |4rW|4j                  dK      } |4j                  dL      }!|4j                  d      }"|4j                  d      }#|4j                  d1d2      }9nAt        |/dKd      } t        |/dLd      }!t        |/dd      }"t        |/dd      }#t        |/d1d2      }9|"duxs |#du}:| duxr |!du};|9xs |;xr |: }<|0r|1r|2r|3rd}=|<r| |!| |!kD  rdM}=n#|!| kD  rdN}=ndO}=n|4K|4j                  dP      }>|>8|>}=|d!k(  sd"tE        |0      v r$d#tE        |1      v rt7        dQ| d%|1 d&|0 dR|>        |=ut?        |/dS      ri|/jT                  ]|/jT                  }=|d!k(  sd"tE        |0      v r?d#tE        |1      v r2t7        dQ| d%|1 d&|0 dT|= dU|4du dV|4r|4j                  dP      nd        |=Lt?        |/dW      r@t?        |/dX      r4|/jV                  xs dY}?|/jX                  xs dY}@|?|@z
  }Ad0d0dZ|A d[z  z  z   z  }=|=dO}=|j                  |0|0      }'|j                  |1|1      }(|'|(|=d0|=z
  |<|-d\}B| | BdK<   |!|!BdL<   |"|"Bd<   |#|#Bd<   |+j[                  B       |<r|2r.|3s,|j                  |0|0      }'|+j[                  |'dd]d^d2|-d\       |3s|2r|j                  |1|1      }(|+j[                  d|(d^d]d2|-d\       I l |+a| a|+S # 1 sw Y   xY w# t4        $ r-}t7        d|        ddl}|j;                          Y d}~d}~ww xY w#  Y xY w#  Y xY w# t4        $ r}t7        d-|        Y d}~d}~ww xY w# t4        $ r-}t7        d;|        ddl}|j;                          Y d}~<d}~ww xY w# t4        $ r}Y d}~6d}~ww xY w)_zGet upcoming games with win probabilities for week 14+ - FBS only, cached for 3 minutes
    Uses lightweight get_games for non-live games, and get_scoreboard for live gamesNrt   ru   r   r   r   r   r   r    r!   r"   r	   r#   rA    z2Warning: Could not build scoreboard name mapping: rO   )rT   zDEBUG: Fetched z games from scoreboardr   r{   r|   namepointsclockperiodwin_probabilitywinProbabilityto_dict__dict__i$SKansasUtahz$DEBUG: Extracting win_prob for game z (z @ z):z   home_team_obj.to_dict() keys: z  win_probability in dict: z  winProbability in dict: z  win_probability value: z  winProbability value: z  Error calling to_dict(): z  Final home_win_prob: 0rB   r   F)r~   r   r   r   r   home_win_probr{   r|   |z'DEBUG: Stored scoreboard data for game z): home_win_prob=z, clock=z	, period=z, home_name=z->z*Warning: Could not fetch scoreboard data:    rM   rN   rP   z&DEBUG: Looking for live data: game_id=z, home=z, away=zDEBUG: Scoreboard has z gameszDEBUG: Found by game_id: z7DEBUG: Not found by game_id, searching by team names...z+DEBUG: Matched game by team names: game_id=z, scoreboard_id=z==z6DEBUG: Matched game by team names (reversed): game_id=r~   r         ?              ?r   zDEBUG: Game z): Using scoreboard win_prob=home_win_probabilityz!): Using games endpoint win_prob=z, live_data=z, scoreboard_win_prob=home_pregame_eloaway_pregame_eloi  r;   i  )r{   r|   r   away_win_probr   rR   gffffff?g?).rV   _upcoming_games_cache_upcoming_games_cache_timeUPCOMING_GAMES_CACHE_TTLrY   rZ   r[   rd   ro   r   r   r   r.   r,   r%   r&   r'   r(   r)   r*   r+   r-   r   r   splitlenr/   r0   r   r   get_scoreboardhasattrr   r   strlistkeys
startswithr   r\   r]   r^   r   r   r   append)Cr_   r`   r   rn   r   r   ru   r   r1   scoreboard_to_displayr%   r2   r3   r4   r5   r"   r6   	cfbd_name	disp_namepartsschool_namer8   r   scoreboard_datascoreboard_by_teamsscoreboard_games	live_gamer   home_team_objaway_team_obj	home_name	away_namer~   r   r   r   r   val	team_dictr   r   team_key_fullteam_key_displayrc   r   rR   rb   r   r{   r|   r   r   	live_data
sb_game_idsb_datasb_homesb_awayapi_completedhas_live_infohas_final_scoresr   	home_probscoreboard_win_probhome_eloaway_eloelo_diff	game_datasC                                                                      r9   get_upcoming_gamesr     s    99;L(l=W.W[s-s$$j)I#%L %&I5LOD(D1PWT645P	Y',00IFL)5OI&  577<<
,AB(C'2a^^A&F77=)U2!$r!:!@!@!BJ WW%8"=CCEF!'+ &8+::+FL $8G8M8M8O 4	9#,#63<L$) 9P
 $0Fo>T>T>V4V/5
  ,$.$4$4$6E"5zQ.1hhuSbz.B#./#A3B;3OL%0O4J4J4L%L3>L AP@U@U@W(<	9+4+C;DL,1 AX
 (@L1*=Y  3l Ob$3353I$4 566LMN)Iit4G !(	; E '	; E ] 'vt DI 'vt DI")-4"HK")-4"HK#Iw=E$Y$?F %)M }.?@%m5FM?,/M$,HX1Y%m5EtL?,/M %,	1R!(5(=(=(?I,5MM:K,L,oPYP]P]^nPoM
 %,!&}jA0=0F0F0J0JK\0]  1Nanawawa{a{  }M  bN
 )+C	N0JvY\]fYgOg DWIRPY{Z]^g]hhjkl"=)<
I,9,A,A,C	 %(HinnN^I_H`&a b %(CDUYbDbCc&d e %(BCSW`C`Ba&b c#4	#A$),EiPaFbEc*d$e#3y#@$),DYO_E`Da*b$c  7GH $9#<#<YH[H[\egpHq#rL#8#<#<YH[H[\egpHq#rL (3'2.38H8H8MqrSX"(%,YU%K)6%1%1	0OG, !Y+4+Qyk(B.:^1\N+K(=D+M:@G+,<= )+C	N0JvY\]fYgOg GyPRS_R``cdpcq  rC  DQ  CR  RZ  [`  Za  aj  kq  jr  r~  H  ~I  IK  LX  KY  Z  [s *@ F R)*Jj"%e	''\R[lq'rE!$d3#D+t<	#D+t<	;Di<7%;Di<7% =DO//8	 i'HI,F6UXYbUcKcB7)7S\R]]dendopq233G2HOP7o#= 9/':R9STU WY Y9 0?/D/D/F+
G")++k2">")++k2">$/I4H(/I&)3C	N8RW]adenaoWo %(ST[S\\lmwlxx  AJ  @K  KM  NU  MV  V]  ^g  ]h  hj  kr  js  't  !u!&'1i76J(/I&)3C	N8RW]adenaoWo %(^_f^ggw  yC  xD  'E  !F! 0G" "+--">K"+--">K%MM'2E&]]84F$-MM+u$EM #*$t"DK")$t"DK#D'48E$T8T:F$+D+u$EM !&T 1 GV45G#.d#:#V{RV?V  *U.>.T}CT	 {{ !%I [%<AX&4(+I(;6(+I(+I %02;--2P/2>,?	#*i#7HI<V[aehires[s$)L	I;cR[Q\\y  {N  zO  +P  %Q %,&t-CDIbIbIn,0,E,E	#*i#7HI<V[aehires[s$)L	I;cR[Q\\}  H  ~I  IU  V_  gk  Vk  Ul  lB  en  CL  CP  CP  Q`  Ca  tx  By  +z  %{ %,&t-?@WTSeEf+/+@+@+HD+/+@+@+HD+3h+>,-RXIO5L1L,M	 %,(+I $3#6#6y)#LL#2#6#6y)#LL &2%1)2)*Y%. $!I #.3>	-0".3>	-0(-2	'*).4	(+MM), #";'6':':9i'P)5)--1-1).$('  %['6':':9i'P)-)5-1-1).$(' q 	 &R #!-M[
 32^  B1#FGb! !  $- I %(CA3&G H HI<  :1#>?	^  		s  ?6g4 5,g'"Ag'%)g'B	g'g'"g'+g4 8?i" 8i" i" Bi" 34h-'i" *Ah5.A i" /A?h=.B1i" !i" 0&i" 9E(j"j(Jj92j-j1-j'g1,g4 4	h*="h%%h*-h2/i" 5h:7i" =	iii" ii" "	j+"jj	j/*j/c           	         ddl }| j                         D ci c]  \  }}|t        |d          }}}| j                         D ci c]  \  }}|t        |d          }}}i }t        d | j                         D              }	|D ]  }
|
j	                  dd      r|
j	                  d      }|
j	                  d	      }|
j	                  d
d      }|
j	                  dd|z
        }|r@|r>||v r||xx   |z  cc<   ||xx   |z  cc<   ||v s||xx   |z  cc<   ||xx   |z  cc<   |r|s||v s||xx   |z  cc<   |s|r||v s||xx   |z  cc<    t               }|D ]  }
|
j	                  dd      r|
j	                  d      }|
j	                  d	      }|s;|s>| j	                  |i       }| j	                  |i       }|j	                  dd      }|j	                  dd      }|j	                  dd      }|j	                  dd      }|dk(  s|dk(  s|dk(  s|dk(  s|t        vs|t        vs|j                  |       |j                  |        d}|j                         D ]  \  }}|j	                  || |   d         }|}| |   d   }| |   d   }|t        v rd}nG|dk\  rd}n>||v rd}n6|dk(  r|D cg c]>  }|j	                  dd      s*|j	                  d      |k(  s|j	                  d	      |k(  r|@ }}|rid}|D ]\  }
|
j	                  d      |k(  r|d|
j	                  d
d      z
  z  }0|
j	                  d	      |k(  sE|d|
j	                  dd      z
  z  }^ d|z
  }n}d}nz|D cg c]>  }|j	                  dd      s*|j	                  d      |k(  s|j	                  d	      |k(  r|@ }}|t        |      z   } | dk  rd}n|dk\  rd}n|dk  rd}nd|dz
  dz  z   }|||<   |t        vs|dk  s||v r||d|z
  z  z  } |j                  |      }!t        |j                               }"t        d | j                         D              }#t        |      dz  }$|#|$z   }%d}&| j                         D ]t  \  }}'|t        v r|'d   }|'d   }|dk(  s||vs$|D cg c]>  }|j	                  dd      s*|j	                  d      |k(  s|j	                  d	      |k(  r|@ }}|sp|&dz  }&v |#|$z   |&z   }(g })g }*g }+|j                         D ]  \  }}|j	                  || |   d         }|}|},|dk\  r|)j                  |       9|t        v r|dk\  r|*j                  |       X|dk\  s^|,dk  sdt        |      dk(  sst        |,      dk(  s|+j                  |        |)j                         }-t        |-      t        k  r,|*D ]'  }|-j                  |       t        |-      t        k\  s' n t        |-      t        k  r=t        |+fdd      }.|.D ]'  }|-j                  |       t        |-      t        k\  s' n d}/t        |-      t        k  r;|*rt        |)      t        k  r	|*d   dd}/n<|+r:t        |+fdd      }.|.r'|.d   d d}/nt        |-      t        kD  r|-t           d!d}/|"||/|!|	|%|(fS c c}}w c c}}w c c}w c c}w c c}w )"z
    Calculate expected number of bowl-eligible teams based on win probabilities
    Returns: (expected_eligible, expected_wins, cutoff_info, std_dev, currently_eligible)
    r   Nry   rz   c              3   F   K   | ]  \  }}|d    dk\  r|t         vrd  ywry   r>   rB   NTRANSITIONAL_TEAMS).0ru   datas      r9   	<genexpr>z1calculate_expected_eligibility.<locals>.<genexpr>  s1      T1E:4"6la/D@R4R 1E   !r   Fr{   r|   r   r   r   rB   r?   r>   r   r   g      @g\(\?g      @g{Gz?gQ?c              3   F   K   | ]  \  }}|d    dk\  r|t         vrd  ywr   r   )r   ru   records      r9   r   z1calculate_expected_eligibility.<locals>.<genexpr>  s1      #]9Mv%+F^q%8TI[=[ $%9Mr   rA      c                 Z    j                  t        |       j                  | d            S Nr   r,   r:   tapr_rankingss    r9   <lambda>z0calculate_expected_eligibility.<locals>.<lambda>  s%    )9)9+a.,JZJZ[\^_J`)arq   Tkeyreversetransitional)ru   typec                 Z    j                  t        |       j                  | d            S r  r  r  s    r9   r
  z0calculate_expected_eligibility.<locals>.<lambda>  s%    \-=-=k!nlN^N^_`bcNd-erq   aprexcluded)mathr   floatsumr,   r   r   r   r   sqrtr   r   roundcopyTOTAL_BOWL_SPOTSsorted)0team_recordsupcoming_gamesr	  r  ru   r   expected_winsexpected_lossesteam_eligibility_probscurrently_eligibler   r{   r|   r   	away_probguaranteed_game_teamshome_recordaway_record	home_winshome_losses	away_winsaway_lossesvariance_sumry   rz   est_winscurrent_winscurrent_lossesprob_eligiblegremaining_gamesprob_lose_allmax_possible_winsstd_devexpected_eligible_sumcurrently_eligible_countguaranteed_game_pairsmin_eligibleother_5win_teamsr  max_eligiblesix_win_teamstransitional_eligiblefive_seven_candidates
est_losseseligible_teams
sorted_aprcutoff_infos0     `                                             r9   calculate_expected_eligibilityr@    s   
  BNASASAUVAU:4T5f..AUMVEQEWEWEYZEYztTtU4>22EYOZ    T1C1C1E T T 88K'HH[)	HH[)	HH_c2	HH_a)m<	 M)i(I5(	*i7*M)i(I5(	*i7*yM)i(I5(yM)i(I5(7 >  E88K'HH[)	HH[)	&**9b9K&**9b9K#2I%//(A6K#2I%//(A6KQ;!#3Q;!#3!33	I[8[ &)))4%)))4' . L#))+
d $$T<+=h+GH#D)&1%d+H5 %%MQM**  MQ +9 Y.Q$%EE+u$=eeK0D8AEE+<NRV<V  !.O Y  #+Dxx,4%!dhh.L*LM+.$6%!dhh.L*LM	 ,
 !"M 1 !$ +9 Y.Q$%EE+u$=eeK0D8AEE+<NRV<V  !.O Y !-s?/C C 1$ #S $S $ !%3$'> >'4t$
 ))mc.A,, ]1B CCI ,N ii%G   6 = = ?@  # #]9K9K9M #]  ]   56!;+.CCL $**,f%%f~!19%::*8 Y.Q$%EE+u$=eeK0D8AEE+<NRV<V  !.O Y  A%  - ,.CCFVVL M#))+
d $$T<+=h+GH 
q=  &''HM!((.]zQX!#j(9Q(>%,,T2 ," #'')N >--)D!!$'>"&66 * >--1a#')
 D!!$'>"&66  K
>-- S%7:J%J#8#;^TK" 5#e'+-J '1!}eD	^	/	/-.>?T -gGY[giuuuI WZlY$YrYs    [
[A[>A[5A[ c                 $     t         v ryt         fd|D              }|dk\  ry|dk\  r
 t        vryy|dk(  r|dk(  ry|dk  r|d	kD  r||z   }|dk\  ryyy t        v r|dk(  ry|dk  r|dk  ryy|dk(  r,|d	kD  r' t        vr||z   dk\  ry
||z   }|dk  ry||z   }|dk  ry t        k(  s dk(  r|dk(  r|dk(  r|d	kD  ry
|dk\  ry|d	kD  ry
|dk  r!|d	kD  r||z   }||z   }|dk\  ry
|dk(  r|dk  ryy|d	k(  r|dk\  r
 t        v ryy|dk(  r|dk(  ryyy
)zrDetermine current status of a team
    Returns: 'eligible', 'undecided_6win', 'undecided_57', or 'ineligible'
    
ineligiblec              3   f   K   | ](  }|j                  d d      s|d   k(  s|d   k(  rd * ywr   Fr{   r|   rB   Nr,   r   r.  ru   s     r9   r   z"get_team_status.<locals>.<genexpr>  s=      M^ !k5 9K.D0AkNd4J ^s   .1r=   r>   eligibleundecided_57r  r?   r   undecided_6winzArmy West Point)INELIGIBLE_TEAMSr  r   	ARMY_TEAM)	ru   ry   rz   r  r  r	  r/  r1  max_possible_lossess	   `        r9   get_team_statusrM    s   
  M^ M MO
 { qy)) {19!AX/A- $ 6 A%%# !!19!AX&1*! qy_q())o%*'"(?":"a'% #)?":"a'% yD$551911)<#q[q # axOa' ?2$6 !#!#(;q(@!   !19))%QY6Q;!rq   c                    t        |       }|dk(  ry|dkD  r|dz
  }| d|dkD  rdnd ddfS |d	k(  ry
|dk(  ry|dk(  ry|dk  r7d|z
  }|dz   }t        |      }t        |dz
        }d| d| d|dkD  rdnd dfS t        |       }	d|	 ddfS )z
    Generate summary text based on expected eligible count and Delaware's status
    Returns: (summary_text, color)
    Note: expected_eligible is rounded to nearest whole number for summary text
    r   )zAll eligible teams bowling#4caf50z bowl eligible teamrB   sr	   z not bowlingz#f44336Q   )z-All eligible teams bowling + {MISSOURI_STATE}rO  P   )z:All eligible teams bowling + {MISSOURI_STATE} + {DELAWARE}rO  O   )zGAll eligible teams bowling + {MISSOURI_STATE} + {DELAWARE} + 1 APR teamrO  z=All eligible teams bowling + {MISSOURI_STATE} + {DELAWARE} + -z	 APR teamrO  z	Expected z eligible teamsz#666)r  )
expected_eligibledelaware_winsdelaware_lossesdelaware_exp_winsrounded_expectedn	apr_countapr_count_roundedapr_count_minus_onerounded_displays
             r9   generate_summaryr_  K  s$    ./26	B	r!'q1u"'=\JIUU	R	I	R	V	R	c	B	!!E	!),#IM2RSfRgghizh{  |E  M^  ab  Mb  FI  hj  Ek  l  nw  w  	w   12?+?;VCCrq   z/api/statusGET)methodsc                    :; 	 t               } t               }t        | |t              \  }}}}}}}| j	                  d| j	                  di             }	|	j	                  dd      }
|	j	                  dd      }|j	                  d|j	                  d|
            }t        ||
||      \  }}i }t               }i }|D ]  }|j	                  d      }|j	                  d      }|j	                  d|      }|j	                  d	d
      }|dk(  xs ||k(  }| }|s|s]|r||vrg ||<   ||   j                  |       |s||vrg ||<   ||   j                  |        | j                         D ]  \  ;}|j	                  ;|d         }t        ;|d   |d   ||t              }|j	                  dd      }||vrg ||<   ||   j                  ;|d    d|d    |t        |d      |j	                  ;g       d        i }d}|D ]  }||   j                  d        t        d ||   D              }d} ||   D ]=  }!|!d   }"|"t        v r|!d   }|!d   j                  d      }#t        |#d         }$t        |#d         }%|!j	                  dg       D &cg c]  }&|&j	                  d	d
      s|& }'}&|$t!        |'      z   }(|(dk  r| dz  } |$dk\  r| dz  } |$dk(  rx|'rod})|'D ]\  }|j	                  d      |"k(  r|)d|j	                  dd      z
  z  })0|j	                  d      |"k(  sE|)d|j	                  dd      z
  z  })^ d|)z
  }*| |*z  } | dz  } |d k\  r| dz  } %|d!k\  r|d!z
  dz  }+| |+z  } 9| dz  } @ || z  }|| |d"||<    g },| j                         D ]  \  ;}|d   }-|d   }.|j	                  ;|-      }d#|z
  }/|-dk\  r	;t        vr6|.d$k\  r<t        ;fd%|D              }'d
}0|-dk(  r|.d&k(  rd'}0nY|-dk(  r|.dk(  r|'dkD  rd'}0nG|-d(k(  r|.d&k(  r|'dkD  rd'}0n5|-dk(  r|.dk(  r|'dk\  rd'}0n#|-d(k(  r|.dk(  r|'dk\  rd'}0n|d)k\  r|d k  r|/d*k  rd'}0|0st        j                  t#        ;      t        j                  ;d            }1|,j                  ;|- d|. |1d+       
 |,j                  d, d'-       d}2g }3|,D ]E  }4t        |4d   j                  d      d         }-|3j                  |4       |-dk\  s:|2dz  }2|2d&k\  sE n |3},t%        dt&        |z
  dz
        }5d}6d| v sd| v rd| v rdnd:t        :fd.|D              }6t)        i d/|d0|d1|d2|d3|d4t&        d5|d6|d7t               d8|d9|d:|d;|,d<|5d=|
d>|d?|6      S c c}&w # t*        $ rP}7dd@l}8|8j/                         }9t1        dA|7        t1        |9       t)        t3        |7      |9dB      dCfcY d@}7~7S d@}7~7ww xY w)Dz;Main API endpoint returning current bowl eligibility statusr   zDelaware Blue Hensry   r   rz   r{   r|   rR   r   Fr   rv   rx   rT  rA   )ru   r  statusr  r  c                 P    t        | d   j                  d      d          | d    fS )Nr  rT  r   r  )intr   xs    r9   r
  zget_status.<locals>.<lambda>  s-    AhK$5$5c$:1$= >>?AS@STrq   )r  c              3   0   K   | ]  }|d    dk(  rd  yw)rc  rG  rB   N )r   r  s     r9   r   zget_status.<locals>.<genexpr>  s$       <+Ja!"8
!: !"+Js   r   ru   r  r  rB   r  r>   r   r?   r   r   r   g      @g      @)eligible_countpredicted_countcumulative_predicted   r=   c              3      K   | ]@  }|j                  d d      s,|j                  d      k(  s|j                  d      k(  rd B ywrD  rE  rF  s     r9   r   zget_status.<locals>.<genexpr>  sH      "]^()k5(A"#%%"4"<k@RVZ@Z #$^   AA	r  T   g      @g      @)ru   r  r  c                     | d   S )Nr  ri  rf  s    r9   r
  zget_status.<locals>.<lambda>9  s    !E(rq   r  c              3      K   | ]@  }|j                  d d      s,|j                  d      k(  s|j                  d      k(  rd B ywrD  rE  )r   r.  delaware_teams     r9   r   zget_status.<locals>.<genexpr>W  sI      %q1*+%%U*C$%EE+$6-$G155Q\K]anKn &'ro  rU  r   r6  r8  r2  total_spotsteams_by_conferenceconference_totalsr   r?  summary_textsummary_colorapr_candidatesexpected_apr_spotsrV  rW  delaware_remaining_gamesNzError in /api/status: )errorr   i  )r   r   r@  rH   r,   r_  rd   r   r   rM  r  sortr  r   r   re  r   r:   r   r  r   r/   r   
format_excr0   r   )<r  r  rU  r  r?  r2  r   r6  r8  delaware_recordrV  rW  rX  rw  rx  ru  r   team_upcoming_gamesr   r{   r|   	game_weekis_completedshould_include_for_displayshould_include_for_probr  exp_winsrc  rv   rv  rl  conf_eligibleconf_predictedr  r   record_partsr+  r,  r.  r/  r1  r0  prob_win_at_least_oneprobry  ry   rz   
exp_lossescould_be_5_7	apr_scoreteams_with_5_plus_winsfiltered_apr_candidates	candidaterz  delaware_remainingr8   r   error_tracers  ru   s<                                                             @@r9   
get_statusr  u  s   {I')+- rP.,r
n=+w@RT`bn
 '**:|7G7GH\^`7ab'++FA6)--h:)--j-:K:KL`bo:pq '77H-Yhj{&|#m ! () "D-I-I6I88K7L +4r/*VY,=V&*6&6# *-D (;;9;+I6'	299$? (;;9;+I6'	299$?+ #. )..0LD&$((vf~>H$fVnfX&6F  L)<J!4424#J/
+22#F^,AfX.>-?@ !&x!3"5"9"9$"C4  1,  -J  
+00T 1 
    <+>z+J  < <M
 !N(4fI	 22_- {005"<?3!$\!_!5 /0ee4Db.I #C.I()k5(A $%.I #C$033G$G! %q("c)N!Q&"c)N!Q&& ),$3D#xx4	A -!dhhPS6T2T U!%+!6)!C -!dhhPS6T2T U	 %4
 12M0A-&*?? '#- _"c)N_ %sNc1D"d*N #c)Nc 5h !N2 "/#1(<-j)G .T (..0LD&&>DH%F$((t4HhJ qyT);; {
 " "]^ "] ]O !LqyVq[#v{/B#v{/B#v{!/C#v{!/C#SX^
c8I#(,,[->@P@PQUWX@YZ	%% !%ax0$' Q 1^ 	 2DA "#"$'Iy*005a89D#**95qy&!+&)Q. ( 1 !$47H$H1$LM %)=)M*4*DJJ^M!$ %q %q "q  
!2
 "4
 L
 L	

 w
 +
 "#6
  !2
 ,.
 ;
 L
 ]
 n
 !"4
 ]
  !
" '(:#
  	E#Cj  I**,&qc*+kQkBCSHHIsZ   DV !V 9EV V+A5V !D2V B#V 8
V B
V V 	W,AW'!W,'W,/c                  ,    t         j                  d      S )zServe the main HTML pagez
index.html)appsend_static_fileri  rq   r9   indexr  v  s     --rq   __main__Ti  )debugport)NNN)?r&   flaskr   r   
flask_corsr   dotenvr   rY   r   jsonrV   r   r   tempfiler   r'   dirnameabspath__file__r)   __name__r(   r  getenvapi_keyConfigurationconfiguration	ApiClientr[   r  nowrQ   r^   CURRENT_WEEKr   rK  rJ  r.   r$   r:   CONFERENCE_GUARANTEESapr_datarH   ImportErrorrW   rX   rd   rh   ri   ro   r   r   r   r   r   r@  rM  r_  router  r  runri  rq   r9   <module>r     sL   	              WW__RWW__X67
HBGGLLX$FXZ[ S	 "))NB
'"""8T^^M*
  x||~"" '
3 	\*  %"
   A<  % !%15  D "2   "2  Nd    l^lv^dN'DT =5'*}I +}I@ 3 . !.
 zGG$TG" q(  Ls   #F+ +F54F5