
    JiH                     t    d Z ddlmZmZmZ ddlmZmZmZ ddlm	Z	 ddl
mZmZ ddlZddlmZ  G d d	      Zy)
zF
Realistic Hours Calculator - More accurate working hours calculation
    )datetime	timedeltatimezone)DictListOptional)Session)funcand_N)ActivityWatchClientc                       e Zd Zd ZdedefdZdedefdZde	e
j                     defdZdeeef   defd	Zdeeef   defd
Zdedede	e   fdZdedededede	e   f
dZde	e   defdZdededededef
dZy)RealisticHoursCalculatorc                     dddd| _         y )Ng      @g       @)lowmediumhigh
thresholds)selfs    @E:\timesheet\timesheet_new\backend\realistic_hours_calculator.py__init__z!RealisticHoursCalculator.__init__   s     
    hoursreturnc                 v    |dk(  ryt        |dz        }|dz  }|dz  }|dk(  r| dS |dk(  r| dS | d| dS )z@Convert decimal hours to readable format (e.g., 5.5 -> '5h 30m')r   0h<   mhzh )int)r   r   total_minutes
hours_partminutes_parts        r   format_time_readablez-RealisticHoursCalculator.format_time_readable   si    A:EBJ"b(
$r)?"^1%%Q \## \L>33r   c                 z    || j                   d   k  rddddddS || j                   d   k  rddd	d
ddS ddddddS )z3Get status color and message based on working hoursr   z#ef4444z#fef2f2zBelow targetu   🔴)statuscolor
backgroundmessageiconr   z#f59e0bz#fffbebzOn tracku   🟡r   z#22c55ez#f0fdf4z
Excellent!u   🟢r   )r   r   s     r   get_status_infoz(RealisticHoursCalculator.get_status_info%   ss    4??5))"')  T__X..""'%  !"'' r   
activitiesc                 (   |sddi dS i }d}|D ]  }|j                   }|j                  }||z  }||vr	ddi d||<   ||   dxx   |z  cc<   ||   dxx   dz  cc<   |j                  }|||   d   vrd||   d   |<   ||   d   |xx   |z  cc<    d}i }	|j                         D ]  \  }}
|
d   }|d	z  }|d
k(  r|}||z  }||ddd|	|<   '|dk(  r|}||z  }||ddd|	|<   >|dk(  r|}||z  }||ddd|	|<   U|dk(  r5| j	                  |
d         }||dz  z  }|||dz  z  z  }|||| dd|	|<   |dk(  r5| j                  |
d         }||dz  z  }|||dz  z  z  }|||| dd|	|<   |dz  }||dz  z  }||ddd|	|<    |d	z  |d	z  |	dS )z<Calculate realistic working hours based on activity patterns        )working_hourstotal_hours	breakdownr   )
total_timecountappsr2   r3      r4   i  developmentd   zAll coding/development work)r0   r/   
percentagereasondatabasezAll database workproductivityzAll productivity toolsbrowserz!% estimated work-related browsingotherz#% estimated work-related activitiesg?
   zMinimal work-related time)categorydurationapplication_nameitemsanalyze_browser_usageanalyze_other_usage)r   r,   category_datar2   activityr?   r@   app_nameworking_timer1   datacat_time	cat_hoursr/   work_percentages                  r   !calculate_realistic_working_hoursz:RealisticHoursCalculator.calculate_realistic_working_hours@   s   !$"  
 #H((H((H("J},"#+h' (#L1X=1(#G,1,  00H}X6v>><=h'/9(#F+H5A5' #, 	+113NHdL)H 4I=( )(#,%2"%;	'	(# Z' )(#,%2"%1	'	(# ^+ )(#,%2"%6	'	(# Y&"&"<"<T&\"J )_s-B COc,A BB#,%2"1!0 11RS	'	(# W$ #'":":4<"H )_s-B COc,A BB#,%2"1!0 11TU	'	(# !*C3.#,%2"$9	'	(#E 4T *D0%,"
 	
r   r4   c                      y)z2Analyze browser usage to determine work percentageU    )r   r4   s     r   rC   z.RealisticHoursCalculator.analyze_browser_usage   s     r   c                 t   g d}t        |j                               }d}|j                         D ]p  \  }}d|j                         v sd|j                         v r	||dz  z  }3d|j                         v r	||dz  z  }Nd|j                         v r	||dz  z  }i||d	z  z  }r |dkD  rt	        ||z  d
z        S y)z:Analyze 'other' category apps to determine work percentage)zdatagrip64.exezPostman.exezSnippingTool.exezLockApp.exer   datagrippostmang      ?snippingg?lockappg      ?r7   2   )sumvaluesrB   lowerr    )r   r4   work_related_appsr2   	work_timeapptimes          r   rD   z,RealisticHoursCalculator.analyze_other_usage   s    
 '
	ICSYY[(I,DTCZ'	syy{*TCZ'	ciik)TCZ'	TCZ'	 & >	J.#566r   
start_dateend_datec                 j   t               }|j                  dddd      }|j                  dddd      }	 |j                  ||      }i }|D ]2  }|d   j                         }||vrg ||<   ||   j                  |       4 g }	|j                         }
|j                         }|
|k  rd|
|v r||
   }g }|D ]6  } t        d	d
|d   |d   |d   |d   d             }|j                  |       8 | j                  |      }|d   }|d   }| j                  |      }|	j                  |
j                  d      t        |d      t        |d      | j                  |      | j                  |      t        |dkD  r||z  dz  ndd      t        |      |d   |d   |d   |d   |d   |d   d       nH| j                  d      }|	j                  |
j                  d      dddddd|d   |d   |d   ddi d       |
t        d       z  }
|
|k  rd|	S # t        $ r}t	        d|        g cY d}~S d}~ww xY w)!z6Calculate daily hours directly from ActivityWatch datar   hourminutesecondmicrosecond   ;   ?B z#Error fetching ActivityWatch data: N	timestampMockActivityrP   r?   r@   rA   )r?   r@   rA   ri   r/   r0   %Y-%m-%d   r7   r5   r&   r'   r(   r)   r*   r1   dater/   r0   working_hours_formattedtotal_hours_formattedproductivity_percentageactivities_countr&   status_colorstatus_backgroundstatus_messagestatus_iconr1   r.   r   No activity   ⚪days)r   replaceget_activity_data	Exceptionprintrn   appendtyperM   r+   strftimeroundr$   lenr   )r   r^   r_   	aw_clientactivity_dataedaily_activitiesrF   activity_dateresultcurrent_dateend_date_onlyday_activitiesmock_activitiesmock_activity
hours_datar/   r0   status_infos                      r   (calculate_daily_hours_from_activitywatchzARealisticHoursCalculator.calculate_daily_hours_from_activitywatch   s   ')	  ''QqPQ'R
##Brv#V	%77
HMM %H$[1668M$4424 /]+228<	 & !( m+//!1,!? #% .H%D$,Z$8$,Z$8,45G,H%-k%:	> % %M $**=9 !/ "CCOT
 *? ;(7"22=A(11*=%*=!%<#(a#8/3/H/H/W-1-F-F{-S/4\gjk\kmk6QTW6Wqrtu/v(+N(;)(3$/$8)4\)B&1)&<#.v#6!+K!8 " #2215(11*=%(#&/3-1/2())(3$/$8)4\)B&3#(!#   I1--Lq m+t Y  	7s;<I	s   H 	H2H-'H2-H2dbuser_idc                    |j                  dddd      }|j                  dddd      }|j                  t        j                        j	                  t        t        j                  j                  |k(  t        j                  j                  |k\  t        j                  j                  |k              j                  t        j                  j                  j                               j                         }i }|D ]9  }|j                  j                         }||vrg ||<   ||   j                  |       ; g }	|j                         }
|j                         }|
|k  r&|
|v r||
   }| j                  |      }|d   }|d   }| j                  |      }|	j                  |
j                  d      t!        |d	      t!        |d	      | j#                  |      | j#                  |      t!        |dkD  r||z  d
z  ndd      t%        |      |d   |d   |d   |d   |d   |d   d       nH| j                  d      }|	j                  |
j                  d      dddddd|d   |d   |d   ddi d       |
t'        d      z  }
|
|k  r&|	S )z.Calculate realistic working hours for each dayr   ra   rf   rg   rh   r/   r0   rk   rl   r7   r5   r&   r'   r(   r)   r*   r1   rm   r.   r   rw   rx   ry   )r{   querymodelsActivityRecordfilterr   r   ri   order_byascallrn   r   rM   r+   r   r   r$   r   r   )r   r   r   r^   r_   r,   r   rF   r   r   r   r   r   r   r/   r0   r   s                    r   calculate_daily_hoursz.RealisticHoursCalculator.calculate_daily_hours1  s   
  ''QqPQ'R
##Brv#V XXf334;;%%--8%%//:=%%//8;
 (6((22668
9##% 	 "H$..335M$4424 /]+228<	 # !( m+//!1,!?!CCNS
 *? ;(7"22=A(11*=%*=!%<#(a#8/3/H/H/W-1-F-F{-S/4\gjk\kmk6QTW6Wqrtu/v(+N(;)(3$/$8)4\)B&1)&<#.v#6!+K!8 " #2215(11*=%(#&/3-1/2())(3$/$8)4\)B&3#(!#   I1--LW m+Z r   
daily_datac           
      *   |sdddddddddS t        d |D              }t        |D cg c]  }|d   dkD  s| c}      }t        |D cg c]  }|d   dk(  s| c}      }t        |D cg c]  }|d   d	k(  s| c}      }t        |D cg c]  }|d   d
k(  s| c}      }|rt        |d       nd}t        |      ||rt        |t        |      z  d      ndt        |d      ||||r|d   |d   ddS ddS c c}w c c}w c c}w c c}w )z!Calculate summary from daily datar   r.   N)
total_daysworking_daysavg_working_hourstotal_working_hoursdays_above_targetdays_on_trackdays_below_targetbest_dayc              3   &   K   | ]	  }|d      yw)r/   NrP   ).0days     r   	<genexpr>z7RealisticHoursCalculator.get_summary.<locals>.<genexpr>  s     !M*3#o"6*s   r/   r&   r   r   r   c                     | d   S )Nr/   rP   )xs    r   <lambda>z6RealisticHoursCalculator.get_summary.<locals>.<lambda>  s	    ?1Cr   )keyrl   rn   )rn   r   )rW   r   maxr   )	r   r   r   r   r   r   r   r   r   s	            r   get_summaryz$RealisticHoursCalculator.get_summary  s]    !%('*%&!"%& 	 	 "!M*!MM:R:C_9MPQ9QC:RS
 V
c(mv>U
 VWJTJS#h-8:SSJTU
 U
c(mu>T
 UVHR3z'CDX\ j/(T^':S_'La!Pde#()<a#@!2*!2  !(!/2
 	
  $
 	
 S VT Us.   DDDD-D;DDDc                     | j                  ||      }| j                  |      }||| j                  |j                  d      |j                  d      ddS )zFGenerate complete realistic daily hours report from ActivityWatch datark   )startend)r   summaryr   
date_range)r   r   r   r   )r   r   r   r^   r_   r   r   s          r   calculate_daily_reportz/RealisticHoursCalculator.calculate_daily_report  s`     BB:xX
"":. %//#,,Z8((4	
 	
r   N)__name__
__module____qualname__r   floatstrr$   r   r+   r   r   r   rM   r    rC   rD   r   r   r	   r   r   r   rP   r   r   r   r      s(   
4% 4C 4 U t 6s
DAVAV<W s
\` s
j$sEz*: s S%Z(8 S 4W8 WW_ Wdhimdn WrL L# L(0L<DLIMdL\#
d4j #
T #
J
 
3 
)1
=E
JN
r   r   )__doc__r   r   r   typingr   r   r   sqlalchemy.ormr	   
sqlalchemyr
   r   r   my_activitywatch_clientr   r   rP   r   r   <module>r      s0    3 2 ' ' " !  7g
 g
r   