
    &i\=              
       Z   U d Z ddlZddlmc mZ ddlZddlZddl	Z	ddl
mZ ddlZ eej                  j                  dd            Z ee      e	j"                  vr"e	j"                  j%                  d ee             ddlmZ ddddd	gd
dddddddgdgdZeed<   dddddiiZeed<   d'dededz  defdZd'dededz  defdZdej6                  dedeeef   fdZdedej6                  ddfdZdedej6                  ddfdZdedej6                  ddfdZ dedej6                  ddfd Z!dedej6                  ddfd!Z"dedej6                  ddfd"Z#dedej6                  ddfd#Z$dedej6                  ddfd$Z%dedej6                  ddfd%Z&dedej6                  ddfd&Z'y)(u  test_todo_sync.py

task-637.1 TDD RED Phase — utils/todo_sync.py 단위 테스트 (아르고스 작성)

테스트 항목:
1. test_sync_task_completion_match: sub_item.task_id 매칭 → done=True
2. test_sync_task_completion_no_match: 매칭 없음 → 변경 없음
3. test_sync_task_completion_already_done: 이미 done=True → 변경 없음
4. test_sync_issue_all_done: 모든 sub_items done → issue.status="done" + completed_at 기록
5. test_retroactive_sync: 다건 completed 태스크 일괄 동기화
6. test_link_task_to_issue: 수동 task_id ↔ issue 연결
7. test_link_task_to_issue_with_sub_item_title: sub_item_title 지정 연결
8. test_backup_created: todo.json 수정 전 .bak 파일 생성
9. test_no_reverse_done: done=True → done=False 되돌리기 불가 (단방향)
10. test_linked_tasks_match: issue.linked_tasks에 task_id 포함 시 매칭

격리: tmp_path + monkeypatch 로 TODO_FILE / TIMERS_FILE 경로 오버라이드
    N)PathWORKSPACE_ROOTz/home/jay/workspace1.0	issue-007pending
task-434.1   Phase 0: 환경 셋업Ftitledonetask_idzPhase 1 POC
task-500.1idstatuscompleted_atlinked_tasks	sub_itemsversionissues_TODO_TEMPLATEtasks	completedr   r   _TIMERS_TEMPLATEtmp_pathdatareturnc                     | dz  }|j                  dd       |dz  }|j                  t        j                  |xs t        d      d       |S )	u<   tmp_path/memory/todo.json 을 생성하고 경로를 반환.memoryTparentsexist_okz	todo.jsonFensure_asciiutf-8encoding)mkdir
write_textjsondumpsr   )r   r   mem	todo_files       +/home/jay/workspace/tests/test_todo_sync.py_write_todor1   G   sP    
X
CIIdTI*k!ID$:NOZab    c                     | dz  }|j                  dd       |dz  }|j                  t        j                  |xs t        d      d       |S )	uC   tmp_path/memory/task-timers.json 을 생성하고 경로를 반환.r!   Tr"   task-timers.jsonFr%   r'   r(   )r*   r+   r,   r-   r   )r   r   r.   timers_files       r0   _write_timersr6   P   sR    
X
CIIdTI***K4::d&>.>US^efr2   monkeypatchc                     t        |      }t        |      }| j                  t        d|       | j                  t        d|       ||fS )uM   todo_sync 모듈의 TODO_FILE / TIMERS_FILE 을 tmp_path 기반으로 패치.	TODO_FILETIMERS_FILE)r1   r6   setattr	todo_sync)r7   r   r/   r5   s       r0   _patch_pathsr=   Y   sE    H%I)K	;	:	=+>k!!r2   c                 t   t        ||       \  }}t        j                  d      }t        |t              }|s!t        j                  d      dz   dt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}|d	   }d
}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}}|d   }
t        |
      }d
}||k\  }|st        j                  d|fd||f      dt        j                         v st        j                  t              rt        j                  t              ndt        j                  |
      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}
x}x}}t        j                   |j#                  d            }|d   d   d   d
   }|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}|d    }d!}||u }|st        j                  d"|fd#||f      t        j                  |      t        j                  |      dz  }t        j                  d$      dz   d|iz  }	t        t        j                  |	            dx}x}}y)%uC   sub_item에 task_id가 있고 해당 task_id로 sync → done=True.r      반환값은 dict이어야 함7
>assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}
isinstanceresultdictpy0py1py2py4Nupdated   ==z%(py1)s == %(py4)srF   rH   u0   한 개의 sub_item이 업데이트되어야 함
>assert %(py6)spy6details>=z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} >= %(py7)slenrE   rG   rH   py7u,   details 리스트에 항목이 있어야 함z
>assert %(py9)spy9r'   r(   r   r   r   r   assert %(py6)sr   Tisz%(py1)s is %(py4)su+   Phase 1 POC sub_item이 done=True여야 함)r=   r<   sync_task_completionrA   rC   
@pytest_ar_format_assertmsg@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation_call_reprcomparerU   r,   loads	read_text)r   r7   r/   _rB   @py_assert3@py_format5@py_assert0@py_assert2@py_format7@py_assert1@py_assert6@py_assert5@py_format8@py_format10savedphase1s                    r0   test_sync_task_completion_matchrv   g   s   X6LIq++L9Ffd#E#EE%EEEEEEE:EEE:EEEEEEfEEEfEEEEEEdEEEdEEE#EEEEEE)UU!UUUUUUUUUUUU#UUUUUUUUi V3 !VQV!Q&VVV!QVVVVVV3VVV3VVV VVV!VVVQVVV(VVVVVVVVJJy**G*<=E8_Q,Q/F),,,,,,,,,,,,,,,,,,,&>PTP>T!PPP>TPPP>PPPTPPP#PPPPPPPPr2   c                    t        ||       \  }}|j                  d      }t        j                  d      }|d   }d}||k(  }|st	        j
                  d|fd||f      t	        j                  |      t	        j                  |      dz  }	t	        j                  d	      d
z   d|	iz  }
t        t	        j                  |
            dx}x}}|j                  d      }t        j                  } ||      }t        j                  } ||      }||k(  }|st	        j
                  d|fd||f      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dt        j                         v st	        j                  t              rt	        j                  t              ndt	        j                  |      dt        j                         v st	        j                  |      rt	        j                  |      ndt	        j                  |      dz  }t	        j                  d      dz   d|iz  }t        t	        j                  |            dx}x}x}x}}y)u:   매칭되는 sub_item이 없는 task_id → 변경 없음.r'   r(   z
task-999.9rI   r   rK   rM   rN   u(   매칭 없으면 updated=0 이어야 함rO   rP   N)z%(py5)s
{%(py5)s = %(py2)s
{%(py2)s = %(py0)s.loads
}(%(py3)s)
} == %(py12)s
{%(py12)s = %(py9)s
{%(py9)s = %(py7)s.loads
}(%(py10)s)
}r,   rt   original)rE   rG   py3py5rW   rX   py10py12u%   파일 내용이 변경되면 안 됨z
>assert %(py14)spy14)r=   rh   r<   r]   r^   rf   rc   r_   rd   re   r,   rg   r`   ra   rb   )r   r7   r/   ri   rx   rB   rl   rj   rm   rk   rn   rt   ro   @py_assert4@py_assert8@py_assert11rp   @py_format13@py_format15s                      r0   "test_sync_task_completion_no_matchr   |   s   X6LIq""G"4H++L9F)MM!MMMMMMMMMMMM#MMMMMMMM1E::]:e]

]
8 4] 44]]] 4]]]]]]4]]]4]]]:]]]]]]e]]]e]]]]]]]]]]]]]]]
]]]]]]8]]]8]]] 4]]]6]]]]]]]]r2   c           	      r   ddddg ddddgd	gd
}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d      }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}}t        j                  |j                  d            }
|
d   d   d   d   d   }d}||u }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}y)u:   이미 done=True인 sub_item → updated=0, 파일 불변.r   z	issue-010r   Nu   이미 완료Tz
task-300.1r
   r   r   r9   r:   r!   r4   rI   r   rK   rM   rN   u+   이미 done=True면 updated=0 이어야 함rO   rP   r'   r(   r   r   r   rZ   r\   rY   )r1   r6   r;   r<   r]   r^   rf   rc   r_   rd   re   r,   rg   rh   )r   r7   already_done_todor/   rB   rl   rj   rm   rk   rn   rt   s              r0   &test_sync_task_completion_already_doner      sk     "# $ "-tU

 H&78I(	;	:	=(X2EHZ2Z[++L9F)PP!PPPPPPPPPPPP#PPPPPPPPJJy**G*<=E?1k*1-f5==5====5===5==========r2   c           
         ddddg ddddd	d
ddgdgd}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d      }|d   }d}||k(  }|slt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }	t        t        j                  |	            dx}x}}t        j                  |j                  d            }
|
d   d   }|d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      d z   d|iz  }	t        t        j                  |	            dx}x}}|d!   }d}||u}|st        j                  d"|fd#||f      t        j                  |      t        j                  |      dz  }t        j                  d$      d z   d|iz  }	t        t        j                  |	            dx}x}}y)%uI   모든 sub_items가 done이면 issue.status='done' + completed_at 기록.r   z	issue-020in_progressNzStep ATz
task-100.1r
   zStep BFz
task-101.1r   r   r9   r:   r!   r4   rI   rJ   rK   rM   rN   rY   rP   r'   r(   r   r   r   r   u-   모든 sub_items done → issue.status='done'rO   r   )is not)z%(py1)s is not %(py4)su#   completed_at이 기록되어야 함)r1   r6   r;   r<   r]   r^   rf   rc   rd   re   r,   rg   rh   r_   )r   r7   one_left_todor/   rB   rl   rj   rm   rk   rn   rt   issues               r0   test_sync_issue_all_doner      s     "' $ "&N&,O	
M Hm4I(	;	:	=(X2EHZ2Z[++L9F)!!!!!!!!!!!!!!!!!!!JJy**G*<=E(OAE?UfU?f$UUU?fUUU?UUUfUUU&UUUUUUUU SS ,SSS SSS SSSSSS.SSSSSSSSr2   c                 l
   ddddg ddddd	dd
dddddgdgd}ddddd
ddddddi}t        | |      }t        | |      }|j                  t        d|       |j                  t        d|       t        j                         }t        |t              }|s!t        j                  d      dz   dt        j                         v st        j                  t
              rt        j                  t
              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}|d   }	d}|	|k(  }
|
st        j                  d|
fd|	|f      t        j                  |	      t        j                  |      d z  }t        j                  d!      d"z   d#|iz  }t        t        j                  |            dx}	x}
}|d$   }t!        |      }d}||k\  }|st        j                  d%|fd&||f      d't        j                         v st        j                  t               rt        j                  t               nd't        j                  |      t        j                  |      t        j                  |      d(z  }d)d*|iz  }t        t        j                  |            dx}x}x}}t#        j$                  |j'                  d+,            }|d-   d.   d/   }|d.   d0   }	d1}|	|u }
|
st        j                  d2|
fd3|	|f      t        j                  |	      t        j                  |      d z  }t        j                  d4      d"z   d#|iz  }t        t        j                  |            dx}	x}
}|d5   d0   }	d1}|	|u }
|
st        j                  d2|
fd3|	|f      t        j                  |	      t        j                  |      d z  }t        j                  d6      d"z   d#|iz  }t        t        j                  |            dx}	x}
}|d   d0   }	d}|	|u }
|
st        j                  d2|
fd3|	|f      t        j                  |	      t        j                  |      d z  }t        j                  d7      d"z   d#|iz  }t        t        j                  |            dx}	x}
}y)8uM   다건 completed 태스크를 전수 스캔하여 todo.json 일괄 동기화.r   z	issue-030r   NzPhase AF
task-200.1r
   zPhase B
task-201.1zPhase Cr   r   r   r   r   
task-202.1r   )r   r   r   r9   r:   r?   r@   rA   rB   rC   rD   total_synced   rK   rM   rN   u2   완료된 태스크 2개가 동기화되어야 함rO   rP   rQ   rR   rT   rU   rV   zassert %(py9)srX   r'   r(   r   r   r   r   TrZ   r\   zPhase A done=TruerJ   zPhase B done=Trueu&   Phase C는 task_id 없어서 그대로)r1   r6   r;   r<   retroactive_syncrA   rC   r^   r_   r`   ra   rb   rc   rd   re   rf   rU   r,   rg   rh   )r   r7   
multi_todomulti_timersr/   r5   rB   rj   rk   rl   rm   rn   ro   rp   rq   rr   rs   rt   r   s                      r0   test_retroactive_syncr      s     "# $ "'<P'<P'4H

J" 	&2kJ&2kJ&2mL
L Hj1I,7K	;	:	=+>'')Ffd#E#EE%EEEEEEE:EEE:EEEEEEfEEEfEEEEEEdEEEdEEE#EEEEEE.!\Q\!Q&\\\!Q\\\!\\\Q\\\(\\\\\\\\i &3 !&Q&!Q&&&&!Q&&&&&&3&&&3&&& &&&!&&&Q&&&&&&&JJy**G*<=Eh";/IQ<<4<4'<<<4<<<<<<4<<<)<<<<<<<<Q<<4<4'<<<4<<<<<<4<<<)<<<<<<<<Q<R5R5(RRR5RRRRRR5RRR*RRRRRRRRr2   c                    t        ||       \  }}t        j                  dd      }t        |t              }|sddt        j                         v st        j                  t              rt        j                  t              nddt        j                         v st        j                  |      rt        j                  |      nddt        j                         v st        j                  t              rt        j                  t              ndt        j                  |      dz  }t        t        j                  |            d}|d	   }d
}||u }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}}d}||v }|st        j                  d|fd||f      t        j                  |      dt        j                         v st        j                  |      rt        j                  |      nddz  }
dd|
iz  }t        t        j                  |            dx}}t        j                  |j!                  d            }|d   d   }d}|d   }||v }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}}y)u@   수동으로 task_id를 issue에 연결: linked_tasks에 추가.z
task-600.1r   z5assert %(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
}rA   rB   rC   rD   NlinkedTrZ   r\   rN   u   linked=True 이어야 함rO   rP   messagein)z%(py1)s in %(py3)s)rF   ry   zassert %(py5)srz   r'   r(   r   r   r   z%(py1)s in %(py4)su#   linked_tasks에 추가되어야 함)r=   r<   link_task_to_issuerA   rC   r`   ra   r^   rb   rc   rd   re   rf   r_   r,   rg   rh   )r   r7   r/   ri   rB   rj   rk   rl   rm   rn   @py_format4@py_format6rt   r   s                 r0   test_link_task_to_issuer     s   X6LIq)),DFfd########:###:######f###f######d###d##########(@t@t#@@@t@@@@@@t@@@%@@@@@@@@999JJy**G*<=E(OAEW50W<00WWW<0WWW<WWW0WWW2WWWWWWWWr2   c                    t        ||       \  }}t        j                  ddd      }|d   }d}||u }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      d	z  }d
d|iz  }	t        t        j                  |	            dx}x}}t        j                  |j                  d            }
|
d   d   }d}|d   }||v }|slt        j                  d|fd||f      t        j
                  |      t        j
                  |      d	z  }d
d|iz  }	t        t        j                  |	            dx}x}}t        d |d   D              }|d   }d}||k(  }|st        j                  d|fd||f      t        j
                  |      t        j
                  |      d	z  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}}y)u?   sub_item_title 지정 시 해당 sub_item.task_id에도 연결.z
task-601.1r   r	   )sub_item_titler   TrZ   r\   rN   rY   rP   Nr'   r(   r   r   r   r   r   c              3   2   K   | ]  }|d    dk(  s|  yw)r   r	   N ).0ss     r0   	<genexpr>z>test_link_task_to_issue_with_sub_item_title.<locals>.<genexpr>)  s     Z1W:AY3Y!Zs   r   r   rK   rM   u'   sub_item.task_id가 설정되어야 함rO   )r=   r<   r   r^   rf   rc   rd   re   r,   rg   rh   nextr_   )r   r7   r/   ri   rB   rl   rj   rm   rk   rn   rt   r   phase0s                r0   +test_link_task_to_issue_with_sub_item_titler     sn   X6LIq))/F (#t#t####t######t#######JJy**G*<=E(OAE0500<00000<0000<00000000000ZU;/ZZF)WW,WWWWWWWWWWWW.WWWWWWWWr2   c                    t        ||       \  }}t        j                  d       |j                  |j                  dz   z  }|j
                  } |       }|st        j                  d      dz   dt        j                         v st        j                  |      rt        j                  |      ndt        j                  |      t        j                  |      dz  }t        t        j                  |            dx}}t        j                  |j!                  d	            d
   }|d   d   d   d   }	d}|	|u }
|
st        j"                  d|
fd|	|f      t        j                  |	      t        j                  |      dz  }t        j                  d      dz   d|iz  }t        t        j                  |            dx}	x}
}y)u/   todo.json 수정 전 .bak 파일 생성 확인.r   z.baku+   todo.json.bak 파일이 생성되어야 함zC
>assert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}bak_file)rE   rG   rH   Nr'   r(   r   r   r   rJ   r   FrZ   r\   rN   u%   백업은 수정 전 상태여야 함rO   rP   )r=   r<   r]   parentnameexistsr^   r_   r`   ra   rb   rc   rd   re   r,   rg   rh   rf   )r   r7   r/   ri   r   ro   rj   rk   original_issuesrl   rm   rn   s               r0   test_backup_createdr   2  s-   X6LIq""<09>>F#:;H??K?KKKKKKKKKK8KKK8KKK?KKKKKKKKKjj!3!3W!3!EFxPO1k*1-f5gg5>ggg5ggg5gggggg@ggggggggr2   c           	         dddddgddddgd	gd
}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d       t        j                  |j                  d            }|d   d   d   d   d   }d}||u }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}}|d   d   d   }d}||k(  }|st        j                  d|fd||f      t        j                  |      t        j                  |      dz  }t        j                  d      dz   d|iz  }	t        t        j                  |	            dx}x}}y)u@   done=True → done=False 되돌리기 불가 (단방향 보장).r   z	issue-040r   z2026-03-10T10:00:00z
task-400.1u   완료된 항목Tr
   r   r   r9   r:   r!   r4   r'   r(   r   r   r   rZ   r\   rN   u(   done=True는 되돌릴 수 없어야 함rO   rP   Nr   rK   rM   u$   issue.status도 되돌리면 안 됨)r1   r6   r;   r<   r]   r,   rg   rh   r^   rf   rc   r_   rd   re   )
r   r7   all_done_todor/   rt   rl   rj   rm   rk   rn   s
             r0   test_no_reverse_doner   D  s     "  5!-0$<X

M Hm4I(	;	:	=(X2EHZ2Z[ ""<0JJy**G*<=E?1k*1-f5ii5=iii5iii5iiiiii?iiiiiiii?1h'Y6Y'61YYY'6YYY'YYY6YYY3YYYYYYYYr2   c           	         dddddgddddgd	gd
}t        | |      }t        |        |j                  t        d|       |j                  t        d| dz  dz         t        j                  d      }g }|d   }d}||k\  }|}	|s|d   }
t        |
      }d}||k\  }|}	|	sqt        j                  d|fd||f      t        j                  |      t        j                  |      dz  }dd|iz  }|j                  |       |st        j                  dfdf      dt        j                         v st        j                  t
              rt        j                  t
              ndt        j                  
      t        j                  |      t        j                  |      dz  }dd|iz  }|j                  |       t        j                  |d      i z  }t        j                  d      dz   d|iz  }t        t        j                   |            dx}	x}x}x}x}x}
x}x}}t#        j$                  |j'                  d             }|d!   d"   d#   d"   }|d$   }	d%}|	|u }|st        j                  d&|fd'|	|f      t        j                  |	      t        j                  |      d(z  }t        j                  d)      d*z   d+|iz  }t        t        j                   |            dx}	x}}y),uK   issue.linked_tasks에 task_id 포함 시 sub_items 없어도 매칭 처리.r   z	issue-050r   Nr   u   연결된 태스크 작업Fr
   r   r   r9   r:   r!   r4   rI   rJ   rQ   rR   )z%(py3)s >= %(py6)s)ry   rP   z%(py8)spy8)z5%(py14)s
{%(py14)s = %(py10)s(%(py12)s)
} >= %(py17)srU   )r{   r|   r}   py17z%(py19)spy19uK   linked_tasks 매칭 시 업데이트 또는 details 기록이 있어야 함z
>assert %(py22)spy22r'   r(   r   r   r   r   TrZ   r\   rN   u4   linked_tasks 매칭 시 sub_item done=True여야 함rO   rP   )r1   r6   r;   r<   r]   rU   r^   rf   rc   appendr`   ra   rb   _format_boolopr_   rd   re   r,   rg   rh   )r   r7   linked_todor/   rB   ro   rm   rq   r~   rl   r   @py_assert13@py_assert16@py_assert15rn   @py_format9@py_format18@py_format20@py_format21@py_format23rt   subrj   rk   s                           r0   test_linked_tasks_matchr   f  s     "# $!- ;EVZ[	
K Hk2I(	;	:	=(X2EHZ2Z[++L9FUyUUQU&,Y&7U"%&7"8U<=U"8A"=U UCTCTUQU UKT9 	U UKT9 U U UNTfUNTUCTCTU"8AU UNTfU U<T<T #&U UKT9 #&U UKT9 '8U UKT9 #9U UKT9 =>U U UNTfUNTUFTnU UCTCTTU U UATATU U U U JJy**G*<=E
/!
[
)!
,Cv;V$V;$VVV;$VVV;VVV$VVV VVVVVVVVr2   )N)(__doc__builtinsr`   _pytest.assertion.rewrite	assertionrewriter^   r,   ossyspathlibr   pytestenvironget
_WORKSPACEstrpathinsertutils.todo_syncr<   r   rC   __annotations__r   r1   r6   MonkeyPatchtupler=   rv   r   r   r   r   r   r   r   r   r   r   r2   r0   <module>r      s  &   	 
   "**..!13HIJ
z?#(("HHOOAs:' $   )N2EdS'<P		
 " #!
 $ $ dTk T D t t "f00 "D "U4QU:EV "Qd QASAS QX\ Q*
^ 
^FDVDV 
^[_ 
^$>T >HZHZ >_c >BTt T&:L:L TQU TJ(SD (Sv7I7I (Sd (S`Xd X9K9K XPT X(X$ XVM_M_ Xdh X4
h$ 
hV5G5G 
hD 
h$Z4 Zf6H6H ZT ZDWd W9K9K WPT Wr2   