Ë
    —@Ìj™4  ã                   ó<  — d 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	 ddl
mZ ddlmZ ddlmZmZmZ ddlmZ  ej(                  d«      Zd	\  ZZZZZd
ZdZ ej:                  d«      Zd:d„Zde dee    fd„Z!de de fd„Z"de dee    fd„Z#de de de fd„Z$de dee%e e f      fd„Z&de dee    fd„Z'de de ddfd„Z(de de de)fd„Z*de de de)ddfd„Z+de de d e,dee)   fd!„Z-de de d e,d"e)ddf
d#„Z.	 	 d;de de d$e d%ee    d&ee)   de)fd'„Z/d<de de d(ee0   de1e)   fd)„Z2d=de d*e,de1e)   fd+„Z3de,fd,„Z4e G d-„ d.«      «       Z5d/e1e)   de1e5   fd0„Z6d/e1e)   dee5   fd1„Z7d2e1e5   d3e,de8e    fd4„Z9d5e1e   de1e   fd6„Z:de de de1e    fd7„Z;de de de)fd8„Z<de de de fd9„Z=y)>u  
shoot_service.py â€” shooting session driven from the photographer's phone (the /shoot web app).

Why this exists: the schools may not give us names, so a child cannot be known in advance, and photographing a
card before each child (the HEC way) is not acceptable for the client.

How a photo finds its child â€” by ORDER and by what the photographer DECLARES, never by clocks. An earlier design
matched photos to phone events by time; one FTP delay and a child's photos landed on the wrong family without
anyone noticing. This one cannot do that silently:

  1. The photographer scans the CLASS QR on the phone (a "run" starts).
  2. After each child they tap how many photos that child had: [1] [2] [3]. (Test shots: "ignore N".)
  3. Closing the run (next class, pause, end) takes a FENCE: the exact list of files that were in the FTP
     folder at that moment and belong to the run. The run therefore owns exactly those files, whatever their
     delay, and a mistake in one run can never shift the next one.
  4. The server turns the run into children ONLY if the declared total equals the files of the fence. If it does
     not, nothing is assigned: the files are parked and the operator is alerted. The phone shows
     "declared N Â· received M" live, so the mismatch is fixed while the child is still in front of the camera.

Files inside a run are ordered by the camera's own capture order (EXIF, then file name): that is a sequence,
not a comparison with any other device's clock. Faces are never compared (biometric data of minors).
é    N)Ú	dataclassÚfield)ÚPath)ÚOptional)Úget_dbÚensure_columnÚTABLE_OPTIONS)Ú
utcnow_isozmeeconic.shoot)ÚclassÚchildÚskipÚundoÚendi€:	 é   z0^MEEC:CLASS:([a-z0-9][a-z0-9-]{0,63}):(.{1,40})$Úreturnc                  ó®   — t        «       5 } | j                  dt        › �«       t        | ddd«       | j	                  «        d d d «       y # 1 sw Y   y xY w)Naò  
        CREATE TABLE IF NOT EXISTS shoot_events (
            id           BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
            school_id    VARCHAR(64) NOT NULL,
            photographer VARCHAR(64) NOT NULL,
            at_ts        DOUBLE NOT NULL,
            kind         VARCHAR(10) NOT NULL,
            target       VARCHAR(64),
            meta         MEDIUMTEXT,
            created_at   VARCHAR(40) NOT NULL,
            KEY idx_shoot_events (school_id, photographer, id)
        ) Úshoot_eventsÚmetaÚ
MEDIUMTEXT)r   Úexecuter	   r   Úcommit)Úconns    ú1/var/www/photos/backend/services/shoot_service.pyÚinit_shoot_tablesr   /   sT   € Ü	‹ð �TØ�‰ð ô ˆ/ðô 	ô 	�d˜N¨F°LÔAØ�‰Œ÷÷ ñ ús   ‹7AÁAÚ	school_idc                 ó   — t        d| › �«      S )Núshoot_token:)Ú_kv_get)r   s    r   Ú	get_tokenr   C   s   € Ü�\ ) Ð-Ó.Ð.ó    c                 óN   — t        j                  d«      }t        d| › �|«       |S )Né   r   )ÚsecretsÚtoken_urlsafeÚ_kv_set)r   Útokens     r   Úrotate_tokenr'   G   s(   € Ü×!Ñ! "Ó%€EÜˆl˜9˜+Ð&¨Ô.Ø€Lr    r&   c                 ól  — | xs dj                  «       } t        | «      dk  st        | «      dkD  ryt        «       5 }|j                  d«      j	                  «       }ddd«       d}D ]=  }t        j                  t        |d   «      | «      sŒ&|d   j                  dd	«      d	   }Œ? |S # 1 sw Y   ŒOxY w)
zXThe school a token opens, or None. Compared in constant time against every stored token.Ú r   éP   Nz@SELECT `key`, value FROM app_kv WHERE `key` LIKE 'shoot_token:%'ÚvalueÚkeyú:é   )	ÚstripÚlenr   r   ÚfetchallÚhmacÚcompare_digestÚstrÚsplit)r&   r   ÚrowsÚfoundÚrs        r   Úschool_for_tokenr9   M   s°   € àŠ[�b×ÑÓ!€EÜ
ˆ5ƒz�B‚œ#˜e›* rš/ØÜ	‹ð k�TØ�|‰|Ð^Ó_×hÑhÓjˆ÷kà€EØò .ˆÜ×Ñœs 1 W¡:›°Õ6Ø�e‘H—N‘N 3¨Ó*¨1Ñ-‰Eð.ð €L÷kð kús   ¼ B*Â*B3Ú
class_namec                 ó   — d| › d|› �S )NzMEEC:CLASS:r-   © )r   r:   s     r   Úclass_qr_payloadr=   ]   s   € Ø˜˜ 1 Z LÐ1Ð1r    Útextc                 óÖ   — t         j                  | xs dj                  «       «      }|r?|j                  d«      dj	                  |j                  d«      j                  «       «      fS d S )Nr)   r.   ú é   )Ú_CLASS_QR_REÚmatchr/   ÚgroupÚjoinr5   )r>   Úms     r   Úparse_class_qrrG   a   sS   € Ü×Ñ˜DšJ B×-Ñ-Ó/Ó0€AÙ9:ˆA�G‰G�A‹J˜Ÿ™ §¡¨£×!1Ñ!1Ó!3Ó4Ð5ÐDÀÐDr    r,   c                 ó”   — t        «       5 }|j                  d| f«      j                  «       }d d d «       r|d   S d S # 1 sw Y   ŒxY w)Nz$SELECT value FROM app_kv WHERE key=?r+   )r   r   Úfetchone)r,   r   Úrows      r   r   r   h   sO   € Ü	‹ð V�TØ�l‰lÐAÀCÀ6ÓJ×SÑSÓUˆ÷Váˆ3ˆw‰<Ð( DÐ(÷Vð Vús	   ‹">¾Ar+   c                 óŠ   — t        «       5 }|j                  d| |f«       |j                  «        d d d «       y # 1 sw Y   y xY w)Nz7INSERT OR REPLACE INTO app_kv (key, value) VALUES (?,?))r   r   r   )r,   r+   r   s      r   r%   r%   n   s=   € Ü	‹ð �TØ�‰ÐNÐQTÐV[ÐP\Ô]Ø�‰Œ÷÷ ñ ús	   ‹%9¹AÚphotographerc                 óŽ   — t        d| › d|› �«      }dg dœ}	 i |¥|rt        j                  |«      ¥S i ¥S # t        $ r |cY S w xY w)zI`processed`: id of the last run already turned into children (or parked).úshoot_state:r-   r   )Ú	processedÚblocked©r   ÚjsonÚloadsÚ
ValueError)r   rL   ÚrawÚbases       r   Ú	get_staterW   t   s^   € ä
�L  ¨1¨\¨NÐ;Ó
<€CØ rÑ*€DðØ;�$Ð;©cœ4Ÿ:™: c›?Ð;Ð;°rÐ;Ð;øÜò ØŠðús   ˜6 ³6 ¶AÁAÚstatec                 óN   — t        d| › d|› �t        j                  |«      «       y )NrN   r-   ©r%   rR   Údumps)r   rL   rX   s      r   Ú	set_stater\   ~   s"   € Üˆl˜9˜+ Q | nÐ5´t·z±zÀ%Ó7HÕIr    Úrun_idc                 ó|   — t        d| › d|› d|› �«      }	 |rt        j                  |«      S d S # t        $ r Y y w xY w©Nz
shoot_run:r-   rQ   )r   rL   r]   rU   s       r   Úget_progressr`   ‚   sK   € Ü
�J˜y˜k¨¨<¨.¸¸&¸ÐBÓ
C€CðÙ"%Œt�z‰z˜#‹Ð/¨4Ð/øÜò Ùðús   –/ ­/ ¯	;º;Úprogressc                 óT   — t        d| › d|› d|› �t        j                  |«      «       y r_   rZ   )r   rL   r]   ra   s       r   Úset_progressrc   Š   s(   € Üˆj˜˜ 1 \ N°!°F°8Ð<¼d¿j¹jÈÓ>RÕSr    ÚkindÚtargetr   c                 ó  — t        «       5 }|j                  d| |t        j                  «       |||rt        j                  |«      nd t        «       f«      }|j                  «        |j                  ||dœcd d d «       S # 1 sw Y   y xY w)NzpINSERT INTO shoot_events (school_id, photographer, at_ts, kind, target, meta, created_at) VALUES (?,?,?,?,?,?,?))Úidrd   re   )r   r   ÚtimerR   r[   r
   r   Ú	lastrowid)r   rL   rd   re   r   r   Úcurs          r   Úrecord_eventrk   �   sz   € ä	‹ð E�TØ�l‰lð%à˜¤d§i¡i£k°4¸ÑUYÄÇÁÈDÔAQÐ_cÔeoÓeqÐrótˆð 	�‰ŒØ—m‘m¨T¸VÑD÷E÷ Eò Eús   ‹A*A?Á?BÚsincec           	      óz  — |€t        j                   «       dz
  n|}t        «       5 }|j                  d| ||f«      j                  «       }d d d «       g }D ]E  }	 |d   rt	        j
                  |d   «      ni }|j                  |d   |d   |d   |d   |dœ«       ŒG |S # 1 sw Y   ŒWxY w# t        $ r i }Y Œ@w xY w)	Ni £ ztSELECT id, at_ts, kind, target, meta FROM shoot_events WHERE school_id=? AND photographer=? AND at_ts>=? ORDER BY idr   rg   Úat_tsrd   re   )rg   Úatrd   re   r   )rh   r   r   r1   rR   rS   rT   Úappend)r   rL   rl   r   r6   Úoutr8   r   s           r   Ú
events_forrr   ›   sß   € Ø).¨ŒT�Y‰Y‹[˜9Ò$¸E€EÜ	‹ð H�TØ�|‰|ðØ% |°UÐ;ó=ç=E¹X»Zð 	÷Hð €CØò nˆð	Ø,-¨fªI”4—:‘:˜a ™iÔ(¸2ˆDð 	�
‰
˜!˜D™'¨¨7©¸Q¸v¹YÐRSÐT\ÑR]ÐgkÑlÕmðnð €J÷Hð Hûô ò 	ØŠDð	ús   ¦$B ÁB,Â B)Â,B:Â9B:Úlimitc           	      óê   — t        «       5 }|j                  d| t        |«      f«      j                  «       }d d d «       D �cg c]  }|d   |d   |d   |d   |d   dœ‘Œ c}S # 1 sw Y   Œ.xY wc c}w )NziSELECT id, photographer, at_ts, kind, target FROM shoot_events WHERE school_id=? ORDER BY id DESC LIMIT ?rg   rL   rn   rd   re   )rg   rL   ro   rd   re   )r   r   Úintr1   )r   rs   r   r6   r8   s        r   Úrecent_eventsrv   «   s“   € Ü	‹ð L�TØ�|‰|ð'Ø)2´C¸³JÐ(?óAçAIÁÃð 	÷Lð
 .2ö3Ø()ð �T‘7¨A¨nÑ,=ÀQÀwÁZÐYZÐ[aÑYbØ˜‘{ó$ò 3ð 3÷	Lð Lüò3s   ‹,A$ÁA0Á$A-c                  óÒ   — t        «       5 } | j                  dt        j                  «       t        z
  f«      j                  }| j                  «        d d d «       |S # 1 sw Y   S xY w)Nz&DELETE FROM shoot_events WHERE at_ts<?)r   r   rh   ÚEVENT_RETENTION_SECSÚrowcountr   )r   Úns     r   Úprune_eventsr{   ´   sV   € Ü	‹ð �TØ�L‰LÐAÄDÇIÁIÃKÔRfÑDfÐChÓi×rÑrˆØ�‰Œ÷ð €H÷ð €Hús   ‹AAÁA&c                   óÄ   — e Zd ZU eed<   eed<    ee¬«      Zee   ed<    ee¬«      Z	ee
eef      ed<   dZeed<   dZeee      ed	<   ed
efd„«       Zed
efd„«       Zy)ÚRunrg   r:   )Údefault_factoryÚbeforeÚitemsFÚclosedNÚfilesr   c                 ó:   — t        d„ | j                  D «       «      S )Nc              3   ó&   K  — | ]	  \  }}|–— Œ y ­w©Nr<   )Ú.0Ú_rz   s      r   ú	<genexpr>zRun.declared.<locals>.<genexpr>È   s   è ø€ Ò,™˜˜A”1Ñ,ùs   ‚©Úsumr€   ©Úselfs    r   ÚdeclaredzRun.declaredÆ   s   € äÑ, §¡Ô,Ó,Ð,r    c                 ó:   — t        d„ | j                  D «       «      S )Nc              3   ó:   K  — | ]  \  }}|t         k(  sŒd –— Œ y­w)r.   N)Ú
KIND_CHILD)r†   Úkr‡   s      r   rˆ   zRun.children.<locals>.<genexpr>Ì   s   è ø€ Ò?™˜˜A¨q´J«”1Ñ?ùs   ‚”r‰   r‹   s    r   ÚchildrenzRun.childrenÊ   s   € äÑ? §¡Ô?Ó?Ð?r    )Ú__name__Ú
__module__Ú__qualname__ru   Ú__annotations__r4   r   Úlistr   r€   Útupler�   Úboolr‚   r   Úpropertyr�   r’   r<   r    r   r}   r}   ½   s�   … àƒGØƒOÙ¨dÔ3€FˆD�‰IÓ3Ù#(¸Ô#>€Eˆ4��c˜3�h‘Ñ Ó>Ø€FˆDÓØ!%€Eˆ8�D˜‘IÑÓ%àð-˜#ò -ó ð-ð ð@˜#ò @ó ñ@r    r}   Úeventsc                 óü  — g }d}t        | d„ ¬«      D �]O  }|d   }|t        k(  rh|�|j                  sd|_        t        |d   |d   xs dt	        |j                  d	i «      j                  d
g «      «      ¬«      }|j                  |«       Œz|�|j                  rŒ‰|t        t        fv r3	 t        |d   «      }|dk\  sŒ¬|j                  j                  ||f«       ŒÊ|t        k(  r(|j                  sŒà|j                  j                  «        Œû|t        k(  s�Œd|_        |j                  d	i «      j                  d«      }t!        |t        «      rt	        |«      nd|_        �ŒR |S # t        t        f$ r Y �Œgw xY w)zDFold the event stream (in insertion order, never by time) into runs.Nc                 ó   — | d   S )Nrg   r<   )Úxs    r   ú<lambda>zbuild_runs.<locals>.<lambda>Ó   s
   € ¨!¨D©'€ r    ©r,   rd   Trg   re   r)   r   r   )rg   r:   r   r.   r‚   )ÚsortedÚ
KIND_CLASSr�   r}   r—   Úgetrp   r�   Ú	KIND_SKIPru   Ú	TypeErrorrT   r€   Ú	KIND_UNDOÚpopÚKIND_ENDÚ
isinstancer‚   )r›   Úrunsrj   Úerd   rz   r‚   s          r   Ú
build_runsr¬   Ï   sY  € à€DØ€CÜ�FÑ 1Ô2ó IˆØ�‰yˆØ”:ÒØˆ s§z¢zØ!�”
Ü˜˜4™¨Q¨x©[Ò->¸BÄtÈAÏEÉEÐRXÐZ\ÓL]×LaÑLaÐbjÐlnÓLoÓGpÔqˆCØ�K‰K˜ÕØˆ[˜CŸJšJØØ”j¤)Ð,Ñ,ðÜ˜˜(™Ó$�ð �A‹vØ—	‘	× Ñ  $¨ Õ+Ø”YÒØ�y‹yØ—	‘	—‘•Ø”XÔØˆCŒJØ—E‘E˜& "Ó%×)Ñ)¨'Ó2ˆEÜ'1°%¼Ô'>œ˜UœÀDˆCŽIð-Ið. €Køô œzÐ*ò Úðús   Â+E(Å(E;Å:E;c                 óH   — t        | «      }|r|d   j                  s|d   S d S )Néÿÿÿÿ)r¬   r�   )r›   rª   s     r   Úopen_runr¯   í   s'   € Ü�fÓ€DÙ D¨¡H§O¢Oˆ4�‰8Ð=¸Ð=r    rª   rO   c                 ó²   — t        «       }| D ]G  }|j                  sŒ|j                  |kD  sŒ |j                  sŒ-|j	                  |j                  «       ŒI |S )zOFiles already owned by a closed run that has not been turned into children yet.)Úsetr�   rg   r‚   Úupdate)rª   rO   rq   r8   s       r   Úclaimed_namesr³   ò   sG   € ä“E€CØò  ˆØ�8‹8˜Ÿ™˜yÓ(¨Q¯W«WØ�J‰J�q—w‘wÕð ð €Jr    Úpathsc                 ó<   ‡‡— dt         fd„Št        | ˆˆfd„¬«      S )zUThe camera's own capture order: EXIF time when present, then the (natural) file name.Únamec                 ó¦   — t        j                  d| «      D �cg c]-  }|j                  «       rt        |«      n|j	                  «       ‘Œ/ c}S c c}w )Nz(\d+))Úrer5   Úisdigitru   Úlower)r¶   Úts     r   Únaturalz#sort_capture_order.<locals>.naturalý   s9   € Ü>@¿h¹hÀxÐQUÓ>VÖW¸˜!Ÿ)™)œ+”�A”¨1¯7©7«9Ñ4ÒWÐWùÒWs   ™2Ac                 ó@   •—  ‰| «      xs d ‰| j                   «      fS )Nr   )r¶   )ÚpÚ	exif_timer¼   s    €€r   rŸ   z$sort_capture_order.<locals>.<lambda>ÿ   s   ø€ ©	°!«Ò(9¸¹7À1Ç6Á6»?Ð'K€ r    r    )r4   r¡   )r´   r¿   r¼   s    `@r   Úsort_capture_orderrÀ   û   s   ù€ ðX”có Xä�%ÔKÔLÐLr    c                 ó  — ddl m} ddlm} ddlm} |j                  D �ch c]  }|j                  «       ’Œ }} || «      }g }	 |j                  «       D ]‡  }	|	j                  «       sŒ|	j                  j                  «       |v sŒ1|	j                  j                  d«      rŒM|j                  | |	j                  «      |k(  sŒm|j                  |	j                  «       Œ‰ 	 t!        |«      S c c}w # t        $ r g cY S w xY w)zZImage files currently waiting in the school's FTP folder that belong to this photographer.r   )Úconfig)Úphotographer_service)Úincoming_dir_forú.)ÚcorerÂ   ÚservicesrÃ   Úservices.organizer_servicerÄ   ÚIMAGE_EXTENSIONSrº   ÚiterdirÚis_fileÚsuffixr¶   Ú
startswithÚresolve_photographerrp   ÚOSErrorr¡   )
r   rL   rÂ   rÃ   rÄ   r«   ÚextsÚfolderÚnamesÚfs
             r   Ú
pool_namesrÔ     sÒ   € åÝ-Ý;Ø%×6Ñ6Ö7˜!ˆA�G‰G�IÐ7€DÐ7Ù˜iÓ(€FØ€EðØ—‘Ó!ò 	%ˆAØ—	‘	• §¡§¡Ó 0°DÒ 8ÀÇÁ×ARÑARÐSVÕAWØ,×AÑAÀ)ÈQÏVÉVÓTÐXdÓdØ—‘˜QŸV™VÕ$ñ	%ô �%‹=Ðùò 8øô ò ØŠ	ðús/   ¡C+Á#C0 Á)C0 ÂC0 Â"C0 ÃC0 Ã0C>Ã=C>c                 óª  — t        | |«      }t        |«      }t        | |«      d   }|r|d   j                  s|d   nd}|€ddddddœS t	        t        | |«      «      }|t        ||«      z
  t	        |j                  «      z
  }|j                  |j                  dœ|j                  t        |«      |j                  |j                  t        |«      k(  dœS )zZWhat the phone shows while shooting: the open run, what was declared and what has arrived.rO   r®   Nr   T)Úactiver�   Úreceivedr’   Úok)r:   Úrun)rr   r¬   rW   r�   r±   rÔ   r³   r   r:   rg   r�   r0   r’   )r   rL   r›   rª   rO   rÙ   ÚpoolÚowns           r   Úlive_countsrÜ     sÊ   € ä˜	 <Ó0€FÜ�fÓ€DÜ˜) \Ó2°;Ñ?€IÙ 4¨¡8§?¢?ˆ$ˆrŠ(¸€CØ
€{Ø¨A¸1È!ÐSWÑXÐXÜŒz˜) \Ó2Ó3€DØ
”˜t YÓ/Ñ
/´#°c·j±j³/Ñ
A€CØ%(§^¡^¸C¿F¹FÑCÐQT×Q]ÑQ]Ü˜C›¨c¯l©lÀ#Ç,Á,ÔRUÐVYÓRZÑBZñ\ð \r    c           	      ó  — ddl m} ddlm} t	        «       5 } |||j                  | «      «      }|j                  d|ddt        «       | f«       |j                  d||f«       |j                  «        ddd«       |S # 1 sw Y   S xY w)z]A new family code attached to `class_name`, created by the shooting itself (nobody types it).r   )Úschool_service)Úgenerate_unique_codezYINSERT INTO families (code, family_name, email, created_at, school_id) VALUES (?,?,?,?,?)r)   Nz;INSERT INTO students (family_code, class_name) VALUES (?,?))	rÇ   rÞ   Úutils.code_generatorrß   r   Úcode_prefix_forr   r
   r   )r   r:   rÞ   rß   r   Úcodes         r   Úcreate_child_familyrã   $  sƒ   € å'Ý9Ü	‹ð �TÙ# D¨.×*HÑ*HÈÓ*SÓTˆØ�‰ÐpØ˜B ¤j£l°IÐ>ô	@à�‰ÐRÐUYÐ[eÐTfÔgØ�‰Œ÷ð €K÷ð €Kús   —AA=Á=B)r   N)NNr…   )é   )>Ú__doc__r2   rR   Úloggingr¸   r#   rh   Údataclassesr   r   Úpathlibr   Útypingr   Úcore.dbr   r   r	   Úcore.timeutilr
   Ú	getLoggerÚloggerr¢   r�   r¤   r¦   r¨   rx   ÚMAX_SKIPÚcompilerB   r   r4   r   r'   r9   r=   r˜   rG   r   r%   ÚdictrW   r\   ru   r`   rc   rk   Úfloatr—   rr   rv   r{   r}   r¬   r¯   r±   r³   rÀ   rÔ   rÜ   rã   r<   r    r   ú<module>rò      s@  ðñó, Û Û Û 	Û Û ß (Ý Ý ç 8Ñ 8Ý $à	ˆ×	Ñ	Ð+Ó	,€à9`Ñ 6€
ˆJ˜	 9¨hØ Ð Ø€àˆr�z‰zÐMÓN€ó
ð(/˜ð / ¨#¡ó /ð˜Cð  Có ð˜Cð  H¨S¡Mó ð 2 ð 2°ð 2¸ó 2ðE˜ð E ¨%°°S°©/Ñ!:ó Eð)�ð )˜ #™ó )ð�ð ˜Sð  Tó ð˜ð ¨Cð °Dó ðJ˜ð J¨Cð J¸ð JÀó Jð˜Cð ¨sð ¸Cð ÀHÈTÁNó ðT˜Cð T¨sð T¸Cð TÈ4ð TÐTXó Tð X\Ø(,ñE˜Cð E¨sð E¸#ð EÀxÐPSÁ}ð EØ ‘~ðEØ15óEñ˜#ð ¨Sð ¸À%¹ð ÐTXÐY]ÑT^ó ñ 3˜Sð 3¨ð 3°d¸4±jó 3ð�có ð ÷@ð @ó ð@ð"�t˜D‘zð  d¨3¡ió ð<>�T˜$‘Zð > H¨S¡Mó >ð
˜˜S™	ð ¨cð °c¸#±hó ðM˜d 4™jð M¸¸T¹
ó Mð˜#ð ¨Sð °T¸#±Yó ð$\˜3ð \¨cð \°dó \ð
 3ð 
°Cð 
¸Cô 
r    