
    jK'                       U d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	 ddl
mZ ddlmZ ddlmZmZmZmZmZmZmZ  ej,                  d	ej.                        Zd
ed<    ej,                  dej.                        Zd
ed<    ej,                  dej.                        Zd
ed<    ej,                  dej.                  ej8                  z        Zd
ed<    ej,                  dej.                        Zd
ed<    ej,                  dej.                        Zd
ed<    ej,                  dej.                        Z d
ed<    e	dd       G d d             Z! G d d      Z"y)zMDeterministically extract permitted metrics from immutable check-in Markdown.    )annotationsN)defaultdict)	dataclass)Path)Final)BaselineBaselineEntryCanonicalDayCoverageDuplicateDayReconciliationSourceRecordu2   ^##\s+D\+(\d+)\s+—\s+(\d{4}-\d{2}-\d{2})(?:\s|$)zFinal[re.Pattern[str]]HEADINGuU   ^\s*-\s+(?:\*\*)?아침\s*공복\s*체중\s*[:：]?(?:\*\*)?\s*(\d+(?:\.\d+)?)\s*kg\bWEIGHTuG   ^\s*-\s+(?:\*\*)?수면\s*[:：]?(?:\*\*)?\s*(\d+(?:\.\d+)?)\s*시간\bSLEEPuV   ^\s*-\s+(?:\*\*)?전날\s*총섭취\s*칼로리\s*[:：]?(?:\*\*)?\s*([\d,]+)\s*kcal\bCALORIESu?   ^\s*-\s+(?:\*\*)?소화\s*상태\s*[:：]?(?:\*\*)?\s*([012])\b	DIGESTIONu;   ^\s*-\s+(?:\*\*)?오늘\s*운동\s*[:：]?(?:\*\*)?\s*(.+)$TRAININGzu^\|\s*(\d{1,3})\s*\|\s*(\d{4}-\d{2}-\d{2})\s*\|\s*([^\n|]+)\|\s*([^\n|]+)\|\s*([^\n|]+)\|\s*([^\n|]+)\|\s*([^\n|]+)\|	TABLE_ROWT)frozenslotsc                  .    e Zd ZU dZded<   edd       Zy)SourceInventoryzFVerified immutable sources permitted to enter the historical importer.ztuple[SourceRecord, ...]sourcesc                j   t        j                  |j                  d            }t        d |d   D              }|D ]m  }t	        j
                  t        |j                        j                               j                         }||j
                  k7  sWt        d|j                           | |      S )z?Load and verify the three explicit attachment paths and hashes.utf-8encodingc           	   3  ~   K   | ]5  }t        t        |d          t        |d         t        |d                7 yw)source_pathsha256	day_rangeN)r   str.0items     m/home/cube/projects/richard/.worktrees/nutricoach-v140-impl/dualcoach/profile/checkin_cli/history_baseline.py	<genexpr>z0SourceInventory.from_manifest.<locals>.<genexpr>+   sH       H  yGptSm)<%=s4>?RTWX\]hXiTjk  yGs   ;=r   z+immutable historical source hash mismatch: )jsonloads	read_texttuplehashlibr!   r   r    
read_bytes	hexdigestRuntimeError)clsmanifest_pathrawrecordsrecordactuals         r'   from_manifestzSourceInventory.from_manifest'   s     jj00'0BC  Hx{  }F  yG  H  HF^^D););$<$G$G$IJTTVF&"%PQWQcQcPd#eff  7|    N)r2   r   returnr   )__name__
__module____qualname____doc____annotations__classmethodr7    r8   r'   r   r   !   s    P%% r8   r   c                  J    e Zd ZW  dZddZddZddZddZddZe	dd       Z
e	dd       Ze	dd	       Ze	dd
       Ze	dd       Ze	d d       Ze	d!d       Ze	d"d       Ze	dd       Ze	d#d       Ze	  fd              Ze	d$d       Ze	d%d       Ze	d&d       Z Zy)'HistoryBaselineParserzOParse only explicitly labelled numeric fields and normalized status categories.c                    || _         y N)
_inventory)self	inventorys     r'   __init__zHistoryBaselineParser.__init__6   s	    #r8   c           	         t         fd j                  j                  D              }t        t              |D ]   }|j
                     j                  |       " t         fdt              D              } j                  |      }t        t         fdt        j                               D                    }t        |||      S )zGDerive canonical daily entries, coverage, and duplicate reconciliation.c              3  N   K   | ]  }j                  |      D ]  }|   y wrD   )_source_candidates)r%   source	candidaterF   s      r'   r(   z.HistoryBaselineParser.parse.<locals>.<genexpr>;   s*     |3J\`\s\stz\{y9\{93Js   "%c              3  F   K   | ]  }j                  |           y wrD   )_select)r%   daygroupedrF   s     r'   r(   z.HistoryBaselineParser.parse.<locals>.<genexpr>?   s     NosWS\2os   !c              3  f   K   | ](  \  }}t        |      d kD  sj                  ||       * yw)   N)len_duplicates)r%   rP   itemsrF   s      r'   r(   z.HistoryBaselineParser.parse.<locals>.<genexpr>A   sH       .H]tzsTYx{  }B  yC  FG  yGd.>.>sE.J]ts   11)r,   rE   r   r   listrP   appendsorted	_coverager   rV   r   )rF   
candidatesrM   entriescoveragereconciliationrQ   s   `     @r'   parsezHistoryBaselineParser.parse9   s    |4??3J3J||
;Ft;L#IIMM")))4 $NfWoNN>>'*'  .H]cdkdqdqds]t  .H  )H  I>::r8   c                   t        |j                        j                  d      }t        t        j                  |            }t        |      D cg c]Y  \  }}| j                  ||||j                         |dz   t        |      k  r||dz      j                         n
t        |             [ }}}|j                  | j                  ||             t        |      S c c}}w )Nr   r   rS   )r   r    r+   r,   r   finditer	enumerate_section_entryendrT   startextend_table_entries)rF   rL   contentheadingsindexmatchr\   s          r'   rK   z(HistoryBaselineParser._source_candidatesD   s   v))*44g4F))'23 nw  x@  nA  B  nA  ^j  ^c  ej4&&vugeiikkpstktwz  |D  xE  lEHUZ]^U^L_LeLeLg  KN  OV  KW  7X  Y  nA  Bt**67;<W~ Bs   ACc                   t        t        |j                  d                  |j                  d      }}t        |||j                  |j
                  d| d| | j                  t        |      | j                  t        |      | j                  t        |      | j                  |      | j                  |      | j                  |            S )NrS      D+@)r
   intgroupr	   r    r!   _numberr   r   _integerr   	_training
_digestion_pain)rF   rL   rk   sectionrP   recorded_dates         r'   rc   z$HistoryBaselineParser._section_entryK   s6   )#ekk!n*=>A]S-1C1CV]]VXY\X]]^_l^mTnptp|p|  ~D  FM  qN  PT  P\  P\  ]b  dk  Pl  nr  n{  n{  |D  FM  nN  PT  P^  P^  _f  Pg  im  ix  ix  y@  iA  CG  CM  CM  NU  CV  W  	Wr8   c                   g }t         j                  |      D ]$  }t        t        |j	                  d                  |j	                  d      }}| j                  |j	                  d            }| j                  |j	                  d      j                  d      d         }| j                  |j	                  d            }	|j                  t        |||j                  |j                  d| d	| d
|||	| j                  |j	                  d            | j                  |j	                  d            d             ' t        |      S )NrS   rm         /r      rn   ro   :table      r@   )r   ra   r
   rp   rq   _plain_numbersplit_plain_integerrX   r	   r    r!   _training_text_digestion_textr,   )
rF   rL   rh   r\   rk   rP   rx   weightsleepcaloriess
             r'   rg   z$HistoryBaselineParser._table_entriesO   s   ')''0E!-c%++a..A!BEKKPQNC''A7F&&u{{1~';';C'@'CDE**5;;q>:HNN=mV=O=OQWQ^Q^bdehdiijkxjyy  aA  CI  KP  RZ  \`  \o  \o  pu  p{  p{  |}  p~  \  AE  AU  AU  V[  Va  Va  bc  Vd  Ae  gi  j  k 1 W~r8   c                    | j                  |      }|r*t        |j                  d      j                  dd            S d S NrS   , )searchfloatrq   replacepatternrw   rk   s      r'   rr   zHistoryBaselineParser._numberY   s7    w'9>uU[[^++C45HDHr8   c                    | j                  |      }|r*t        |j                  d      j                  dd            S d S r   )r   rp   rq   r   r   s      r'   rs   zHistoryBaselineParser._integer^   s7    w'7<s5;;q>))#r23F$Fr8   c                j    t        j                  d|       }|rt        |j                  d            S d S )Nz\s*(\d+(?:\.\d+)?)\s*rS   )re	fullmatchr   rq   valuerk   s     r'   r   z#HistoryBaselineParser._plain_numberc   s-    5u=(-uU[[^$747r8   c                    t        j                  d|       }|r*t        |j                  d      j	                  dd            S d S )Nz\s*([\d,]+)\s*rS   r   r   )r   r   rp   rq   r   r   s     r'   r   z$HistoryBaselineParser._plain_integerh   s:    .67<s5;;q>))#r23F$Fr8   c                |    t         j                  |       }|r$t        j                  |j	                  d            S dS )NrS   r@   )r   r   rB   r   rq   rw   rk   s     r'   rt   zHistoryBaselineParser._trainingm   s2    (GL$33EKKNCTRTTr8   c                    | j                         t        fddD              }t        t        j                  |            S )Nc              3  2   K   | ]  \  }}|v s|  y wrD   r@   r%   labeltoken
normalizeds      r'   r(   z7HistoryBaselineParser._training_text.<locals>.<genexpr>u   s6       w  2_  ch  lv  cvu  2_   ))pushr   )u   푸쉬r   )pullr   )u   풀r   )legsr   )u   레그r   )u
   등+가슴
back_chest)backr   )u   어깨shoulders_arms)u   휴식rest)u   복싱boxinglowerr,   dictfromkeys)r   tokensr   s     @r'   r   z$HistoryBaselineParser._training_textr   s?    [[]
  w  2_  w  wT]]6*++r8   c                |    t         j                  |       }|r$t        j                  |j	                  d            S d S NrS   )r   r   rB   r   rq   r   s     r'   ru   z HistoryBaselineParser._digestionx   s4      )HM$44U[[^DWSWWr8   c                H    ddddj                  | j                               S )Ngoodnormalbloating)012)getstrip)r   s    r'   r   z%HistoryBaselineParser._digestion_text}   s     (<@@OOr8   c                    | j                         t        fddD              }t        t        j                  |            S )Nc              3  2   K   | ]  \  }}|v s|  y wrD   r@   r   s      r'   r(   z.HistoryBaselineParser._pain.<locals>.<genexpr>   s6       d  2L  PU  Yc  Pcu  2Lr   ))u   무릎knee)u   전경골근anterior_tibial)u   가슴 통증
chest_painr   )rw   r   r   s     @r'   rv   zHistoryBaselineParser._pain   s?    ]]_
  d  2L  d  dT]]6*++r8   c                   t        | d       t        fd| D              }t        j                  j                  j
                  j                  j                  t        j                  j                  t        d |D                    t        j                  j                  t        d |D                    t        j                  j                  t        d |D                    t        j                  j                  t        d |D                    t        j                  j                  t        d |D                    t        j                  j                   t        d	 |D                          S )
Nc                   t        d | j                  | j                  | j                  | j                  fD              t        | j                        z   t        | j                        z   | j                  j                  d      fS )Nc              3  $   K   | ]  }|d u 
 y wrD   r@   r%   r   s     r'   r(   zBHistoryBaselineParser._select.<locals>.<lambda>.<locals>.<genexpr>   s$       :l  ZkPU%t:K  Zks   r~   )
sum	weight_kgsleep_hourscalories_kcaldigestion_statusrT   training_tokenspain_tokenssection_anchorendswith)entrys    r'   <lambda>z/HistoryBaselineParser._select.<locals>.<lambda>   s    c  :lZ_ZiZikpk|k|  D  R  R  TY  Tj  Tj  Zk  :l  7l  or  sx  sH  sH  oI  7I  LO  PU  Pa  Pa  Lb  7b  di  dx  dx  dA  dA  BJ  dK  6Lr8   )keyc              3  V   K   | ]   }|j                   j                   k(  s| " y wrD   )r    )r%   r&   selecteds     r'   r(   z0HistoryBaselineParser._select.<locals>.<genexpr>   s%     dZT4;K;KxOcOc;cDZs   ))c              3  4   K   | ]  }|j                     y wrD   )r   r$   s     r'   r(   z0HistoryBaselineParser._select.<locals>.<genexpr>   s7       Hp  do  \`  IM  IW  IW  do   c              3  4   K   | ]  }|j                     y wrD   )r   r$   s     r'   r(   z0HistoryBaselineParser._select.<locals>.<genexpr>   s7       r\  P[  HL  sw  sC  sC  P[r   c              3  4   K   | ]  }|j                     y wrD   )r   r$   s     r'   r(   z0HistoryBaselineParser._select.<locals>.<genexpr>   s7       `L  @K  x|  ae  as  as  @Kr   c              3  4   K   | ]  }|j                     y wrD   )r   r$   s     r'   r(   z0HistoryBaselineParser._select.<locals>.<genexpr>   s7       SA	  u@	  mq  TX  Th  Th  u@	r   c              3  4   K   | ]  }|j                     y wrD   )r   r$   s     r'   r(   z0HistoryBaselineParser._select.<locals>.<genexpr>   s7       H
w
  k
v
  c
g
  I
M
  I
^
  I
^
  k
v
r   c              3  4   K   | ]  }|j                     y wrD   )r   r$   s     r'   r(   z0HistoryBaselineParser._select.<locals>.<genexpr>   s7       zd  Xc  PT  {  {K  {K  Xcr   )maxr,   r	   rP   rx   r    source_sha256r   rB   _unique_valuer   r   r   _unique_tokensr   r   r   )r[   same_sourcer   s     @r'   rO   zHistoryBaselineParser._select   s]   z  (L  MdZddX\\8+A+A8CWCWYaYoYoqy  rI  rI  K`  Kn  Kn  ow  oA  oA  CH  Hp  do  Hp  Cp  Kq  sH  sV  sV  W_  Wk  Wk  mr  r\  P[  r\  m\  s]  _t  _B  _B  CK  CY  CY  [`  `L  @K  `L  [L  _M  Od  Os  Os  t|  tL  tL  NS  SA	  u@	  SA	  NA	  OB	  D	Y	  D	g	  D	g	  h	p	  h	A
  h	A
  C
H
  H
w
  k
v
  H
w
  C
w
  D	x
  z
O  z
^  z
^  _g  _s  _s  uz  zd  Xc  zd  ud  z
e  f  	fr8   c                     d x}fddcS )Tc                |    |D ch c]  }||	 }}| t        |      dk7  r| S t        t        |            S c c}w r   )rT   nextiter)r   r[   r   valuess       r'   r   z#HistoryBaselineParser._unique_value   sF    %/EZE53D%ZE#/3v;!3Cx[dSYlI[[ Fs   99)r   T | Noner[   ztuple[T | None, ...]r9   r   r@   )	.defaultsr   __classdict__s     r'   z%<generic parameters of _unique_value>z;HistoryBaselineParser.<generic parameters of _unique_value>   s     \r8   c           
     l    | r| S t        t        |D ch c]  }|D ]  }|  c}}            S c c}}w rD   )r,   rY   )r   r[   rM   r   s       r'   r   z$HistoryBaselineParser._unique_tokens   s6    #xrvj6pjfo]bufouj6p/q)rr6ps   0c                4   | D ch c]  }|j                    c}t              t              }}t        fdt	        d|dz         D              }t        d | D              }t        ||||t        d | D              t        d | D                    S c c}w )Nc              3  P   K   | ]  }t        |      vst        |        y wrD   )r
   )r%   rP   observeds     r'   r(   z2HistoryBaselineParser._coverage.<locals>.<genexpr>   s(     r:L3P\]`PaiqPq\#.:Ls   &&rS   c           
   3     K   | ]e  }t        d  |j                  |j                  |j                  |j                  |j
                  |j                  fD              sX|j                   g yw)c              3  2   K   | ]  }|d u xs |dk(    y wNr@   r@   r   s     r'   r(   z<HistoryBaselineParser._coverage.<locals>.<genexpr>.<genexpr>   s6       Pw  {vqvPUY]P]PlafjlalPl  {vs   N)allr   r   r   r   r   r   rP   r%   r   s     r'   r(   z2HistoryBaselineParser._coverage.<locals>.<genexpr>   s       *xC  Pw  |A  |K  |K  MR  M^  M^  `e  `s  `s  uz  uK  uK  MR  Mb  Mb  di  du  du  {v  Pw  Mw%))s   AA-A-c              3  N   K   | ]  }|j                   |j                    y wrD   )r   rP   r   s     r'   r(   z2HistoryBaselineParser._coverage.<locals>.<genexpr>   s7       TSkrbgv{  wF  wF  wRTYT]T]kr   %%c              3  N   K   | ]  }|j                   |j                    y wrD   )r   rP   r   s     r'   r(   z2HistoryBaselineParser._coverage.<locals>.<genexpr>   sS       Z[  ry  in  }B  }N  }N  }Z  [`  [d  [d  ryr   )rP   minr   r,   ranger   )r\   r   firstlastmissing_daysdays_without_measurementsr   s         @r'   rZ   zHistoryBaselineParser._coverage   s    +237%EII73(mS]tr%4!8:Lrr$)  *x  *x  %x!t\3Le  TSkr  TS  OS  UZ  Z[  ry  Z[  U[  \  	\	 4s   Bc                j    d}t        fd|D              }t        | t        d D              |      S )N)rx   r   r   r   r   r   r   c           
   3     K   | ]<  }t        D ch c]  }t        ||      d vst        ||       c}      dkD  s9| > yc c}w w)r   rS   N)rT   getattr)r%   fieldr&   r[   s      r'   r(   z4HistoryBaselineParser._duplicates.<locals>.<genexpr>   sl       YVEs]g  <S]gUYkrswy~k  HR  lRGD%<P]g  <S  8T  WX  8X%V  <Ss   A
A
A

A
A
c              3  4   K   | ]  }|j                     y wrD   )r   r$   s     r'   r(   z4HistoryBaselineParser._duplicates.<locals>.<genexpr>   s     &Rztt':':zr   )r,   r   )rP   r[   fields	conflictss    `  r'   rU   z!HistoryBaselineParser._duplicates   s?     F  YV  Y  Y	C&Rz&R!RT]^^r8   N)rG   r   r9   None)r9   r   )rL   r   r9   tuple[BaselineEntry, ...])rL   r   rk   zre.Match[str]rw   r#   r9   r	   )rL   r   rh   r#   r9   r   )r   re.Pattern[str]rw   r#   r9   float | None)r   r  rw   r#   r9   
int | None)r   r#   r9   r  )r   r#   r9   r  )rw   r#   r9   tuple[str, ...])r   r#   r9   r  )rw   r#   r9   
str | None)r   r#   r9   r  )r[   list[BaselineEntry]r9   r	   )r   r  r[   ztuple[tuple[str, ...], ...]r9   r  )r\   r   r9   r   )rP   r
   r[   r  r9   r   )r:   r;   r<   r=   rH   r_   rK   rc   rg   staticmethodrr   rs   r   r   rt   r   ru   r   rv   rO   r   r   rZ   rU   __classdictcell__)r   s   @r'   rB   rB   3   sT   Y$	;W I I G G 8 8 G G U U , ,
 X X P P , ,
 f f
 \ \ \ s s \ \ _ _r8   rB   )#r=   
__future__r   r-   r)   r   collectionsr   dataclassesr   pathlibr   typingr   checkin_cli.history_modelsr   r	   r
   r   r   r   r   compile	MULTILINEr   r>   r   r   
IGNORECASEr   r   r   r   r   rB   r@   r8   r'   <module>r     s   S "   	 # !     #-"**-bdfdpdp"q	 q!+  -E  GI  GS  GS  "T  T *

+uwy  xD  xD  !E  E#-2::  /H  JL  JV  JV  Y[  Yf  Yf  Jf  $g
   g$.BJJ/qsuss  %A	!  A#-2::.lnpnznz#{
  {$.BJJ  0h  jl  jv  jv  %w	!  w $d#  $"o_ o_r8   