U
    —âñj
k  ã                   @   s  d dl Z d dlmZmZ ddlmZ ddlmZmZmZm	Z	 ddl
mZmZmZmZmZmZmZmZmZmZmZ d dlZdd„ Zed	œd
d„Zdi dfeeeeeedœdd„Zdd„ Zdd„ Zeeeedœd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'„ Z(dS ))é    N)ÚdatetimeÚ	timedeltaé   )Úprocess_one_day_data)Úfetch_data_collectionÚfetch_visitas_collectionÚdata_analyticÚcameras_collection)Úsave_analytics_dataÚfetch_analytic_dataÚget_docs_by_date_and_areaÚfetch_analytic_area_dataÚget_docs_by_regionÚfetch_analytic_region_dataÚ_init_value_summaryÚ_init_tasa_summaryÚ_postprocess_valuesÚ_postprocess_tasaÚvalidar_y_sumarc                 C   s   t | ƒ d S ©N)Úprint)Útext© r   ú:/var/www/itgmanager/itgmanager/Analytic/Scapp_analytics.pyÚdata_analytic_logger   s    r   )Úscapp_configsc                 C   sj   t  ¡ }t |j|j|jƒ}|tdd� }t  ¡ }t|d| dd�}t  ¡ }td||  	¡ d d›d	�ƒ d
S )z“ Calcula y alamacena los datos del dia anterior. 
    Se llama diariamente para siempre tener los datos del dia anterior ya almacenados en BD.
    r   ©Údaysr   F)Ú
day_rangesr   Ú
parse_dataz@Datos de Analitica del dia anterior calculados correctamente en ç     @�@ú.4fúms.N)
r   ÚtodayÚyearÚmonthÚdayr   ÚnowÚcompute_multiple_analytic_daysr   Útotal_seconds)r   r#   Ú	start_dayZ	yesterdayÚt1Ú_Út_endr   r   r   Úcompute_daily_analytic_data   s    r.   é   T)Ú	center_idÚ
_start_dayr   r   r   Úreturnc              
   C   sî  i }t |ƒ}|dk rtdƒ‚t|j|j|jƒ}|t|d� }td|›�ƒ td|›�ƒ | di ¡ dd¡}| d	i ¡ dd
¡}	t	t
| ||ƒ}
g }t ¡ }t|j|j|jƒ}t ¡ }z4ddi}ttt |¡ƒƒd d }dd„ |D ƒ}W n@ tk
�r( } z td|jj› d|› �ƒ i }W 5 d}~X Y nX g }g }g }t|ƒD ]~}|t|d� }|tdd� }| d¡}||k�r†td|› d�ƒ �q>||
k�r–i }n|
| }| |¡ |�r>t|||ƒ �q>d}t|ƒdk�r"|dt|ƒ› d�7 }t|ƒ�r|dt|ƒ› d|› d|› d�7 }n|d|› d�7 }n*t|ƒ�rH|dt|ƒ› d |› d�7 }nd!}t|ƒ |�rftt
||ƒ t ¡ }|	�sz|�rêt|ƒdk�rŒd"nd#t|ƒ› d$�}t|
ƒdk�r®d"nd%t|
ƒ› d$�}tƒ  td&||  ¡ d' d(›d)|› |› �ƒ |S )*a·   Calcula los datos de analitica para un conjunto de dias, especificando su dia inicial y el rango de dias solicitado
    
    @params
    - center_id (str): ID de centro, en formato string, correspondiente al identificador unico de cada centro.
    - _start_day (datetime): Fecha, en formato datetime, correspondiente al dia inicial solicitado.
    - day_ranges (int): Cantidad de dias solicitados.
    - parse_data (bool): Flag que dicta si parsear los datos al formato esperado por front.
    - verbose (bool): Flag para entregar informacion detallada.
    - timed (bool): Imprime tiempos de ejecucion.

    @returns
    - analytic_data (dict): Diccionario agrupado por jaula y por dia con los datos procesados. 
        Cada jaula contiene las llaves: 
            { name, sfr_value, delivered_food, tasa_units, tasa_values,  tasa_data, fasts_count, feeding_time_range, alarms_data, alarms_count }
        
        - parse_data=True:
          Cada llave es un array de la forma [{day, value}, ...]
        
        - parse_data=False:
          Cada llave es un diccionario, de la forma {day, value}
        
        - Llave 'name':
          Siempre contiene como valor el nombre de la Jaula.
    
    r   u*   La cantidad de dÃ­as debe ser mayor a ceror   zLDRd start_day=zLDRd end_day=ZAnalytic_debug_timedÚvalueTZAnalytic_debug_verboseFÚ_idZCamerasr   ZCamsc                 S   s   i | ]}|d  |d “qS )ÚIndexZNombrer   )Ú.0Úcamr   r   r   Ú
<dictcomp>g   s      z2compute_multiple_analytic_days.<locals>.<dictcomp>z+Error leyendo nombres de camaras desde BD (z): Nz%d/%m/%Yz*Se han solicitados datos de fecha futura: z, omitiendo calculo.zSe han zcargado los datos de z dias zy procesado los datos de z dias: 
	cargado: z
	procesado: Ú
z
 cargado: zprocesado los datos de z dias: 
	procesado: z'No se han obtenido datos de analitica.
Ú zSe han procesado z dias.
zSe han cargado zEl proceso ha tardado r    r!   z ms.
)ÚintÚ
ValueErrorr   r$   r%   r&   r   r   Úgetr   r   r#   r'   Úlistr	   ÚfindÚ	Exceptionr   Ú__traceback__Ú	tb_linenoÚrangeÚstrftimeÚappendÚparse_one_day_dataÚlenr
   r)   )r0   r1   r   r   r   Úanalytic_datar*   Úend_dayÚtimedÚverboseÚdays_with_dataZ
docs_arrayZ_todayr#   r+   Zfilter_camerasZdb_cam_dataZcam_names_dictÚeZcomputed_daysZloaded_daysZ
saved_daysr   Zstart_of_dayZ
end_of_dayÚformatted_dayÚone_day_dataZinfo_msgr-   Zcomputed_infoZloaded_infor   r   r   r(   &   st    	


!

 "
"" &r(   c                 C   s†   |  ¡ D ]x\}}|| kr i | |< |  ¡ D ]V\}}|| | kr^|dkrR|| | |< ng | | |< |dkr(| | |  ||dœ¡ q(qdS )a   Agrega los datos de un dia para cada jaula al diccionario que contiene todos los dias solicitados.
    @params
    - analytic_data (dict) : Diccionario por jaula que contiene los datos de multiples dias:
        { jaula: [{ ... } , ... ] }
    - one_day_data (dict): Diccionario de los datos del dia
        { jaula: { sfr_value, delivered_food, tasa_units, tasa_values,  tasa_data, fasts_count, feeding_time_range, alarms_data, alarms_count } }
    - formatted_day (str): Dia formateado (ej. '25/04/2025').
    Úname)r&   r3   N)ÚitemsrE   )rH   rO   rN   ÚjaulaÚ
jaula_dataÚkÚvr   r   r   rF   É   s    
  rF   c                 C   s    i }| D ]’}zj|  d¡}|r$d|kr(W q| d¡}t|ƒdkrBW q|d › d|d › d|d › �}t |d ¡||< W q tk
r˜ } zW 5 d}~X Y qX q|S )	zU ### ! Obsoleto: 
    ahora este trabajo lo realiza directamente fetch_analytic_data Úmetadataú/é   é   r   r   ÚdataN)r=   ÚsplitrG   ÚcopyÚdeepcopyr@   )Zloaded_datarL   Zdata_dayZ
y_m_d_dataZdate_splittedZchilean_daterM   r   r   r   Úidentify_days_with_dataç   s    
 
  r^   )Úarea_idr*   r   r2   c                 C   sš  t   ¡ }|t|d� }tt| ||ƒ}t|ttgdd�}| ¡ D �]2\}}|d  ¡ D �]\}	}
| |	i ¡}dddœ}dddœ}| ¡ D ]ª\}}| 	|d ¡sžq†| di ¡}| d	¡}| d
¡}|r†|sÈq†t
 |¡}t
 |¡}|d dksö||d k �r||d< ||d< |d dk�s ||d kr†||d< ||d< q†|d dk	rT|d |d  ¡ dœ|d |d  ¡ dœdœ|
d< qTq>t   ¡ | }td|d›d�ƒ | |iS )uà   
    - area_id:      "REGION-AREA"
    - start_day:    datetime de inicio (00:00)
    - day_ranges:   nÂº de dias a procesar
    Devuelve: { area_id: { centro_id: { values_summary, tasa_summary, feeding_time_range } } }
    r   F©Ú	key_funcsÚ	show_areaÚvalues_summaryN)rR   ÚhoraÚ-Zfeeding_time_rangeÚinicioÚfinalrd   rR   )rf   Úfinz*[compute_analytic_area_data] Procesado en z.2fÚs)Útimer   r   r   Úcompute_analytic_summaryÚarea_fnÚ	centro_fnrQ   r=   Ú
startswithr   ÚfromisoformatÚ	isoformatr   )r_   r*   r   Út0rI   Ú	area_dataÚarea_summaryÚ	centro_idZcentro_blockÚfechaÚstatsZ
raw_jaulasZ
min_inicioZ	max_finalZ
jaula_fullrS   ÚfrZinirh   Zdt_iniZdt_finZ
total_timer   r   r   Úcompute_analytic_area_data  sP    ý







þ
þûrx   c              
   C   s®   t  ¡ }|}|t|d� }z$t| |||ƒ}t|ttgdd�}W nD tk
r‚ }	 z&td|› d|	j	j
› d|	› �ƒ d }W 5 d }	~	X Y nX t  ¡ }
td|
|  ¡ d d	›d
�ƒ |S )Nr   Fr`   z"Error generando analitica de area z por error: z : zBDatos de Analitica versus entre areas calculados correctamente en r    r!   r"   )r   r'   r   r   rk   rl   rm   r@   r   rA   rB   r)   )Ú
collectionÚarear*   Ú
range_daysr+   Zfecha_inicialZfecha_finalrr   rs   rM   r-   r   r   r   Ú!compute_analytic_area_versus_datac  s    r|   c              
   C   sÎ   t  ¡ }i }|t|d� }| d }z,t||||ƒ}t|ƒ}	t|	ttgdd�}
W nD tk
r’ } z&t	d|› d|j
j› d|› �ƒ i }
W 5 d }~X Y nX |
|dœ}t  ¡ }td	|› d
||  ¡ d d›d�ƒ |S )Nr   r   Tr`   u@   No se ha generado correctamente a anaÄºitica Scapp de la region z por error en linea z: 
)rH   rP   zDatos de Analitica de Region z calculados correctamente en r    r!   r"   )r   r'   r   r   r   rk   rl   rm   r@   r   rA   rB   r   r)   )ÚdbÚ	region_idr*   r   r+   ZsummaryrI   ry   Zdocuments_by_regionZcomputed_analytic_region_dataZregion_analytic_resumerM   r-   r   r   r   Úcompute_analytics_by_regionw  s    
$r   c              
      sˆ  i }|   ¡ D �]`\}}|  ¡ D �]L\}}| d¡}g }	|D ]}
|	 |
||ƒ¡ q:|}|	D ]0}|rn| |i ¡}qX| d¡dkrX| |i ¡}qX| di ¡}| di ¡}| |tƒ ¡}| |tƒ ¡}| di ¡  ¡ D ]\}}||krÎ||  |¡ qÎ| d¡púi }| d¡�p
i }dD ]Z}|| d  | |i ¡ d	d
¡7  < || d  | |i ¡ dg ¡�pd| |g ¡¡ �qqq‡ fdd„‰ ˆ |ƒ |S )z—
    key_funcs: [
      # por cada jaula, devuelve la ruta de claves donde acumular:
      # e.g. ["centro_id", jaula_id] o [] para solo por fecha
    re   r   rc   Útasa_summaryÚalarms_by_tasa_levelsÚalarms_by_tasa©ÚaltaÚmediaÚbajaÚalarmr3   r   Útasasc                    s¸   t | tƒsd S d| kržd| kržt | d tƒr`tdd„ | d  ¡ D ƒƒr`t| d ƒ t| d ƒ q´| d  ¡ D ]\}}t|ƒ ql| d  ¡ D ]\}}t|ƒ qŠn|  ¡ D ]}ˆ |ƒ q¦d S )Nrc   r€   c                 s   s   | ]}t |tƒV  qd S r   )Ú
isinstancer>   )r6   rU   r   r   r   Ú	<genexpr>Ö  s     z<compute_analytic_summary.<locals>.recurse.<locals>.<genexpr>)r‰   ÚdictÚallÚvaluesr   r   rQ   )ÚnodeZfecha2ÚvsÚtsÚsub©Úrecurser   r   r“   Ñ  s    
(
z)compute_analytic_summary.<locals>.recurse)	rQ   r[   rE   Ú
setdefaultÚcountr   r   r=   Úupdate)rr   ra   rb   rg   ru   ÚjaulasrR   ÚdatosÚpartesZrutaÚfnrŽ   rT   Zvs_dictZts_dictr�   r�   ÚkeyÚvalZ	tasas_nivZalar_nivÚnivelr   r’   r   rk   �  s>    
$
þ	rk   c                 C   s   d  | d d… ¡S )Nre   rX   ©Újoin©ÚpartsrR   r   r   r   rm   æ  s    rm   c                 C   s"   t | ƒdkrd | dd … ¡S d S )Né   re   rX   )rG   rŸ   r    r   r   r   Újaula_fné  s    r£   c                 C   s   d  | d d… ¡S )Nre   rY   rž   r    r   r   r   rl   ì  s    rl   c                 C   sT  i }|   ¡ D �]V\}}|  ¡ D �]B\}}| d¡}t|ƒdk r@qd |d d… ¡}d |dd … ¡}| |i ¡}	|	 di ¡}
|	 di ¡}|
 |g g g g g g g g g dœ	¡}| |i ¡}| |i ¡}| di ¡  ¡ D ]\}}||krÐ||  |¡ qÐ| d¡püi }| d¡�pi }d	D ]N}| |g ¡}| |d
¡}| |d
tƒ dœ¡}|�rV|d  |¡ ||d< �qqq| 	¡ D ]à}	|	d   ¡ D ]|\}}|  ¡ D ]h\}}|dk�rÆ|�r¼t
t|ƒt|ƒ dƒnd
||< n.|dk�rè|�rÞ|d
 nd ||< nt|ƒ||< �qŽ�q~|	d   ¡ D ]B\}}|  ¡ D ].\}}|D ]}t|| d ƒ|| d< �q$�q�q�qn|S )Nre   r¢   rX   rc   r€   ©	Úalarms_by_tonÚalarms_countÚalarms_thresholdÚdelivered_foodZfasts_countÚperdidos_countÚ	sfr_valueÚ
tasa_unitsÚvisitas_countr�   r‚   rƒ   r   ©r‡   rˆ   rˆ   r‡   ©rª   r§   rY   r«   )rQ   r[   rG   rŸ   r”   r=   rE   Úsetr–   r�   ÚroundÚsumr   r>   )rr   Úfinal_resultsru   r—   rR   r˜   r™   rt   Zjaula_idÚcentroZvs_por_fechaZts_por_fechaÚresumenZ
tasa_fechaZ
tasa_jaular›   rœ   Útasas_por_nivelÚalarmas_por_nivelr�   rˆ   r‡   ZregistroÚvaloresZnivelesr   r   r   Ú#compute_multiple_analytic_area_daysñ  sb    
÷
&
(r¸   c                 C   sÒ  i }|   ¡ D �]\}}| |g g g g g g g g g dœ	dtƒ dœdtƒ dœdtƒ dœdœdœ¡}|d }|d }|  ¡ D ]œ\}}| di ¡  ¡ D ]\}	}
|	|krŒ||	  |
¡ qŒ| d¡p¸i }| d	¡pÆi }dD ]B}| |g ¡}| |d¡}|| d
  |7  < || d  |¡ qÌqtq|  ¡ D ]°\}}|d }|  ¡ D ]h\}	}|	dk�rl|�rbtt|ƒt|ƒ dƒnd||	< n.|	dk�rŽ|�r„|d nd ||	< nt	|ƒ||	< �q4dD ]&}t
|d | d ƒ|d | d< �q¢�q|S )Nr¤   r   r­   rƒ   )rc   r€   rc   r€   r�   r‚   r‡   rˆ   r®   rY   r«   )rQ   r”   r¯   r=   rE   r–   r°   r±   rG   r   r>   )rr   r²   ru   r—   Zdia_resumenr´   r€   rR   r˜   r›   rœ   rµ   r¶   r�   rˆ   r‡   r·   r   r   r   Úcompute_area_summary_by_day5  sT    ÷


ýô
&
(r¹   )T))r\   r   r   Úutilsr   Zscapp_databaser   r   r   r	   Z,scapp_database.utils.analytic_database_utilsr
   r   r   r   r   r   r   r   r   r   r   rj   r   r‹   r.   Ústrr;   Úboolr(   rF   r^   rx   r|   r   rk   rm   r£   rl   r¸   r¹   r   r   r   r   Ú<module>   s*   4  $2J
VD: