Ë
    ]Pîio  ã                  óV   — d Z ddlmZ ddlZddlmZ ddlmZ  G d„ d«      Z	 e	«       Z
y)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   — e Z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d	„Z
dd
„Zy)ÚFraudServicec                óh   — i | _         i | _        i | _        i | _        i | _        t        «       | _        y ©N)Ú_tab_switchesÚ_paste_eventsÚ_face_violationsÚ_inactivityÚ_total_violationsÚsetÚ_disqualified)Úselfs    ú_/Users/priyanka/Documents/Gols_Ai_Dev/public_hub_candidate/people_hub/services/fraud_service.pyÚ__init__zFraudService.__init__   s4   € à.0ˆÔØ.0ˆÔØ02ˆÔØ.0ˆÔØ13ˆÔÜ.1«eˆÕó    Nc              ƒ  óŠ  K  — || j                   v r| j                  |ddd«      S | j                  ||«      ƒ d{  –—† }t        j                  t
        j                  |||||||xs i dœ«       | j                  j                  |d«      }|dk(  rd}	n
|dk\  rd}	nd	}	d
d|› d|› �ddœ}
d||	||
j                  |d«      dœS 7 Œ†­w)zƒ
        Log a fraud event from the browser FraudDetector class.
        Returns action to take: none / warn / disqualify.
        r   Ú
disqualifyz(Candidate has already been disqualified.N©Úcandidate_idÚ
event_typeÚmessageÚ	timestampÚroundÚactionÚmetadataÚcriticalé   ÚwarningÚokzActivity logged.zWarning z: u:   âš  You have been disqualified due to repeated violations.)ÚnoneÚwarnr   TzLogged.©ÚloggedÚviolation_countÚwarning_levelr   r   )	r   Ú_make_responseÚ_handle_eventÚdbÚinsertr   ÚFRAUD_LOG_FILEr   Úget)r   r   r   r   r   Ú	round_numr   r   ÚtotalÚlevelÚmsg_maps              r   Ú	log_eventzFraudService.log_event   s  è ø€ ð ˜4×-Ñ-Ñ-Ø×&Ñ&Ø˜a Ø:óð ð ×)Ñ)¨,¸
ÓC×Cˆô 	�	‰	”(×)Ñ)Ø(Ø&Ø#Ø%Ø%Ø"Ø$šN¨ñ,
ô 	ð ×&Ñ&×*Ñ*¨<¸Ó;ˆð �\Ò!Ø‰EØ�aŠZØ‰EàˆEð .Ø% e W¨B¨w¨iÐ8ØWñ
ˆð  $Ø$Ø$Ø%Ø&Ÿ{™{¨6°9Ó=ñ
ð 	
ð= Dús   ‚8CºC»BCc                ó   — || j                   v S r	   )r   ©r   r   s     r   Úis_disqualifiedzFraudService.is_disqualifiedX   s   € Ø˜t×1Ñ1Ð1Ð1r   c           	     ó  — || j                   j                  |d«      | j                  j                  |d«      | j                  j                  |d«      | j                  j                  |d«      || j
                  v | j                  |«      dœS )Nr   )r   Útab_switchesÚpaste_eventsÚface_violationsÚtotal_violationsÚdisqualifiedÚ
risk_score)r
   r.   r   r   r   r   Ú
_calc_riskr5   s     r   Ú
get_reportz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                óL   — t        j                  t        j                  |¬«      S )N)r   )r+   Ú	find_manyr   r-   r5   s     r   Úget_all_eventszFraudService.get_all_eventsf   s   € Ü�|‰|œH×3Ñ3À,ÔOÐOr   c              ƒ  ó~  K  — d}|dk(  r‘| j                   j                  |d«      dz   | j                   |<   | j                   |   t        j                  k\  rd}| j	                  |«       |S d}| j
                  j                  |d«      dz   | j
                  |<   |S |dv r‘| j                  j                  |d«      dz   | j                  |<   | j                  |   t        j                  k\  rd}| j	                  |«       |S d}| j
                  j                  |d«      dz   | j
                  |<   |S |dk(  r“| j                  j                  |d«      dz   | j                  |<   | j                  |   }|t        j                  k\  rd}| j	                  |«       |S d}| j
                  j                  |d«      dz   | j
                  |<   |S |d	v r0d}| j
                  j                  |d«      dz   | j
                  |<   |S |d
k(  r0d}| j
                  j                  |d«      dz   | j
                  |<   |S |dv rd}|S d}|S ­w)z'Increment counter and determine action.r#   Ú
TAB_SWITCHr   é   r   r$   )ÚPASTEÚCOPYÚMULTIPLE_FACES)Ú	NO_CAMERAÚCAMERA_LOSTÚNO_MICÚ
INACTIVITY)ÚWINDOW_BLURÚSCREEN_CAPTURE)
r
   r.   r   ÚFRAUD_MAX_TAB_SWITCHESÚ_disqualifyr   r   ÚFRAUD_MAX_PASTE_EVENTSr   ÚFRAUD_MAX_FACE_VIOLATIONS)r   Úcidr   r   Úcounts        r   r*   z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   ‚H;H=c                ó,  — | j                   j                  |«       | j                  j                  |d«      dz   | j                  |<   t	        j
                  t        j                  |ddt	        j                  «       dd| j                  |«      dœ«       y )Nr   rE   ÚDISQUALIFIEDz1Candidate auto-disqualified due to max violationsr   r   )
r   Úaddr   r.   r+   r,   r   r-   Únow_isor?   )r   rS   s     r   rP   zFraudService._disqualify�   s{   € Ø×Ñ×Ñ˜sÔ#Ø&*×&<Ñ&<×&@Ñ&@ÀÀaÓ&HÈ1Ñ&Lˆ×Ñ˜sÑ#Ü
�	‰	”(×)Ñ)ØØ*ØOÜŸJ™J›LØØ(Ø ŸO™O¨CÓ0ñ,
õ 	r   c                ór   — | j                   j                  |d«      }|| j                  v ry|dk\  ry|dk\  ryy)Nr   ÚCRITICALé   ÚHIGHr    ÚMEDIUMÚLOW)r   r.   r   )r   rS   r0   s      r   r>   zFraudService._calc_riskª   sB   € Ø×&Ñ&×*Ñ*¨3°Ó2ˆØ�$×$Ñ$Ñ$ØØ�AŠ:ØØ�AŠ:ØØr   c                ó    — d||dk(  rdnd||dœS )NTr   r   r!   r%   © )r   rS   r0   r   Úmsgs        r   r)   zFraudService._make_response´   s$   € à#Ø$Ø-3°|Ò-C™zÈØ%Ø"ñ
ð 	
r   )ÚreturnÚNone)rE   N)r   Ústrr   rd   r   rd   r   rd   r/   Úintr   zdict | Nonerb   Údict)r   rd   rb   Úbool)r   rd   rb   rf   )r   rd   rb   z
list[dict])rS   rd   r   rd   rb   rd   )rS   rd   rb   rc   )rS   rd   rb   rd   )
rS   rd   r0   re   r   rd   ra   rd   rb   rf   )Ú__name__Ú
__module__Ú__qualname__r   r3   r6   r?   rB   r*   rP   r>   r)   r`   r   r   r   r      s~   „ ó4ð" Ø $ð8
àð8
ð ð8
ð ð	8
ð
 ð8
ð ð8
ð ð8
ð 
ó8
ót2ó	
óPó
0ódóô
r   r   )Ú__doc__Ú
__future__r   ÚasyncioÚconfigr   Úutilsr   r+   r   Úfraud_servicer`   r   r   Ú<module>rq      s.   ðñ	õ #Û Ý Ý ÷j
ñ j
ñZ “�r   