§
    E«j7Ö  ã                   óÀ  — U d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	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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ZddlZddlZddlZddlZddl m!Z! ddl"m#Z#m$Z$m%Z% ddl&m'Z'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z. dd	l/m0Z0 dd
l1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9 ddl:m;Z;m<Z=m>Z>m?Z?m@Z@ ddlAmBZB ddlCmDZD ddlEmFZFmGZG ddlHmIZI ddlJmKZK ddlLmMZM ddlCmNZN ddlOmPZPmQZQmRZR ddlSmTZT eGejU                 ZVeReWd<   eMZXeReWd<    G d„ dePd¬¦  «        ZY G d„ deP¦  «        ZZ ej[        e\¦  «        Z] e^ej_         `                    ej_         a                    eb¦  «        d¦  «        ¦  «        5 Zc ejd        ec¦  «        ZeeZeWd<   ddd¦  «         n# 1 swxY w Y   eed         Zfd egfd!„Zhd“d"„Zid#ejd$eTdz  d dfd%„Zk ej        ejl        ek¦  «         d&e	jm        d egfd'„Znd(e6d&e	jm        d dfd)„Zod(e6d*ejp        d dfd+„Zqd,e9d-e$d.erd dfd/„Zsd0ejd1erdz  d2egd dfd3„Ztd4e8d0ejd5erdz  d6egd df
d7„Zud4e8d dfd8„Zv	 d”d&e	jm        d9e2d-e$d:ejd5erdz  d6egd;egd dfd<„Zwd=erd>exer         d dfd?„Zyd&e	jm        d9e2d-e$d@eVd(e6dAe7dBe8d,e9d;egd dfdC„ZzdDeXd>exer         d-e$d dfdE„Z{d(e6d e3fdF„Z|da}dDeXdGe3dAe7d@eVdHeYd>exer         dIejd dfdJ„Z~dKee4         d>exer         dIejdDeXdHeYd dfdL„Z€d&e	jm        d@eVd>exer         dIejd df
dM„Z�d&e	jm        d9e2dNe*d dfdO„Z‚d@eVdPe$d dfdQ„Zƒd&e	jm        dRerd egfdS„Z„d>exer         dRerdHeYdDeXd df
dT„Z…dGe3dDeXdHeYd-e$dUeer         dAe7d>exer         dKee4         d dfdV„Z†dGe3d-e$d egfdW„Z‡dGe3d&e	jm        d@eVdPe$d9e2dXeDeree*         f         dYe!d dfdZ„Zˆ ej‰        ejŠ        e‹d[e	jŒ        e	j�        ¬\¦  «        d&e	jm        dRerd(e6d9e2d-e$d@eVdAe7dBe8d,e9d dfd]„¦   «         ZŽd^ej�        d ejfd_„Z�d^ej�        d`ejd dfda„Z‘d^ej�        d dfdb„Z’dcee4         d dfdd„Z“dRerd erfde„Z”dferdge$dheDererf         d erfdi„Z•dje'dkerdlerdmej–        d df
dn„Z—d-e$dmej–        d^ej�        d ejp        fdo„Z˜dmej–        d dfdp„Z™dqeFeš         d e5fdr„Z›d^ej�        d ej–        fds„Zœd^ej�        dtej�        dz  dmej–        d egfdu„Z�d^ej�        dmej–        d egfdv„Zžd^ej�        d egfdw„ZŸdmej–        d^ej�        dtej�        dz  d&e	jm        dxegd egfdy„Z d(e6dAe7d^ej�        dxegdzerd,e9d dfd{„Z¡d|ej�        dtej�        dz  d egfd}„Z¢d^ej�        dmej–        d dfd~„Z£d&e	jm        d-e$d^ej�        dmej–        dej¤        d erfd€„Z¥d&e	jm        d-e$d^ej�        dmej–        dej¤        d erfd�„Z¦dd‚œd-e$dRerdƒerd„erd…erd†egd‡egd erfdˆ„Z§d‰ej¨        j�        d^ej�        d dfdŠ„Z©d^ej�        d eªererejz  f         fd‹„Z«dGe3d-e$d…erd dfdŒ„Z¬d erfd�„Z­dŽZ®d“d�„Z¯d“d�„Z°d“d‘„Z±d“d’„Z²dS )•z*The main module that controls lichess-bot.é    N)Úfind_variant)Úengine_wrapperÚmodelÚlichessÚmatchmaking)ÚOnlineBlocklist)Úload_configÚConfigurationÚ
log_config)ÚConversationÚChatLine)ÚTimerÚsecondsÚmsecÚhoursÚ
to_seconds)Ústop)ÚUserProfileTypeÚ	EventTypeÚGameTypeÚGameEventTypeÚCONTROL_QUEUE_TYPEÚCORRESPONDENCE_QUEUE_TYPEÚLOGGING_QUEUE_TYPEÚPGN_QUEUE_TYPE)ÚChunkedEncodingErrorÚConnectionErrorÚ	HTTPErrorÚReadTimeoutÚRequestException)ÚRichHandler)Údefaultdict)ÚIteratorÚMutableSequence)ÚRemoteDisconnected)ÚEmpty)ÚPool)ÚCounter)Ú	TypedDictÚcastÚ	TypeAlias)Ú	FrameTypeÚMULTIPROCESSING_LIST_TYPEÚ	POOL_TYPEc                   óx   — e Zd ZU dZej        ed<   eed<   eed<   e	ed<   e
ed<   eed<   eed<   eed	<   eed
<   dS )ÚPlayGameArgsTypezType hint for `play_game_args`.ÚliÚcontrol_queueÚuser_profileÚconfigÚchallenge_queueÚcorrespondence_queueÚlogging_queueÚ	pgn_queueÚgame_idN)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   ÚLichessÚ__annotations__r   r   r
   r-   r   r   r   Ústr© ó    ú*/app/lichess-bot-master/lib/lichess_bot.pyr0   r0   1   s�   € € € € € € Ø)Ð)àŒÐÐÑØ%Ð%Ð%Ñ%Ø!Ð!Ð!Ñ!ØÐÐÑØ.Ð.Ð.Ñ.Ø3Ð3Ð3Ñ3Ø%Ð%Ð%Ñ%ØÐÐÑØ€L€L�L€L€LrB   r0   F)Útotalc                   óF   — e Zd ZU dZeed<   eed<   eed<   ej        ed<   dS )ÚVersioningTypezAType hint for the versioning information from lib/versioning.yml.Úlichess_bot_versionÚminimum_python_versionÚdeprecated_python_versionÚdeprecation_dateN)r:   r;   r<   r=   r@   r?   ÚdatetimeÚdaterA   rB   rC   rF   rF   ?   sJ   € € € € € € ØKÐKàÐÐÑØÐÐÑØ"Ð"Ð"Ñ"Ø”mÐ#Ð#Ñ#Ð#Ð#rB   rF   zversioning.ymlÚversioning_inforG   Úreturnc                  ó   — t           j        S )z@Decide whether to restart lichess-bot when exiting main program.©r   ÚrestartrA   rB   rC   Úshould_restartrR   P   s
   € åŒ<ÐrB   c                  ó   — dt           _        dS )zFDisable restarting lichess-bot when errors occur. Used during testing.FNrP   rA   rB   rC   Údisable_restartrT   U   s   € à…D„L€L€LrB   ÚsignalÚframec                 óº   — t           j        s(t                               d¦  «         dt           _        dS t                               d¦  «         dt           _        dS )zTerminate lichess-bot.z$Received SIGINT. Terminating client.Tz%Received second SIGINT. Quitting now.N)r   Ú
terminatedÚloggerÚdebugÚ
force_quit)rU   rV   s     rC   Úsignal_handlerr\   Z   sH   € åŒ?ð Ý�ŠÐ;Ñ<Ô<Ð<Ø�Œˆˆå�ŠÐ<Ñ=Ô=Ð=Ø�ŒˆˆrB   r1   c                 ó¼   — 	 |                       ¦   «          n+# t          $ r t                               d¦  «         Y dS w xY wt                               d¦  «         dS )z%Upgrade the account to a BOT account.z!Failed to upgrade to Bot Account.Fz%Successfully upgraded to Bot Account!T)Úupgrade_to_bot_accountr   rY   Ú	exceptionÚinfo)r1   s    rC   Úupgrade_accountra   g   sm   € ðØ
×!Ò!Ñ#Ô#Ð#Ð#øÝð ð ð Ý×ÒÐ<Ñ=Ô=Ð=Øˆuˆuðøøøõ ‡K‚KÐ7Ñ8Ô8Ð8Øˆ4s   ‚ —$?¾?r2   c                 óD  — t           j        sü	 |                     ¦   «         5 }|                     ¦   «         }|D ]X}|r=t	          j        |                     d¦  «        ¦  «        }|                      |¦  «         ŒA|                      ddi¦  «         ŒY	 ddd¦  «         n# 1 swxY w Y   nR# t          $ rE t           
                    dt          j        ¦   «         › �¦  «         t          j        d¦  «         Y nw xY wt           j        ¯ü|                      ddi¦  «         dS )zPut the events in a queue.úutf-8ÚtypeÚpingNz$Control stream error, reconnecting:
é   rX   )r   rX   Úget_event_streamÚ
iter_linesÚjsonÚloadsÚdecodeÚ
put_nowaitÚ	ExceptionrY   ÚwarningÚ	tracebackÚ
format_excÚtimeÚsleep)r2   r1   ÚresponseÚlinesÚlineÚevents         rC   Úwatch_control_streamrw   s   s„  € åŒoð ð	Ø×$Ò$Ñ&Ô&ð C¨(Ø ×+Ò+Ñ-Ô-�Ø!ð Cð C�DØð CÝ $¤
¨4¯;ª;°wÑ+?Ô+?Ñ @Ô @˜Ø%×0Ò0°Ñ7Ô7Ð7Ð7à%×0Ò0°&¸&Ð1AÑBÔBÐBÐBðCðCð Cð Cñ Cô Cð Cð Cð Cð Cð Cð Cøøøð Cð Cð Cð Cøøõ ð 	ð 	ð 	Ý�NŠNÐ[Å9ÔCWÑCYÔCYÐ[Ð[Ñ\Ô\Ð\ÝŒJ�q‰MŒMˆMˆMˆMð	øøøõ Œoð ð ×Ò˜f lÐ3Ñ4Ô4Ð4Ð4Ð4s6   ŽB+ ¢A0BÂB+ ÂB#Â#B+ Â&B#Â'B+ Â+AC:Ã9C:Úperiodc                 óª   — t           j        sFt          j        t	          |¦  «        ¦  «         |                      ddi¦  «         t           j        ¯DdS dS )zÁ
    Tell the engine to check the correspondence games.

    :param control_queue: Queue to put events in.
    :param period: How many seconds to wait before sending a correspondence ping.
    rd   Úcorrespondence_pingN)r   rX   rq   rr   r   rl   )r2   rx   s     rC   Údo_correspondence_pingr{   †   sf   € õ Œoð BÝŒ
•:˜fÑ%Ô%Ñ&Ô&Ð&Ø× Ò  &Ð*?Ð!@ÑAÔAÐAõ Œoð Bð Bð Bð Bð BrB   r8   r4   Úusernamec                 óö   — 	 d}	 |                       ¦   «         }d}|rt          |||¦  «         n5# t          $ r Y n)t          $ r t                               d¦  «         Y nw xY w|r|                      ¦   «          Œy)z+Write PGN records to files as games finish.TFzCould not write PGN to file)ÚgetÚsave_pgn_recordÚInterruptedErrorrm   rY   r_   Ú	task_done)r8   r4   r|   Úmark_task_donerv   s        rC   Úwrite_pgn_recordsrƒ   ’   s¬   € ð"Øˆð	<Ø—M’M‘O”OˆEØ!ˆNØð 9Ý  v¨xÑ8Ô8Ð8øøÝð 	ð 	ð 	ØˆDÝð 	<ð 	<ð 	<Ý×ÒÐ:Ñ;Ô;Ð;Ð;Ð;ð	<øøøð ð 	"Ø×ÒÑ!Ô!Ð!ð"s   …)/ ¯
A!»#A!Á A!ÚlevelÚfilenameÚdisable_auto_logsc                 óL  — t          ¦   «         }t          j        d¦  «        }|                     |¦  «         |                     | ¦  «         |g}|rlt          j        |dd¬¦  «        }d}t          j        |¦  «        }|                     |¦  «         |                     | ¦  «         |                     |¦  «         |sÃt          j        t          d¬¦  «         t          j
                             t          d¦  «        }	t          j                             |	dddd	¬
¦  «        }
|
                     t          j        ¦  «         d}t          j        |¦  «        }|
                     |¦  «         |                     |
¦  «         t          j        t          j        |d¬¦  «         dS )a#  
    Configure the logger.

    :param level: The logging level. Either `logging.INFO` or `logging.DEBUG`.
    :param filename: The filename to write the logs to. If it is `None` then the logs aren't written to a file.
    :param disable_auto_logs: Whether to disable automatic logging.
    z%(message)sTrc   )ÚdelayÚencodingzH%(asctime)s %(name)s (%(filename)s:%(lineno)d) %(levelname)s %(message)s©Úexist_okzlichess-bot.logÚmidnighté   )rˆ   r‰   ÚwhenÚbackupCount)r„   ÚhandlersÚforceN)r!   ÚloggingÚ	FormatterÚsetFormatterÚsetLevelÚFileHandlerÚappendÚosÚmakedirsÚauto_log_directoryÚpathÚjoinr�   ÚTimedRotatingFileHandlerÚDEBUGÚbasicConfig)r„   r…   r†   Úconsole_handlerÚconsole_formatterÚall_handlersÚfile_handlerÚFORMATÚfile_formatterÚauto_log_filenameÚauto_file_handlers              rC   Úlogging_configurerr¨   ¤   s«  € õ "‘m”m€OÝÔ)¨-Ñ8Ô8ÐØ× Ò Ð!2Ñ3Ô3Ð3Ø×Ò˜UÑ#Ô#Ð#Ø+:Ð*;€Làð *ÝÔ*¨8¸4È'ÐRÑRÔRˆØ[ˆÝ Ô*¨6Ñ2Ô2ˆØ×!Ò! .Ñ1Ô1Ð1Ø×Ò˜eÑ$Ô$Ð$Ø×Ò˜LÑ)Ô)Ð)àð /Ý
ŒÕ&°Ð6Ñ6Ô6Ð6õ œGŸLšLÕ);Ð=NÑOÔOÐÝ#Ô,×EÒEÐFWØLPØOVØKUØRSð	 Fñ Uô UÐð
 	×"Ò"¥7¤=Ñ1Ô1Ð1à[ˆÝ Ô*¨6Ñ2Ô2ˆØ×&Ò& ~Ñ6Ô6Ð6Ø×ÒÐ-Ñ.Ô.Ð.åÔ�gœmØ!-Ø"ð$ñ $ô $ð $ð $ð $rB   ÚqueueÚlog_filenameÚdisable_auto_loggingc                 óN  — t          |||¦  «         t          j        ¦   «         }	 d}	 |                      d¬¦  «        }n:# t          $ r t          j        d¦  «         Y nt          $ r Y nt          $ r Y nw xY w|€ŒX| 	                    |¦  «         |  
                    ¦   «          Œ�)z¶
    Handle events from the logging queue.

    This allows the logs from inside a thread to be printed.
    They are added to the queue, so they are printed outside the thread.
    TNF)Úblockgš™™™™™¹?)r¨   r’   Ú	getLoggerr~   r&   rq   rr   r€   rm   Úhandler�   )r©   r„   rª   r«   rY   Útasks         rC   Úlogging_listener_procr±   Ð   sÔ   € õ �u˜lÐ,@ÑAÔAÐAÝÔÑ Ô €FðØ)-ˆð	Ø—9’9 5�9Ñ)Ô)ˆDˆDøÝð 	ð 	ð 	ÝŒJ�s‰OŒOˆOˆOˆOÝð 	ð 	ð 	ØˆDÝð 	ð 	ð 	ØˆDð	øøøð ˆ<Øà�Š�dÑÔÐØ�ŠÑÔÐðs   ©A  Á A7Á 	A7Á+	A7Á6A7c                 ó  — t           j                             | ¦  «        }t          j        ¦   «         }|j                             ¦   «          |                     |¦  «         |                     t           j        ¦  «         dS )zConfigure the game logger.N)r’   r�   ÚQueueHandlerr®   ÚclearÚ
addHandlerr•   rž   )r©   ÚhÚroots      rC   Úthread_logging_configurerr¸   ì   sf   € åÔ×%Ò% eÑ,Ô,€AÝÔÑÔ€DØ„M×ÒÑÔÐØ‡O‚O�AÑÔÐØ‡M‚M•'”-Ñ Ô Ð Ð Ð rB   r3   Úlogging_levelÚone_gamec                 ón  — t                                d|j        › d�¦  «         t          j        ¦   «         }|                     ¦   «         }|                     ¦   «         }	t          j        t          |	| f¬¦  «        }
|
 	                    ¦   «          t          j        t          |	t          |j        j        ¦  «        f¬¦  «        }| 	                    ¦   «          |                     ¦   «         }|                     ¦   «         }t          j        t          ||||f¬¦  «        }| 	                    ¦   «          |                     ¦   «         }t          j        t          |||d         f¬¦  «        }| 	                    ¦   «          t!          |¦  «         	 t#          | ||||	||||¦	  «	         |
                     ¦   «          |
                     ¦   «          |                     ¦   «          |                     ¦   «          t)          j        d¦  «         t-          |||¦  «         |                     ¦   «          |                     ¦   «          |                     ¦   «          |                     ¦   «          dS # |
                     ¦   «          |
                     ¦   «          |                     ¦   «          |                     ¦   «          t)          j        d¦  «         t-          |||¦  «         |                     ¦   «          |                     ¦   «          |                     ¦   «          |                     ¦   «          w xY w)aF  
    Start lichess-bot.

    :param li: Provides communication with lichess.org.
    :param user_profile: Information on our bot.
    :param config: The config that the bot will use.
    :param logging_level: The logging level. Either `logging.INFO` or `logging.DEBUG`.
    :param log_filename: The filename to write the logs to. If it is `None` then the logs aren't written to a file.
    :param disable_auto_logging: Whether to disable automatic logging.
    :param one_game: Whether the bot should play only one game. Only used in `test_bot/test_bot.py` to test lichess-bot.
    zYou're now connected to z and awaiting challenges.)ÚtargetÚargsr|   g      ð?N)rY   r`   ÚurlÚmultiprocessingÚManagerÚlistÚQueueÚProcessrw   Ústartr{   r   ÚcorrespondenceÚcheckin_periodr±   rƒ   r¸   Úlichess_bot_mainÚ	terminaterœ   rq   rr   r¨   )r1   r3   r4   r¹   rª   r«   rº   Úmanagerr5   r2   Úcontrol_streamÚcorrespondence_pingerr6   r7   Úlogging_listenerr8   Úpgn_listeners                    rC   rÄ   rÄ   õ   s(  € õ ‡K‚KÐP¨6¬:ÐPÐPÐPÑQÔQÐQÝÔ%Ñ'Ô'€GØ18·²±´€OØ(/¯ª©¬€MÝ$Ô,Õ4HÐP]Ð_aÐObÐcÑcÔc€NØ×ÒÑÔÐÝ+Ô3Õ;QØ:GÝ:AÀ&ÔBWÔBfÑ:gÔ:gð:iðjñ jô jÐð ×ÒÑ!Ô!Ð!Ø6=·m²m±o´oÐà—M’M‘O”O€MÝ&Ô.Õ6KØ5BØ5BØ5AØ5Ið5KðLñ Lô LÐð
 ×ÒÑÔÐà—’‘”€IÝ"Ô*Õ2CØ1:Ø17Ø1=¸jÔ1Ið1KðLñ Lô L€Lð ×ÒÑÔÐå˜mÑ,Ô,Ð,ðÝ˜Ø%ØØ(Ø&Ø-Ø&Ø"Ø!ñ	#ô 	#ð 	#ð 	× Ò Ñ"Ô"Ð"Ø×ÒÑÔÐØ×'Ò'Ñ)Ô)Ð)Ø×"Ò"Ñ$Ô$Ð$ÝŒ
�3‰ŒˆÝ˜=¨,Ð8LÑMÔMÐMØ×"Ò"Ñ$Ô$Ð$Ø×ÒÑÔÐØ×ÒÑ Ô Ð Ø×ÒÑÔÐÐÐøð 	× Ò Ñ"Ô"Ð"Ø×ÒÑÔÐØ×'Ò'Ñ)Ô)Ð)Ø×"Ò"Ñ$Ô$Ð$ÝŒ
�3‰ŒˆÝ˜=¨,Ð8LÑMÔMÐMØ×"Ò"Ñ$Ô$Ð$Ø×ÒÑÔÐØ×ÒÑ Ô Ð Ø×ÒÑÔÐÐøøøs   ÆI- É-CL4ÚchangeÚactive_gamesc           	      ó‚   — | dk    rdnd}t                                |› d| › dt          |¦  «        › d|pd› �¦  «         dS )z·
    Log the number of active games and their IDs.

    :param change: Either "Freed", "Used", or "Queued".
    :param active_games: A set containing the IDs of the active games.
    ÚFreedz+++z---z	 Process z	. Count: z. IDs: N)rY   r`   Úlen)rÎ   rÏ   Úsymbols      rC   Úlog_proc_countrÔ   6  s[   € ð  Ò'Ð'ˆUˆU¨U€FÝ
‡K‚K�6ÐeÐe FÐeÐeµS¸Ñ5FÔ5FÐeÐeÈ|ÐOcÐ_cÐeÐeÑfÔfÐfÐfÐfrB   r5   r6   r7   c	                 óÐ  ‡— |j         j        }	d}
|                      ¦   «         pg }t          |¦  «         d„ |D ¦   «         Šˆfd„|D ¦   «         }g }t	          t          d¦  «        ¦  «        }t          j        | ||¦  «        }|                     ¦   «          t          | |||||||¬¦  «        }t          t          ¦  «        }t          |j         j        ¦  «        }|j        r4t                               d¦  «         t                               d¦  «         t"          j                             |	dz   ¦  «        5 }t(          j        �s÷|r|
�sòt(          j        �såt/          |¦  «        }|sŒ1|d         d	k    r"d
t(          _        |                     ¦   «          �n¥|d         dk    rH|                     |d         d         ¦  «         |                     ¦   «          t7          d|¦  «         d
}
n¾|d         dk    rt9          || ||j         |||¦  «         n—|d         dk    r|                     |¦  «         nu|d         dk    r2|                     |d         d         ¦  «         t7          d|¦  «         n7|d         dk    r+|                     |¦  «         t?          ||||‰|||¦  «         tA          |||	||¦  «         tC          |||||||	¦  «         tE          | |||	¦  «         |                      |||	¦  «         tG          | ||¦  «         |                     ¦   «          t(          j        s|r|
st(          j        �¯åtI          |||¦  «         ddd¦  «         dS # 1 swxY w Y   dS )až  
    Handle all the games and challenges.

    :param li: Provides communication with lichess.org.
    :param user_profile: Information on our bot.
    :param config: The config that the bot will use.
    :param challenge_queue: The queue containing the challenges.
    :param control_queue: The queue containing all the events.
    :param correspondence_queue: The queue containing the correspondence games.
    :param logging_queue: The logging queue. Used by `logging_listener_proc`.
    :param pgn_queue: The queue containing the PGN games.
    :param one_game: Whether the bot should play only one game. Only used in `test_bot/test_bot.py` to test lichess-bot.
    Fc                 ó6   — g | ]}|d          dk    ¯|d         ‘ŒS )ÚspeedrÅ   ÚgameIdrA   ©Ú.0Úgames     rC   ú
<listcomp>z$lichess_bot_main.<locals>.<listcomp>]  s9   € ð $Jð $Jð $JØ(,Ø'+¨G¤}Ð8HÒ'HÐ'Hð %)¨¤Nà'HÐ'HÐ'HrB   c                 ó4   •— h | ]}|d          ‰v¯|d          ’ŒS ©rØ   rA   )rÚ   rÛ   Ústartup_correspondence_gamess     €rC   ú	<setcomp>z#lichess_bot_main.<locals>.<setcomp>`  s:   ø€ ð Kð Kð KØØ˜H”~Ð-IÐIÐIð ˜”NàIÐIÐIrB   rf   )r1   r2   r3   r4   r5   r6   r7   r8   zKWhen quitting, lichess-bot will first wait for all running games to finish.z'Press Ctrl-C twice to quit immediately.rd   rX   TÚlocal_game_donerÛ   ÚidrÑ   Ú	challengeÚchallengeDeclinedÚchallengeCanceledÚ	gameStartN)%rã   ÚconcurrencyÚget_ongoing_gamesÚprune_takeback_recordsr   r   r   ÚMatchmakingÚshow_earliest_challenge_timer0   r"   rÁ   r   Úonline_block_listÚquit_after_all_games_finishrY   r`   r¿   Úpoolr'   r   rX   rQ   Ú
next_eventr�   ÚdiscardÚ	game_donerÔ   Úhandle_challengeÚdeclined_challengeÚaccepted_challengeÚ
start_gameÚstart_low_time_gamesÚ check_in_on_correspondence_gamesÚaccept_challengesÚcheck_online_statusÚ
close_pool)r1   r3   r4   r5   r2   r6   r7   r8   rº   Ú	max_gamesÚone_game_completedÚ	all_gamesrÏ   Úlow_time_gamesÚlast_check_online_timeÚ
matchmakerÚplay_game_argsÚrecent_bot_challengesrì   rî   rv   rß   s                        @rC   rÇ   rÇ   A  sD  ø€ ð, Ô Ô,€IàÐà×$Ò$Ñ&Ô&Ð,¨"€IÝ˜9Ñ%Ô%Ð%ð$Jð $JØ09ð$Jñ $Jô $JÐ ðKð Kð Kð KØ )ðKñ Kô K€Lð &(€Nå"¥5¨¡8¤8™_œ_ÐÝÔ(¨¨V°\ÑBÔB€JØ×+Ò+Ñ-Ô-Ð-å%¨¸=ÐWcØ-3À_Ø;OÐ_lØ09ð;ñ ;ô ;€Nõ
 <GÅtÑ;LÔ;LÐå'¨Ô(8Ô(JÑKÔKÐàÔ)ð ?Ý�ŠÐaÑbÔbÐbÝ�ŠÐ=Ñ>Ô>Ð>å	Ô	×	"Ò	" 9¨q¡=Ñ	1Ô	1ð 6/°TÝ”?ñ 3	& xð 3	&Ð4Fñ 3	&Í4Ì<ñ 3	&Ý˜}Ñ-Ô-ˆEØð Øà�VŒ} Ò,Ð,Ø#•”Ø×'Ò'Ñ)Ô)Ð)Ùà�VŒ}Ð 1Ò1Ð1Ø×$Ò$ U¨6¤]°4Ô%8Ñ9Ô9Ð9Ø×$Ò$Ñ&Ô&Ð&Ý˜w¨Ñ5Ô5Ð5Ø%)Ð"Ð"Ø�v” +Ò-Ð-Ý  Ø!#Ø!0Ø!'Ô!1Ø!-Ø!6Ø!2ñ4ô 4ð 4ð 4ð �v”Ð"5Ò5Ð5Ø×-Ò-¨eÑ4Ô4Ð4Ð4Ø�v”Ð"5Ò5Ð5Ø×$Ò$ U¨;Ô%7¸Ô%=Ñ>Ô>Ð>Ý˜w¨Ñ5Ô5Ð5Ð5Ø�v” +Ò-Ð-Ø×-Ò-¨eÑ4Ô4Ð4Ý˜5ØØ)Ø!Ø7Ø/Ø'Ø)ñ+ô +ð +õ ! °¸yÈ$ÐP^Ñ_Ô_Ð_Ý,¨TØ-2Ø-AØ-<Ø-;Ø-9Ø-6ñ8ô 8ð 8õ ˜b /°<ÀÑKÔKÐKØ× Ò  ¨À	ÑJÔJÐJÝ  LÐ2HÑIÔIÐIà×#Ò#Ñ%Ô%Ð%õg ”?ð 3	& xð 3	&Ð4Fð 3	&Í4Ì<ñ 3	&õj 	�4˜ vÑ.Ô.Ð.ðm6/ð 6/ð 6/ñ 6/ô 6/ð 6/ð 6/ð 6/ð 6/ð 6/ð 6/ð 6/øøøð 6/ð 6/ð 6/ð 6/ð 6/ð 6/s   Ä8HMÍMÍ"Mrî   c                 ó    — |j         rF|rt                               d¦  «         |                      ¦   «          |                      ¦   «          dS dS )zXShut down pool after possibly waiting on games to finish depending on the configuration.z,Waiting for games to finish before quitting.N)rí   rY   r`   Úcloserœ   )rî   rÏ   r4   s      rC   rú   rú   ¯  sQ   € àÔ)ð Øð 	HÝ�KŠKÐFÑGÔGÐGØ�
Š
‰ŒˆØ�	Š	‰Œˆˆˆð	ð rB   c                 óf  — 	 |                       ¦   «         }|€i S n# t          $ r i cY S w xY wd|vrJt                               d¦  «         t                               |¦  «         |                      ¦   «          i S |                      d¦  «        dk    rt                               d|› �¦  «         |S )z*Get the next event from the control queue.Nrd   z+Unable to handle response from lichess.org:re   zEvent: )r~   r€   rY   rn   r�   rZ   )r2   rv   s     rC   rï   rï   ¸  sË   € ðØ×!Ò!Ñ#Ô#ˆØˆ=ØˆIð øåð ð ð Øˆ	ˆ	ˆ	ðøøøð �UÐÐÝ�ŠÐDÑEÔEÐEÝ�Š�uÑÔÐØ×ÒÑ!Ô!Ð!Øˆ	à‡y‚y�ÑÔ˜FÒ"Ð"Ý�ŠÐ&˜uÐ&Ð&Ñ'Ô'Ð'à€Ls   ‚ ›*©*rv   r  rû   c                 óx  — |d         dk    r|                      ¦   «         an|d         dk    rdS |rdS t          |¦  «        |k     rot          dk    rh|                     ¦   «         }t          dz  a|                     ¦   «          t          |||| ¦  «         t          |¦  «        |k     rt          dk    °bdS dS dS dS )zStart correspondence games.rd   rz   rá   Nr   rf   )ÚqsizeÚcorrespondence_games_to_startrÒ   Ú
get_nowaitr�   Ústart_game_thread)rî   rv   r6   r5   r  rÏ   rû   r9   s           rC   r÷   r÷   Ð  sã   € ð ˆV„}Ð-Ò-Ð-Ø(<×(BÒ(BÑ(DÔ(DÐ%Ð%Ø	ˆvŒÐ+Ò	+Ð	+Øˆàð Øˆå
ˆlÑ
Ô
˜iÒ
'Ð
'Õ,IÈAÒ,MÐ,MØ&×1Ò1Ñ3Ô3ˆÝ%¨Ñ*Ð%Ø×&Ò&Ñ(Ô(Ð(Ý˜,¨°ÀÑFÔFÐFõ	 ˆlÑ
Ô
˜iÒ
'Ð
'Õ,IÈAÒ,MÐ,MÐ,MÐ,MÐ
'Ð
'Ð
'Ð
'Ð,MÐ,MrB   rþ   c                 óî   — |                       d„ ¬¦  «         | rWt          |¦  «        |k     rH|                      d¦  «        d         }t          ||||¦  «         | rt          |¦  «        |k     °BdS dS dS dS )z4Start the games based on how much time we have left.c                 óB   — |                       dt          j        ¦  «        S )NÚsecondsLeft)r~   ÚmathÚinf)Úgs    rC   ú<lambda>z&start_low_time_games.<locals>.<lambda>ì  s   €  a§e¢e¨M½4¼8Ñ&DÔ&D€ rB   )Úkeyr   râ   N)ÚsortrÒ   Úpopr
  )rþ   rÏ   rû   rî   r  r9   s         rC   rö   rö   é  s§   € ð ×ÒÐDÐDÐÑEÔEÐEØ
ð G�S Ñ.Ô.°Ò:Ð:Ø ×$Ò$ QÑ'Ô'¨Ô-ˆÝ˜,¨°ÀÑFÔFÐFð ð G�S Ñ.Ô.°Ò:Ð:Ð:Ð:ð Gð Gð Gð GÐ:Ð:rB   c                 ó8  — t          |¦  «        |k     �r|�r |                     d¦  «        }|j        rŒ4	 t                               d|› �¦  «         |                      |j        ¦  «         |                     |j        ¦  «         t          d|¦  «         ng# t          t          f$ rS}t          |t          ¦  «        r4|j        �-|j        j        dk    rt                               d|› �¦  «         Y d}~nd}~ww xY wt          |¦  «        |k     r|°üdS dS dS dS )zAccept a challenge.r   zAccept ÚQueuedNi”  zSkip missing )rÒ   r  Ú	from_selfrY   r`   Úaccept_challengerâ   ÚaddrÔ   r   r   Ú
isinstancers   Ústatus_code)r1   r5   rÏ   rû   Úchlngr_   s         rC   rø   rø   ò  s=  € õ ˆlÑ
Ô
˜iÒ
'Ñ
'¨OÑ
'Ø×#Ò# AÑ&Ô&ˆØŒ?ð 	Øð	5Ý�KŠKÐ) %Ð)Ð)Ñ*Ô*Ð*Ø×Ò ¤Ñ)Ô)Ð)Ø×Ò˜UœXÑ&Ô&Ð&Ý˜8 \Ñ2Ô2Ð2Ð2øÝ�;Ð'ð 	5ð 	5ð 	5Ý˜)¥YÑ/Ô/ð 5°IÔ4FÐ4RÐW`ÔWiÔWuÐy|ÒW|ÐW|Ý—’Ð3¨EÐ3Ð3Ñ4Ô4Ð4øøøøøøøøøð	5øøøõ ˆlÑ
Ô
˜iÒ
'Ð
'¨OÐ
'Ð
'Ð
'Ð
'Ð
'Ð
'Ð
'Ð
'Ð
's   ¶A!B ÂC<Â)A	C7Ã7C<rÿ   c                 ó  — |                      ¦   «         rp	 |                      |d         ¦  «        s&t                               d¦  «         dt          _        |                     ¦   «          dS # t          t          f$ r Y dS w xY wdS )zQCheck if lichess.org thinks the bot is online or not. If it isn't, we restart it.râ   zWill restart lichess-botTN)	Ú
is_expiredÚ	is_onlinerY   r`   r   rQ   Úresetr   r   )r1   r3   rÿ   s      rC   rù   rù     s—   € à×(Ò(Ñ*Ô*ð ð	Ø—<’< ¨TÔ 2Ñ3Ô3ð $Ý—’Ð6Ñ7Ô7Ð7Ø#•”Ø"×(Ò(Ñ*Ô*Ð*Ð*Ð*øÝ�;Ð'ð 	ð 	ð 	ØˆDˆDð	øøøðð s   –AA- Á-BÂBÚchallenge_configc                 óÐ   — t          | ¦  «        }|j        dk    r|                     d„ d¬¦  «         |j        dk    r!|                     d„ |j        dk    ¬¦  «         || dd…<   dS )	zé
    Sort the challenges.

    They can be sorted either by rating (the best challenger is accepted first),
    or by time (the first challenger is accepted first). The bot can also
    prioritize playing against humans or bots.
    Úbestc                 ó*   — |                       ¦   «         S ©N)Úscore©Ú
challengers    rC   r  z!sort_challenges.<locals>.<lambda>  s   € °:×3CÒ3CÑ3EÔ3E€ rB   T)r  ÚreverseÚnonec                 ó   — | j         j        S r%  )r(  Úis_botr'  s    rC   r  z!sort_challenges.<locals>.<lambda>  s   € °:Ô3HÔ3O€ rB   ÚbotN)rÁ   Úsort_byr  Ú
preference)r5   r!  Úchallenge_lists      rC   Úsort_challengesr1    s…   € õ ˜/Ñ*Ô*€NØÔ 6Ò)Ð)Ø×ÒÐ EÐ EÈtÐÑTÔTÐTØÔ" fÒ,Ð,Ø×ÒÐ OÐ OÐYiÔYtÐx}ÒY}ÐÑ~Ô~Ð~Ø'€O�A�A�AÑÐÐrB   r9   c                 óN   — |                       ¦   «         }|€dS |d„ |D ¦   «         v S )z*Determine if a game is still being played.NTc              3   ó&   K  — | ]}|d          V — ŒdS )rØ   NrA   )rÚ   Úongoing_games     rC   ú	<genexpr>z!game_is_active.<locals>.<genexpr>%  s'   è è € ÐOÐO°,�| HÔ-ÐOÐOÐOÐOÐOÐOrB   )rè   )r1   r9   rÏ   s      rC   Úgame_is_activer6     s8   € à×'Ò'Ñ)Ô)€LØÐØˆtØÐOÐOÀ,ÐOÑOÔOÐOÐOrB   c                 ó¸   ‡‡— |                       ‰¦  «         t          d| ¦  «         ‰‰d<   dt          ddfˆˆfd„}|                     t          ‰|¬¦  «         dS )zStart a game thread.ÚUsedr9   ÚerrorrN   Nc           	      ó  •— t                                d| ¬¦  «         ‰d         }‰d         }‰d         }|                     dd‰idœ¦  «         |                     d	‰|                     ‰¦  «        t	          |‰¦  «         d
œi¦  «         d S )NzGame ended due to error:)Úexc_infor2   r8   r1   rá   râ   ©rd   rÛ   rÛ   ©râ   ÚpgnÚcomplete)rY   r_   rl   Úget_game_pgnr6  )r9  r2   r8   r1   r9   r  s       €€rC   Úgame_error_handlerz-start_game_thread.<locals>.game_error_handler.  s¸   ø€ Ý×ÒÐ3¸eÐÑDÔDÐDØ& Ô7ˆØ" ;Ô/ˆ	Ø˜DÔ!ˆØ× Ò Ð*;ÀdÈGÀ_Ð!UÐ!UÑVÔVÐVØ×Ò˜f¨WØ.0¯oªo¸gÑ.FÔ.FÝ7EÀbÈ'Ñ7RÔ7RÐ3Rð'Tð 'Tð Uñ 	Vô 	Vð 	Vð 	Vð 	VrB   )ÚkwdsÚerror_callback)r  rÔ   ÚBaseExceptionÚapply_asyncÚ	play_game)rÏ   r9   r  rî   rA  s    ``  rC   r
  r
  (  s�   øø€ à×Ò�WÑÔÐÝ�6˜<Ñ(Ô(Ð(Ø '€N�9ÑðV¥-ð V°Dð Vð Vð Vð Vð Vð Vð Vð 	×Ò•YØ(Ø$6ð ñ 8ô 8ð 8ð 8ð 8rB   rß   c                 ó”  — | d         d         }||v r£t          | |¦  «        r;t                               d|j        |z   › �¦  «         |                     |¦  «         nAt                               d|j        |z   › d�¦  «         |                     | d         ¦  «         |                     |¦  «         dS t          ||||¦  «         dS )av  
    Start a game.

    :param event: The gameStart event.
    :param pool: The thread pool that the game is added to, so they can be run asynchronously.
    :param play_game_args: The args passed to `play_game`.
    :param config: The config the bot will use.
    :param startup_correspondence_games: A list of correspondence games that have to be started.
    :param correspondence_queue: The queue that correspondence games are added to, to be started.
    :param active_games: A set of all the games that aren't correspondence games.
    :param low_time_games: A list of games, in which we don't have much time remaining.
    rÛ   râ   z--- Enqueue z--- Will start z as soon as possibleN)Úenough_time_to_queuerY   r`   r¾   rl   r—   Úremover
  )	rv   rî   r  r4   rß   r6   rÏ   rþ   r9   s	            rC   rõ   rõ   =  sÚ   € ð( �FŒm˜DÔ!€GØÐ.Ð.Ð.Ý  vÑ.Ô.ð 	1Ý�KŠKÐ= v¤z°GÑ';Ð=Ð=Ñ>Ô>Ð>Ø ×+Ò+¨GÑ4Ô4Ð4Ð4å�KŠKÐT¨&¬*°wÑ*>ÐTÐTÐTÑUÔUÐUØ×!Ò! %¨¤-Ñ0Ô0Ð0Ø$×+Ò+¨GÑ4Ô4Ð4Ð4Ð4å˜,¨°ÀÑFÔFÐFÐFÐFrB   c                 óž   — |j         }|j        |j        z   dz  }| d         }|d          p#|                     dt          j        ¦  «        |k    S )zGCheck whether the correspondence must be started now or if it can wait.é
   rÛ   ÚisMyTurnr  )rÅ   rÆ   Ú	move_timer~   r  r  )rv   r4   Úcorr_cfgÚminimum_timerÛ   s        rC   rH  rH  ^  sP   € àÔ$€HØÔ+¨hÔ.@Ñ@ÀBÑF€LØ�Œ=€DØ�JÔÐÐS 4§8¢8¨M½4¼8Ñ#DÔ#DÀ|Ò#SÐSrB   r  rì   c                 óh  — t          j        | d         |¦  «        }|j        rdS |                     ¦   «         pg }t	          d„ |D ¦   «         ¦  «        }	|	                     d„ |D ¦   «         ¦  «         |                     ¦   «          |                     |||	||¦  «        \  }
}|
rq|                     |¦  «         t          ||¦  «         |j
        }|�A||j        j                                      t          t          |¦  «        ¦  «        ¦  «         dS dS |                     |j        |¬¦  «         dS )zXHandle incoming challenges. It either accepts, declines, or queues them to accept later.rã   Nc              3   ó2   K  — | ]}|d          d         V — ŒdS )Úopponentr|   NrA   rÙ   s     rC   r5  z#handle_challenge.<locals>.<genexpr>o  s,   è è € Ð"YÐ"YÀD 4¨
Ô#3°JÔ#?Ð"YÐ"YÐ"YÐ"YÐ"YÐ"YrB   c              3   ó.   K  — | ]}|j         j        V — Œd S r%  )r(  Úname)rÚ   rã   s     rC   r5  z#handle_challenge.<locals>.<genexpr>p  s(   è è € Ð[Ð[¸i 	Ô 4Ô 9Ð[Ð[Ð[Ð[Ð[Ð[rB   )Úreason)r   Ú	Challenger  rè   r(   ÚupdateÚrefreshÚis_supportedr—   r1  Úrecent_bot_challenge_ager(  rT  r   r   Údecline_challengerâ   )rv   r1   r5   r!  r3   r  rì   r  rÏ   Úopponent_engagementsrY  Údecline_reasonÚtime_windows                rC   rò   rò   f  sY  € õ ŒO˜E +Ô.°Ñ=Ô=€EØ„ð Øˆà×'Ò'Ñ)Ô)Ð/¨R€LÝ"Ð"YÐ"YÈLÐ"YÑ"YÔ"YÑYÔYÐØ×ÒÐ[Ð[È?Ð[Ñ[Ô[Ñ[Ô[Ð[à×ÒÑÔÐà#(×#5Ò#5Ð6FØ6KØ6JØ6GØ6Bñ	$Dô $DÑ €L�.ð
 ð >Ø×Ò˜uÑ%Ô%Ð%Ý˜Ð)9Ñ:Ô:Ð:Ø&Ô?ˆØÐ"Ø! %Ô"2Ô"7Ô8×?Ò?ÅÅgÈkÑFZÔFZÑ@[Ô@[Ñ\Ô\Ð\Ð\Ð\ð #Ð"ð 	×Ò˜UœX¨nÐÑ=Ô=Ð=Ð=Ð=rB   iX  )Úmax_timeÚgiveupÚ
on_backoffc	                 óZ  — t          |¦  «         t          j        t          ¦  «        }	|                      |¦  «        5 }
|
                     ¦   «         }t          j        t          |¦  «         	                    d¦  «        ¦  «        }|	 
                    d|› �¦  «         t          |j        ¦  «        }t          j        ||d         | j        |¦  «        }t!          j        ||¦  «        5 }|                     |¦  «         |	 
                    d|› d|                     ¦   «         › �¦  «         t)          ||| t*          |¦  «        }|	                     d|› �¦  «         |j        dk    }|j        }t          |j        ¦  «        }t          |j        ¦  «        }|j        }|r|n|}|j        p|j        }t=          |j        ¦  «        }t=          |j         ¦  «        }tC          |¦  «        }|j"        }tG          tH          |j%        j&        |j'        j&        ¬¦  «        }tQ          d	|j)        |¦  «        }tQ          d
|j)        |¦  «        }tQ          d|j)        |¦  «        }tQ          d|j)        |¦  «        } |j*         +                    d¦  «        s|nt          d¦  «        }!d}"tY          j-        ¦   «         }#t]          j/        t          j0        |j*        ¦  «         1                    d¦  «        g|¦  «        }$|j2        }%d}&|&�rGtf          j4        r|%�r8tf          j5        �s+d}'	 tm          |$¦  «        }(|(r|(d         nd})|)dk    r$| 7                    tq          |(¦  «        ¦  «         �n`|)dk    �r>|(|_*        ts          |¦  «        }#|j:        r|j*         +                    d¦  «        n|j*         +                    d¦  «        }*tw          |¦  «        s“ty          ||"|#¦  «        r‚|}!t{          ||||#¦  «         t}          ¦   «         }+t          |#¦  «         d}'| @                    |#|| |+|||||tƒ          ||#|¦  «        ¦
  «
         t…          jC        t‰          |¦  «        ¦  «         n¼tw          |¦  «        rSt‹          ||#¦  «         | F                    ||#¦  «         | G                    d|¦  «         | G                    d| ¦  «         nZ|*rXt‘          ||#¦  «        sH|  I                    |jJ        ||k     ¦  «        r)|dz  }t—          ||¦  «         | L                    ¦   «          |(t!          jM        |#¦  «                 },|(t!          jN        |#¦  «                 }-t=          |,¦  «        t=          |-¦  «        z   t          d¦  «        z   }.| O                    ||.|!¦  «         t¡          jQ        |¦  «        }"n|)dk    rt¥          |#||"| |¦  «        rd}&ne# t¦          t¨          tª          t¬          t®          t°          f$ r9}/t³          |/t°          ¦  «        }0|0 o|'ptµ          | |jJ        ¦  «        }&Y d}/~/nd}/~/ww xY w|&rtf          j4        r|%rtf          j5        �¯+t·          | |||#|¦  «        }1ddd¦  «         n# 1 swxY w Y   t¹          |||||1|¦  «         t»          |¦  «         ddd¦  «         dS # 1 swxY w Y   dS )a^  
    Play a game.

    :param li: Provides communication with lichess.org.
    :param game_id: The id of the game.
    :param control_queue: The control queue that contains events (adds `local_game_done` to the queue).
    :param user_profile: Information on our bot.
    :param config: The config that the bot will use.
    :param challenge_queue: The queue containing the challenges.
    :param correspondence_queue: The queue containing the correspondence games.
    :param logging_queue: The logging queue. Used by `logging_listener_proc`.
    :param pgn_queue: The queue containing the PGN games.
    rc   zInitial state: r|   zThe engine for game z	 has pid=z+++ rÅ   )ÚmerR  ÚhelloÚgoodbyeÚhello_spectatorsÚgoodbye_spectatorsÚmovesr   NTFrd   re   ÚchatLineÚ	gameStateÚ	btakebackÚ	wtakebackÚplayerÚ	spectatorrf   é<   )^r¸   r’   r®   r:   Úget_game_streamrh   ri   rj   Únextrk   rZ   r   Ú
abort_timer   ÚGameÚbaseUrlr   Úcreate_engineÚget_opponent_infoÚget_pidr   Ú__version__r`   r×   rÅ   rM  Údisconnect_timeÚengineÚ
uci_ponderÚponderr   Úmove_overheadÚrate_limiting_delayÚread_takeback_recordÚmax_takebacks_acceptedr"   r@   rc  rT  rR  Úget_greetingÚgreetingÚstater~   ÚchessÚBoardÚ	itertoolsÚchainÚdumpsÚencoderí   r   rX   r[   Únext_updateÚreactr   Úsetup_boardÚis_whiteÚis_game_overÚis_engine_moveÚ	say_hellor   Úprint_move_numberÚ	play_moveÚfake_think_timerq   rr   r   Útell_user_game_resultÚsend_game_resultÚsend_messageÚbot_to_moveÚaccept_takebackrâ   Úrecord_takebackÚdiscard_last_move_commentaryÚwbtimeÚwbincre   ÚcopyÚdeepcopyÚshould_exit_gamer   r   r%   r   ÚRequestsConnectionErrorÚStopIterationr  r6  Útry_get_pgn_game_recordÚfinal_queue_entriesÚdelete_takeback_record)2r1   r9   r2   r3   r4   r5   r6   r7   r8   rY   rs   rt   Úinitial_staterr  rÛ   rz  ÚconversationÚis_correspondenceÚcorrespondence_cfgÚcorrespondence_move_timeÚcorrespondence_disconnect_timeÚ
engine_cfgÚ
ponder_cfgÚ
can_ponderr}  rˆ   Útakebacks_acceptedr€  Úkeyword_maprd  re  rf  rg  ry  Ú
prior_gameÚboardÚgame_streamrí   Ústay_in_gameÚmove_attemptedÚupdÚu_typeÚtakeback_fieldÚsetup_timerr›  rœ  Úterminate_timeÚeÚstoppedÚ
pgn_records2                                                     rC   rF  rF  ƒ  ss  € õ0 ˜mÑ,Ô,Ð,ÝÔ�xÑ(Ô(€Fà	×	Ò	˜GÑ	$Ô	$ð a%¨Ø×#Ò#Ñ%Ô%ˆõ œ
¥4¨¡;¤;×#5Ò#5°gÑ#>Ô#>Ñ?Ô?ˆØ�ŠÐ6 }Ð6Ð6Ñ7Ô7Ð7Ý˜VÔ.Ñ/Ô/ˆ
ÝŒz˜-¨°jÔ)AÀ2Ä:ÈzÑZÔZˆåÔ)¨&°$Ñ7Ô7ð V	R¸6Ø×$Ò$ TÑ*Ô*Ð*Ø�LŠLÐT°ÐTÐTÀ&Ç.Â.ÑBRÔBRÐTÐTÑUÔUÐUÝ'¨¨f°b½+ÀÑWÔWˆLà�KŠK˜˜t˜˜Ñ&Ô&Ð&à $¤
Ð.>Ò >ÐØ!'Ô!6ÐÝ'.Ð/AÔ/KÑ'LÔ'LÐ$Ý-4Ð5GÔ5WÑ-XÔ-XÐ*àœˆJØ/@ÐPÐ+Ð+ÀjˆJØ#Ô.ÐC°*Ô2CˆJÝ  Ô!5Ñ6Ô6ˆMÝ˜Ô3Ñ4Ô4ˆEå!5°dÑ!;Ô!;ÐØ%+Ô%BÐ"å1<½SÀTÄWÄ\Ð\`Ô\iÔ\nÐ1oÑ1oÔ1oˆKÝ  ¨&¬/¸;ÑGÔGˆEÝ" 9¨f¬o¸{ÑKÔKˆGÝ+Ð,>ÀÄÐQ\Ñ]Ô]ÐÝ!-Ð.BÀFÄOÐU`Ñ!aÔ!aÐàDHÄJÇNÂNÐSZÑD[ÔD[ÐkÐ<Ð<ÕahÐijÑakÔakˆOØˆJÝ”K‘M”MˆEÝ#œ/­4¬:°d´jÑ+AÔ+A×+HÒ+HÈÑ+QÔ+QÐ*RÐTYÑZÔZˆKØ*0Ô*LÐ'ØˆLØñ 3c­¬ð 3cÐ;Vñ 3cÕ`dÔ`oñ 3cØ!&�ð1cÝ% kÑ2Ô2�CØ,/Ð;˜S œ[˜[°V�FØ Ò+Ð+Ø$×*Ò*­8°C©=¬=Ñ9Ô9Ð9Ñ9Ø ;Ò.Ñ.Ø%(˜œ
Ý +¨DÑ 1Ô 1˜ØHLÌÐ)v¨¬¯ª¸Ñ)DÔ)DÐ)DÐ[_Ô[e×[iÒ[iÐjuÑ[vÔ[v˜å+¨DÑ1Ô1ð BµnÀTÈ:ÐW\Ñ6]Ô6]ð BØ.L˜OÝ% l°EÐ;KÈUÑSÔSÐSÝ*/©'¬'˜KÝ-¨eÑ4Ô4Ð4Ø-1˜NØ"×,Ò,¨UØ-1Ø-/Ø-8Ø-:Ø-7Ø->Ø-EØ-7Ý-<¸VÀUÈDÑ-QÔ-Qñ	Sô 	Sð 	Sõ !œJ¥z°%Ñ'8Ô'8Ñ9Ô9Ð9Ð9Ý)¨$Ñ/Ô/ð 
BÝ1°$¸Ñ>Ô>Ð>Ø"×3Ò3°D¸%Ñ@Ô@Ð@Ø(×5Ò5°hÀÑHÔHÐHØ(×5Ò5°kÐCUÑVÔVÐVÐVØ,ð BÝ(3°D¸%Ñ(@Ô(@ðBà$&×$6Ò$6°t´wÐ@RÐUkÒ@kÑ$lÔ$lðBð /°!Ñ3Ð.Ý+¨DÐ2DÑEÔEÐEØ"×?Ò?ÑAÔAÐAà!$¥^Ô%:¸5Ñ%AÔ%AÔ!B˜Ø #¥NÔ$8¸Ñ$?Ô$?Ô @˜Ý)-¨f©¬½¸U¹¼Ñ)CÅgÈbÁkÄkÑ)Q˜ØŸ	š	 *¨n¸oÑNÔNÐNÝ%)¤]°4Ñ%8Ô%8˜
˜
Ø 6Ò)Ð)Õ.>¸uÀdÈJÐXZÐ\mÑ.nÔ.nÐ)Ø',˜øøÝ!¥;Õ0BÕDXÕZqÝ%ð'ð cð cð cå(¨­MÑ:Ô:�GØ'. ;Ð#b°NÐ4aÅnÐUWÐY]ÔY`ÑFaÔFa�L�L�L�L�L�Løøøøðcøøøða ð 3c­¬ð 3cÐ;Vð 3cÕ`dÔ`oñ 3cõj 1°°V¸TÀ5È&ÑQÔQˆJðmV	Rð V	Rð V	Rñ V	Rô V	Rð V	Rð V	Rð V	Rð V	Rð V	Rð V	Røøøð V	Rð V	Rð V	Rð V	Rõn 	˜MÐ+?ÀÐGXÐZdÐfoÑpÔpÐpÝ˜tÑ$Ô$Ð$ðCa%ð a%ð a%ñ a%ô a%ð a%ð a%ð a%ð a%ð a%ð a%ð a%øøøð a%ð a%ð a%ð a%ð a%ð a%sb   ¾B,Z Ã*H3Y%ÌJ%W×Y%×)X&×-/X!ØY%Ø!X&Ø&3Y%ÙZ Ù%Y)	Ù)Z Ù,Y)	Ù-&Z Ú Z$Ú'Z$rÛ   c                 óÞ   — 	 t          t          | j        ¦  «        ¦  «        5 }t          |                     ¦   «         ¦  «        cddd¦  «         S # 1 swxY w Y   dS # t
          $ r Y dS w xY w)z=Read the number of move takeback requests accepted in a game.Nr   )ÚopenÚtakeback_record_file_namerâ   ÚintÚreadrm   )rÛ   Útakeback_files     rC   r  r    sº   € ðÝÕ+¨D¬GÑ4Ô4Ñ5Ô5ð 	-¸Ý�}×)Ò)Ñ+Ô+Ñ,Ô,ð	-ð 	-ð 	-ð 	-ñ 	-ô 	-ð 	-ð 	-ð 	-ð 	-ð 	-ð 	-øøøð 	-ð 	-ð 	-ð 	-ð 	-ð 	-øåð ð ð Øˆqˆqðøøøs4   ‚!A £!AÁA ÁAÁA ÁAÁA Á
A,Á+A,Úaccepted_countc                 óÀ   — t          t          | j        ¦  «        d¦  «        5 }|                     t	          |¦  «        ¦  «         ddd¦  «         dS # 1 swxY w Y   dS )z?Record the number of move takeback requests accepted in a game.ÚwN)r¾  r¿  râ   Úwriter@   )rÛ   rÃ  rÂ  s      rC   r™  r™    sš   € å	Õ'¨¬Ñ0Ô0°#Ñ	6Ô	6ð 1¸-Ø×Ò�C Ñ/Ô/Ñ0Ô0Ð0ð1ð 1ð 1ñ 1ô 1ð 1ð 1ð 1ð 1ð 1ð 1ð 1øøøð 1ð 1ð 1ð 1ð 1ð 1s   £#AÁAÁAc                 óØ   — t          | ¦  «        rZt          j        t          ¦  «        5  t	          j        t          | j        ¦  «        ¦  «         ddd¦  «         dS # 1 swxY w Y   dS dS )z:Delete the takeback record from a game if it has finished.N)rŽ  Ú
contextlibÚsuppressrm   r˜   rI  r¿  râ   )rÛ   s    rC   r¤  r¤    s¬   € å�DÑÔð :ÝÔ ¥Ñ+Ô+ð 	:ð 	:ÝŒIÕ/°´Ñ8Ô8Ñ9Ô9Ð9ð	:ð 	:ð 	:ñ 	:ô 	:ð 	:ð 	:ð 	:ð 	:ð 	:ð 	:ð 	:øøøð 	:ð 	:ð 	:ð 	:ð 	:ð 	:ð:ð :s   ©'AÁA!Á$A!rý   c                 ó|  — d„ | D ¦   «         }t          d¦  «        }|                     d¦  «        \  }}t          j        |¦  «        D ]s}|                     |¦  «                             |¦  «        }||vrEt          j        t          ¦  «        5  t          j	        |¦  «         ddd¦  «         n# 1 swxY w Y   ŒtdS )z3Delete takeback records from games that have ended.c                 ó   — h | ]
}|d          ’ŒS rÞ   rA   rÙ   s     rC   rà   z)prune_takeback_records.<locals>.<setcomp>  s   € Ð<Ð<Ð<¨$�t˜H”~Ð<Ð<Ð<rB   ú*N)
r¿  ÚsplitÚglobÚremoveprefixÚremovesuffixrÈ  rÉ  rm   r˜   rI  )rý   Úactive_game_idsÚtakeback_file_templateÚprefixÚsuffixÚtakeback_file_namer9   s          rC   ré   ré     s  € à<Ð<°)Ð<Ñ<Ô<€OÝ6°sÑ;Ô;ÐØ+×1Ò1°#Ñ6Ô6�N€FˆFÝ"œiÐ(>Ñ?Ô?ð .ð .ÐØ$×1Ò1°&Ñ9Ô9×FÒFÀvÑNÔNˆØ˜/Ð)Ð)ÝÔ$¥YÑ/Ô/ð .ð .Ý”	Ð,Ñ-Ô-Ð-ð.ð .ð .ñ .ô .ð .ð .ð .ð .ð .ð .øøøð .ð .ð .ð .øð.ð .s   ÂB0Â0B4	Â7B4	c                 óT   — t           j                             t          d| › d�¦  «        S )zFGet the file name for recording the number of move takebacks accepted.ztakeback-count-z.txt)r˜   r›   rœ   rš   )r9   s    rC   r¿  r¿  $  s%   € åŒ7�<Š<Õ*Ð,K¸gÐ,KÐ,KÐ,KÑLÔLÐLrB   r‚  Úgreeting_cfgr¯  c                 óV   — |                      | ¦  «        }|                     |¦  «        S )z%Get the greeting to send to the chat.)ÚlookupÚ
format_map)r‚  r×  r¯  Úgreeting_texts       rC   r�  r�  )  s)   € à%×,Ò,¨XÑ6Ô6€MØ×#Ò# KÑ0Ô0Ð0rB   r¦  rd  rf  r±  c                 ó’   — t          |j        ¦  «        dk     r.|                      d|¦  «         |                      d|¦  «         dS dS )z%Send the greetings to the chat rooms.é   rm  rn  N)rÒ   Ú
move_stackr–  )r¦  rd  rf  r±  s       rC   r�  r�  /  sS   € å
ˆ5ÔÑÔ˜qÒ Ð Ø×!Ò! (¨EÑ2Ô2Ð2Ø×!Ò! +Ð/?Ñ@Ô@Ð@Ð@Ð@ð !Ð rB   c                 ó2  — t          d¦  «        }| j        r€t          |j        ¦  «        dk    rht	          t          d¦  «        |                     ¦   «         t          | j        ¦  «        z
  ¦  «        }|dz  }dt          |j        ¦  «        dz
  z  }||z  }|S )z;Calculate how much time we should wait for fake_think_time.g        é	   r   gš™™™™™™?g®Gáz®ï?rK  )r   r“  rÒ   rÞ  ÚmaxÚmy_remaining_timer   r}  )r4   r±  rÛ   rr   Ú	remainingrˆ   Úaccels          rC   r“  r“  6  s�   € å�C‰LŒL€EàÔð ¥# eÔ&6Ñ"7Ô"7¸!Ò";Ð";Ý� ™
œ
 D×$:Ò$:Ñ$<Ô$<½tÀFÔDXÑ?YÔ?YÑ$YÑZÔZˆ	Ø˜EÑ!ˆØ�˜UÔ-Ñ.Ô.°Ñ3Ñ4ˆØ˜‘ˆà€LrB   c                 ó¤   — t                                d¦  «         t                                dt          | j        ¦  «        dz  dz   › �¦  «         dS )zLog the move number.Ú zmove: rÝ  rf   N)rY   r`   rÒ   rÞ  )r±  s    rC   r‘  r‘  C  sG   € å
‡K‚K��O„O€OÝ
‡K‚KÐ9�˜UÔ-Ñ.Ô.°!Ñ3°aÑ7Ð9Ð9Ñ:Ô:Ð:Ð:Ð:rB   rt   c                 óÞ   — t          | ¦  «        }|r:t          t          t          j        |                     d¦  «        ¦  «        ¦  «        ni }|rt                               d|› �¦  «         |S )zGet the next game state.rc   zGame state: )rq  r*   r   ri   rj   rk   rY   rZ   )rt   Úbinary_chunkrµ  s      rC   rŠ  rŠ  I  sg   € å˜‘;”;€LØKWÐ
_�$�}�dœj¨×)<Ò)<¸WÑ)EÔ)EÑFÔFÑ
GÔ
GÐ
GÐ]_€CØ
ð +Ý�ŠÐ) CÐ)Ð)Ñ*Ô*Ð*Ø€JrB   c           	      óD  — | j                              ¦   «         dk    rt          j        | j        d¬¦  «        }nl| j         dk    rCt          t          | j        ¦  «        }t          j        |t          j        |¦  «        ¬¦  «        }nt          | j         ¦  «        } |¦   «         }| j
        d                              ¦   «         D ]Z}	 |                     |¦  «         Œ# t          $ r5 t                               d|› d|                     ¦   «         › �¦  «         Y ŒWw xY w|S )zSet up the board.Úchess960T)rê  zFrom Positionrh  zIgnoring illegal move z
 on board )Úvariant_nameÚlowerr„  r…  Úinitial_fenr*   r@   r   Úis_chess_960r   rƒ  rÍ  Úpush_uciÚ
ValueErrorrY   r_   Úfen)rÛ   r±  rñ  ÚVariantBoardÚmoves        rC   rŒ  rŒ  R  s+  € àÔ×ÒÑ Ô  JÒ.Ð.Ý”˜DÔ,°tÐ<Ñ<Ô<ˆˆØ	Ô	˜oÒ	-Ð	-Ý•3˜Ô(Ñ)Ô)ˆÝ”˜C­%Ô*<¸SÑ*AÔ*AÐBÑBÔBˆˆõ $ DÔ$5Ñ6Ô6ˆØ�‘”ˆà”
˜7Ô#×)Ò)Ñ+Ô+ð Uð Uˆð	UØ�NŠN˜4Ñ Ô Ð Ð øÝð 	Uð 	Uð 	UÝ×ÒÐS°dÐSÐSÀeÇiÂiÁkÄkÐSÐSÑTÔTÐTÐTÐTð	Uøøøð €Ls   ÃCÃ<DÄDr°  c                 óB   — t          | |¦  «        ot          | |¦  «        S )z&Check whether it is the engine's turn.)Úgame_changedr—  )rÛ   r°  r±  s      rC   r�  r�  g  s!   € å˜˜jÑ)Ô)ÐF­k¸$ÀÑ.FÔ.FÐFrB   c                 ó>   — | j         |j        t          j        k    k    S )a†  
    Determine whether it is the bot's move on the given board.

    This only determines if the board state shows the bot is on move. It does not check if the board state has changed.
    Messages from lichess can contain repeat board states if another game aspect has changed (draw offer, takeback offer,
    etc.). Use is_engine_move() to determine if the engine should play a move.
    )r�  Úturnr„  ÚWHITE)rÛ   r±  s     rC   r—  r—  l  s   € ð Œ=˜UœZ­5¬;Ò6Ò7Ð7rB   c                 ó(   — | j         d         }|dk    S )zCheck whether the game is over.ÚstatusÚstarted©rƒ  )rÛ   rú  s     rC   rŽ  rŽ  w  s   € àŒZ˜Ô!€FØ�YÒÐrB   r§  c                 ó   — |r't          ||| ¦  «        s|                     ¦   «         rdS |                     ¦   «         rLt                               d|                     ¦   «         › d�¦  «         |                     |j        ¦  «         dS |                     ¦   «         r`t                               d|                     ¦   «         › d�¦  «         | 	                    ¦   «         r|                     |j        ¦  «         dS dS )zWhether we should exit a game.Tz	Aborting z by lack of activityzTerminating F)
r�  Úshould_disconnect_nowÚshould_abort_nowrY   r`   r¾   Úabortrâ   Úshould_terminate_nowÚis_abortable)r±  rÛ   r°  r1   r§  s        rC   rŸ  rŸ  }  sú   € ð 	ð Ý" 4¨°UÑ;Ô;ðà×*Ò*Ñ,Ô,ðð ˆtØ×ÒÑÔð Ý�ŠÐ@ §¢¡
¤
Ð@Ð@Ð@ÑAÔAÐAØ
�Š�”ÑÔÐØˆtØ× Ò Ñ"Ô"ð Ý�ŠÐC 4§8¢8¡:¤:ÐCÐCÐCÑDÔDÐDØ×ÒÑÔð 	Ø�HŠH�T”WÑÔÐØˆtØˆ5rB   r¼  c                 ó´  — |rYt          |¦  «        sJt                               d|                     ¦   «         › �¦  «         |                     |j        ¦  «         n0t                               d|                     ¦   «         › d�¦  «         |                      dd|j        idœ¦  «         |                     d|j        |t          |¦  «        dœi¦  «         d	S )
z½
    Log the game that ended or we disconnected from, and sends a `local_game_done` for the game.

     If this is an unfinished correspondence game, put it in a queue to resume later.
    z--- Disconnecting from z--- z
 Game overrá   râ   r<  rÛ   r=  N)rŽ  rY   r`   r¾   rl   râ   )r2   r6   rÛ   r§  r¼  r8   s         rC   r£  r£  �  sí   € ð ð 3¥¨dÑ!3Ô!3ð 3Ý�ŠÐ:¨d¯hªh©j¬jÐ:Ð:Ñ;Ô;Ð;Ø×'Ò'¨¬Ñ0Ô0Ð0Ð0å�ŠÐ1˜4Ÿ8š8™:œ:Ð1Ð1Ð1Ñ2Ô2Ð2à×ÒÐ&7À$ÈÌÀÐQÐQÑRÔRÐRØ×Ò˜&¨¬Ø*4Ý/;¸DÑ/AÔ/Að#Cð #Cð Dñ Eô Eð Eð Eð ErB   Úcurrent_gamec                 óJ   — |€dS | j         d         }|j         d         }||k    S )zOCheck whether the current game state is different from the previous game state.NTrh  rü  )r  r°  Úcurrent_game_moves_strÚprior_game_moves_strs       rC   rõ  rõ  £  s5   € àÐØˆtà)Ô/°Ô8ÐØ%Ô+¨GÔ4ÐØ!Ð%9Ò9Ð9rB   c                 óv  — | j                              d¦  «        }| j                              d¦  «        }|dk    r| j        j        n| j        j        }|dk    r| j        j        n| j        j        }|�t
                               |› d�¦  «         nY|t          j        j	        t          j        j
        fv rt
                               d¦  «         nt
                               d¦  «         t          j        j        d	t          j        j        |› d
�t          j        j        di}||v r"t
                               ||         ¦  «         dS |t          j        j	        k    r…|                     ¦   «         df|                     ¦   «         df|                     ¦   «         df|                     ¦   «         dfdg}d„ |D ¦   «         }t
                               |d         ¦  «         dS |t          j        j
        k    r¡|rt
                               |› d�¦  «         dS | j                              d¦  «        dk    r| j        j        n| j        j        }	|	| j        j        k    r| j        j        n| j        j        }
t
                               |	› d|
› d�¦  «         dS |rt
                               d|› �¦  «         dS dS )zLog the game result.Úwinnerrú  ÚwhiteÚblackNz won!zGame ended in a draw.zGame adjourned.zGame won by checkmate.z
 resigned.zGame aborted.zGame drawn by 50-move rule.z#Game drawn by threefold repetition.z&Game drawn from insufficient material.zGame drawn by stalemate.)TzGame drawn by agreement.c                 ó   — g | ]	\  }}|¯|‘Œ
S rA   rA   )rÚ   Ú	is_resultÚdraw_messages      rC   rÜ   z)tell_user_game_result.<locals>.<listcomp>È  s#   € ÐZÐZÐZÑ%< Y°ÐPYÐZ�LÐZÐZÐZrB   r   z forfeited on time.Úwtimez ran out of time, but z& did not have enough material to mate.zGame ended by )rƒ  r~   r
  rT  r  rY   r`   r   ÚTerminationÚDRAWÚTIMEOUTÚMATEÚRESIGNÚABORTÚis_fifty_movesÚis_repetitionÚis_insufficient_materialÚis_stalemate)rÛ   r±  r	  ÚterminationÚwinning_nameÚlosing_nameÚsimple_endingsÚdraw_resultsÚmessagesÚtimeout_nameÚ
other_names              rC   r”  r”  ­  sª  € àŒZ�^Š^˜HÑ%Ô%€FØ”*—.’. Ñ*Ô*€Kà&,°Ò&7Ð&7�4”:”?�?¸T¼Z¼_€LØ%+¨wÒ%6Ð%6�$”*”/�/¸D¼J¼O€KàÐÝ�Š�|Ð*Ð*Ð*Ñ+Ô+Ð+Ð+Ø	�Ô*Ô/µÔ1BÔ1JÐKÐ	KÐ	KÝ�ŠÐ+Ñ,Ô,Ð,Ð,å�ŠÐ%Ñ&Ô&Ð&å&+Ô&7Ô&<Ð>VÝ&+Ô&7Ô&>À;Ð@ZÐ@ZÐ@ZÝ&+Ô&7Ô&=¸ð&P€Nð �nÐ$Ð$Ý�Š�N ;Ô/Ñ0Ô0Ð0Ð0Ð0Ø	�Ô)Ô.Ò	.Ð	.Ø×-Ò-Ñ/Ô/Ð1NÐOØ×,Ò,Ñ.Ô.Ð0UÐVØ×7Ò7Ñ9Ô9Ð;cÐdØ×+Ò+Ñ-Ô-Ð/IÐJØ:ð	<ˆð
 [ÐZÀÐZÑZÔZˆÝ�Š�H˜Q”KÑ Ô Ð Ð Ð Ø	�Ô)Ô1Ò	1Ð	1Øð 	sÝ�KŠK˜;Ð;Ð;Ð;Ñ<Ô<Ð<Ð<Ð<à.2¬j¯nªn¸WÑ.EÔ.EÈÒ.JÐ.J˜4œ:œ?˜?ÐPTÔPZÔP_ˆLØ,8¸D¼J¼OÒ,KÐ,K˜œœ˜ÐQUÔQ[ÔQ`ˆJÝ�KŠK˜<ÐqÐq¸zÐqÐqÐqÑrÔrÐrÐrÐrØ	ð 4Ý�ŠÐ2 [Ð2Ð2Ñ3Ô3Ð3Ð3Ð3ð4ð 4rB   rz  c                 ó€   — 	 t          | ||||¦  «        S # t          $ r t                               d¦  «         Y dS w xY w)a±  
    Call `print_pgn_game_record` to write the game to a PGN file and handle errors raised by it.

    :param li: Provides communication with lichess.org.
    :param config: The config that the bot will use.
    :param game: Contains information about the game (e.g. the players' names).
    :param board: The board. Contains the moves.
    :param engine: The engine. Contains information about the moves (e.g. eval, PV, depth).
    zError writing game record:ræ  )Úpgn_game_recordrm   rY   r_   )r1   r4   rÛ   r±  rz  s        rC   r¢  r¢  Õ  sT   € ðÝ˜r 6¨4°¸Ñ?Ô?Ð?øÝð ð ð Ý×ÒÐ5Ñ6Ô6Ð6Øˆrˆrðøøøs   ‚ •$=¼=c           
      óÀ  — |j         sdS t          j                             t	          j        |                      |j        ¦  «        ¦  «        ¦  «        pt          j                             ¦   «         }	 t          ||j        |j
        j        |j        j        |j        j        t          |¦  «        d¬¦  «        }t          |¦  «        5 }t          j                             |¦  «        p|}ddd¦  «         n# 1 swxY w Y   |j                             |j        ¦  «         n# t$          $ r |}Y nw xY wt'          ||¦  «         |                     ¦   «         }	|                     ¦   «         }
t+          |j        ¦  «        D �]-\  }}|	                     ¦   «         }|�|j        |k    r|	                     |¦  «        }	n|}	|
                     ¦   «         }|ra|}
|	                     |
                     ¦   «         ¦  «         |	j        |
j        k    r(|	j        › d|
j        › �                     ¦   «         |	_        |                     |¦  «        }d|v r |	j                              |d         ¦  «        n|	}| !                    | "                    d¦  «        | "                    d¦  «        ¦  «         �Œ/t          j         #                    ¦   «         }| $                    |¦  «        S )	aw  
    Return the text of the game's PGN.

    :param li: Provides communication with lichess.org.
    :param config: The config that the bot will use.
    :param game: Contains information about the game (e.g. the players' names).
    :param board: The board. Contains the moves.
    :param engine: The engine. Contains information about the moves (e.g. eval, PV, depth).
    ræ  T©Úforce_singleNú Úpvr&  Údepth)%Úpgn_directoryr„  r>  Ú	read_gameÚioÚStringIOr@  râ   rs  Úget_game_file_pathr
  rT  r  rc  rŽ  r¾  ÚheadersrW  ÚFileNotFoundErrorÚfill_missing_pgn_headersrÛ   Ú	enumeraterÞ  rq  ró  Úadd_main_variationÚ	set_clockÚclockÚcommentÚstripÚcomment_for_board_indexÚparentÚadd_lineÚset_evalr~   ÚStringExporterÚaccept)r1   r4   rÛ   r±  rz  Úlichess_game_recordÚprevious_game_pathÚ	game_dataÚgame_recordÚcurrent_nodeÚlichess_nodeÚindexró  Ú	next_nodeÚnext_lichess_nodeÚ
commentaryÚpv_nodeÚ
pgn_writers                     rC   r#  r#  ç  s  € ð Ôð Øˆråœ)×-Ò-­b¬k¸"¿/º/È$Ì'Ñ:RÔ:RÑ.SÔ.SÑTÔTÐhÕX]ÔXa×XfÒXfÑXhÔXhÐð*å/°Ø04´Ø04´
´Ø04´
´Ø04´´Ý0<¸TÑ0BÔ0BØ=AðCñ Cô CÐõ Ð$Ñ%Ô%ð 	P¨Ýœ)×-Ò-¨iÑ8Ô8ÐOÐ<OˆKð	Pð 	Pð 	Pñ 	Pô 	Pð 	Pð 	Pð 	Pð 	Pð 	Pð 	Pøøøð 	Pð 	Pð 	Pð 	PàÔ×"Ò"Ð#6Ô#>Ñ?Ô?Ð?Ð?øÝð *ð *ð *Ø)ˆˆˆð*øøøõ ˜[¨$Ñ/Ô/Ð/à9D×9IÒ9IÑ9KÔ9K€LØ9L×9QÒ9QÑ9SÔ9S€LÝ  Ô!1Ñ2Ô2ð Kñ K‰ˆˆtØ ×%Ò%Ñ'Ô'ˆ	ØÐ 	¤°$Ò 6Ð 6Ø'×:Ò:¸4Ñ@Ô@ˆLˆLà$ˆLà(×-Ò-Ñ/Ô/ÐØð 	`Ø,ˆLØ×"Ò" <×#5Ò#5Ñ#7Ô#7Ñ8Ô8Ð8ØÔ# |Ô';Ò;Ð;Ø*6Ô*>Ð'WÐ'WÀÔAUÐ'WÐ'W×']Ò']Ñ'_Ô'_�Ô$à×3Ò3°EÑ:Ô:ˆ
ØDHÈJÐDVÐDV�,Ô%×.Ò.¨z¸$Ô/?Ñ@Ô@Ð@Ð\hˆØ×Ò˜Ÿš¨Ñ0Ô0°*·.².ÀÑ2IÔ2IÑJÔJÐJÑJå”×)Ò)Ñ+Ô+€JØ×Ò˜jÑ)Ô)Ð)s7   Á2AD  Ã"C5Ã)D  Ã5C9Ã9D  Ã<C9Ã="D  Ä D/Ä.D/r%  Ú
white_nameÚ
black_nameÚ	user_nameÚgame_is_overr&  c                óÚ   ‡ — dt           dt           fˆ fd„}‰ j        dk    s|r|r ||› d|› d|› d�¦  «        S ‰ j        dk    r||k    r|n|} ||› d	|› d�¦  «        S  ||› d
�¦  «        S )zBReturn the path of the file where the game record will be written.ÚsrN   c                 ó’   •‡— dŠt           j                             ‰j        d                     ˆfd„| D ¦   «         ¦  «        ¦  «        S )Nz	<>:"/\|?*ræ  c              3   ó$   •K  — | ]
}|‰v¯|V — Œd S r%  rA   )rÚ   ÚcÚillegals     €rC   r5  z@get_game_file_path.<locals>.create_valid_path.<locals>.<genexpr>)  s.   øè è € Ð9[Ð9[ÀÈ!ÐSZÐJZÐJZ¸!ÐJZÐJZÐJZÐJZÐ9[Ð9[rB   )r˜   r›   rœ   r*  )rO  rS  r4   s    @€rC   Úcreate_valid_pathz-get_game_file_path.<locals>.create_valid_path'  sC   øø€ ØˆÝŒw�|Š|˜FÔ0°"·'²'Ð9[Ð9[Ð9[Ð9[ÀQÐ9[Ñ9[Ô9[Ñ2[Ô2[Ñ\Ô\Ð\rB   rÛ   z vs z - z.pgnrR  z games vs. z
 games.pgn)r@   Úpgn_file_grouping)	r4   r9   rJ  rK  rL  rM  r&  rT  Úopponent_names	   `        rC   r.  r.    sØ   ø€ ð]�Sð ]¥Sð ]ð ]ð ]ð ]ð ]ð ]ð Ô 6Ò)Ð)°Ð)ÀÐ)Ø Ð  JÐ!PÐ!P°JÐ!PÐ!PÀ7Ð!PÐ!PÐ!PÑQÔQÐQØ	Ô	! ZÒ	/Ð	/Ø&/°:Ò&=Ð&=˜
˜
À:ˆØ Ð  IÐ!MÐ!M¸-Ð!MÐ!MÐ!MÑNÔNÐNà Ð  IÐ!9Ð!9Ð!9Ñ:Ô:Ð:rB   rA  c                 ó   — t          |¦  «        }|                     ¦   «         D ]Y\  }}| j                             |¦  «        }|r!|                     d¦  «        s|dk    r|dk    rt          |¦  «        | j        |<   ŒZdS )aV  
    Fill in any missing headers in the PGN record provided by lichess.org with information from `game`.

    :param game_record: A `chess.pgn.Game` object containing information about the game lichess.org's PGN file.
    :param game: Contains information about the game (e.g. the players' names), which is used to get the local headers.
    ú?ÚResultrÌ  N)Úget_headersÚitemsr/  r~   Ú
startswithr@   )rA  rÛ   Úlocal_headersÚheaderÚ
game_valueÚrecord_values         rC   r1  r1  4  s˜   € õ   Ñ%Ô%€MØ+×1Ò1Ñ3Ô3ð :ð :Ñˆ�
Ø"Ô*×.Ò.¨vÑ6Ô6ˆØð 	:˜|×6Ò6°sÑ;Ô;ð 	:ÀÈ(Ò@RÐ@RÐWcÐgjÒWjÐWjÝ*-¨j©/¬/ˆKÔ Ñ'øð:ð :rB   c                 ó  — i }|                       ¦   «         |d<   |                      ¦   «         |d<   | j                             d¦  «        |d<   | j        j        pt          | j        ¦  «        |d<   | j        j        pt          | j        ¦  «        |d<   |                      ¦   «         |d<   | j        j	        r| j        j	        |d<   | j        j
        r| j        j
        |d	<   | j        d
k    r|                      ¦   «         |d<   |d         |d<   | j                             d¦  «        |d<   | j        |d<   | j        r| j        dk    rd|d<   | j        |d<   | j        j	        r| j        j	        |d<   | j        j
        r| j        j
        |d<   |S )z²
    Create local headers to be written in the PGN file.

    :param game: Contains information about the game (e.g. the players' names).
    :return: The headers in a dict.
    ÚEventÚSitez%Y.%m.%dÚDateÚWhiteÚBlackrY  ÚBlackEloÚ
BlackTitlerÅ   ÚTimeControlÚUTCDatez%H:%M:%SÚUTCTimeÚVariantÚstartposrf   ÚSetupÚFENÚWhiteEloÚ
WhiteTitle)Ú	pgn_eventÚ	short_urlÚ
game_startÚstrftimer
  rT  r@   r  ÚresultÚratingÚtitleÚ	perf_nameÚtime_controlrë  rí  )rÛ   r/  s     rC   rZ  rZ  B  s�  € ð %'€GØ—~’~Ñ'Ô'€GˆGÑØ—n’nÑ&Ô&€GˆF�OØ”o×.Ò.¨zÑ:Ô:€GˆF�OØ”z”Ð9­#¨d¬j©/¬/€GˆGÑØ”z”Ð9­#¨d¬j©/¬/€GˆGÑØŸš™œ€GˆHÑà„zÔð 0Ø"œjÔ/ˆ�
ÑØ„zÔð 1Ø $¤
Ô 0ˆ�Ñà„~Ð)Ò)Ð)Ø!%×!2Ò!2Ñ!4Ô!4ˆ�Ñà  œ€GˆIÑØœ×1Ò1°*Ñ=Ô=€GˆIÑØÔ*€GˆIÑàÔð *˜DÔ,°
Ò:Ð:Øˆ�ÑØÔ)ˆ�‰à„zÔð 0Ø"œjÔ/ˆ�
ÑØ„zÔð 1Ø $¤
Ô 0ˆ�Ñà€NrB   c           	      óÄ  — | d         d         }t           j                             t          j        |¦  «        ¦  «        }|j        r|€dS | d         d         }|d         }|d         }| d         d         }t          j        |j        d¬	¦  «         t          ||||||¦  «        }	t          ||||||d¬
¦  «        }
|	|
k    rdnd}t           
                    d|	› �¦  «         t          |	|¦  «        5 }|                     |dz   ¦  «         ddd¦  «         n# 1 swxY w Y   t          j                             |
¦  «        r|	|
k    rt          j        |
¦  «         dS dS dS )zÈ
    Write the game PGN record to a file.

    :param event: A local_game_done event from the control queue.
    :param config: The user's bot configuration.
    :param user_name: The bot's name.
    rÛ   r>  Nrâ   re  rf  r?  TrŠ   r%  rÅ  ÚazWriting PGN game record to: z

)r„  r>  Úread_headersr,  r-  r*  r˜   r™   r.  rY   rZ   r¾  rÆ  r›   ÚexistsrI  )rv   r4   rL  r>  Úpgn_headersr9   rJ  rK  rM  Ú	game_pathÚsingle_game_pathÚ
write_modeÚ	game_files                rC   r   r   i  s¸  € ð �Œ-˜Ô
€CÝ”)×(Ò(­¬°SÑ)9Ô)9Ñ:Ô:€KØÔð  ;Ð#6Øˆà�FŒm˜DÔ!€GØ˜WÔ%€JØ˜WÔ%€JØ˜”= Ô,€Lå„K�Ô$¨tÐ4Ñ4Ô4Ð4Ý" 6¨7°JÀ
ÈIÐWcÑdÔd€IÝ)¨&°'¸:ÀzÐS\Ð^jÐy}Ð~Ñ~Ô~ÐØ!Ð%5Ò5Ð5��¸3€JÝ
‡L‚LÐ;°	Ð;Ð;Ñ<Ô<Ð<Ý	ˆi˜Ñ	$Ô	$ð &¨	Ø�Š˜˜f™Ñ%Ô%Ð%ð&ð &ð &ñ &ô &ð &ð &ð &ð &ð &ð &øøøð &ð &ð &ð &õ 
„w‡~‚~Ð&Ñ'Ô'ð $¨IÐ9IÒ,IÐ,IÝ
Œ	Ð"Ñ#Ô#Ð#Ð#Ð#ð$ð $Ð,IÐ,Is   Ã3DÄDÄDc                  óh   — dt           › dt          j        ¦   «         › dt          j        ¦   «         › d�S )zReturn the intro string.z5
    .   _/|
    .  // o\
    .  || ._)  lichess-bot z on r'  z<
    .  //__\
    .  )___(   Play on Lichess with a bot
    )rx  ÚplatformÚsystemÚreleaserA   rB   rC   Úintrorˆ  ‡  sQ   € ðõ (ðð õ .6¬_Ñ->Ô->ðð õ BJÔAQÑASÔASðð ð ð rB   Úlichess_bot_auto_logsc            	      ó^  — t                                dd                     t          t          t
          j        ¦  «        ¦  «        › �¦  «         d} t          j         	                    ¦   «         }|D ]}| |j        d         › d|j
        › d�z  } Œ| dz  } t                                | ¦  «         dS )z3Log the installed libraries and the python version.zPython version: ú.zInstalled libraries:
ÚNamez==ú
N)rY   rZ   rœ   Úmapr@   ÚsysÚversion_infoÚ	importlibÚmetadataÚdistributionsÚversion)Útextr“  Údistributions      rC   Úlog_python_and_librariesr—  •  s©   € å
‡L‚LÐJ C§H¢H­SµµcÔ6FÑ-GÔ-GÑ$HÔ$HÐJÐJÑKÔKÐKØ#€DÝÔ&×4Ò4Ñ6Ô6€MØ%ð Mð MˆØ�<Ô(¨Ô0ÐLÐL°LÔ4HÐLÐLÐLÑLˆˆØˆD�L€DÝ
‡L‚L�ÑÔÐÐÐrB   c                  óö  — t          j        d¬¦  «        } |                      ddd¬¦  «         |                      ddd¬¦  «         |                      d	d
¬¦  «         |                      dddd¬¦  «         |                      ddd¬¦  «         |                      ¦   «         }|j        rt
          j        nt
          j        }t          ||j	        |j
        ¦  «         t                               t          ¦   «         ddi¬¦  «         t          |j        pd¦  «        }|j
        set!          t"          j                             t(          d¦  «        d¦  «        5 }t+          |j        |j        ¦  «         ddd¦  «         n# 1 swxY w Y   t                               d¦  «         t/          j        |¦  «        5  	 ddd¦  «         n# 1 swxY w Y   t                               d¦  «         |j        j        j        }t9          ¦   «          t;          ¦   «          t=          j        |j         |j!        tD          ||¦  «        }| #                    ¦   «         }|d         }| $                    d¦  «        dk    }	t                               d|› d�¦  «         |j%        r|	stM          |¦  «        }	|	rtO          |||||j	        |j
        ¦  «         nt           (                    |› d�¦  «         t          j)        ¦   «          dS ) z@Parse arguments passed to lichess-bot.py and starts lichess-bot.zPlay on Lichess with a bot)Údescriptionz-uÚ
store_truez&Upgrade your account to a bot account.)ÚactionÚhelpz-vzAMake output more verbose. Include all communication with lichess.z--configz8Specify a configuration file (defaults to ./config.yml).)rœ  z-lz	--logfilez(Record all console output to a log file.N)rœ  Údefaultz--disable_auto_loggingzDisable automatic logging.Úhighlighter)Úextraz./config.ymlz
config.logrÅ  z!Checking engine configuration ...zEngine configuration OKr|   rx  ÚBOTzWelcome ú!z: is not a bot account. Please upgrade it to a bot account!)*ÚargparseÚArgumentParserÚadd_argumentÚ
parse_argsÚvr’   rž   ÚINFOr¨   Úlogfiler«   rY   r`   rˆ  r	   r4   r¾  r˜   r›   rœ   rš   r   rÆ  r   ru  rz  Úonline_movesÚmax_retriesÚcheck_python_versionr—  r   r>   Útokenr¾   rx  Úget_profiler~   Úura   rÄ   r9  Úshutdown)
Úparserr½   r¹   ÚCONFIGÚ
config_logrª  r1   r3   r|   r,  s
             rC   Ústart_lichess_botr³     s;  € åÔ$Ð1MÐNÑNÔN€FØ
×Ò˜ \Ð8`ÐÑaÔaÐaØ
×Ò˜ \Ð8{ÐÑ|Ô|Ð|Ø
×Ò˜
Ð)cÐÑdÔdÐdØ
×Ò˜˜kÐ0ZÐdhÐÑiÔiÐiØ
×ÒÐ0¸ÐLhÐÑiÔiÐiØ×ÒÑÔ€Dà%)¤VÐ=•G”M�Mµ´€MÝ�} d¤l°DÔ4MÑNÔNÐNÝ
‡K‚K•‘” ¨tÐ4€KÑ5Ô5Ð5å˜œÐ6¨Ñ7Ô7€FØÔ$ð 8Ý•"”'—,’,Õ1°<Ñ@Ô@À#ÑFÔFð 	8È*Ý�v”} jÔ&6Ñ7Ô7Ð7ð	8ð 	8ð 	8ñ 	8ô 	8ð 	8ð 	8ð 	8ð 	8ð 	8ð 	8øøøð 	8ð 	8ð 	8ð 	8å
‡K‚KÐ3Ñ4Ô4Ð4Ý	Ô	% fÑ	-Ô	-ð ð Øðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð å
‡K‚KÐ)Ñ*Ô*Ð*à”-Ô,Ô8€KÝÑÔÐÝÑÔÐÝ	Œ˜œ v¤zµ;ÀÈ{Ñ	[Ô	[€Bà—>’>Ñ#Ô#€LØ˜JÔ'€HØ×Ò˜gÑ&Ô&¨%Ò/€FÝ
‡K‚KÐ&˜8Ð&Ð&Ð&Ñ'Ô'Ð'à„vð %�fð %Ý  Ñ$Ô$ˆàð ^Ýˆb�, ¨°t´|ÀTÔE^Ñ_Ô_Ð_Ð_å�Š˜Ð\Ð\Ð\Ñ]Ô]Ð]ÝÔÑÔÐÐÐs$   ÅE=Å=FÆFÆ6GÇGÇGc                  ór  — dt           dt          t                   fd„}  | t          d         ¦  «        } | t          d         ¦  «        }t          d         }t          t          j        dd…         ¦  «        }d	t          t                   dt           fd
„}d ||¦  «        › d ||¦  «        › d�}t          d|› d�¦  «        }d|› d|› d�} | t          ¦  «        }	t          |                     ¦   «         dd…         ¦  «        }
||k     r|‚||k    r$|	|
k     rt           
                    |¦  «         dS |‚dS )zPRaise a warning or an exception if the version isn't supported or is deprecated.Úversion_strrN   c                 ó@   — d„ |                       d¦  «        D ¦   «         S )Nc                 ó,   — g | ]}t          |¦  «        ‘ŒS rA   )rÀ  ©rÚ   Úns     rC   rÜ   zAcheck_python_version.<locals>.version_numeric.<locals>.<listcomp>Î  s   € Ð7Ð7Ð7˜1•�A‘”Ð7Ð7Ð7rB   r‹  )rÍ  )rµ  s    rC   Úversion_numericz-check_python_version.<locals>.version_numericÍ  s$   € Ø7Ð7 × 1Ò 1°#Ñ 6Ô 6Ð7Ñ7Ô7Ð7rB   rI   rH   rJ   r   rÝ  r”  c                 óF   — dd                      d„ | D ¦   «         ¦  «        › �S )NzPython r‹  c              3   ó4   K  — | ]}t          |¦  «        V — Œd S r%  )r@   r¸  s     rC   r5  z<check_python_version.<locals>.version_str.<locals>.<genexpr>Ö  s(   è è € Ð!:Ð!:¨Q¥# a¡&¤&Ð!:Ð!:Ð!:Ð!:Ð!:Ð!:rB   )rœ   )r”  s    rC   rµ  z)check_python_version.<locals>.version_strÕ  s+   € Ø<˜ŸšÐ!:Ð!:°'Ð!:Ñ!:Ô!:Ñ:Ô:Ð<Ð<Ð<rB   zYou are currently running z. Please upgrade to z	 or newerzJA newer version of Python is required to run this version of lichess-bot. r‹  z.A newer version of Python will be required on z to run lichess-bot. z before then.é   N)r@   rÁ   rÀ  rM   r�  r�  ÚRuntimeErrorrx  Ú	timetuplerY   rn   )rº  Úpython_deprecated_versionÚpython_good_versionÚversion_change_dateÚthis_python_versionrµ  Úupgrade_requestÚout_of_date_errorÚout_of_date_warningÚthis_lichess_bot_versionÚlichess_bot_breaking_versions              rC   r«  r«  Ë  sÄ  € ð8¥Sð 8­Tµ#¬Yð 8ð 8ð 8ð 8ð !0 µÐ@[Ô0\Ñ ]Ô ]ÐØ)˜/­/Ð:RÔ*SÑTÔTÐÝ)Ð*<Ô=ÐÝ�sÔ/°°!°Ô4Ñ5Ô5Ðð=�T¥#œYð =­3ð =ð =ð =ð =ðX°K°KÐ@SÑ4TÔ4Tð Xð XØ,7¨KÐ8KÑ,LÔ,LðXð Xð X€Oå$ð &_ØL[ð&_ð &_ð &_ñ `ô `ÐðjØ!4ðjð jØKZðjð jð jÐð  /˜­{Ñ;Ô;ÐÝ#'Ð(;×(EÒ(EÑ(GÔ(GÈÈ!ÈÔ(LÑ#MÔ#MÐ àÐ6Ò6Ð6ØÐàÐ7Ò7Ð7Ø#Ð&BÒBÐBÝ�NŠNÐ.Ñ/Ô/Ð/Ð/Ð/à#Ð#ð	 8Ð7rB   c                  ó  — t          j        d¦  «         	 t          ¦   «         r¼t          ¦   «          	 t	          ¦   «          n6# t
          $ r) dt          _        t           	                    d¦  «         Y nw xY wt          j
        st          j        rt                               d¦  «         dS t          j        t          ¦   «         rdnd¦  «         t          ¦   «         °ºdS dS # t          $ r t           	                    d¦  «         Y dS w xY w)	z*Start lichess-bot and restart when needed.ÚspawnTz.Restarting lichess-bot due to a network error:z.Termination requested - stopping restart cyclerK  r   z%Quitting lichess-bot due to an error:N)r¿   Úset_start_methodrR   rT   r³  r    r   rQ   rY   r_   rX   r[   r`   rq   rr   rm   rA   rB   rC   Ústart_programrÌ  ì  s8  € åÔ$ WÑ-Ô-Ð-ðBÝÑÔð 	6ÝÑÔÐðSÝ!Ñ#Ô#Ð#Ð#øÝ#ð Sð Sð SØ#•”Ý× Ò Ð!QÑRÔRÐRÐRÐRðSøøøõ Œð ¥$¤/ð Ý—’ÐLÑMÔMÐMØ�ÝŒJ�^Ñ-Ô-Ð4�r�r°1Ñ5Ô5Ð5õ ÑÔð 	6ð 	6ð 	6ð 	6ð 	6øõ ð Bð Bð BÝ×ÒÐ@ÑAÔAÐAÐAÐAÐAðBøøøs:   –C" ³A ÁC" Á0A5Á2C" Á4A5Á55C" Â,2C" Ã"$D
Ä	D
)rN   N)F)³r=   r¢  r„  Ú	chess.pgnÚchess.variantr   Úlibr   r   r   r   ri   r’   Úlogging.handlersr¿   rU   rq   rK   Úbackoffr˜   r,  r�  r  r�  Úyamlro   r†  rÎ  r…  Úimportlib.metadatar‘  rÈ  Úlib.blocklistr   Ú
lib.configr	   r
   r   Úlib.conversationr   r   Ú	lib.timerr   r   r   r   r   Úlib.lichessr   Úlib.lichess_typesr   r   r   r   r   r   r   r   Úrequests.exceptionsr   r   r   r   r   r    Úrich.loggingr!   Úcollectionsr"   Úcollections.abcr#   r$   Úhttp.clientr%   r©   r&   Úmultiprocessing.poolr'   r(   Útypingr)   r*   r+   Útypesr,   rV  r-   r?   r.   r0   rF   r®   r:   rY   r¾  r›   rœ   ÚdirnameÚ__file__Úversion_fileÚ	safe_loadrM   rx  ÚboolrR   rT   rÀ  r\   ÚSIGINTr>   ra   rw   Ú	timedeltar{   r@   rƒ   r¨   r±   r¸   rÄ   ÚsetrÔ   rÇ   rú   rï   r  r÷   rÁ   rö   rø   rù   r1  r6  r
  rõ   rH  rò   Úon_exceptionÚexporD  Úis_finalÚbackoff_handlerrF  rs  r  r™  r¤  ré   r¿  r�  r…  r�  r“  r‘  ÚbytesrŠ  rŒ  r�  r—  rŽ  rŸ  r£  rõ  r”  ÚEngineWrapperr¢  r#  r.  r>  r1  ÚdictrZ  r   rˆ  rš   r—  r³  r«  rÌ  rA   rB   rC   ú<module>rñ     sô  ðØ 0Ð 0Ð 0Ø €€€Ø €€€Ø Ð Ð Ð Ø &Ð &Ð &Ð &Ð &Ð &Ø ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ð ;Ø €€€Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ø €€€Ø €€€Ø €€€Ø €€€Ø 	€	€	€	Ø 	€	€	€	Ø €€€Ø €€€Ø 
€
€
€
Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ø €€€Ø €€€Ø Ð Ð Ð Ø Ð Ð Ð Ø )Ð )Ð )Ð )Ð )Ð )Ø =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ø =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ð =Ø Ð Ð Ð Ð Ð ð^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð ^ð3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3ð 3à $Ð $Ð $Ð $Ð $Ð $Ø #Ð #Ð #Ð #Ð #Ð #Ø 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5Ø *Ð *Ð *Ð *Ð *Ð *Ø Ð Ð Ð Ð Ð Ø %Ð %Ð %Ð %Ð %Ð %Ø Ð Ð Ð Ð Ð Ø -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ø Ð Ð Ð Ð Ð Ø'6°u´Ô'GÐ ˜9Ð GÐ GÑ GØ€	ˆ9Ð Ð Ñ ðð ð ð ð �y¨ð ñ ô ð ð$ð $ð $ð $ð $�Yñ $ô $ð $ð 
ˆÔ	˜8Ñ	$Ô	$€à	€Tˆ"Œ'�,Š,�r”w—’ xÑ0Ô0Ð2BÑ
CÔ
CÑDÔDð CÈØ&4 d¤n°\Ñ&BÔ&B€O�^ÐBÐBÑBðCð Cð Cñ Cô Cð Cð Cð Cð Cð Cð Cøøøð Cð Cð Cð Cð Ð3Ô4€ð˜ð ð ð ð ð
ð ð ð ð
˜3ð  y°4Ñ'7ð ¸Dð ð ð ð ð €„ˆfŒm˜^Ñ ,Ô ,Ð ,ð	˜œð 	¨Dð 	ð 	ð 	ð 	ð5Ð(:ð 5ÀÄð 5ÐTXð 5ð 5ð 5ð 5ð&	BÐ*<ð 	BÀhÔFXð 	BÐ]að 	Bð 	Bð 	Bð 	Bð" ð "¸ð "ÐRUð "ÐZ^ð "ð "ð "ð "ð$)$˜cð )$¨S°4©Zð )$ÈDð )$ÐUYð )$ð )$ð )$ð )$ðXÐ!3ð ¸Cð ÈsÐUYÉzð Ø04ðØ9=ðð ð ð ð8!Ð%7ð !¸Dð !ð !ð !ð !ð RWð>ð >ˆgŒoð >¨_ð >Àmð >Ðdgð >Ø˜d™
ð>Ø:>ð>ØJNð>Ø[_ð>ð >ð >ð >ðBg˜3ð g¨c°#¬hð g¸4ð gð gð gð gðk/˜œð k/Ø#2ðk/à*ðk/ð '@ðk/ð %7ð	k/ð
 ,Eðk/ð %7ðk/ð !/ðk/ð  $ðk/ð )-ðk/ð k/ð k/ð k/ð\�Yð ¨c°#¬hð Àð ÐRVð ð ð ð ðÐ0ð °Yð ð ð ð ð* !"Ð ðG¨9ð GØ,5ðGà;TðGð 7PðGð 6Fð	Gð
 47°s´8ðGð 14ðGð 9=ðGð Gð Gð Gð2G¨¨h¬ð GÀsÈ3Äxð GÐ\_ð GØ(ðGØ:JðGØOSðGð Gð Gð Gð5˜'œ/ð 5Ð<Uð 5ÐehÐilÔemð 5Ø!$ð5Ø)-ð5ð 5ð 5ð 5ð$	˜GœOð 	¸?ð 	Ðdið 	Ðnrð 	ð 	ð 	ð 	ð(Ð%>ð (ÐR_ð (Ðdhð (ð (ð (ð (ð P�w”ð P°ð P¸ð Pð Pð Pð Pð8 C¨¤Hð 8°sð 8ÐL\ð 8Ðdmð 8Ðrvð 8ð 8ð 8ð 8ð*G�ið GØðGà/ðGð %ðGð .2°#¬Yð	Gð
 &?ðGð ! œXðGð  $ Hœ~ðGð 37ðGð Gð Gð GðBT 	ð T°=ð TÀTð Tð Tð Tð Tð>˜Ið >¨7¬?ð >ÐMfð >Ø'4ð>ØDSð>à,7¸¸TÀ%¼[Ð8HÔ,Ið>à^mð>àrvð>ð >ð >ð >ð: €Ô�g”l M¸CÈÔHXØ!(Ô!8ð:ñ :ô :ðz%�'”/ð z%Øðz%à/ðz%ð ,ðz%ð $ð	z%ð
  9ðz%ð %>ðz%ð 0ðz%ð (ðz%ð -1ðz%ð z%ð z%ñ:ô :ðz%ðz˜uœzð ¨cð ð ð ð ð1˜%œ*ð 1°cð 1¸dð 1ð 1ð 1ð 1ð: ¤ð :°ð :ð :ð :ð :ð	. d¨8¤nð 	.¸ð 	.ð 	.ð 	.ð 	.ðM sð M¨sð Mð Mð Mð Mð
1˜3ð 1¨mð 1È+ÐVYÐ[^ÐV^ÔJ_ð 1Ðdgð 1ð 1ð 1ð 1ðA˜Lð A°ð AÈð AÐTYÔT_ð AÐdhð Að Að Að Að
˜Mð 
°%´+ð 
ÀUÄZð 
ÐT\ÔTfð 
ð 
ð 
ð 
ð;˜Uœ[ð ;¨Tð ;ð ;ð ;ð ;ð�x ”ð ¨=ð ð ð ð ð�e”jð  U¤[ð ð ð ð ð*G˜œð G°´¸dÑ1Bð GÈ5Ì;ð GÐ[_ð Gð Gð Gð Gð
8�e”jð 8¨¬ð 8¸ð 8ð 8ð 8ð 8ð�u”zð  dð ð ð ð ð˜EœKð ¨u¬zð ÀuÄzÐTXÑGXð Ð^eÔ^mð Ø(,ðØ15ðð ð ð ð&EÐ'9ð EÐQjð EØ#œjðEØ=AðEØORðEØ_mðEØrvðEð Eð Eð Eð&:˜uœzð :°u´zÀDÑ7Hð :ÈTð :ð :ð :ð :ð%4 ¤
ð %4°5´;ð %4À4ð %4ð %4ð %4ð %4ðP ¤ð ¸ð ÈeÌjð ÐafÔalð Ø$2Ô$@ðØEHðð ð ð ð$5*˜œð 5*°ð 5*ÀeÄjð 5*ÐY^ÔYdð 5*Ø*Ô8ð5*Ø=@ð5*ð 5*ð 5*ð 5*ð| 05ð;ð ;ð ;˜}ð ;Ø #ð;à#&ð;ð $'ð;ð #&ð	;ð
 &*ð;ð )-ð;ð :=ð;ð ;ð ;ð ;ð*:¨%¬)¬.ð :ÀÄ
ð :Ètð :ð :ð :ð :ð$�e”jð $ T¨#¨s°S©y¨.Ô%9ð $ð $ð $ð $ðN$˜9ð $¨mð $Èð $ÐPTð $ð $ð $ð $ð<ˆsð ð ð ð ð -Ð ðð ð ð ð(ð (ð (ð (ðV$ð $ð $ð $ðBBð Bð Bð Bð Bð Bs   Å?F!Æ!F%Æ(F%