o
    4ai.(                     @   s   d dl Z d dlmZmZ d dlZddlmZ edddZdd Zddd	Z	dd
dZ
d dlmZ dddZdd ZdddZdddZdddZdS )    N)datetime	timedelta   )infer_sale_eventsi  c                 C   s   | du s| dk r
dS | dk rdS | dk rt |  dS | d }|dk r*t | d	S |d }|d
k r9t | dS |d
 }|dk rHt | dS |d }|dk rWt | dS |d }t | dS )z9Converts minutes into a human-readable 'time ago' string.Nr   -r   zjust now<   z minutes ago   z
 hours ago   z	 days ago   z
 weeks ago      z months agom  z
 years ago)int)minutes_ago	hours_agodays_ago	weeks_ago
months_ago	years_ago r   4/var/www/agentarbitrage/keepa_deals/new_analytics.pyformat_time_ago   s(   r   c              
   C   sB  d}|s	t t}| dd}d| vs"t| d tr"t| d dk r0|d| d| d d	S t| \}}|s:d	S zCt	
|}t	|d
 |d
< t tdd }||d
 |k }t|dk rq|d| dt| d W d	S |d  }	||	d iW S  ty }
 z|jd| d| d|
 dd W Y d	}
~
d	S d	}
~
ww )z
    Displays the median inferred sale price over the last 365 days.
    Returns None if there are not enough sale events.
    z	1yr. Avg.asinN/Acsv   zASIN z: Incomplete data for .Nevent_timestampr   )daysr   z: Insufficient sale events (z) for a meaningful average.inferred_sale_price_centsg      Y@z: Error calculating z: Texc_info)logging	getLogger__name__get
isinstancelistlenwarningr   pd	DataFrameto_datetimer   nowr   infomean	Exceptionerror)productloggerCOLUMN_NAMEr   sale_events_dfone_year_agodf_last_yearmean_price_centser   r   r   get_1yr_avg_sale_price"   s2   
&
 r<   c              
   C   s   d}|s	t t}| du s|du s| dkrdS z|| kr!|diW S | | |  d }||iW S  ttfyR } z|jd|  d| d| d	d
 W Y d}~dS d}~ww )zc
    Calculates the percentage discount of the current 'Price Now' compared to the '1yr. Avg.'
    z% DownNr   g        d   z(Error calculating discount with inputs 'z' and 'z': Tr    )r"   r#   r$   
ValueError	TypeErrorr1   )	avg_price	now_pricer3   r4   discountr;   r   r   r   get_percent_discountE   s   


 rC   )groupbyc                    s  d}|s	t t}| dd}| di }|dg }d}t|dkr-|d dur-|d }d	}|dkr@|d
k r:d}n|dk r@d}| dg }g  |r[t|dkr[|d r[ |d  |rnt|dkrn|d rn |d   st|diS t fddtdt dD }	dd tdd |	D D }
t|
dk r|diS |
| d }t|dk r|diS |d }|d }|dkr|diS || | d }|dkr|diS |dk r|diS |diS )u   
    Indicates the price trend based on a dynamic sample of recent unique price changes.
    Returns an arrow string: ⇧ (up), ⇩ (down), ⇨ (flat).
    Trendr   r   statsavg365r   N   i 
   i     r   r         ⇨c                    s0   g | ]} |d   dkr |  |d   fqS )r   r   r   ).0icombined_historyr   r   
<listcomp>z   s   0 zget_trend.<locals>.<listcomp>c                 S   s   g | ]\}}|qS r   r   )rN   kgr   r   r   rR   {       c                 S   s   g | ]}|d  qS )r   r   )rN   pr   r   r   rR   {   rU   r=   u   ⇧u   ⇩)	r"   r#   r$   r%   r(   extendsortedrangerD   )r2   r3   r4   r   rF   avg_365_rank_rawavg_ranksample_sizecsv_dataprice_pointsunique_pricesanalysis_windowfirst_price
last_pricetrend_percentr   rP   r   	get_trend]   sH   
&&"rd   c                 C   s   |  di }| ddgd d }| ddgd d }| ddgd d }|dks3|dks3|dkr7dd	iS |d	krC|| | d
 nd	}d|iS )z;
    Analyzes the 30-day and 90-day sales rank trends.
    rF   currentrH   r
   rI   avg30avg90zSales Rank Trend %r   r=   )r%   )r2   rF   current_rankrf   rg   thirty_day_trendr   r   r   analyze_sales_rank_trends   s   rj   c              
   C   sf  |st t}z| di }|d}|d}|d}|du s*t|tr*|dk r/ddiW S t|tr:|dkr:|nd}t|trG|dkrG|nd}|| }|| }	|	dk rWd}	|d	g }
d
}|
rkt|
dkrk|
d }|d
kss|du rzdt|	iW S d}|	|krd}n|	|k rd}d|	 d| iW S  ty } z|j	d| dd ddiW  Y d}~S d}~ww )uo   
    Calculates the trend for Used Offer Count.
    Returns: "Count ↘", "Count ↗", "Count ⇨", or "-"
    rF   offerCountFBAofferCountFBMtotalOfferCountNr   Offersr   rf   rH   r   rM      ↗   ↘ z%Error calculating Offer Count Trend: Tr    )
r"   r#   r$   r%   r&   r   r(   strr0   r1   )r2   r3   rF   offer_count_fba_newoffer_count_fbm_newtotal_offer_countval_fba_newval_fbm_newcurrent_new_totalcurrent_used_countavg30_arrayavg_used_countarrowr;   r   r   r   get_offer_count_trend   s>   




r}   c           	   
   C     |st t}zc| di }|dg }d}|r"t|dkr"|d }|dks*|du r/ddiW S |dg }d}|rCt|dkrC|d }|dksK|du rRdt|iW S d	}||kr[d
}n||k rad}d| d| iW S  ty } z|jd| dd ddiW  Y d}~S d}~ww )u   
    Calculates the trend for Used Offer Count (180 days).
    Compares 90-day avg to 180-day avg.
    Returns: "Count ↘", "Count ↗", "Count ⇨", or "-"
    rF   avg180rH   r   Nz
Offers 180r   rg   rM   ro   rp   rq   z)Error calculating Offer Count Trend 180: Tr    r"   r#   r$   r%   r(   rr   r0   r1   )	r2   r3   rF   avg180_arrayavg180_countavg90_arrayavg90_countr|   r;   r   r   r   get_offer_count_trend_180   s6   

r   c           	   
   C   r~   )u   
    Calculates the trend for Used Offer Count (365 days).
    Compares 180-day avg to 365-day avg.
    Returns: "Count ↘", "Count ↗", "Count ⇨", or "-"
    rF   rG   rH   r   Nz
Offers 365r   r   rM   ro   rp   rq   z)Error calculating Offer Count Trend 365: Tr    r   )	r2   r3   rF   avg365_arrayavg365_countr   r   r|   r;   r   r   r   get_offer_count_trend_365   s6   

r   )N)r"   r   r   pandasr*   stable_calculationsr   KEEPA_EPOCHr   r<   rC   	itertoolsrD   rd   rj   r}   r   r   r   r   r   r   <module>   s   

#
6

/+