
    i              
       8   U d Z ddlZddlZddlmZmZ ddlmZ ddlm	Z	  ee
      j                  Zg dg dg dg d	g d
dZeeee   f   ed<    ej$                  d      Z ej$                  d      Ze G d d             ZdefdZdedeeef   fdZdedefdZdedefdZd&dede	e   deeee   f   fdZd&dede	e   deeee   f   fdZd'dededefdZe dk(  rdZ! ee!      Z" e#de"jH                           e#de"jJ                           e#d e"jL                           e#d!e"jN                           e#d"e"jP                           e#d#e"jR                   d$e"jT                          e"jV                  r e#d%e"jV                          yyy)(uz  hook_scorer.py — thread-hook-formula 자동 스코어링

5감정 훅 공식 체크리스트를 자동으로 평가한다.
- 분노(anger): "절대 안 됨", "왜 다들", "이러면 안 되는", "문제는", "심각한"
- 놀라움(surprise): "진짜", "실화", "충격", "몰랐", "알고 보니", 비라운드 숫자 패턴
- 공감(empathy): "나도", "겪어본", "공감", "맞아", "그렇지", "이거 아는 사람"
- 두려움(fear): "안 하면", "모르면 손해", "놓치면", "위험", "주의", "잃"
- 호기심(curiosity): "아무도 안 알려주는", "비밀", "알면 소름", "이거 알면", "왜 아무도"
    N)	dataclassfield)Path)Optional)u   절대\s*안\s*됨u   왜\s*다들u   이러면\s*안u	   문제는u	   심각한u   화가\s*나u   분통u	   어이없u   말이\s*안\s*됨u   이게\s*말이\s*됨\?u	   도대체u   한심)	u	   진짜\??u   실화u   충격u   몰랐u   알고\s*보니u   이게\s*되u   놀라u   대박u   헐)	u   나도u   겪어\s*본u   공감u   맞아u	   그렇지u   이거\s*아는\s*사람u   다들\s*그런u   저도u   우리\s*모두)u   안\s*하면u   모르면\s*손해u	   놓치면u   위험u   주의u   잃u   후회u	   늦으면u   빨리\s*안\s*하면u   큰일u   손해)u   아무도\s*안\s*알려u   비밀u   알면\s*소름u   이거\s*알면u   왜\s*아무도u	   숨겨진u   몰래u   진짜\s*이유)angersurpriseempathyfear	curiosityEMOTION_PATTERNSuk   \d{1,3}(,\d{3})+(?!\s*[%원만억천]?\s*(명|건|개|원|만|억|천)?\s*$)|\d+[,.]?\d*(?:명|건|개|원)u!   \b\d+0{2,}\b|약\s*\d+[만억천]c                       e Zd ZU dZ ee      Zeeef   e	d<   dZ
ee	d<   dZee	d<   dZee	d<   dZee	d	<   dZee	d
<    ee      Zee   e	d<   dZee	d<   dZee	d<   dZee	d<   dZee	d<    ee      Zee   e	d<   y)	HookScoreu   스코어링 결과)default_factoryemotions_detectedr   emotion_countFhas_min_emotionshas_non_round_numbershas_round_numbershas_company_mentionmentioned_companiesis_within_length
char_count  
max_lengthpassedfail_reasonsN)__name__
__module____qualname____doc__r   dictr   strbool__annotations__r   intr   r   r   r   listr   r   r   r   r   r        M/home/jay/workspace/.worktrees/task-2116-dev1/content-pipeline/hook_scorer.pyr   r   9   s    ).t)DtCIDM3"d""'4'#t# %%%*4%@c@"d"JJFD#D9L$s)9r(   r   returnc                      t         dz  } | j                         r-t        | dd      5 }t        j                  |      cddd       S g g g dS # 1 sw Y   xY w)u   blacklist.json 로드zblacklist.jsonrzutf-8)encodingN)company_nameskeywordspatterns)PIPELINE_DIRexistsopenjsonload)bl_pathfs     r)   _load_blacklistr8   J   sW    --G~~'31 	 Q99Q<	  	 RR@@	  	 s   AAtextc                 v     i }t         j                         D ]  \  }}t         fd|D              }|||<     |S )u   텍스트에서 5감정 감지c              3   J   K   | ]  }t        j                  |        y wN)research).0pr9   s     r)   	<genexpr>z"detect_emotions.<locals>.<genexpr>W   s     <aryyD)<s    #)r   itemsany)r9   resultemotionr0   detecteds   `    r)   detect_emotionsrG   S   sE     F-335 #<8<<"w# Mr(   c                     t        j                  d|       }|ryt        j                  d|       }|D ]&  }t        |      }|dk\  s|dz  dk7  s|dz  dk7  s& y y)u(   비라운드 숫자 사용 여부 확인z\d{2,3},\d{3}Tz\d+d   
   r   F)r=   r>   findallr%   )r9   specificnumbersnum_strnums        r)   check_non_round_numbersrP   \   sf     yy)40Hjj&G 'l#:#(a-C#IN r(   c                 >    t        t        j                  |             S )u'   라운드 숫자 사용 여부 (경고))r#   ROUND_NUMBER_PATTERNr>   )r9   s    r)   check_round_numbersrS   k   s    $++D122r(   	blacklistc                     |
t               }|j                  dg       }|D cg c]	  }|| v s| }}t        |      |fS c c}w )u"   특정 회사 언급 여부 체크r.   )r8   getr#   )r9   rT   r.   c	mentioneds        r)   check_company_mentionsrY   p   sM    #%	MM/26M)7qQ$Y7I7	?I%% 8s
   	A A c                    |
t               }|j                  dg       }|D cg c]	  }|| v s| }}|j                  dg       D ]-  }t        j                  ||       s|j	                  d|        / t        |      |fS c c}w )u'   블랙리스트 키워드 저촉 여부r/   r0   zpattern:)r8   rV   r=   r>   appendr#   )r9   rT   r/   kfoundpatterns         r)   check_blacklist_keywordsr_   y   s    #%	}}Z,H .1AIQ.E.==R0 /99Wd#LL8G9-./ ; /s
   	BBr   c                 :   t               }t        |      }t        |       |_        t	        d |j                  j                         D              |_        |j                  dk\  |_        t        |       |_	        t        |       |_        t        | |      \  |_        |_        t        |       |_        |j                   |k  |_        g |_        |j                  s)|j$                  j'                  d|j                   d       |j                  r7|j$                  j'                  ddj)                  |j                                |j"                  s,|j$                  j'                  d|j                    d	| d
       t        |j$                        dk(  |_        |S )u   텍스트에 대한 전체 스코어링 수행

    Args:
        text: 스코어링할 텍스트
        max_length: 최대 글자 수 (기본 500)

    Returns:
        HookScore 결과 객체
    )r   c              3   &   K   | ]	  }|sd   yw)   Nr'   )r?   vs     r)   rA   zscore.<locals>.<genexpr>   s     QQqqQs      u   5감정 중 u"   개만 감지 (최소 2개 필요)u   특정 회사 언급: z, u   글자 수 초과: u   자 (최대 u   자)r   )r8   r   rG   r   sumvaluesr   r   rP   r   rS   r   rY   r   r   lenr   r   r   r[   joinr   )r9   r   rT   rD   s       r)   scoreri      s}     !I*-F  /t4FQ&*B*B*I*I*KQQF$22a7F $;4#@F 248F >TTXZc=d:F : D	F$//:=F F""""6//00RS	
 !!""$TYYv/I/I%J$KL	
 """"!&"3"3!4LDQ	
 ++,1FMMr(   __main__u   7월부터 수수료 구조가 완전히 바뀌는데, 아직도 모르는 설계사가 47,382명이나 된다니. 이거 겪어본 사람? 안 하면 진짜 큰일남.u   통과 여부: u   감지된 감정: u   감정 수: u   비라운드 숫자: u   회사 언급: u   글자 수: /u   실패 사유: r<   )r   ),r    r4   r=   dataclassesr   r   pathlibr   typingr   __file__parentr1   r   r!   r"   r&   r$   compileNON_ROUND_NUMBER_PATTERNrR   r   r8   r#   rG   rP   rS   tuplerY   r_   r%   ri   r   samplerD   printr   r   r   r   r   r   r   r   r'   r(   r)   <module>rv      sI    	 (  H~$$

'* $sDI~& 4 &2::'  "rzz( 
 : : : A A# $sDy/ # $ 3c 3d 3
& &$ &5QUW[\_W`Q`Ka &
3 
8D> 
USWY]^aYbSbMc 
. . .y .b z	@  6]F	OFMM?
+,	v778
9:	L--.
/0	!&">">!?
@A	OF667
89	L**+1V->->,?
@A 3 3456  r(   