+
    ]Pîio  ã                  óX   € R t ^ RIHt ^ RIt^ RIHt ^ RIHt  ! R R4      t	]	! 4       t
R# )u#  
services/fraud_service.py â€” FraudDetectionService
Passive background monitoring: tab switches, copy-paste, camera,
multiple faces, inactivity. Runs asynchronously per-candidate.

Face violation rules:
  1st offence â†’ warning
  2nd offence â†’ warning
  3rd offence â†’ disqualify + log
)ÚannotationsN)Úsettings)Újson_dbc                  ó†   € ] tR t^tR R ltRR R lltR R ltR R	 ltR
 R ltR R lt	R R lt
R R ltR R ltRtR# )ÚFraudServicec               ó   € V ^8„  d   QhRR/# )é   ÚreturnÚNone© )Úformats   "Ú;D:\Python_Codes\gen_ai\people_hub\services\fraud_service.pyÚ__annotate__ÚFraudService.__annotate__   s   € ÷ 4ñ 4˜$ñ 4ó    c                	ój   € / V n         / V n        / V n        / V n        / V n        \        4       V n        R # ©N)Ú_tab_switchesÚ_paste_eventsÚ_face_violationsÚ_inactivityÚ_total_violationsÚsetÚ_disqualified)Úselfs   &r   Ú__init__ÚFraudService.__init__   s4   € à.0ˆÔØ.0ˆÔØ02ˆÔØ.0ˆÔØ13ˆÔÜ.1«eˆÖr   Nc               ó4   € V ^8„  d   QhRRRRRRRRRRRR	R
R/# )r   Úcandidate_idÚstrÚ
event_typeÚmessageÚ	timestampÚ	round_numÚintÚmetadatazdict | Noner	   Údictr   )r   s   "r   r   r      sP   € ÷ 8
ñ 8
àð8
ð ð8
ð ð	8
ð
 ð8
ð ð8
ð ð8
ð 
ñ8
r   c              ƒ  óº  "  € WP                   9   d   V P                  V^ RR4      # V P                  W4      G Rj  x€L
 p\        P                  ! \
        P                  RTRTRTRTRTR	TR
T;'       g    / /4       V P                  P                  V^ 4      pVR8X  d   Rp	MV^8¼  d   Rp	MRp	RRRRV RV 2RR/p
RRRVRV	R	VRV
P                  VR4      /#  L�5i)zk
Log a fraud event from the browser FraudDetector class.
Returns action to take: none / warn / disqualify.
Ú
disqualifyz(Candidate has already been disqualified.Nr   r    r!   r"   ÚroundÚactionr%   ÚcriticalÚwarningÚokÚnonezActivity logged.ÚwarnzWarning z: u:   âš  You have been disqualified due to repeated violations.ÚloggedTÚviolation_countÚwarning_levelzLogged.)	r   Ú_make_responseÚ_handle_eventÚdbÚinsertr   ÚFRAUD_LOG_FILEr   Úget)r   r   r    r!   r"   r#   r%   r*   ÚtotalÚlevelÚmsg_maps   &&&&&&&    r   Ú	log_eventÚFraudService.log_event   s   é € ð ×-Ñ-Ô-Ø×&Ñ&Ø˜a Ø:óð ð ×)Ñ)¨,ÓC×Cˆô 	�	Š	”(×)Ñ)Ø˜LØ˜JØ˜GØ˜IØ˜IØ˜FØ˜HŸN˜N¨ð,
ô 	ð ×&Ñ&×*Ñ*¨<¸Ó;ˆð �\Ô!Ø‰EØ�aŒZØ‰EàˆEð Ð-Ø˜X e W¨B¨w¨iÐ8ØÐWð
ˆð ˜tØ˜uØ˜uØ˜vØ˜wŸ{™{¨6°9Ó=ð
ð 	
ñ= Dùs   ‚9C»C¼8CÁ5A%Cc               ó    € V ^8„  d   QhRRRR/# )r   r   r   r	   Úboolr   )r   s   "r   r   r   X   s   € ÷ 2ñ 2¨Cð 2°Dñ 2r   c                	ó   € WP                   9   # r   )r   ©r   r   s   &&r   Úis_disqualifiedÚFraudService.is_disqualifiedX   s   € Ø×1Ñ1Ñ1Ð1r   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r	   r&   r   )r   s   "r   r   r   [   s   € ÷ 	
ñ 	
 sð 	
¨tñ 	
r   c                	ó(  € R VRV P                   P                  V^ 4      RV P                  P                  V^ 4      RV P                  P                  V^ 4      RV P                  P                  V^ 4      RWP
                  9   RV P                  V4      /# )r   Útab_switchesÚpaste_eventsÚface_violationsÚtotal_violationsÚdisqualifiedÚ
risk_score)r   r8   r   r   r   r   Ú
_calc_riskrA   s   &&r   Ú
get_reportÚFraudService.get_report[   s�   € à Ø × 2Ñ 2× 6Ñ 6°|ÀQÓ GØ × 2Ñ 2× 6Ñ 6°|ÀQÓ GØ × 5Ñ 5× 9Ñ 9¸,ÈÓ JØ × 6Ñ 6× :Ñ :¸<ÈÓ KØ ×0BÑ0BÑ BØ §¡°Ó =ð
ð 	
r   c               ó    € V ^8„  d   QhRRRR/# )r   r   r   r	   z
list[dict]r   )r   s   "r   r   r   f   s   € ÷ Pñ P¨3ð P°:ñ Pr   c                	óN   € \         P                  ! \        P                  VR 7      # ))r   )r5   Ú	find_manyr   r7   rA   s   &&r   Úget_all_eventsÚFraudService.get_all_eventsf   s   € Ü�|Š|œH×3Ñ3À,ÔOÐOr   c               ó$   € V ^8„  d   QhRRRRRR/# )r   Úcidr   r    r	   r   )r   s   "r   r   r   k   s!   € ÷ 0ñ 0 sð 0¸ð 0Àñ 0r   c              ƒ  ó  "  € RpVR8X  d¡   V P                   P                  V^ 4      ^,           V P                   V&   V P                   V,          \        P                  8¼  d   RpV P	                  V4       V# RpV P
                  P                  V^ 4      ^,           V P
                  V&    V# VR9   d¡   V P                  P                  V^ 4      ^,           V P                  V&   V P                  V,          \        P                  8¼  d   RpV P	                  V4       V# RpV P
                  P                  V^ 4      ^,           V P
                  V&    V# VR8X  d£   V P                  P                  V^ 4      ^,           V P                  V&   V P                  V,          pV\        P                  8¼  d   RpV P	                  V4       V# RpV P
                  P                  V^ 4      ^,           V P
                  V&    V# VR9   d5   RpV P
                  P                  V^ 4      ^,           V P
                  V&   V# VR8X  d5   RpV P
                  P                  V^ 4      ^,           V P
                  V&   V# VR	9   d   RpV# RpV# 5i)
z'Increment counter and determine action.r.   Ú
TAB_SWITCHr(   r/   ÚMULTIPLE_FACESÚ
INACTIVITY)ÚPASTEÚCOPY)Ú	NO_CAMERAÚCAMERA_LOSTÚNO_MIC)ÚWINDOW_BLURÚSCREEN_CAPTURE)
r   r8   r   ÚFRAUD_MAX_TAB_SWITCHESÚ_disqualifyr   r   ÚFRAUD_MAX_PASTE_EVENTSr   ÚFRAUD_MAX_FACE_VIOLATIONS)r   rU   r    r*   Úcounts   &&&  r   r4   ÚFraudService._handle_eventk   s‡  é € àˆà˜Ô%Ø&*×&8Ñ&8×&<Ñ&<¸SÀ!Ó&DÀqÕ&HˆD×Ñ˜sÑ#Ø×!Ñ! #Õ&¬(×*IÑ*IÔIØ%�Ø× Ñ  Ô%ðP ˆðM  �Ø.2×.DÑ.D×.HÑ.HÈÈaÓ.PÐSTÕ.T�×&Ñ& sÒ+ðJ ˆðG Ð,Ô,Ø&*×&8Ñ&8×&<Ñ&<¸SÀ!Ó&DÀqÕ&HˆD×Ñ˜sÑ#Ø×!Ñ! #Õ&¬(×*IÑ*IÔIØ%�Ø× Ñ  Ô%ð> ˆð;  �Ø.2×.DÑ.D×.HÑ.HÈÈaÓ.PÐSTÕ.T�×&Ñ& sÒ+ð8 ˆð5 Ð+Ô+Ø)-×)>Ñ)>×)BÑ)BÀ3ÈÓ)JÈQÕ)NˆD×!Ñ! #Ñ&Ø×)Ñ)¨#Õ.ˆEØœ×:Ñ:Ô:Ø%�Ø× Ñ  Ô%ð* ˆð%  �Ø.2×.DÑ.D×.HÑ.HÈÈaÓ.PÐSTÕ.T�×&Ñ& sÒ+ð" ˆð ÐAÔAØˆFØ*.×*@Ñ*@×*DÑ*DÀSÈ!Ó*LÈqÕ*PˆD×"Ñ" 3Ñ'ð ˆð ˜<Ô'ØˆFØ*.×*@Ñ*@×*DÑ*DÀSÈ!Ó*LÈqÕ*PˆD×"Ñ" 3Ñ'ð ˆð Ð<Ô<àˆFð
 ˆð ˆFàˆùs   ‚I?Jc               ó    € V ^8„  d   QhRRRR/# )r   rU   r   r	   r
   r   )r   s   "r   r   r   �   s   € ÷ ñ ˜sð  tñ r   c                	óF  € V P                   P                  V4       V P                  P                  V^ 4      ^,           V P                  V&   \        P
                  ! \        P                  RVRRRRR\        P                  ! 4       R^ RR	R
V P                  V4      /4       R# )é    r   r    ÚDISQUALIFIEDr!   z1Candidate auto-disqualified due to max violationsr"   r)   r*   r(   r%   N)
r   Úaddr   r8   r5   r6   r   r7   Únow_isorM   )r   rU   s   &&r   rb   ÚFraudService._disqualify�   sŠ   € Ø×Ñ×Ñ˜sÔ#Ø&*×&<Ñ&<×&@Ñ&@ÀÀaÓ&HÈ1Õ&Lˆ×Ñ˜sÑ#Ü
�	Š	”(×)Ñ)Ø˜CØ˜NØÐOØœBŸJšJ›LØ˜AØ˜LØ˜DŸO™O¨CÓ0ð,
ö 	r   c               ó    € V ^8„  d   QhRRRR/# )r   rU   r   r	   r   )r   s   "r   r   r   ª   s   € ÷ ñ ˜cð  cñ r   c                	ó†   € V P                   P                  V^ 4      pWP                  9   d   R# V^8¼  d   R# V^8¼  d   R# R# )ri   ÚCRITICALÚHIGHÚMEDIUMÚLOW)r   r8   r   )r   rU   r9   s   && r   rL   ÚFraudService._calc_riskª   s@   € Ø×&Ñ&×*Ñ*¨3°Ó2ˆØ×$Ñ$Ô$ÙØ�AŒ:ÙØ�AŒ:ÙÙr   c          
     ó,   € V ^8„  d   QhRRRRRRRRRR/# )	r   rU   r   r9   r$   r*   Úmsgr	   r&   r   )r   s   "r   r   r   ´   s/   € ÷ 
ñ 
 #ð 
¨cð 
¸3ð 
ÀSð 
ÈTñ 
r   c           
     	ó,   € R RRTRVR8X  d   RMRRVRV/# )	r0   Tr1   r2   r(   r+   r,   r*   r!   r   )r   rU   r9   r*   rv   s   &&&&&r   r3   ÚFraudService._make_response´   s.   € à˜tØ˜uØ¨V°|Ô-C™zÈØ˜vØ˜sð
ð 	
r   )r   r   r   r   r   r   )é   N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__r   r<   rB   rM   rR   r4   rb   rL   r3   Ú__static_attributes__r   r   r   r   r      s7   † õ4÷8
õt2õ	
õPõ
0õdõ÷
ñ 
r   r   )Ú__doc__Ú
__future__r   ÚasyncioÚconfigr   Úutilsr   r5   r   Úfraud_servicer   r   r   Ú<module>r…      s.   ðñ	õ #Û Ý Ý ÷j
ñ j
ñZ “‚r   