
    !\i$                         d Z ddlmZmZmZ ddlmZmZ ddlZddl	m
Z
 ddlmZmZ ddlmZ ddlmZmZ dd	lmZ dd
lmZ ddlmZ ddlZ ej4                  e      Z G d d      Zy)zFeature engineering    )ListDictOptional)datetime	timedeltaN)Session)MatchMatchStatus)Team)TeamFormDailyFeature)MatchRepository)	EloRating)settingsc                       e Zd ZdZdefdZdededede	e
ef   fdZd	ee   dede	eef   fd
Z	 ddedededede	e
ef   f
dZdedefdZdedee   fdZy)FeatureBuilderzBuild features for matchesdbc                 \    || _         t        |      | _        t        j                  | _        y N)r   r   
match_repor   rolling_window_matchesrolling_window)selfr   s     /app/app/ml/features.py__init__zFeatureBuilder.__init__   s#    )"-&==    team_iddateis_homereturnc                 2   | j                   j                  |t        d      z
  |t        d      z
  d      }g }|D ]M  }|j                  |k(  r|r|j	                  |df       (|j
                  |k(  s8|r;|j	                  |df       O |j                  d d	       |d
| j                   }|sddddddS g }g }g }	g }
d
}|D ]  \  }}|r|j	                  |j                  xs d       |j	                  |j                  xs d       |j                  |j                  kD  r$|	j	                  d       |
j	                  d       n7|j                  |j                  k(  r#|	j	                  d       |
j	                  d       n|	j	                  d       |
j	                  d       n|j	                  |j                  xs d       |j	                  |j                  xs d       |j                  |j                  kD  r#|	j	                  d       |
j	                  d       n^|j                  |j                  k(  r#|	j	                  d       |
j	                  d       n"|	j	                  d       |
j	                  d       |r|j                  } d}|r||z
  j                  }|rt        |      t        |      z  nd|rt        |      t        |      z  nd|	rt        |	      t        |	      z  nd|
rt        |
      t        |
      dz  z  |dS d|dS )z1Calculate team form statistics up to a given dateim  days     	from_dateto_datelimitTFc                      | d   j                   S )Nr   
match_datexs    r   <lambda>z4FeatureBuilder.calculate_team_form.<locals>.<lambda>1   s    !r   keyreverseN              @)goals_for_avggoals_against_avg
points_avgform_last_n	days_restr      )r   get_finishedr   home_team_idappendaway_team_idsortr   
home_score
away_scorer,   r#   sumlen)r   r   r   r   matchesteam_matchesmatch	goals_forgoals_againstpointsform_pointslast_match_dateis_home_teamr9   s                 r   calculate_team_formz"FeatureBuilder.calculate_team_form   s    //..YC009!,, / 
 E!!W,##UDM2##w.w##UEN3	  	7F#$8T%8%89!$%(!"   	#/E<  !1!1!6Q7$$U%5%5%:;##e&6&66MM!$&&q)%%)9)99MM!$&&q)MM!$&&q)  !1!1!6Q7$$U%5%5%:;##e&6&66MM!$&&q)%%)9)99MM!$&&q)MM!$&&q)""'"2"27 $0< 	/55I AJS^c)n<sLY]!3c-6H!H_b7=#f+F33HS3{+s;/?!/CD"
 	
 Z]"
 	
r   rD   c                    i }|D cg c]  }|j                   |k  s| }}|j                  d        |D ]  }|j                  t        j                  j
                  k7  r+|j                  |j                  Dt        j                  ||j                  |j                  |j                  |j                          |S c c}w )z0Calculate Elo ratings for all teams up to a datec                     | j                   S r   r+   r-   s    r   r/   z6FeatureBuilder.calculate_elo_ratings.<locals>.<lambda>y   s    allr   )r1   )r,   r?   statusr
   FINISHEDvaluer@   rA   r   calculate_ratingsr<   r>   )r   rD   r   team_ratingsmhistorical_matchesrF   s          r   calculate_elo_ratingsz$FeatureBuilder.calculate_elo_ratingso   s     *, *1HAALL44GaH$:;'E||{33999'5+;+;+C''""""     ( # Is
   C C r<   r>   r)   c                    | j                   j                  |t        d      z
  |t        d      z
  d      }g }|D ]Q  }|j                  |k(  r|j                  |k(  s |j                  |k(  s1|j                  |k(  sA|j                  |       S |j                  d d       |d	| }d
}d
}	d
}
|D ]  }|j                  |j                  |j                  |k(  rD|j                  |j                  kD  r|dz  }J|j                  |j                  k(  r|	dz  }	i|
dz  }
o|j                  |j                  kD  r|dz  }|j                  |j                  k(  r|	dz  }	|
dz  }
 ||	|
dS )z!Calculate head-to-head statisticsi  r"   r$   r%   r&   c                     | j                   S r   r+   r-   s    r   r/   z.FeatureBuilder.calculate_h2h.<locals>.<lambda>   s    q||r   Tr0   Nr   )h2h_home_wins	h2h_drawsh2h_away_wins)	r   r;   r   r<   r>   r=   r?   r@   rA   )r   r<   r>   r   r)   rD   h2h_matchesrF   	home_winsdraws	away_winss              r   calculate_h2hzFeatureBuilder.calculate_h2h   s    //..YG449!,, / 
 E##|38J8Jl8Z##|38J8Jl8Z""5) 
 	3TB!&5)		 E'5+;+;+C!!\1##e&6&66NI%%)9)99QJENI##e&6&66NI%%)9)99QJENI# !( '&
 	
r   rF   c                    | j                  |j                  |j                  d      }| j                  |j                  |j                  d      }| j                  j                  d      }| j                  ||j                        }|j                  |j                  t        j                        }|j                  |j                  t        j                        }| j                  |j                  |j                  |j                        }t        di d|j                  dt        j                         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   }	|	S )z!Build features for a single matchT)r   Fi  )r)   match_idcalculated_athome_goals_for_avgr5   home_goals_against_avgr6   home_points_avgr7   home_form_last_nr8   home_elohome_days_restr9   away_goals_for_avgaway_goals_against_avgaway_points_avgaway_form_last_naway_eloaway_days_restrZ   r[   r\    )rM   r<   r,   r>   r   r;   rW   getr   INITIAL_RATINGra   r   idr   utcnow)
r   rF   	home_form	away_formall_matcheselo_ratingsri   ro   h2hfeatures
             r   build_features_for_matchz'FeatureBuilder.build_features_for_match   s    ,,U-?-?AQAQ[_,`	,,U-?-?AQAQ[`,a	 oo222>00e>N>NO??5#5#5y7O7OP??5#5#5y7O7OP   !3!3U5G5GIYIYZ  
XX
"//+
  )9
 $--@#A	

 &l3
 '}5
 
 %[1
  )9
 $--@#A
 &l3
 '}5
 
 %[1
 o.
  +&!
" o.#
( r   r{   c                    |j                   xs d|j                  xs d|j                  xs d|j                  xs d|j                  xs d|j
                  xs d|j                  xs d|j                  xs d|j                  xs d|j                  xs d|j                  xs d|j                  xs dt        |j                  xs d      t        |j                  xs d      t        |j                  xs d      gS )z&Convert feature to vector for ML modelr3   g     p@r4   r   )re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   rp   floatrZ   r[   r\   )r   r{   s     r   build_feature_vectorz#FeatureBuilder.build_feature_vector   s     &&-#**1c##*s$$+&"")c&&-#**1c##*s$$+&"")c''',1-'##(q)''',1-
 	
r   N)
   )__name__
__module____qualname____doc__r   r   intr   boolr   strr~   rM   r   r	   rW   ra   r   r|   r   rq   r   r   r   r      s    $>7 >
S
S
 S
 	S

 
c5j	S
je  
c5j		B 2
2
 2
 	2

 2
 
c3h2
h%e % %N
G 
U 
r   r   )r   typingr   r   r   r   r   pandaspdsqlalchemy.ormr   app.core.db.models.matchr	   r
   app.core.db.models.teamr   app.core.db.models.featurer   r   )app.core.db.repositories.match_repositoryr   
app.ml.elor   app.core.configr   logging	getLoggerr   loggerr   rq   r   r   <module>r      sJ     ' ' (  " 7 ( = E   $ 			8	$f
 f
r   