3
c\C<                 @   s   d Z ddlmZ ddlZyddlZW n ek
r@   edY nX G dd deZdd Zi fd	d
Z	dd Z
dd Zdd Zdd Zdd Zdd Zdd ZdS )z1
Calculates the optimal Dragon Sight buff target
    )	timedeltaNzzFFlogs parsing requires the Requests module for python.Run the following to install it:
    python -m pip install requestsc               @   s   e Zd ZdS )TetherCalcExceptionN)__name__
__module____qualname__ r   r   '/var/www/ffxiv/tethercalc/tethercalc.pyr      s   r   c          
   C   s   t jd |d< d|d< tj| |d}y|j }W n   td|j Y nX |jdkr~d|krptd	|d  ntd
|j |S )z/
    Gets a url and handles any API errors
    ZFFLOGS_API_KEYZapi_keyT	translate)paramszCould not parse response:    errorzFFLogs error: z!Unexpected FFLogs response code: )osenvironrequestsgetjsonr   textstatus_code)api_urloptionsresponseZresponse_dictr   r   r   fflogs_fetch   s    
r   c             C   s   | dkri S dj | |}t||}| dkr.|S xRd|kr|d |d< t||}|d j|d  d|krv|d |d< q0|d= P q0W |S )	zA
    Makes a call to the FFLogs API and returns a dictionary
    fightseventstables/damage-donez*https://www.fflogs.com:443/v1/report/{}/{}ZnextPageTimestampstart)r   r   r   )r   r   )formatr   extend)callreportr   r   dataZ	more_datar   r   r   
fflogs_api*   s    


r!   c                s   ||dd}t d| |}g }x|d D ]  d dkrV|j d  d  d d	 q& d d
kr& fdd|D }|r|d } d |d< q&|j d  d t d d | d d q&W |S )z%
    Gets a list of tether buffs
    zability.id=1001454)r   endfilterr   type	applybuffsourceIDtargetID	timestamp)sourcetargetr   
removebuffc                s(   g | ] }|d   d krd|kr|qS )r)   r&   r"   r   ).0tether)eventr   r   
<listcomp>g   s   zget_tethers.<locals>.<listcomp>r   r"   i N  )r)   r*   r   r"   )r!   appendmax)r   r   r"   r   Z
event_datatethersZ
tether_setr-   r   )r.   r   get_tethersN   s.    
r3   c             C   sB   ||dd}t d| |}i }x |d D ]}|d ||d < q&W |S )zD
    Gets non-tick, non-pet damage caused between start and end
    z%isTick="false" and source.type!="pet")r   r"   r#   ztables/damage-doneentriestotalid)r!   )r   r   r"   r   Zdamage_datadamagesdamager   r   r   get_damagesy   s    r9   c             C   s  ||d dd}t d| |}g }i }i }x |d D ]}|d |d d f}	|d d dkr|d |krx||d  }
ni }
|d	 d
krd|
kr|d |
d< nF|d	 dkrd|
kr|d d |
d< n |d	 dkrd|
kr|d |
d< |d |
d< |
||d < q4|d	 d$kr0|d |k r0|	|kr(|j|	 q4|d	 d%krb|d |krb|	|kr(|j|	 q4|d	 d&kr|	|kr(|j|	 q4|d	 dkr4|	d dkr|d |k r|d |kr||d   |d 7  < n|d ||d < q4|	|kr4|d |kr||d   |d 7  < q4|d ||d < q4W x|j D ]\}}
d|
krTd|
d< d|
krd|
kr|
d |kr|
d |k r||kr||  |
d 7  < n|
d ||< q8d|
kr|
d |krnd|
kr8d|
kr||
d< |
d |kr ||
d< |
d |d< |
d |d< d|d< |d  dt| 7  < |d  dt|
d  7  < t d | |}t|d! spnL||kr||  td"|d! d d#  7  < ntd"|d! d d#  ||< q8W |S )'z
    Gets the damage each player caused between start and end from tick damage
    that was snapshotted in the start-end window
    i`  aV  
            source.type="player" and
            ability.id not in (1000493, 1000819, 1000820, 1001203, 1000821, 1000140, 1001195, 1001291, 1001221)
            and (
                (
                    type="applydebuff" or type="refreshdebuff" or type="removedebuff"
                ) or (
                    isTick="true" and
                    type="damage" and
                    target.disposition="enemy" and
                    ability.name!="Combined DoTs"
                ) or (
                    (
                        type="applybuff" or type="refreshbuff" or type="removebuff"
                    ) and (
                        ability.id=1000190 or ability.id=1000749 or ability.id=1000501
                    )
                ) or (
                    type="damage" and ability.id=799
                )
            )
        )r   r"   r#   r   r&   ZabilityZguidiE r$   applydebuffr   r(   removedebuffr"   i  r8   amountr'   r*   refreshdebuffr%   refreshbuffr+      i  Z	supportIDr   zsource.type!="pet"r#   z and source.id=z and target.id=ztables/damage-doner4   g      ?r5   )r:   r=   r%   r>   )r:   r=   r%   r>   )r;   r+   )r!   r0   removeitemsstrlenint)r   r   r"   r   Z	tick_dataZactive_debuffsZtick_damageZ	wildfiresr.   actionZwildfirer)   Zwildfire_datar   r   r   get_tick_damages   s    










&"rF   c             C   sD   i }x:| j  D ].}||kr0| | ||  ||< q| | ||< qW |S )z$
    Combines the two arguments
    )keys)r7   tick_damagesreal_damagesr)   r   r   r   get_real_damages3  s    rJ   c             C   s0  d}x$| D ]}t dj||d  d ||d  d |d  d}|d d	 d	 |d krv||d d
 d	  d }n||d d	 d	  d }t dj| t |jddd t dd  xf|d D ]Z}|d	 |d krq||d	  d dkrqt |j||d	  d ||d	  d |d
  qW t   qW dS )z7
    Prints the results of the tether calculations
    z{:<22}{:<13}{}z{} tethered {} at {}r)   namer*   timing r7   r   r?   zThe correct target was {}ZPlayerZJobZDamage-0   r$   
LimitBreakN)printr   )resultsfriendsZtabularresultcorrectr8   r   r   r   print_results@  s.    rV   c                s  t d| } fdd|d D d }|s0td|d }|d }t|d |d  d}|d	 t|d
d d|krz|d ndd}dd |d D }t| ||}	|	stdg }
x0|	D ]&}d|kr||d< d|kr||d< t| |d |d }t| |d |d }t||}|d |kr:t||d  d ||d < t	|j
 dd dd}t|d | d}xH|D ]@}|d |d krh||d  d dkrh||d  d	 }P qhW |sd}|
j|t|d
d |d |d |d qW |
||fS ) zK
    Reads an FFLogs report and solves for optimal Dragon Sight usages
    r   c                s   g | ]}|d   kr|qS )r6   r   )r,   fight)fight_idr   r   r/   q  s    ztethercalc.<locals>.<listcomp>r   zFight ID not found in report
start_timeend_time)millisecondsrK         killF)enc_nameenc_timeenc_killc             S   s   i | ]}||d  qS )r6   r   )r,   Zfriendr   r   r   
<dictcomp>  s    ztethercalc.<locals>.<dictcomp>Z
friendlieszNo tethers found in fightr   r"   r*   g?c             S   s   | d S )Nr?   r   )Zdmgr   r   r   <lambda>  s    ztethercalc.<locals>.<lambda>T)keyreverser)   r$   rP   zNobody?)r7   rL   r)   r*   rU   )r!   r   r   rB   r3   r9   rF   rJ   rD   sortedrA   r0   )r   rX   report_datarW   Zencounter_startZencounter_endZencounter_timingencounter_inforS   r2   rR   r-   r7   rH   rI   Zdamage_listrL   toprU   r   )rX   r   
tethercalcj  sP    


(rj   c             C   s   t d| }|d d d S )z Get the last fight in the reportr   r?   r6   )r!   )r   rg   r   r   r   get_last_fight_id  s    
rl   )__doc__datetimer   r   r   ImportError	Exceptionr   r   r!   r3   r9   rF   rJ   rV   rj   rl   r   r   r   r   <module>   s"   $+ (*Q