o
    ahi^                  	   @   sj  d dl Z d dlmZmZmZmZ d dlZd dlZd dl	m
Z
mZmZmZ d dlmZ d dlZd dlmZmZ d dlZedZdddd	d
Zg dZddd d d d dZg dg dg dg dg ddZg dZdZdZd	Ze ZdZ dZ!dd Z"dd Z#d^d d!Z$d"d# Z%d$d% Z&d&d' Z'd(d) Z(d_d+eee)ef  fd,d-Z*d.d/ Z+d0d1 Z,d+ej-fd2d3Z.d`d5d6Z/dad9ej-d:ee d;e0fd<d=Z1d>e2d+e2fd?d@Z3dAdB Z4dCdD Z5dEeee)ef  fdFdGZ6dEeee)ef  fdHdIZ7dEee2 dJe)fdKdLZ8dMdN Z9dbdOee2 dPee2 dQe0dRe2fdSdTZ:dbdPee2 dQe0dRe2fdUdVZ;dWdX Z<dcdYe2fdZd[Z=dcdYe2fd\d]Z>dS )d    N)AnyDictListTuple)load_players_dataload_teams_data&load_team_upcoming_fix_difficulty_data	load_infoget_player_stats)get_ai_transfer_suggestions$get_transfer_suggestions_for_playersfpl_data         )GKDEFMIDFWD)z5-4-1z5-3-2z5-2-3z4-5-1z4-4-2z4-3-3z3-4-3z3-5-2         ?)adisun)r         ?      ?gffffff?r   r   r   333333?r   r   皙?r    g?      )r   r   r   g?333333?r   r   r   r   r   r    r    r    r"   )r   r   r   r    r    gr!   r!   r   r   g?r!   r    r"   )r   r   r   r   {Gz?g333333ÿr   r$   g      ?g      ?r   r   r   r"   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   ZMNG)Zpoints_per_gameformZ	ict_indexZexpected_goalsZexpected_assistsZexpected_goals_concededZgoals_scoredZassistsZclean_sheetsZsaves$corners_and_indirect_freekicks_orderpenalties_orderdirect_freekicks_order
Difficultyb   d   zChttps://fantasy.premierleague.com/api/entry/{mng}/event/{gw}/picks/z1https://fantasy.premierleague.com/api/dream-team/c                 C   s$   t | d  }|d |d |d dS )z4
    Returns the team name for a given team ID.
    r   idZ
short_namecode)r,   namer-   )TEAMS)team_idteam r2   3/var/www/html/fantasy/fantasy_api/squad/services.pyget_team_nameF   s   r4   c                 C   s*   t dd | D }|tk s|tkrdS dS )zZ
    Validates overall team constraints:
      - Total price within the budget range.
    c                 s       | ]}|d  V  qdS now_costNr2   .0playerr2   r2   r3   	<genexpr>S       z validate_team.<locals>.<genexpr>FT)sum
BUDGET_MIN
BUDGET_MAX)r1   Ztotal_pricer2   r2   r3   validate_teamN   s   r@   '  r    c                 C   sF  dd t  D }| D ]}|d |v r||d  | qt|D ]}g }i }d}t  D ]h\}	}
||	g }tdtt|| }|d| }g }d}t||
k r|dk rt	
|}||vrx||d	 d}|tk rx|| |d ||d	 < |d7 }t||
k r|dk sVt||
k rd
} n|| q-|rt|r|  S q!dS )a  
    Generates a team using greedy randomized selection:
      - For each position, sort players by a greedy metric ('form') or (Total points).
      - Create a Restricted Candidate List (RCL) from the top rcl_percent of players.
      - Randomly select players from the RCL while enforcing the maximum team constraint.
      - Validate overall constraints (budget and team composition).
    c                 S      i | ]}|g qS r2   r2   r9   posr2   r2   r3   
<dictcomp>c       z3generate_team_greedy_randomized.<locals>.<dictcomp>element_typeTr   Nr      r1   F)	SELECTIONkeysappendrangeitemsgetmaxintlenrandomchoiceMAX_PLAYERS_PER_TEAMextendr@   )playersmax_attemptsrcl_percentposition_groupspattemptr1   Zteam_countsvalidrD   count
candidatesrcl_sizerclZselected_for_positionZattempts_for_position	candidateZcurrent_team_countr2   r2   r3   generate_team_greedy_randomizedZ   s@   	

rb   c                 C   s  d}d}i }t t }dd |D }g g d}dg}	|	dd | dD  t|D ]\}
}|d | }|d | }t|D ]J\}}|dd}|d	d}|dkr|d |k rk|d |d	< || d
 |f|d< q@|dksu|d |k r|| d
 |f|d	< q@|| d
 |f|d< q@|jdd t|dd dd}t	|}t
| |d dd |d |	|
  D  |t|d |	|
  7 }|d dd ||	|
 d  D  |t||	|
 d  7 }|d |= |d |= q,||d d 7 }||||fS )Nr   c                 S      g | ]}t |qS r2   r
   r9   r,   r2   r2   r3   
<listcomp>       z"create_team_XI.<locals>.<listcomp>XISubsr   c                 S   rc   r2   rP   r9   Zplayers_numr2   r2   r3   re          -CVCr,   Treversec                 S      | d S NXPr2   )r:   r2   r2   r3   <lambda>       z create_team_XI.<locals>.<lambda>)keyrq   rh   c                 S      g | ]}|qS r2   r2   r8   r2   r2   r3   re          ri   c                 S   rx   r2   r2   r8   r2   r2   r3   re      ry   )listrI   valuesrU   split	enumeraterN   sortsortedformat_squadprintr=   )	formationscoresr1   xi_scorebench_scorestatsplayers_per_positionZteam_playersteam_layoutplayers_countr   
players_noscores_by_positionZplayers_by_positionjscoreZcurent_captainZcurent_vicer2   r2   r3   create_team_XI   sH   
$$
r   c              	   C   s  g }i }d}d}t t }dd | D }g }|D ]	}||d  qtD ]b}	|dd }
dg}d}|dd |	d	D  t|D ]$\}}t|
d| d
d}|t	dd |d||  D 7 }|
d|= qC|||	< ||kr~|}|	}|
  ||	 q%||kr||	 q%t||fS )aH  
    Suggest a team formation using greedy selection:
      - For each position, choose the best players by a greedy metric ('form') or (Total points) to make the best XI for the given foramtion and team.
      - Assign each formation a score Calculated fto the greedy metric
      - Choose The Formation with Heighst score
    r    c                 S   rc   r2   r
   rd   r2   r2   r3   re      rf   z*suggest_team_formation.<locals>.<listcomp>rt   Nr   c                 S   rc   r2   rj   rk   r2   r2   r3   re      rl   rm   Trp   c                 s   s    | ]}|V  qd S Nr2   )r9   r   r2   r2   r3   r;      s    
z)suggest_team_formation.<locals>.<genexpr>)rz   rI   r{   rK   
FORMATIONSrU   r|   r}   r   r=   clearrR   rS   )r1   Zequal_scored_formsZscore_per_formationZheighst_scoreZselected_formationr   Zposition_candidatesZplayers_expected_scoresra   r   r   r   Zmetric_scorer   r   r   r2   r2   r3   suggest_team_formation   s@   


r   c                 C   8   t | }|g d }|d dd |d< |jddS )N)r,   web_namerG   r1   r7   r%   total_pointsstatusnews	opta_codert   r1   c                 S      t | S r   r4   xr2   r2   r3   ru      rv   zformat_squad.<locals>.<lambda>recordsorientpd	DataFrameapplyto_dict)squaddfr2   r2   r3   r      s   
r   c                 C   s:   t | g}|g d }|d dd |d< |jddS )N)r,   r   rG   r1   r7   r   r   r   r   r)   rt   r1   c                 S   r   r   r   r   r2   r2   r3   ru     rv   z!format_transfer.<locals>.<lambda>r   r   r   r:   r   r2   r2   r3   format_transfer   s   r   Freturnc                 C   s4   t  }| r	g dnddg}|j|dd}|jddS )N)rt   r   r   r   r   Fby	ascendingr   r   )create_player_selection_poolsort_valuesr   )use_xprV   Zsorting_criteriar2   r2   r3   selectable_players_data  s   r   c                 C   s   | d }t | }d}ttD ]%\}}d}|dv r%tt| | ||  }n
t| | ||  }||7 }qt|| d  t| d d d dS )	NrG   r   )r&   r'   r(   availabilitychance_of_playing_this_roundr+   r   r   )SELECTION_WEIGHTSr}   SELECTION_COLSfloatcalculate_setpiece_rank_scoreround)rowrD   weightsZweighted_sumr   colr   r2   r2   r3    calculate_player_composite_score  s   
$r   c                 C   s$   | dkrdS | dkrdS d| d  S )Nr   r   r#   r2   )rankr2   r2   r3   r   +  s
   r   c                  C   s   t t } | g dtd d   }|d dd |d< t t ddg }|jdd	id
}t j||d	dd}|jt	dd|d< |S )N)r,   r   r7   r   r   r1   rG   r   r   r   rt   r   c                 S   s   t |  S r   )STATUS)elemr2   r2   r3   ru   F  rv   z.create_player_selection_pool.<locals>.<lambda>r   r,   r)   r1   )columnsinner)onhowr   )axisr   )
r   r   r   r   mapr   renamemerger   r   )rV   Zplayer_selectionteamsr2   r2   r3   r   2  s    

r   Tc                 C   sX   | d |v s| | d dtkrdS | d |k rdS | d |kr"dS | d dkr*dS d	S )
z
    Validates a transfer selection:
      - Checks if the player Xp is not less than the Old.
      - Checks if the player cost is within the budget.
    r,   r1   r   Frt   r7   r   r   T)rN   rT   )r:   Zold_XPbudgetidsr]   Zis_availbler2   r2   r3   validate_trasfer_selectionS  s    r     Q?all_playersplayer_changer   c              	   C   s  dd t  D }| }| D ]}	|	d |v r ||	d  |	 qi }
d}t|
dk r| }| }t|}i }|}t|dkrt|}||d g }tdt	t|| }|d| }t
|D ]@}t|}t||d ||||d	 d
v rt|||d < ||d  ||d dd ||d < ||d 8 }||  nqctd|d  d| d| d nt|dksAt||kr|nd|
d| < |
d|  durt|d|
d|  d< |d7 }t|
dk s+|
S )ab  
    Generates transfer suggestion using greedy randomized selection:
      - For each position, sort players by a XP and Composite Score.
      - Create a Restricted Candidate List (RCL) from the top rcl_percent of players.
      - Randomly select players from the RCL while enforcing the  constraint.
      - Validate overall constraints (budget).
    c                 S   rB   r2   r2   rC   r2   r2   r3   rE   t  rF   z8generate_transfers_greedy_randomized.<locals>.<dictcomp>rG   r   r   r   Nrt   r   adr   r,   r1   r7   z&No valid candidate found for position z after z attempts with budget .ZTRZrem_balance)rI   rJ   copyrK   rQ   rR   rS   rN   rO   rP   rL   r   r   removeloggerwarningr   )r   r   r1   
team_countr   rW   rX   rY   Zsuggested_players_idsrZ   Ztransfer_suggestionsZsuggestZteam_player_countZplayer_changesZ
no_changes	selectionbankZcurrent_player_to_chnager^   r_   r`   r[   Zselected_candidater2   r2   r3   $generate_transfers_greedy_randomizedk  sL   	


",r   r0   c                 C   s   t  }|| d  d S )Nr   ZGW_1)r   )r0   Zteam_fixr2   r2   r3   !get_current_gw_opponent_diffuclty  s   r   c                  C   s*   t  } t| }tdd |D t|dS )Nc                 s   r5   r6   r2   r8   r2   r2   r3   r;     r<   z&select_random_squad.<locals>.<genexpr>)zTotal Team PriceTeam)r   rb   r=   r   )ZplayersListr1   r2   r2   r3   select_random_squad  s
   r   c                 C   r   )N)r,   r   rG   r1   r   r7   Zevent_pointsr1   c                 S   r   r   r   r   r2   r2   r3   ru     rv   z#format_dream_team.<locals>.<lambda>r   r   r   r   r2   r2   r3   format_dream_team  s   
r   picksc              	   C   s\  d\}}}g }g }d}d}i }g g d}	| D ]l}
t |
d }|
d dk rw|
d r9|d |d	 f|d
< ||d	 7 }n|
d rG|d |d	 f|d< ||d dkrPdnd7 }||d dkr\dnd7 }||d dkrhdnd7 }|| ||d	 7 }q|| ||d	 7 }q|	d dd t|D  |	d dd t|D  |	|||| d| d| fS )Nr   r   r   r   rg   elementposition   Z
is_captainr,   rt   rn   Zis_vice_captainro   rG   r   r   r   r   rh   c                 S   rx   r2   r2   r8   r2   r2   r3   re     ry   z(get_squad_from_picks.<locals>.<listcomp>ri   c                 S   rx   r2   r2   r8   r2   r2   r3   re     ry   rm   )r   rK   rU   r   )r   
fwd_counts	mid_count	def_countxisubsr   r   r   r   pickr:   r2   r2   r3   get_squad_from_picks  s2   



r   c                 C   s   d\}}}d}g }| D ]7}t |d }||d dkrdnd7 }||d dkr(dnd7 }||d dkr4dnd7 }|| ||d	 7 }qd
d t|D }||| d| d| fS )Nr   r   r   rG   r   r   r   r   pointsc                 S   rx   r2   r2   r8   r2   r2   r3   re     ry   z"get_dream_team.<locals>.<listcomp>rm   )r   rK   r   )r   r   r   r   r   r1   r   r:   r2   r2   r3   get_dream_team  s   

r   r   c           
      C   s   t |d\}}}t|t|t|}}}g }g }d}|| d  || dd|   || dd|   || dd|   |D ]}t|}	||	 ||	d 7 }qHdd t|D }||fS )	Nrm   r   r      r   rt   c                 S   rx   r2   r2   r8   r2   r2   r3   re     ry   z%get_ai_dream_team.<locals>.<listcomp>)tupler|   rP   rK   rU   r   r   )
r   r   r   r   r   r1   r   r   r   r:   r2   r2   r3   get_ai_dream_team  s   
r   c                 C   s0   t | \}}t||| \}}}}|||||dS )N)	Formationr   Xi Expected ScoreSubs Expected ScoreCaptain)r   r   )r1   r   Zplayers_scoresr   captainr   
subs_scorer2   r2   r3   
pick_squad  s   r   rV   r1   bank_balancefree_transfersc                 C   s   g }i }|}d}|D ]C}t |}	|| v r?|	d }
|	d }|dkr/|
d | t|
d  d }
||	 ||	d 7 }||
7 }q
||	d dd ||	d < q
td	d
}t|||||}|t|krcdnd|t|  }||dS )a  
    Suggest transfers up to three given the players to be changed and the current balance

    @param player: List of players id to be changed
    @param free_transfers: Number of free transfers available
    @param bank_balance: Current bank balance
    @return: Dictionary with suggested transfers , remaining balance ,and negative pomits if transfers exceeds the free transfers
    r   r7   Zcost_change_start
   r   rt   r1   r   Tr      )Zsuggested_transfersZ	minus_pts)r   mathfloorrK   rN   r   r   rQ   )rV   r1   r   r   Zplayers_to_be_changedr   r   Zold_expected_pointsr:   player_statsZplayer_selling_priceZplayer_price_changeplayers_poolsuggestionsminusr2   r2   r3   suggest_transfers  s&   	


 
r  c           
      C   sv   g }i }|}| D ]}t |}|| ||d dd ||d < qtdd}|jdd d t||| ||}	d	|	iS )
Nr1   r   r   Tr   c                 S   rr   rs   r2   r   r2   r2   r3   ru   C  rv   z%ai_suggest_transfer.<locals>.<lambda>)rw   Zai_suggestions)r   rK   rN   r   r~   r   )
r1   r   r   rV   r   r   r:   r   r   r   r2   r2   r3   ai_suggest_transfer7  s   

r  c                 C   s   t  }t| |r|d nd}|dkrdn|d }td|  d| d|  ttj| |d }z|d d d	 }|d
 }t|\}}}	}
}|||	|
||dW S    t	d|  d)z/
    Load a squad from a given manager ID.
    gwr   zLoading Squad for Manager ID: z	 for GW: z but current GW is )Zmngr  Zentry_historyr   r   r   )r   r   r   r   r   r   z+Could not load the squad with the given ID r   )
r	   r   inforequestsrN   get_mmg_squad_urlformatjsonr   
ValueError)Z
manager_idr  curr_gwr  Zrespnser   r   r   r   r   r   r   r2   r2   r3   load_squad_using_manager_idI  s   
r  r  c                 C   s:   t t |   }|d }t|\}}}|||| dS )/
    Load the dream team from the FPL API.
    r1   r   r1   totalr  )r  rN   DREAM_TEAM_URLr	  r   )r  responser1   r   r   r2   r2   r3   load_dream_team^  s   r  c           
      C   s   t t jg ddd}g }t D ]\}}||d |k |}||jdddf 	  qt
|\}}t||\}}	|||	| dS )r  )rG   r   rt   Fr   rG   Nr,   r  )r   r   r   r   rI   rM   headrU   loctolistr   r   )
r  r   Ztop_15rD   numberZplayers_per_posr   _r1   r   r2   r2   r3   load_ai_dream_teami  s   r  )rA   r    )F)T)r   r   )r   r   )r   )?r   typingr   r   r   r   pandasr   r  fantasy_data.servicesr   r   r   r	   Zplayers.servicesr   rR   Zsquad.tr_v3r   r   logging	getLoggerr   rI   r   r   r   r   r>   r?   rT   r/   r  r  r4   r@   rb   r   r   r   r   strr   r   r   r   r   r   r   r   rP   r   r   r   r   r   r   r   r  r  r  r  r  r2   r2   r2   r3   <module>   sz    


7.+	
!C!$$