
    ChR                       d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlZd dl	m
Z
mZmZmZmZ d dlZd dlmZ ej                            ej                            ej                            e          d                    Zeej        vrej                            e           d dlmZ  ej        dd                                          Z ej        ed	
            ej        d          Z dZ!dZ" ej#        e"d           dPdZ$dQdZ%dRdZ&dSdZ'dTdZ(dUdZ)dVd!Z*dWd#Z+dXd&Z,dYdZd*Z-d[d-Z.d\d]d4Z/d^d:Z0d; Z1d_d@Z2d`dCZ3dadFZ4	 dbdcdMZ5dN Z6e7dOk    r e6             dS dS )d    )annotationsN)AnyDictListOptionalTuple)	PdfReaderz..
get_client	LOG_LEVELINFOz[%(levelname)s] %(message)s)levelformatkepco_history_collectz$https://alio.go.kr/download/pdf.jsonz/var/www/html/bot/tmp/alioT)exist_oksOptional[str]returnstrc                    | sdS |                      dd          } |                      dd          } t          j        dd|           } t          j        dd|           } |                                 S )N      z[ \t]+z
[ ]*\n[ ]*
)replaceresubstrip)r   s    2/var/www/html/bot/scripts/kepco_history_collect.py	normalizer!      sf    RR			$A			(C  A
y#q!!A
}dA&&A7799    texts	List[str]c                    d                     d | D                       }t          j        dd|          }|                                S )Nr   c                0    g | ]}|t          |          S  )r!   ).0ts     r    
<listcomp>z$merge_page_texts.<locals>.<listcomp>!   s#    999q9	!999r"   z\n{2,})joinr   r   r   )r#   joineds     r    merge_page_textsr-       sC    YY99e999::FVItV,,F<<>>r"   patc                    t          j        | |t           j                  }|r'|                    d                                          nd S )N)flags   )r   search	MULTILINEgroupr   )r.   r   ms      r    pickr6   %   s@    
	#q---A!",1771::,r"   boolc                    | sdS t          j        dd|                                           }|dv pt          j        d|          d uS )NT\s+r   >      –   —-u   (미정|무기한))r   r   r   r2   )r   vs     r    is_blank_dater>   )   sO    TT
vr1##%%A##Vry1F'J'JRV'VVr"   krc                "   | sd S t          j        d|           }|sd S t          |                    d                    t          |                    d                    t          |                    d                    }}}|dd|dd|dS )Nu1   (\d{4})\s*년\s*(\d{1,2})\s*월\s*(\d{1,2})\s*일r1         04dr<   02dr   r2   intr4   )r?   r5   ymods        r    to_iso_from_krrJ   .   s    dd
	FKKATT1771::AGGAJJQWWQZZ1rA&&&b&&&q&&&&r"   dotc                "   | sd S t          j        d|           }|sd S t          |                    d                    t          |                    d                    t          |                    d                    }}}|dd|dd|dS Nz(\d{4})\.(\d{1,2})\.(\d{1,2})r1   rA   rB   rC   r<   rD   rE   rK   r5   rG   rH   rI   s        r    to_iso_from_dotsrO   5   s    tt
	2C88ATT1771::AGGAJJQWWQZZ1rA&&&b&&&q&&&&r"   merged_textc                    t          j        d|           }|r'|                    d                                          nd S )Nu-   임원\s*현황\s*\n([^\n]+)\n임원\s*현황r1   )r   r2   r4   r   )rP   r5   s     r    extract_department_from_headerrR   <   s:    
	BKPPA!",1771::,r"   bodyc                D    g t          j        d           D ])}                    |                                           *sg S                     t	                                 fdt          t	                    dz
            D             }d |D             S )Nu   (?m)^\s*직위\bc                f    g | ]-}|         |d z                                                      .S )r1   r   )r(   irS   idxss     r    r*   z/_split_sections_by_position.<locals>.<listcomp>I   s;    LLLAT!WT!A#Y&'--//LLLr"   r1   c                <    g | ]}|                     d           |S )   직위)
startswith)r(   r   s     r    r*   z/_split_sections_by_position.<locals>.<listcomp>J   s)    :::!1<<#9#9:A:::r"   )r   finditerappendstartlenrange)rS   r5   sectionsrX   s   `  @r    _split_sections_by_positionrb   B   s    D[,d33  AGGII 	KKD		LLLLLs4yy{9K9KLLLH::x::::r"   sec#Tuple[Optional[str], Optional[str]]c                "   t          j        d|           }|r|                    d                                          |                    d                                          }}t	          |          rd nt          j        dd|          }t	          |          rd nt          j        dd|          }||fS t          j        d|           }|r|                    d                                          |                    d                                          }}t	          |          rd nt          j        dd|          }t	          |          rd nt          j        dd|          }||fS t          j        d|           }|r|                    d                                          |                    d                                          }}t	          |          rd nt          j        dd|          }t	          |          rd nt          j        dd|          }||fS t          j        d|           }|rR|                    d                                          }t	          |          rd nt          j        dd|          }|d fS d	S )
NuG   임기\s*\(시작일\)\s*([^\n(]+?)\s*\(종료일\)\s*([^\n]+?)(?:\n|$)r1   rA   r9   r   uW   임기\s*시작(?:일)?\s*[:：]?\s*([^\n]+?)[\s,/]*종료(?:일)?\s*[:：]?\s*([^\n]+)u>   임기\s*[:：]?\s*([^\n~\-–—]+?)\s*[~\-–—]\s*([^\n]+)u1   임기\s*(?:시작(?:일)?)?\s*[:：]?\s*([^\n]+)NN)r   r2   r4   r   r>   r   )rc   r5   s_rawe_raws_vale_vals         r    _parse_term_blockrk   L   sP   
	\^abbA wwqzz''))1771::+;+;+=+=u%e,,L"&e2L2L%e,,L"&e2L2Le|
	lnqrrA wwqzz''))1771::+;+;+=+=u%e,,L"&e2L2L%e,,L"&e2L2Le|
	SUXYYA wwqzz''))1771::+;+;+=+=u%e,,L"&e2L2L%e,,L"&e2L2Le|
	FLLA 

  ""%e,,L"&e2L2Ld{:r"   department_hint
debug_discList[Dict[str, Any]]c                "   |pt          |           }|                     d          }|dk    r
| |d          n| }t          |          }|s|rt                              d|           g S g }|D ] }t          |          }	|	                    d          sd|	v rt          j        d|	          sAt          d|	          }
t          d|	          }t          d	|	          }t          d
|	          }dd} ||
          dv s ||          dv rt          |	          \  }}t          d|	          }d }|r8d t          j        d|          D             }|rd                    |          nd }|s|                    |||
|||||d           "|S )NrZ   r   u'   [parse][%s] no '직위' sections found.u   직위 변경 전u   변경사유u   (임기|직책|성별)\suA   직위\s*[:：]?\s*([^\n]+?)\s*(?:성명|직책|성별|임기|\n)u>   성명\s*[:：]?\s*([^\n]+?)(?=\s*(?:직책|성별|임기|\n))u7   직책\s*[:：]?\s*([^\n]+?)(?=\s*(?:성별|임기|\n))u   성별\s*[:：]?\s*([남여])xr   r   r   c                2    | pd                     dd          S )Nr   r   )r   )rp   s    r    tokzparse_people.<locals>.tok~   s    !'r1B1B31K1K*Kr"   >   	   변경전rZ   >      성명	   변경후u   주요경력\s*([\s\S]*?)(?=\n\s*(?:선임\s*절차|선임절차|선임\s*절차\s*규정|선임절차규정|당연직여부|직위\s|기준일|제출일|기관\s*공시\s*담당자|$))c                ^    g | ]*}|                                 |                                 +S r'   rV   r(   lns     r    r*   z parse_people.<locals>.<listcomp>   s-    WWWBBHHJJWRXXZZWWWr"   z\n+r   )
departmentnamepositiontaskgenderr^   endcareer)rp   r   r   r   )rR   findrb   loggerdebugr!   r[   r   r2   r6   rk   splitr+   r]   )rP   rl   rm   ry   	start_idxrS   ra   outrawrc   r{   rz   r|   r}   rr   r^   r~   career_blockr   liness                       r    parse_peopler   f   s    O$B;$O$OJ  **I&/1nn;yzz""+D*400H  	PLLBJOOO	 "C ' 'nn >>-.. 	>S3H3HQSQZ[vx{Q|Q|3H\^abbY[^__RTWXX8#>>KKKK3x==222cc$iiCY6Y6Y&s++
s I
 
 !% 	9WW"(6<*H*HWWWE).8TYYu%%%DF 	

$ 	
 	
 		 		 		 		 Jr"   posted_at_dotDict[Tuple[str, str], str]c           	        dd}d}t          j        d|           }|rt          j        dd|                    d	                    }t          j        d
|          }|rmt	          |                    d	                    ddt	          |                    d                    ddt	          |                    d                    d}|s ||          }t          j        d|           }|si S |                    d          }i }	d}
t          j        d|
 d|
 dt           j                  }|                    |          D ]}|                    d                                          }|                    d                                          }|                    d                                          }|dv rdn|}|dv rdn|}|dk    r	|r||	||f<   |	S )u  
    변경표 블록에서 '직위  변경전성명  변경후성명  변경사유' 라인들을 안전하게 파싱.
    - 이름은 한글 2~4자 또는 '(공석)'/'공석'으로만 인정
    - 공백/탭/다중 스페이스 모두 허용
    - 사유에 붙은 조사(…에/…으로/…따른 등)는 전부 무시
    반환: {(position, prev_name) -> actual_end(YYYY-MM-DD)}
    rK   r   r   c                "   | sd S t          j        d|           }|sd S t          |                    d                    t          |                    d                    t          |                    d                    }}}|dd|dd|dS rM   rE   rN   s        r    rO   z'parse_changes.<locals>.to_iso_from_dots   s    44I6<<qwwqzz??C

OOS__q2***"***1****r"   NuB   기준일\s*([0-9]{4}\s*년\s*[0-9]{1,2}\s*월\s*[0-9]{1,2}\s*일)r9   r   r1   u"   (\d{4})년(\d{1,2})월(\d{1,2})일rC   r<   rA   rD   rB   u   (?:^|\n)\s*직위\s*변경\s*전\s*성명\s*변경\s*후\s*성명\s*변경사유\s*\n(?P<body>[\s\S]*?)(?=\n\s*직위\s+(?:상임|비상임|상임기관장|상임감사|상임이사|비상임이사)|\Z)rS   u$   (?:[가-힣]{2,4}|\(공석\)|공석)z^\s*(?P<pos>\S+)\s+(?P<prev>z)\s+(?P<next>z)\s+(?P<reason>.+?)\s*$posprevnext>      (공석)   공석r   rK   r   r   r   )	r   r2   r   r4   rF   compiler3   r\   r   )rP   r   rO   baser5   ymdm2blkrS   actual_end_mapNAMEline_rer   r   nxt	prev_norm	next_norms                    r    parse_changesr      s   + + + + D
	WYdeeA ^fVR,,Y<cBB]RXXa[[))]]]BHHQKK0@0@]]]s288TU;;GWGW]]]t /.. ) 	V C  	99VD13N 3DjXXX4XXX
 G
 d## 4 4$$&&%%''%%'' !%(> > >HHD	 #(> > >HHC	   T /3NC+,r"   Fsessionrequests.Sessiondiscr   Dict[str, Any]c                   t           j                            t          | d          }t           j                            |          r>t          |dd          5 }t          j        |          cd d d            S # 1 swxY w Y   |                     t          d|id          }|
                                 |j        }t           j                            t          | d          }t          |d	          5 }|                    |           d d d            n# 1 swxY w Y   g }	 t          |          }	|	j        D ]A}
	 |
                                pd
}n# t           $ r d
}Y nw xY w|                    |           Bn3# t           $ r&}t$                              d||           Y d }~nd }~ww xY wt)          |          }|t+          |          d t-          |          D             |d}t          |dd          5 }t          j        ||dd           d d d            n# 1 swxY w Y   |r7t$                              d|t+          |          t+          |                     |S )Nz.jsonrutf-8)encodingdisclosureNo<   )paramstimeoutz.pdfwbr   z#[WARN] PdfReader failed disc=%s: %sc                $    g | ]\  }}|d z   |dS )r1   )pagetextr'   )r(   rW   r)   s      r    r*   z(ensure_json_for_disc.<locals>.<listcomp>   s(    NNNca!A#q11NNNr"   )r   
page_countpagesmergedwFrA   )ensure_asciiindentz%[disc=%s] page_count=%d merged_len=%d)ospathr+   TMP_DIRexistsopenjsonloadgetPDF_JSON_URLraise_for_statuscontentwriter	   r   extract_text	Exceptionr]   r   warningr-   r_   	enumeratedumpr   )r   r   r   	json_pathfr   	pdf_bytespdf_pathr#   readerr   r)   er   payloads                  r    ensure_json_for_discr      s8   Wnnn55I	w~~i    )S7333 	 q9Q<<	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	  	L.$)?LLA	Iw||G]]]33H	h		 		               E	G8$$L 	 	D%%''-2   LLOOOO	  G G G<dAFFFFFFFFG e$$F#3u::NNYu=M=MNNN! !G 
iw	/	/	/ <1	'15;;;;< < < < < < < < < < < < < < < ]<dCJJPSTZP[P[\\\Nsr   A;;A?A?8DD!D(F EF E'$F &E''F 
F1F,,F1 H%%H),H)deptrz   roler^   r~   c                    |  d| d| d|pd d|pd d|pd }t          j        |                    d                                                    S )Nz::r   r   )hashlibmd5encode	hexdigest)r   r   rz   r   r^   r~   r   s          r    make_idr      si    NNdNNdNNdjbNNEKRNN39"NND;t{{7++,,66888r"   c                     t                      S Nr
   r'   r"   r    sbr     s    <<r"   	src_table	only_dept	only_discOptional[List[str]]c                *   t                                          |                               d                              d          }|r|                    d|          }|r|                    d|          }|                                }|j        pg S )Nz(department,disclosure_no,posted_at,titlei ry   disclosure_no)r   tableselectlimiteqin_executedata)r   r   r   qress        r    fetch_sourcesr     s     	

9$$%OPPVVW]^^A *DDy)) .EE/9--
))++C8>rr"   	out_tablerowsc                   |sd S t                      }	 |                    |                               |d                                           d S # t          $ r"}t          |          }d|v rhd|v rdt                              d|            d |D             }|                    |                               |d                                           nt                              d|           d}t          d	t          |          |          D ]`}||||z            }	 |                    |           
                    |                                           K# t          $ r Y Ww xY wY d }~d S Y d }~d S d }~ww xY w)
Nid)on_conflictcolumn
actual_endz5[WARN] '%s' has no 'actual_end'. retrying without it.c                J    g | ] }d  |                                 D             !S )c                &    i | ]\  }}|d k    ||S )r   r'   )r(   kr=   s      r    
<dictcomp>z*upsert_rows.<locals>.<listcomp>.<dictcomp>  s(    DDDca!|2C2Ca2C2C2Cr"   )items)r(   r   s     r    r*   zupsert_rows.<locals>.<listcomp>  s/    SSSDDQWWYYDDDSSSr"   z?[WARN] upsert failed (%s). fallback to insert-ignore by chunks.i  r   )r   r   upsertr   r   r   r   r   r`   r_   insert)	r   r   clientr   msgrows2CHUNKrW   parts	            r    upsert_rowsr     s   TTFY&&t&>>FFHHHHH   !ffs??|s22NNRT]^^^SSdSSSELL##**5d*CCKKMMMM NN\^abbbE1c$ii//  AagILL++22488@@BBBB    D NMMMMM
     s<   <A E?CE:#:EE:
E+(E:*E++E::E?valr   c                   | dS t          |                                           }|sdS |                    d          r|                    d          s*|                    d          r:|                    d          r%	 t	          j        |          S # t          $ r Y nw xY wd |                    d          D             }|r|ndS )u   
    kepco_history.career 가 jsonb 인 경우 대비:
    - 줄바꿈 텍스트면 라인 배열로 변환
    - 이미 JSON 텍스트면 파싱 시도
    - 없으면 None
    N[]{}c                ^    g | ]*}|                                 |                                 +S r'   rV   rw   s     r    r*   z#_jsonify_career.<locals>.<listcomp>9  s-    >>>B288::>RXXZZ>>>r"   r   )r   r   r[   endswithr   loadsr   r   )r   r   r   s      r    _jsonify_careerr  (  s     {44CATT	S ajjoo 1<<3D3D TW 	:a==  	 	 	D	 ?>!''$-->>>E#55t#s   ?B 
B B ry   	prev_namer{   actual_end_isostarts_in_current_pdfrF   c           	        |sdS |r!d}t          t          |                    D ]}|                                }|s	 |                     d                              d|i                              d|                              d|                              d|                              dd                                           |dz  }t          	                    d	||||           # t          $ r(}t                              d
||||           Y d}~d}~ww xY w|r|S 	 |                     d                              d                              d|                              d|                              dd          }	|	                                }
|
j        pg }n5# t          $ r(}t                              d|||           Y d}~dS d}~ww xY w|st          	                    d||           dS rfd|D             }|r|}t          |          dk    rK|                    d d           t                              dt          |          ||           |d         g}	 |d         d         }|                     d                              d|i                              d|                                           t          	                    d||||           dS # t          $ r@}t                              d|d                             d          |           Y d}~dS d}~ww xY w)u  
    실제 종료일(= actual_end_iso)을 과거 열(미종료행)에 UPDATE.
    우선순위:
      1) (dept, name, start in starts_in_current_pdf, actual_end IS NULL)
      2) (dept, name, position, actual_end IS NULL)
      3) (dept, name, actual_end IS NULL) 중 최신 1건
    r   kepco_historyr   ry   rz   r^   nullr1   u*   [actual_end][by start] %s ← (%s, %s, %s)z)[actual_end][by start][fail] %s/%s/%s: %sNzAid, department, name, position, start, end, posted_at, actual_endz#[actual_end][query][fail] %s/%s: %sz/[actual_end][skip] open row not found for %s/%sc                    g | ]E}|                     d           pd                                pd                                k    C|FS )r{   r   )r   r   )r(   r   r{   s     r    r*   z.update_actual_end_for_prev.<locals>.<listcomp>v  sQ    eee!j(9(9(?R'F'F'H'HX^Y[LbLbLdLd'd'dA'd'd'dr"   c                ^    |                      d          pd|                      d          pdfS )N	posted_atr   r^   r   r   s    r    <lambda>z,update_actual_end_for_prev.<locals>.<lambda>|  s+    {!3!3!9r155>>;OR P r"   T)keyreversez=[actual_end][multi] %d candidates; pick most recent for %s/%sr   u.   [actual_end][by fallback] %s ← id=%s (%s/%s)z$[actual_end][update][fail] id=%s: %s)sortedsetr   r   updater   is_r   r   infor   r   r   r   r_   sortr   )r   ry   r  r{   r	  r
  hitstr   r   r   r   narrowed	target_ids      `          r    update_actual_end_for_prevr   =  s{     q  23344 	j 	jBB jo..&,788"\:.."VY''"Wb//#lF++')))qH.Zdfoqstttt j j jJJXaceghiiiiiiiij 	J
\\/**fXYYbz**b##c,''	 	

 iikkx~2   <j)UVWWWqqqqq  EzS\]]]q  eeeeteee 	D 4yy1}}		PPZ^	___VX[\`XaXacmoxyyyQy
GDM		o	&	&
&,/
0
0
"T9


')))DnV_akmvwwwq   =tAw{{4?P?PRSTTTqqqqqsK   B/C11
D#;DD#+BF- -
G7GG5A<K3 3
L==5L88L=c                 n   t          j        d          } |                     dd           |                     dd           |                     dt          dd	
           |                     dt          dd
           |                     dt          d            |                     dt          d            |                                 }|j        r$t                              t          j	                   |j
        r$d |j
                            d          D             nd }t          |j        |j        |          }|                    d            t!          j                    }|j                            ddi           g }t)                      }|D ]}|                    d          pd}|                    d          pd}	|                    d          pd}
|                    d          pd}|	r|sd	 t-          ||	|j                  }|                    d          pd}t/          |||	          }t1          ||
          }i }|D ]}|                    d           pd                                }|                    d!          pd                                }|r+|r)|                    |g                               |           |D ]}|d"         |d#         k    r|                    d$          r|                    |d"                   }|j        sDt;          |||d"         |                    d%          t=          |
          p|d$         |&           t                              d'|d$         ||d"         |           |D ]Y}|                    d(          p|                    d%          pd                                pd }tA          |	||                    d           pd||                    d!          |                    d)                    }t=          |
          p|
}|||                    d           |                    d%          |                    d(          |                    d*          |                    d!          |                    d)          d tC          |                    d+                    |d d,}|                    |           [W# tD          $ r'}t          #                    d-|	|           Y d }~d }~ww xY wt                              d.tI          |          |j%                   |j        stM          |j%        |           t                              d/           tO          |j%        |j        rd0ntI          |          d1           d S )2NzhBuild kepco_history from kepco_id PDFs (insert current roster + update past actual_end via change table))descriptionz--debug
store_true)actionz	--dry-runz--srckepco_id_testz%source table (default: kepco_id_test))typedefaulthelpz--outr  z%target table (default: kepco_history)z--only-dept)r&  r'  z--only-discc                6    g | ]}|                                 S r'   rV   )r(   rp   s     r    r*   zmain.<locals>.<listcomp>  s     CCCAaggiiCCCr"   ,c                    |                      d          pd|                      d          pd|                      d          pdfS )Nr  r   ry   r   r  r  s    r    r  zmain.<locals>.<lambda>  sF    {!3!3!9r155;N;N;TRTVWV[V[\kVlVlVrpr s r"   )r  z
User-Agentz*GovBot/1.0 (+https://work.jjickjjicks.com)ry   r   r   r  title)r   r   )rl   rm   )r   rz   r^   r  	next_namer   r{   )r
  z3[DRY] would set actual_end=%s for %s/%s (starts=%s)r|   r~   r}   r   )r   ry   rz   r{   r|   r}   r^   r~   r   r   r  pdf_urlz[WARN] disc=%s parse failed: %sz"ready to write rows: %d (table=%s)zdone.r   )targetinserted_or_upserted)(argparseArgumentParseradd_argumentr   
parse_argsr   r   setLevelloggingDEBUGr   r   r   srcr   r  requestsSessionheadersr  r   r   r   r   r   r   
setdefaultr]   dry_runr   rO   r  r   r  r   r   r_   r   r   print)pargsonly_disc_listsrc_rowsr   out_rowsr   r   r   r   r  r,  pjr   peoplechangesstarts_by_namepinfonmr  chstarts_for_prevr   row_id
posted_isorowr   s                              r    mainrO    s     -W  	X  	X  	XANN9\N222NN;|N444NN7oDkNlllNN7oDkNlllNN=sDN999NN=sDN999<<>>Dz '&&&GK~_CC)=)=c)B)BCCCC[_NTXt~~FFHMMssMttt  GOL*VWXXX%'HTTF CG CGEE,''-2EE/**0bEE+&&,"	EE'NN(b 	4 	;	G%gt4:FFFBVVH%%+F "&$4PPPF $F)DDDG 46N A Aii''-24466ii((.B5577 A" A"--b"55<<R@@@  ^ ^k?bo55"&&:N:N5&4&8&8K&I&IO< ^2"D"[/266*;M;M,Y77K2l;K2A     $Y$&|$4dB{O_^ ^ ^   % %		&))HUYYz-B-BHbOOQQYUY tUYYv->->-D"dEIIV]L^L^`e`i`ijo`p`pqq .i88EI

 !"&!IIf-- %		* 5 5!IIf--#ii11"YYw// 99U++"&-eii.A.ABB!+#  $$$$/%2  	G 	G 	GNN<dAFFFFFFFF	G KK4c(mmTXNNN< (DHh'''
KK	TXDL7[qqcRZmm
\
\]]]]]s   >K0S00
T!:TT!__main__)r   r   r   r   )r#   r$   r   r   )r.   r   r   r   r   r   )r   r   r   r7   )r?   r   r   r   r   )rP   r   r   r   )rS   r   r   r$   )rc   r   r   rd   rf   )rP   r   rl   r   rm   r   r   rn   )rP   r   r   r   r   r   )F)r   r   r   r   r   r7   r   r   )r   r   r   r   rz   r   r   r   r^   r   r~   r   r   r   )r   r   r   r   r   r   r   rn   )r   r   r   rn   )r   r   r   r   r   )ry   r   r  r   r{   r   r	  r   r
  r   r   rF   )8
__future__r   r   sysr   r   r1  r6  r   typingr   r   r   r   r   r9  pypdfr	   r   abspathr+   dirname__file__ROOT_DIRr]   app.services.supabase_servicer   getenvupperr   basicConfig	getLoggerr   r   r   makedirsr!   r-   r6   r>   rJ   rO   rR   rb   rk   r   r   r   r   r   r   r   r  r   rO  __name__r'   r"   r    <module>r`     sB   " " " " " " 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 3 3 3 3 3 3 3 3 3 3 3 3 3 3        7??27<<(A(A4HHII38HOOH 4 4 4 4 4 4BIk6**0022	  ),I J J J J		2	3	35
& Gd # # # #      
- - - -W W W W
' ' ' '' ' ' '- - - -; ; ; ;   44 4 4 4 4p: : : :z! ! ! ! !F9 9 9 9
  	 	 	 	   .$ $ $ $4 MQN N N N Nbb^ b^ b^H zDFFFFF r"   