§
    YrjJ•  ã                  ó$  — d dl m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mZmZmZ dZdZeeef         Zd+d„Zd,d-d„Ze G d„ d¦  «        ¦   «         Zd.d„Zd/d„Z	 d0d1d„Zd2d„Zd3d„Zd4d „Zd5d!„Zd5d"„Zd6d&„Z d7d(„Z! G d)„ d*¦  «        Z"dS )8é    )ÚannotationsN)Ú	dataclass)ÚDecimalÚInvalidOperationÚROUND_HALF_UP)ÚAnyÚDictÚListÚOptionalÚTupleé   é   ÚpenniesÚintÚreturnÚstrc                ód   — t          dt          | ¦  «        ¦  «        }|dz  }|dz  }d|d›d|d›�S )z&Format integer pennies as `$1,234.56`.r   éd   ú$ú,ú.Ú02d©Úmaxr   )r   ÚvalueÚdollarsÚcentss       ú²D:\Dyzine Tek Dropbox\Chris Cummings\Dyzine Tek, LLC\Engineering\Digital Signage\Overhead Bank Signage\DyzineFrame\Cursor OHD Project\DyzineFrame\reusable_odometer\core\engine.pyÚformat_dollarsr      sE   € å�•3�w‘<”<Ñ Ô €EØ�s‰l€GØ�C‰K€EØ&ˆwÐ&Ð&Ð&˜5Ð&Ð&Ð&Ð&ó    r   r   Údefaultc           
     óú  — | €t          dt          |¦  «        ¦  «        S t          | t          ¦  «        rt          dt          | ¦  «        ¦  «        S t          | t          ¦  «        rpt	          t          | ¦  «        ¦  «        t	          d¦  «        z  }t          dt          |                     t	          d¦  «        t          ¬¦  «        ¦  «        ¦  «        S t          | ¦  «                             ¦   «         }|st          dt          |¦  «        ¦  «        S | 	                    dd¦  «         	                    dd¦  «        }	 t	          |¦  «        }n4# t          t          f$ r  t          dt          |¦  «        ¦  «        cY S w xY wd	|v rV|t	          d¦  «        z  }t          dt          |                     t	          d¦  «        t          ¬¦  «        ¦  «        ¦  «        S t          dt          |¦  «        ¦  «        S )
z9Parse an int-pennies or dollar-string value into pennies.Nr   Ú100Ú1)Úroundingr   Ú r   r   )r   r   Ú
isinstanceÚfloatr   r   Úquantizer   ÚstripÚreplacer   Ú
ValueError)r   r!   r   ÚtextÚparseds        r   Úparse_display_to_penniesr/      s©  € à€}Ý�1•c˜'‘l”lÑ#Ô#Ð#Ý�%�ÑÔð "Ý�1•c˜%‘j”jÑ!Ô!Ð!Ý�%�ÑÔð QÝ�˜E™
œ
Ñ#Ô#¥g¨e¡n¤nÑ4ˆÝ�1•c˜%Ÿ.š.­°©¬Å˜.ÑNÔNÑOÔOÑPÔPÐPåˆu‰:Œ:×ÒÑÔ€DØð $Ý�1•c˜'‘l”lÑ#Ô#Ð#Ø�<Š<˜˜RÑ Ô ×(Ò(¨¨bÑ1Ô1€Dð$Ý˜‘”ˆˆøÝ�jÐ)ð $ð $ð $Ý�1•c˜'‘l”lÑ#Ô#Ð#Ð#Ð#ð$øøøð ˆd€{€{Ø� ™œÑ'ˆÝ�1•c˜%Ÿ.š.­°©¬Å˜.ÑNÔNÑOÔOÑPÔPÐPÝˆq•#�f‘+”+ÑÔÐs   ÅE Å.FÆFc                  ó˜  — e Zd ZU dZded<   dZded<   dZded<   dZded	<   dZded
<   dZ	ded<   dZ
ded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded<   dZded <   d!Zded"<   d#Zded$<   dZded%<   dZded&<   d'Zded(<   d)Zded*<   d+Zded,<   d-Zded.<   d/Zded0<   e	 d9d:d8„¦   «         Zd1S );ÚOdometerConfigiè  r   Úmax_lag_penniesiô  Úpenny_max_lag_penniesr   Údime_continuous_lag_penniesi„  Údime_roll_max_lag_penniesÚpenny_roll_max_lag_penniesg333333Ã?r(   Úmin_rateç      à?Úmax_rateç      @Údime_max_rateg      9@Úidle_catchup_secç      @Úcontribution_idle_secg      @Úpenny_roll_secç        Úpenny_roll_sec_minÚcarry_roll_secÚcarry_roll_sec_minÚinitial_display_pennies© úTuple[CurvePoint, ...]Ú
rate_curveÚroll_curve_secç      ð?Úchase_rate_scaleé   Úcatchup_lag_thresholdÚcatchup_lag_bonus_per_centÚsnap_behind_threshold_pennieséÈ   Úsnap_behind_to_lag_penniesgš™™™™™Ù?Úroll_smooth_taugš™™™™™É?Úpenny_roll_sec_floorr   Údime_catchup_enter_pennieséP   Údime_catchup_exit_penniesNÚdataúOptional[Dict[str, Any]]Úkwargsr   r   ú'OdometerConfig'c           	     ó~  — i }|r|                      |¦  «         |                      |¦  «          | ¦   «         }dD ])}||v r#t          ||         |j        ¬¦  «        |_         nŒ*i dd“dd“dd“dd“dd“dd“d	d“d
d
“dd
“dd“dd“dd“dd“dd“dd“dd“dd“i dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“dd“d d“d!d!“d"d"“d#d#“d$d#“¥d%d%d&œ¥}|                     ¦   «         D ] \  }}||v rt	          ||||         ¦  «         Œ!d'}	|	D ]/\  }}}
||v r%t	          ||t          ||         |
¦  «        ¦  «         Œ0|S )(N)Úinitial_displayÚinitial_dollarsÚinitial_pennies)r!   r2   r3   Úpenny_max_lagr6   Úpenny_roll_max_lagr4   Údime_continuous_lagr5   Údime_roll_max_lagr7   r9   r;   r<   r>   Úmax_lagÚpennies_min_rateÚpennies_max_rater?   rA   rB   rC   Údime_roll_secÚdime_roll_sec_minrJ   rL   rM   rN   rP   Ú!progressive_snap_behind_thresholdÚprogressive_snap_behind_lagrQ   rR   rS   Údime_catchup_enterrU   )rU   Údime_catchup_exit))rG   rG   Úrate)Úchase_rate_curverG   rk   )Úpennies_per_second_curverG   rk   )rH   rH   Úsec)Úpenny_roll_curve_secrH   rn   )Úroll_sec_curverH   rn   )Úupdater/   rD   ÚitemsÚsetattrÚ_parse_curve_points)ÚclsrV   rX   ÚmergedÚcfgÚkeyÚkey_mapÚsrcÚdstÚ	curve_mapÚ	value_keys              r   Úfrom_mappingzOdometerConfig.from_mappingQ   sø  € ð "$ˆØð 	 Ø�MŠM˜$ÑÔÐØ�Š�fÑÔÐØˆc‰eŒeˆàLð 	ð 	ˆCØ�fˆ}ˆ}Ý.FØ˜3”K¨Ô)Dð/ñ /ô /�Ô+ð �ð	 ð%
ØÐ0ð%
à#Ð%<ð%
ð Ð4ð%
ð )Ð*Fð	%
ð
 !Ð">ð%
ð *Ð+Hð%
ð "Ð#@ð%
ð (Ð)Dð%
ð  Ð!<ð%
ð ˜
ð%
ð ˜
ð%
ð ˜_ð%
ð Ð 2ð%
ð $Ð%<ð%
ð Ð(ð%
ð   
ð!%
ð"  
ð#%
ð %
ð$ Ð.ð%%
ð& !Ð"6ð'%
ð( Ð.ð)%
ð* !Ð"6ð+%
ð, Ð-ð-%
ð.  Ð!5ð/%
ð0 Ð 2ð1%
ð2 $Ð%<ð3%
ð4 )Ð*Fð5%
ð6 ,Ð-Lð7%
ð8 )Ð*Fð9%
ð: 0Ð1Pð;%
ð< *Ð+Gð=%
ð> Ð0ð?%
ð@ #Ð$:ðA%
ðB )Ð*FðC%
ðD !Ð">ðE%
ð %
ðF *EØ!<ðI%
ð %
ð %
ˆðL  Ÿš™œð 	/ð 	/‰HˆC�Ø�fˆ}ˆ}Ý˜˜S &¨¤+Ñ.Ô.Ð.øð
ˆ	ð $-ð 	Oð 	OÑˆC��iØ�fˆ}ˆ}Ý˜˜SÕ"5°f¸S´kÀ9Ñ"MÔ"MÑNÔNÐNøØˆ
r    ©N)rV   rW   rX   r   r   rY   ) Ú__name__Ú
__module__Ú__qualname__r2   Ú__annotations__r3   r4   r5   r6   r7   r9   r;   r<   r>   r?   rA   rB   rC   rD   rG   rH   rJ   rL   rM   rN   rP   rQ   rR   rS   rU   Úclassmethodr~   rE   r    r   r1   r1   /   s  € € € € € € à€OÐÐÐÑØ!$ÐÐ$Ð$Ð$Ñ$Ø'(ÐÐ(Ð(Ð(Ñ(Ø%(ÐÐ(Ð(Ð(Ñ(Ø&'ÐÐ'Ð'Ð'Ñ'Ø€HÐÐÐÑØ€HÐÐÐÑØ€MÐÐÐÑØ"ÐÐ"Ð"Ð"Ñ"Ø#&ÐÐ&Ð&Ð&Ñ&Ø€NÐÐÐÑØ #ÐÐ#Ð#Ð#Ñ#Ø€NÐÐÐÑØ #ÐÐ#Ð#Ð#Ñ#Ø#$ÐÐ$Ð$Ð$Ñ$Ø)+€JÐ+Ð+Ð+Ñ+Ø-/€NÐ/Ð/Ð/Ñ/Ø!ÐÐ!Ð!Ð!Ñ!Ø!#ÐÐ#Ð#Ð#Ñ#Ø(+ÐÐ+Ð+Ð+Ñ+à)-Ð!Ð-Ð-Ð-Ñ-Ø&)ÐÐ)Ð)Ð)Ñ)ð !€OÐ Ð Ð Ñ à"&ÐÐ&Ð&Ð&Ñ&à&)ÐÐ)Ð)Ð)Ñ)Ø%'ÐÐ'Ð'Ð'Ñ'àà.2ðDð Dð Dð Dñ „[ðDð Dð Dr    r1   rw   c                ó~   — | j         rt          d„ | j         D ¦   «         ¦  «        S | j        dk    r| j        S | j        S )Nc              3  ó&   K  — | ]}|d          V — ŒdS )r   NrE   ©Ú.0Úpoints     r   ú	<genexpr>z'_penny_roll_ramp_lag.<locals>.<genexpr>›   ó&   è è € Ð<Ð< �5˜”8Ð<Ð<Ð<Ð<Ð<Ð<r    r   )rH   r   r6   r3   )rw   s    r   Ú_penny_roll_ramp_lagrŒ   ™   sM   € Ø
Ôð =ÝÐ<Ð<¨Ô);Ð<Ñ<Ô<Ñ<Ô<Ð<Ø
Ô%¨Ò)Ð)ØÔ-Ð-ØÔ$Ð$r    r(   c                ó¤   — | j         rt          d„ | j         D ¦   «         ¦  «        S t          | j        d¦  «        }| j        dk    r| j        n|dz  S )Nc              3  ó&   K  — | ]}|d          V — ŒdS )é   NrE   r‡   s     r   rŠ   z#slowest_roll_sec.<locals>.<genexpr>£   r‹   r    ç�íµ ÷Æ°>r   r:   )rH   r   r?   rA   )rw   Úfasts     r   Úslowest_roll_secr’   ¡   s^   € Ø
Ôð =ÝÐ<Ð<¨Ô);Ð<Ñ<Ô<Ñ<Ô<Ð<ÝˆsÔ! 4Ñ(Ô(€DØ%(Ô%;¸aÒ%?Ð%?ˆ3Ô!Ð!ÀTÈCÁZÐOr    éÿÿÿÿÚpowerÚlag_penniesc                óR   — ~ |dk    r|nt          |¦  «        }t          ||¦  «        S ©Nr   )rŒ   Ú_penny_roll_sec_at_lag)r”   rw   r•   Úlags       r   Úcarry_roll_sec_for_powerrš   ¨   s3   € ð 	Ø$¨Ò)Ð)ˆ+ˆ+Õ/CÀCÑ/HÔ/H€CÝ! # sÑ+Ô+Ð+r    Údeltac                ó‚  — |j         rt          | |j         ¦  «        }nut          |j        d¦  «        }|j        dk    r|j        n|dz  }t          t          |¦  «        d¦  «        }t          t          d| ¦  «        |¦  «        |z  }||||z
  z  z   }t          |j        pd¦  «        }|dk    rt          ||¦  «        }|S )Nr�   r   r:   r�   r@   )	rH   Ú_curve_value_at_lagr   r?   rA   rŒ   Úminr(   rR   )r›   rw   rn   r‘   ÚslowÚcapÚtÚfloors           r   r˜   r˜   °   sÉ   € Ø
Ôð 'Ý! %¨Ô);Ñ<Ô<ˆˆå�3Ô% tÑ,Ô,ˆØ),Ô)?À!Ò)CÐ)CˆsÔ%Ð%ÈÐPSÉˆÝÕ& sÑ+Ô+¨QÑ/Ô/ˆÝ•�A�u‘”˜sÑ#Ô# cÑ)ˆØ�Q˜$ ™+Ñ&Ñ&ˆÝ�#Ô*Ð1¨cÑ2Ô2€EØˆs‚{€{Ý�#�u‰oŒoˆØ€Jr    ú	List[int]c                ó~   ‡ — t          dt          ‰ ¦  «        ¦  «        Š ˆ fd„t          t          ¦  «        D ¦   «         S )Nr   c                ó&   •— g | ]}‰d |z  z  d z  ‘ŒS )é
   rE   )rˆ   Úir   s     €r   ú
<listcomp>z&_pennies_to_digits.<locals>.<listcomp>Á   s'   ø€ ÐBÐBÐB¨!ˆW˜˜Q™Ñ 2Ñ%ÐBÐBÐBr    )r   r   ÚrangeÚNUM_COLUMNS)r   s   `r   Ú_pennies_to_digitsr«   ¿   s:   ø€ Ý�!•S˜‘\”\Ñ"Ô"€GØBÐBÐBÐB­uµ[Ñ/AÔ/AÐBÑBÔBÐBr    Údigitsc                óh   — t          t          dz
  dd¦  «        D ]}| |         dk    r|c S Œt          S )Nr�   r“   r   )r©   rª   ÚMIN_DISPLAY_POWER)r¬   r”   s     r   Úleftmost_significant_powerr¯   Ä   sD   € Ý•{ Q‘¨¨BÑ/Ô/ð ð ˆØ�%Œ=˜AÒÐØˆLˆLˆLð åÐr    c                óŽ  — t          | ¦  «        }t          d| ¦  «        }t          || ¦  «        }| j        s| j        r£| j        rdt	          | j        ¦  «        › d�n| j        › d| j        › d| j        › d�}| j        rdt	          | j        ¦  «        › d�n	|d›d|d›d	�}| j        dk    rd
| j        › d�nd}dt          | j
        ¦  «        › d|› d|› d|› d| j        › d�S | j        dk    rd
| j        › d�nd}dt          | j
        ¦  «        › d| j        › d|› d|d›d|d›d|› d| j        › d| j        › d| j        › d| j        › d�S )Nr   zcurve[ú]z->ú+zc/sz.2fzs->Úszdime_catchup@Úczdimes=intermittentzstart=z  chase=z  roll=ú  z  @ z  chase@zc  roll@zc zs  zc/s @ )rŒ   r˜   rG   rH   Úlenr7   r9   r;   rS   r   rD   r2   r3   )rw   Úroll_capÚ	roll_slowÚ	roll_fastÚ
chase_descÚ	roll_descÚ	dime_descs          r   Úformat_odometer_config_summaryr½   Ë   sJ  € Ý# CÑ(Ô(€HÝ& q¨#Ñ.Ô.€IÝ& x°Ñ5Ô5€IØ
„~ð 
˜Ô+ð 
ð Œ~ðJÐ+•S˜œÑ(Ô(Ð+Ð+Ð+Ð+à”LÐIÐI C¤LÐIÐI°3Ô3DÐIÐIÐIð 	ð Ô!ð7Ð/•S˜Ô+Ñ,Ô,Ð/Ð/Ð/Ð/àÐ6Ð6Ð6 iÐ6Ð6Ð6Ð6ð 	ð Ô-°Ò1Ð1ð >˜CÔ:Ð=Ð=Ð=Ð=à%ð 	ð5•^ CÔ$?Ñ@Ô@ð 5ð 5Øð5ð 5Ø(1ð5ð 5àð5ð 5à!Ô1ð5ð 5ð 5ð	
ð Ô)¨AÒ-Ð-ð 	:˜Ô6Ð9Ð9Ð9Ð9à!ð ð	$• Ô ;Ñ<Ô<ð 	$ð 	$ØÔ*ð	$ð 	$Ø4<ð	$ð 	$àÐ/ð	$ð 	$à&Ð/ð	$ð 	$ð ð	$ð 	$ð œð	$ð 	$ð ),¬ð	$ð 	$ð 8;Ô7Hð	$ð 	$ð Ô ð		$ð 	$ð 	$ðr    c                ój  — t          | d¬¦  «        }dg}dD ]ˆ}t          t          |dz  ¦  «        ¦  «        }|                     |¦  «        }t	          || ¦  «        }d|z  }t          ||¦  «        }|                     d|d›d	|d
›d	|d›d	|d›d	|d›d	|d›�¦  «         Œ‰d                     |¦  «        S )Nr   )Úinitial_target_penniesz2lag($)  lag(c)  chase  roll_s  roll_cap  EFFECTIVE)g      Ð?r8   rI   g       @r=   g      @g      @g      @gö(\�Âõ@r:   g      @g      @g      @g       @g      !@g{®Gáú!@g      "@ç      $@r   rI   z  $z4.2frµ   Ú5dz5.2fú
)ÚOdometerEnginer   ÚroundÚ_pennies_per_secondr˜   rž   ÚappendÚjoin)	rw   ÚengineÚlinesr   r™   ÚchaseÚrollÚrcapÚeffs	            r   Úformat_odometer_lag_maprÎ   ò   s÷   € Ý˜C¸Ð:Ñ:Ô:€FØAÐB€Eðð 
ð 
ˆõ( •%˜ #™Ñ&Ô&Ñ'Ô'ˆØ×*Ò*¨3Ñ/Ô/ˆÝ% c¨3Ñ/Ô/ˆØ�T‰zˆÝ�%˜ÑÔˆØ�ŠØ^�'Ð^Ð^Ð^ #Ð^Ð^Ð^¨EÐ^Ð^Ð^¸$Ð^Ð^Ð^ÀtÐ^Ð^Ð^ÐTWÐ^Ð^Ð^ñ	
ô 	
ð 	
ð 	
ð �9Š9�UÑÔÐr    Úrawr}   rF   c           
     óŠ  — t          | t          t          f¦  «        sdS i }| D �]r}d }d }t          |t          ¦  «        rÄ|                     d|                     d|                     d¦  «        ¦  «        ¦  «        }|                     ||                     d|                     d¦  «        ¦  «        ¦  «        }|�|€Œ›	 t          dt          |¦  «        ¦  «        }t          |¦  «        }n˜# t          t          f$ r Y ŒÜw xY wt          |t          t          f¦  «        ret          |¦  «        dk    rR	 t          dt          |d         ¦  «        ¦  «        }t          |d	         ¦  «        }n# t          t          f$ r Y �Œ]w xY w|�|�|d
k    r�Œm|||<   �Œtt          t          |                     ¦   «         ¦  «        ¦  «        S )NrE   r•   r™   Úxr   Úyr   r   r�   r@   )r'   ÚlistÚtupleÚdictÚgetr   r   r(   Ú	TypeErrorr,   r¶   Úsortedrr   )rÏ   r}   ÚpointsÚentryr™   r   Úlag_rawÚ	value_raws           r   rt   rt     s»  € Ý�c�D¥%˜=Ñ)Ô)ð ØˆrØ!€FØð ñ ˆØ!ˆØ!%ˆÝ�e�TÑ"Ô"ð 	Ø—i’i ¨u¯yªy¸ÀÇ	Â	È#ÁÄÑ/OÔ/OÑPÔPˆGØŸ	š	ØØ—	’	˜' 5§9¢9¨S¡>¤>Ñ2Ô2ñô ˆIð ˆ )Ð"3ØðÝ˜!�S ™\œ\Ñ*Ô*�Ý˜iÑ(Ô(��øÝ�zÐ*ð ð ð Ø�ðøøøå˜¥¥e˜}Ñ-Ô-ð 	µ#°e±*´*À²/°/ðÝ˜!�S  q¤™]œ]Ñ+Ô+�Ý˜e Aœh™œ��øÝ�zÐ*ð ð ð Ø‘ðøøøàˆ;˜%˜-¨5°Cª<¨<ÙØˆˆs‰‰Ý•˜Ÿš™œÑ'Ô'Ñ(Ô(Ð(s$   Â?,C,Ã,D Ã?D Ä38E,Å,FÆ FÚcurvec                ó   — |sdS | |d         d         k    r|d         d         S |d         \  }}|dd …         D ]7\  }}| |k    r(t          ||z
  d¦  «        }| |z
  |z  }||||z
  z  z   c S ||}}Œ8|d         d         S )Nr@   r   r�   r“   )r   )r›   rÝ   Úprev_lagÚ
prev_valuer™   r   Úspanr¡   s           r   r�   r�   4  s¸   € Øð ØˆsØ��a”˜”ÒÐØ�QŒx˜Œ{ÐØ  œ8Ñ€HˆjØ˜A˜B˜B”ið *ð *‰
ˆˆUØ�CŠ<ˆ<Ý�s˜X‘~ qÑ)Ô)ˆDØ˜Ñ! TÑ)ˆAØ  U¨ZÑ%7Ñ 8Ñ8Ð8Ð8Ð8Ø" E�*ˆˆØ�Œ9�QŒ<Ðr    c                  ó@  — e Zd Z	 	 dUdVd„ZdWd
„ZdWd„ZdWd„ZdXd„ZdXd„Ze	dYd„¦   «         Z
dZd„Ze	d[d„¦   «         ZdYd„ZdZd„ZdZd„ZdZd„Zd\d]d„Zd\d]d„Zd^d„Zd^d„Zd_d"„Zd\d`d$„Zdad%„Zdbd'„Zdbd(„ZdZd)„Zdad*„Zdcd+„Zd\ddd-„Zeded0„¦   «         Zd\dfd2„Z dZd3„Z!dad4„Z"dad5„Z#dcd6„Z$dad7„Z%dcd8„Z&dcd9„Z'dcd:„Z(dgd;„Z)dad<„Z*dad=„Z+edhd?„¦   «         Z,dZd@„Z-didA„Z.didB„Z/djdC„Z0ed_dD„¦   «         Z1dkdF„Z2dgdG„Z3dldH„Z4dmdndK„Z5edodL„¦   «         Z6dpdM„Z7dqdO„Z8djdP„Z9dYdQ„Z:drdS„Z;dadT„Z<dS )srÃ   NÚconfigúOptional[OdometerConfig]r¿   úOptional[int]c                óÖ  — |pt          ¦   «         | _        |€| j        j        nt          dt	          |¦  «        ¦  «        }|| _        t          |¦  «        | _        t          j	        ¦   «         | _
        dgt          z  | _        dgt          z  | _        d gt          z  | _        dgt          z  | _        d | _        d| _        t%          | j        ¦  «        | _        d| _        d | _        d S ©Nr   r@   F)r1   rã   rD   r   r   Útarget_penniesr(   Údisplay_floatÚtimeÚperf_counterÚ_last_target_change_timerª   Ú_carry_scroll_phaseÚ_carry_finishingÚ_carry_from_digitÚ_carry_was_inÚ_last_maintained_lagÚ_penny_scroll_visualr’   Ú_smoothed_roll_secÚ_dime_drivenÚ_cosmetic_penny_digit)Úselfrã   r¿   Ústarts       r   Ú__init__zOdometerEngine.__init__D  sã   € ð
 Ð0¥Ñ 0Ô 0ˆŒð &Ð-ð ŒKÔ/Ð/å�Q�Ð2Ñ3Ô3Ñ4Ô4ð 	ð
 $)ˆÔÝ$)¨%¡L¤LˆÔÝ/3Ô/@Ñ/BÔ/BˆÔ%Ø14°½Ñ0CˆÔ Ø-2¨GµkÑ,AˆÔØ7;°f½{Ñ6JˆÔØ*/¨µ;Ñ)>ˆÔØ37ˆÔ!Ø+.ˆÔ!Ý)9¸$¼+Ñ)FÔ)FˆÔà"'ˆÔà48ˆÔ"Ð"Ð"r    rè   r   ÚNonec                óÈ   — |€d S t          dt          |¦  «        ¦  «        }|| j        k    r5|| _        t          j        ¦   «         | _        |                      ¦   «          d S d S r—   )r   r   rè   rê   rë   rì   Úsnap_if_too_far_behind©rö   rè   r¡   s      r   Úset_target_penniesz!OdometerEngine.set_target_pennies^  sk   € ØÐ!ØˆFÝ�•3�~Ñ&Ô&Ñ'Ô'ˆØ�Ô#Ò#Ð#Ø"#ˆDÔÝ,0Ô,=Ñ,?Ô,?ˆDÔ)Ø×'Ò'Ñ)Ô)Ð)Ð)Ð)ð $Ð#r    c                ó°   — |€dS t          dt          |¦  «        ¦  «        }|| _        t          j        ¦   «         | _        |                      |¦  «         dS )zCSnap target and display immediately to a known starting/live value.Nr   )r   r   rè   rê   rë   rì   Ú_snap_display_to_settled_centsrü   s      r   Údisplay_immediate_penniesz(OdometerEngine.display_immediate_penniesg  sW   € àÐ!ØˆFÝ�•3�~Ñ&Ô&Ñ'Ô'ˆØˆÔÝ(,Ô(9Ñ(;Ô(;ˆÔ%Ø×+Ò+¨AÑ.Ô.Ð.Ð.Ð.r    c                ó0   — |                       |¦  «         d S r   )rý   )rö   rè   s     r   Ú
set_targetzOdometerEngine.set_targetp  s   € Ø×Ò Ñ/Ô/Ð/Ð/Ð/r    Údelta_penniesr   c                óZ   — |                       | j        t          |¦  «        z   ¦  «         d S r   )rý   rè   r   ©rö   r  s     r   Úbump_target_penniesz"OdometerEngine.bump_target_penniess  s,   € Ø×Ò Ô 3µc¸-Ñ6HÔ6HÑ HÑIÔIÐIÐIÐIr    c                ó0   — |                       |¦  «         d S r   )r  r  s     r   Úbump_targetzOdometerEngine.bump_targetv  s   € Ø× Ò  Ñ/Ô/Ð/Ð/Ð/r    c                ó*   — |                       ¦   «         S r   )Ú_settled_cents©rö   s    r   Údisplay_pennieszOdometerEngine.display_penniesy  s   € à×"Ò"Ñ$Ô$Ð$r    Úboolc                óº   — |                       ¦   «         dk    pC| j        p<| j        dk    p1t          d„ | j        D ¦   «         ¦  «        pt          | j        ¦  «        S )Nr   r�   c              3  ó"   K  — | ]
}|d k    V — ŒdS )r�   NrE   )rˆ   Úps     r   rŠ   z.OdometerEngine.is_animating.<locals>.<genexpr>‚  s&   è è € Ð>Ð> �1�t’8Ð>Ð>Ð>Ð>Ð>Ð>r    )r•   rô   rò   Úanyrí   rî   r  s    r   Úis_animatingzOdometerEngine.is_animating}  so   € à×ÒÑÔ Ò"ð *ØÔ ð*àÔ(¨4Ò/ð*õ Ð>Ð> TÔ%=Ð>Ñ>Ô>Ñ>Ô>ð*õ �4Ô(Ñ)Ô)ð	
r    r   c                ó   — | j         rdndS )z6HUD/debug: who owns catch-up math (`dime` or `penny`).ÚdimeÚpenny)rô   r  s    r   Úcatchup_modezOdometerEngine.catchup_mode†  s   € ð Ô*Ð7ˆvˆv°Ð7r    c                ó*   — t          | j        ¦  «        S r   )r   ré   r  s    r   r
  zOdometerEngine._settled_cents‹  s   € Ý�4Ô%Ñ&Ô&Ð&r    c                ó–   — t          | j        ¦  «        | j        z
  }|| j        j        k    rdS |                      | j        ¦  «         dS )NFT)r   ré   rè   rã   r2   rÿ   )rö   Ú	overshoots     r   Úsnap_if_wonzOdometerEngine.snap_if_wonŽ  sK   € Ý˜Ô*Ñ+Ô+¨dÔ.AÑAˆ	Ø˜œÔ3Ò3Ð3Ø�5Ø×+Ò+¨DÔ,?Ñ@Ô@Ð@Øˆtr    c                ót  — |                       ¦   «         }t          dt          | j        j        ¦  «        ¦  «        }t          dt          | j        j        ¦  «        ¦  «        }|dk    s||k    rdS t          d| j        |z
  ¦  «        }|                      ¦   «         |k    rdS |                      |¦  «         dS )zDIf lag exceeds threshold, jump display to a fixed lag behind target.r   FT)	r•   r   r   rã   rN   rP   rè   r
  rÿ   )rö   r™   Ú	thresholdÚ
target_lagÚsnap_displays        r   rû   z%OdometerEngine.snap_if_too_far_behind•  s¯   € à×ÒÑ Ô ˆÝ˜�3˜tœ{ÔHÑIÔIÑJÔJˆ	Ý˜�C ¤Ô FÑGÔGÑHÔHˆ
Ø˜Š>ˆ>˜S IÒ-Ð-Ø�5Ý˜1˜dÔ1°JÑ>Ñ?Ô?ˆØ×ÒÑ Ô  LÒ0Ð0Ø�5Ø×+Ò+¨LÑ9Ô9Ð9Øˆtr    c                óˆ   — |                       ¦   «         dk    rdS t          j        ¦   «         | j        z
  | j        j        k     S )Nr   T)r•   rê   rë   rì   rã   r>   r  s    r   Ú_contributions_activez$OdometerEngine._contributions_active¢  sD   € Ø×ÒÑÔ Ò!Ð!Ø�4åÔÑÔ $Ô"?Ñ?ØŒKÔ-ò.ð 	.r    r›   r(   c                óX   — |€|                       ¦   «         }|                      |¦  «        S r   )r•   rÅ   ©rö   r›   s     r   Úpennies_per_secondz!OdometerEngine.pennies_per_second©  s,   € Øˆ=Ø×$Ò$Ñ&Ô&ˆEØ×'Ò'¨Ñ.Ô.Ð.r    c                óø  — |€|                       ¦   «         }|dk    rdS | j        s-| j        j        dk    r7|t	          | j        j        ¦  «        k    rt          | j        d¦  «        }d|z  S t          |                      |¦  «        |  	                    |¦  «        ¦  «        }|  
                    ¦   «         }t          d|t          |                      ¦   «         ¦  «        z
  ¦  «        dz  }t          ||¦  «        S )Nr   r@   r�   rÀ   g      N@)r•   rô   rã   rS   r   r   ró   rž   rÅ   Ú_chase_animation_capÚ_intermittent_display_ceilingr(   r
  )rö   r›   rË   rÊ   ÚceilÚheadrooms         r   Úeffective_pennies_per_secondz+OdometerEngine.effective_pennies_per_second®  sð   € Øˆ=Ø×$Ò$Ñ&Ô&ˆEØ�AŠ:ˆ:Ø�3ØÔð 	ØŒKÔ2°QÒ6Ð6Ø�˜Tœ[ÔCÑDÔDÒDÐDõ �tÔ.°Ñ5Ô5ˆDØ˜$‘;ÐÝ�D×,Ò,¨UÑ3Ô3°T×5NÒ5NÈuÑ5UÔ5UÑVÔVˆØ×1Ò1Ñ3Ô3ˆÝ�s˜D¥5¨×)<Ò)<Ñ)>Ô)>Ñ#?Ô#?Ñ?Ñ@Ô@À4ÑGˆÝ�5˜(Ñ#Ô#Ð#r    c                ó
  — | j         }|dk    rdS |                      ¦   «         st          |j        ||j        z  ¦  «        S |j        rt          ||j        ¦  «        }n‰t          |j        d¦  «        }||k    r ||z  }|j        ||j        |j        z
  z  z   }nN|j        }t          |j	        |j        z
  d¦  «        }t          ||j        z
  |¦  «        }||z  }|||j        z  z   }t          dt          |j        ¦  «        ¦  «        }	||	z  }t          dt          |j        ¦  «        ¦  «        }
t          dt          |j        ¦  «        ¦  «        }|
dk    r+|dk    r%||
k    r|                      ¦   «         r|||
z
  |z  z  }|S )Nr   r@   r�   gš™™™™™©?)rã   r   r   r7   r<   rG   r�   r3   r9   r2   rž   r;   r(   rJ   r   rL   rM   )rö   r›   rw   rk   Ú	penny_capr¡   Ú
penny_rateÚbandÚexcessÚscaler  Úbonuss               r   rÅ   z"OdometerEngine._pennies_per_second¿  sœ  € ØŒkˆØ�AŠ:ˆ:Ø�3Ø×)Ò)Ñ+Ô+ð 	CÝ�s”| U¨SÔ-AÑ%AÑBÔBÐBØŒ>ð 	:Ý& u¨c¬nÑ=Ô=ˆDˆDå˜CÔ5°qÑ9Ô9ˆIØ˜	Ò!Ð!Ø˜IÑ%�Ø”| a¨3¬<¸#¼,Ñ+FÑ&GÑG��à œ\�
Ý˜3Ô.°Ô1JÑJÈAÑNÔN�Ý˜U SÔ%>Ñ>ÀÑEÔE�Ø˜T‘M�Ø! A¨Ô(9Ñ$9Ñ9�Ý�D�% Ô 4Ñ5Ô5Ñ6Ô6ˆØ�e‰|ˆÝ˜�3˜sÔ8Ñ9Ô9Ñ:Ô:ˆ	Ý�C�˜sÔ=Ñ>Ô>Ñ?Ô?ˆà˜ŠMˆMØ˜’	�	Ø˜	Ò!Ð!Ø×*Ò*Ñ,Ô,ð "ð �U˜YÑ&¨%Ñ/Ñ/ˆDØˆr    c           	     óŽ   — dt          t          t          d|¦  «        t          | j        ¦  «        ¦  «        | j        ¦  «        z  S )NrI   r   )r˜   rž   r   rŒ   rã   r"  s     r   r%  z#OdometerEngine._chase_animation_capß  s@   € ØÕ+Ý•�A�u‘”Õ3°D´KÑ@Ô@ÑAÔAÀ4Ä;ñ
ô 
ñ 
ð 	
r    ré   r”   c                ó   — d|z  }||z  |z  S ©Nr¦   rE   )rö   ré   r”   Úunits       r   Ú_column_fractionzOdometerEngine._column_fractionä  s   € Ø�5‰yˆØ Ñ$¨Ñ,Ð,r    r   c                ó  — |€|                       ¦   «         nt          dt          |¦  «        ¦  «        }t          |¦  «        | _        d| _        t          | j        ¦  «        | _        d| _	        d | _
        |                      ¦   «          d S rç   )r
  r   r   r(   ré   rò   r’   rã   ró   rô   rõ   Ú_clear_all_carry_scroll)rö   r   r   s      r   rÿ   z-OdometerEngine._snap_display_to_settled_centsè  s|   € Ø).¨�×#Ò#Ñ%Ô%Ð%½CÀÅ3ÀuÁ:Ä:Ñ<NÔ<NˆÝ" 5™\œ\ˆÔØ$'ˆÔ!Ý"2°4´;Ñ"?Ô"?ˆÔØ!ˆÔØ%)ˆÔ"Ø×$Ò$Ñ&Ô&Ð&Ð&Ð&r    c                ó  — |                       ¦   «         }t          | j        |z
  ¦  «        dk    rt          |¦  «        | _        |                      ¦   «         dk    r+d| _        d| _        d | _        |                      ¦   «          d S d S )Nç•Ö&è.>r   r@   F)	r
  Úabsré   r(   r•   rò   rô   rõ   r7  )rö   Úsettleds     r   Ú_discard_sub_cent_slopz%OdometerEngine._discard_sub_cent_slopñ  s‹   € Ø×%Ò%Ñ'Ô'ˆÝˆtÔ! GÑ+Ñ,Ô,¨tÒ3Ð3Ý!& w¡¤ˆDÔØ×ÒÑÔ Ò"Ð"Ø(+ˆDÔ%Ø %ˆDÔØ)-ˆDÔ&Ø×(Ò(Ñ*Ô*Ð*Ð*Ð*ð	 #Ð"r    Údtc           	     ó€  — t          t          t          d|                      ¦   «         ¦  «        t	          | j        ¦  «        ¦  «        | j        ¦  «        }|| j        k    r|| _        nPt          | j        j        d¦  «        }dt          j	        | |z  ¦  «        z
  }| xj        || j        z
  |z  z  c_        | j        S )aF  Exponentially smooth roll duration toward the lag-derived target.

        One-sided: deceleration (longer roll = slower speed) is immediate so the
        odometer always approaches lag=0 at the slowest scroll speed.  Acceleration
        (shorter roll = faster speed) eases in over roll_smooth_tau to prevent jerks.
        r�   r�   rI   )
r˜   rž   r   r•   rŒ   rã   ró   rQ   ÚmathÚexp)rö   r=  ÚtargetÚtauÚalphas        r   Ú_smooth_roll_seczOdometerEngine._smooth_roll_secû  s¹   € õ (Ý•�A�t×'Ò'Ñ)Ô)Ñ*Ô*Õ,@ÀÄÑ,MÔ,MÑNÔNØŒKñ
ô 
ˆð �TÔ,Ò,Ð,Ø&,ˆDÔ#Ð#å�d”kÔ1°4Ñ8Ô8ˆCØ�$œ( B 3¨¡9Ñ-Ô-Ñ-ˆEØÐ#Ô#¨°Ô1HÑ(HÈEÑ'QÑQÐ#Ô#ØÔ&Ð&r    c                ó2   — |t          | j        d¦  «        z  S )Nr�   )r   ró   )rö   r=  s     r   Ú_penny_roll_stepzOdometerEngine._penny_roll_step  s   € Ø•C˜Ô/°Ñ6Ô6Ñ6Ð6r    c                ó\   — |                       ¦   «         }| j        |z
  }|dk    o|dz  dk    S )Nr   r¦   é	   )r
  rè   )rö   r;  Úgaps      r   Ú_chase_needs_penny_carry_chainz-OdometerEngine._chase_needs_penny_carry_chain  s8   € Ø×%Ò%Ñ'Ô'ˆØÔ! GÑ+ˆØ�QŠwÐ.˜G b™L¨QÒ.Ð.r    c                óŽ  — t          dt          | j        j        ¦  «        ¦  «        }|dk    r=| j        r4| j        d         dk    r#d| _        d| _        |                      d¦  «         dS t          dt          | j        j        ¦  «        ¦  «        }||k    rt          d|dz  ¦  «        }|  	                    ¦   «         }| j        d         dk    }| j        ss||k    rkd| _        t          t          t          d|¦  «        t          | j        ¦  «        ¦  «        | j        ¦  «        | _        |                      ¦   «         dz  | _        dS |dz   }||k     rn|sn|                      ¦   «         dz  }| j        }|du p t          |¦  «        dz  |k    o
| j        dk    }|sdS d| _        d| _        |                      d¦  «         dS dS dS )	z7Enter/exit lag-gated dime-driven catch-up (hysteresis).r   r�   r�   FNr   Tr¦   )r   r   rã   rS   rô   rí   rõ   Ú_clear_carry_scrollrU   r•   r˜   rž   rŒ   ró   r
  rò   )	rö   ÚenterÚexit_lagr™   Údime_inflightÚhandoffÚsettled_digitÚcosmeticÚaligneds	            r   Ú_update_dime_mode_statez&OdometerEngine._update_dime_mode_state  sì  € å�A•s˜4œ;ÔAÑBÔBÑCÔCˆØ�AŠ:ˆ:ØÔ ð , TÔ%=¸aÔ%@ÀDÒ%HÐ%HØ$)�Ô!Ø-1�Ô*Ø×(Ò(¨Ñ+Ô+Ð+ØˆFÝ�q�#˜dœkÔCÑDÔDÑEÔEˆØ�uÒÐÝ˜1˜e q™jÑ)Ô)ˆHØ×ÒÑ Ô ˆØÔ0°Ô3°dÒ:ˆØÔ ð 		Ø�eŠ|ˆ|Ø$(�Ô!å*@Ý�˜A˜s™œÕ%9¸$¼+Ñ%FÔ%FÑGÔGØ”Kñ+ô +�Ô'ð .2×-@Ò-@Ñ-BÔ-BÀRÑ-G�Ô*ØˆFð ˜R‘-ˆØ�Š=ˆ= ˆ=Ø ×/Ò/Ñ1Ô1°BÑ6ˆMØÔ1ˆHØ $Ð&ð Ý�H‘” Ñ" mÒ3ð 6ØÔ-°Ò5ð ð ð Ø�Ø %ˆDÔØ)-ˆDÔ&Ø×$Ò$ QÑ'Ô'Ð'Ð'Ð'ð ˆ=ˆ=ˆ=r    c                ó  — | j         €|                      ¦   «         dz  | _         |                      |¦  «        }t          d| j        |z   ¦  «        | _        | j        dk    r(d| _        t          | j         ¦  «        dz   dz  | _         dS dS )zCFree-spin pennies 0-9 at current roll rate without advancing value.Nr¦   rI   ç¡�vÿÿÿï?r@   r�   )rõ   r
  rF  rž   rò   r   )rö   r=  Ústeps      r   Ú_chase_penny_cosmeticz$OdometerEngine._chase_penny_cosmeticA  s“   € àÔ%Ð-Ø)-×)<Ò)<Ñ)>Ô)>ÀÑ)CˆDÔ&Ø×$Ò$ RÑ(Ô(ˆÝ$'¨¨TÔ-FÈÑ-MÑ$NÔ$NˆÔ!ØÔ$¨
Ò2Ð2Ø(+ˆDÔ%Ý*-¨dÔ.HÑ*IÔ*IÈAÑ*MÐQSÑ)SˆDÔ&Ð&Ð&ð 3Ð2r    r;  c                ó~   — |€|                       ¦   «         nt          dt          |¦  «        ¦  «        }|dz  dz  dz   S )Nr   r¦   )r
  r   r   )rö   r;  r   s      r   Ú_next_dime_boundaryz"OdometerEngine._next_dime_boundaryK  s@   € Ø)0¨�×#Ò#Ñ%Ô%Ð%½cÀ!ÅSÈÁ\Ä\Ñ>RÔ>RˆØ˜‘˜rÑ! BÑ&Ð&r    ÚbeforeÚafterc                óœ   — d|z  }t          dt          | ¦  «        ¦  «        |z  dz  t          dt          |¦  «        ¦  «        |z  dz  k    S )zLTrue when this decimal column's glyph changes between two whole-cent values.r¦   r   r   )r[  r\  r”   r4  s       r   Ú_digit_changes_crossingz&OdometerEngine._digit_changes_crossingO  sM   € ð �5‰yˆÝ�Q�˜F™œÑ$Ô$¨Ñ,°Ñ2½¸QÅÀEÁ
Ä
Ñ9KÔ9KÈtÑ9SÐWYÑ8YÒZÐZr    r£   c                ó  ‡ ‡‡— |€‰                       ¦   «         nt          dt          |¦  «        ¦  «        Št          ‰                      ‰¦  «        ‰ j        ¦  «        Š‰‰k    rg S ˆˆ ˆfd„t          dt          ¦  «        D ¦   «         S )uG   Dollar+ powers whose digits wrap when the next independent +10Â¢ lands.Nr   c                óB   •— g | ]}‰                      ‰‰|¦  «        ¯|‘ŒS rE   )r^  )rˆ   r”   Únxtrö   r   s     €€€r   r¨   zCOdometerEngine._powers_scrolling_with_next_dime.<locals>.<listcomp>[  sA   ø€ ð 
ð 
ð 
àØ×+Ò+¨E°3¸Ñ>Ô>ð
Øð
ð 
ð 
r    r   )r
  r   r   rž   rZ  rè   r©   rª   )rö   r;  ra  r   s   ` @@r   Ú _powers_scrolling_with_next_dimez/OdometerEngine._powers_scrolling_with_next_dimeU  sœ   øøø€ à)0¨�×#Ò#Ñ%Ô%Ð%½cÀ!ÅSÈÁ\Ä\Ñ>RÔ>RˆÝ�$×*Ò*¨5Ñ1Ô1°4Ô3FÑGÔGˆØ�%Š<ˆ<ØˆIð
ð 
ð 
ð 
ð 
ð 
å˜q¥+Ñ.Ô.ð
ñ 
ô 
ð 	
r    c                ó`   — |                       ¦   «         D ]}| j        |         }|dk     r dS ŒdS )zNTrue while a dollar+ cascade for the pending next-dime boundary is unfinished.rV  TF)rb  rí   ©rö   r”   Úphases      r   Ú%_higher_columns_pending_for_next_dimez4OdometerEngine._higher_columns_pending_for_next_dimea  sF   € à×:Ò:Ñ<Ô<ð 	ð 	ˆEØÔ,¨UÔ3ˆEØ�zÒ!Ð!Ø�t�tð "àˆur    c                óÆ   — |                       d¦  «         t          dt          ¦  «        D ]5}| j        |         dk    s| j        |         r|                       |¦  «         Œ6dS )uF   Clear dimes + any dollar+ phases that ride the independent +10Â¢ land.r�   r   r�   N)rL  r©   rª   rí   rî   ©rö   r”   s     r   Ú_clear_dime_cascade_columnsz*OdometerEngine._clear_dime_cascade_columnsi  sn   € à× Ò  Ñ#Ô#Ð#Ý˜1�kÑ*Ô*ð 	0ð 	0ˆEØÔ'¨Ô.°Ò5Ð5¸Ô9NÈuÔ9UÐ5Ø×(Ò(¨Ñ/Ô/Ð/øð	0ð 	0r    c                óê   — |                       ¦   «         }|                      |¦  «        }|| j        k    r|                      ¦   «          dS t	          |¦  «        | _        |                      ¦   «          dS )zOComplete a decoupled dime roll: next dime boundary only (never snap to target).N)r
  rZ  rè   ri  r(   ré   )rö   r;  Ú	next_dimes      r   Ú_land_independent_dimez%OdometerEngine._land_independent_dimep  ss   € à×%Ò%Ñ'Ô'ˆØ×,Ò,¨WÑ5Ô5ˆ	Ø�tÔ*Ò*Ð*à×,Ò,Ñ.Ô.Ð.ØˆFÝ" 9Ñ-Ô-ˆÔà×(Ò(Ñ*Ô*Ð*Ð*Ð*r    c                ó.  — |                       |¦  «         |                      ¦   «         }| j        |z
  }| j        d         }|                      |¦  «        }t          dt          | j        j        ¦  «        ¦  «        }t          d|dz   ¦  «        }|dk    rF||k     rdS |dz  dz  | j	        d<   d| j
        d<   d| j        d<   t          d|¦  «        | j        d<   dS |dk     r|                      ¦   «          dS t          d||z   ¦  «        }|| j        d<   dS )	uñ   Dimes own +10Â¢ on their own schedule; pennies are cosmetic only.

        When the next +10Â¢ changes dollars (and higher), those columns scroll in
        sync via ``_update_intermittent_scroll`` â€” do not land until they finish.
        r�   r   r¦   r�   NTFrI   )rX  r
  rè   rí   rF  r   r   rã   rU   rï   rð   rî   rž   ri  )rö   r=  r;  rI  re  rW  rN  Úmin_gap_to_starts           r   Ú_update_dime_driven_catchupz*OdometerEngine._update_dime_driven_catchup|  s2  € ð 	×"Ò" 2Ñ&Ô&Ð&Ø×%Ò%Ñ'Ô'ˆØÔ! GÑ+ˆØÔ(¨Ô+ˆØ×$Ò$ RÑ(Ô(ˆÝ�q�#˜dœkÔCÑDÔDÑEÔEˆõ ˜r 8¨b¡=Ñ1Ô1ÐØ�DŠ=ˆ=ØÐ%Ò%Ð%Ø�Ø)0°B©¸"Ñ(<ˆDÔ" 1Ñ%Ø$(ˆDÔ˜qÑ!Ø',ˆDÔ! !Ñ$Ý*-¨c°4©.¬.ˆDÔ$ QÑ'ØˆFØ�Š8ˆ8à×,Ò,Ñ.Ô.Ð.ØˆFÝ�C˜ ™Ñ&Ô&ˆØ&+ˆÔ  Ñ#Ð#Ð#r    c                ó’   — | j         sdS | j        d         dk     rdS |                      ¦   «         rdS |                      ¦   «          dS )uG   Apply +10Â¢ land when dime roll is complete and higher digits finished.Nr�   rV  )rô   rí   rf  rl  r  s    r   Ú_try_land_independent_dimez)OdometerEngine._try_land_independent_dime›  s[   € àÔ ð 	ØˆFØÔ# AÔ&¨Ò3Ð3ØˆFØ×5Ò5Ñ7Ô7ð 	ØˆFØ×#Ò#Ñ%Ô%Ð%Ð%Ð%r    c                ó¸  — |                       ¦   «         }| j        |k    rd S |                      ¦   «         r4|                      |¦  «        }t	          d| j        |z   ¦  «        | _        d S |                      |¦  «        }t	          d| j        |z   ¦  «        | _        | j        dk    r3d| _        t          t	          |dz   | j        ¦  «        ¦  «        | _        d S d S )NrI   rV  r@   r�   )r
  rè   rJ  rF  rž   rò   r(   ré   ©rö   r=  r;  rW  s       r   Ú_chase_cent_upzOdometerEngine._chase_cent_up¥  sÞ   € Ø×%Ò%Ñ'Ô'ˆØÔ 'Ò)Ð)ØˆFØ×.Ò.Ñ0Ô0ð 	Ø×(Ò(¨Ñ,Ô,ˆDÝ(+¨C°Ô1JÈTÑ1QÑ(RÔ(RˆDÔ%ØˆFØ×$Ò$ RÑ(Ô(ˆÝ$'¨¨TÔ-FÈÑ-MÑ$NÔ$NˆÔ!ØÔ$¨
Ò2Ð2Ø(+ˆDÔ%Ý!&¥s¨7°Q©;¸Ô8KÑ'LÔ'LÑ!MÔ!MˆDÔÐÐð 3Ð2r    c                ó’  — |                       ¦   «         }|| j        k    rd S |                      |¦  «        }| j        dk    r[t	          d| j        |z
  ¦  «        | _        | j        dk    r1d| _        t          t	          |dz
  | j        ¦  «        ¦  «        | _        d S t          t	          |dz
  | j        ¦  «        ¦  «        | _        d S )Nr�   r@   r9  r�   )r
  rè   rF  rò   r   r(   ré   rs  s       r   Ú_chase_cent_downzOdometerEngine._chase_cent_down³  sÄ   € Ø×%Ò%Ñ'Ô'ˆØ�dÔ)Ò)Ð)ØˆFØ×$Ò$ RÑ(Ô(ˆØÔ$ tÒ+Ð+Ý(+¨C°Ô1JÈTÑ1QÑ(RÔ(RˆDÔ%ØÔ(¨DÒ0Ð0Ø,/�Ô)Ý%*­3¨w¸©{¸DÔ<OÑ+PÔ+PÑ%QÔ%Q�Ô"ØˆFÝ"¥3 w°¡{°DÔ4GÑ#HÔ#HÑIÔIˆÔÐÐr    c                óð  — |dk    rd S |                       ¦   «          |                      ¦   «          |                      ¦   «          |                      |¦  «         |                      ¦   «         }| j        |k    rw| j        rB|                      |¦  «         |                      |d¬¦  «         |  	                    ¦   «          d S |  
                    |¦  «         |                      |d¬¦  «         d S | j        |k     rPd| _        d | _        |                      |¦  «         |                      ¦   «          |                      |d¬¦  «         d S |                      ¦   «          |                      |d¬¦  «         d S )Nr   r   )Ú	min_powerr�   F)r  rû   rT  rD  r
  rè   rô   ro  Ú_update_intermittent_scrollrq  rt  rõ   rv  Ú$_sync_intermittent_phases_to_displayr<  )rö   r=  r;  s      r   rq   zOdometerEngine.updateÀ  s“  € Ø�Š7ˆ7ØˆFØ×ÒÑÔÐØ×#Ò#Ñ%Ô%Ð%Ø×$Ò$Ñ&Ô&Ð&Ø×Ò˜bÑ!Ô!Ð!Ø×%Ò%Ñ'Ô'ˆØÔ Ò(Ð(ØÔ ð Bð ×0Ò0°Ñ4Ô4Ð4Ø×0Ò0°¸qÐ0ÑAÔAÐAØ×/Ò/Ñ1Ô1Ð1Ð1Ð1à×#Ò# BÑ'Ô'Ð'Ø×0Ò0°¸qÐ0ÑAÔAÐAÐAÐAØÔ  7Ò*Ð*Ø %ˆDÔØ)-ˆDÔ&Ø×!Ò! "Ñ%Ô%Ð%Ø×5Ò5Ñ7Ô7Ð7Ø×,Ò,¨R¸1Ð,Ñ=Ô=Ð=Ð=Ð=à×'Ò'Ñ)Ô)Ð)Ø×,Ò,¨R¸1Ð,Ñ=Ô=Ð=Ð=Ð=r    c                óV   — d| j         |<   d| j        |<   d | j        |<   d| j        |<   d S )Nr@   F)rí   rî   rï   rð   rh  s     r   rL  z"OdometerEngine._clear_carry_scrollÜ  s<   € Ø*-ˆÔ  Ñ'Ø',ˆÔ˜eÑ$Ø(,ˆÔ˜uÑ%Ø$)ˆÔ˜5Ñ!Ð!Ð!r    c                ó^   — t          t          ¦  «        D ]}|                      |¦  «         Œd S r   )r©   rª   rL  rh  s     r   r7  z&OdometerEngine._clear_all_carry_scrollâ  s:   € Ý�;Ñ'Ô'ð 	,ð 	,ˆEØ×$Ò$ UÑ+Ô+Ð+Ð+ð	,ð 	,r    c                ó2  — | j         }t          dt          ¦  «        D ]y}| j        |         }|dk    rŒ|                      |¦  «        r|                      |¦  «        }n%| j        |         r|                      ||¦  «        }nŒf||dz   k    r
|| j        |<   Œzd S )Nr�   r�   )ré   r©   rª   rí   Ú_column_cascade_activeÚ_intermittent_scroll_targetrî   r5  )rö   Údfr”   re  rA  s        r   rz  z3OdometerEngine._sync_intermittent_phases_to_displayæ  s¸   € ØÔˆÝ˜1�kÑ*Ô*ð 	9ð 	9ˆEØÔ,¨UÔ3ˆEØ˜Š}ˆ}ØØ×*Ò*¨5Ñ1Ô1ð Ø×9Ò9¸%Ñ@Ô@��ØÔ& uÔ-ð Ø×.Ò.¨r°5Ñ9Ô9��àØ�v ‘}Ò$Ð$Ø28�Ô(¨Ñ/øð	9ð 	9r    Úsettled_centsc                ó   — | d|z  z  dz  S r3  rE   )r�  r”   s     r   Ú_digit_at_powerzOdometerEngine._digit_at_powerõ  s   € à " e¡)Ñ,°Ñ2Ð2r    c                ó2   — |                       ¦   «         dk    S r—   )r•   r  s    r   Ú_display_is_chasingz"OdometerEngine._display_is_chasingù  s   € Ø×ÒÑ!Ô! AÒ%Ð%r    c                óN   — | j         |         }|dk    r|dk     p| j        |         S )Nr�   rV  )rí   rî   rd  s      r   Ú_carry_roll_in_progressz&OdometerEngine._carry_roll_in_progressü  s0   € ØÔ(¨Ô/ˆØ˜’Ð3 ¨Ò!3ÐT¸Ô8MÈeÔ8TÐTr    c                óf  — |dk    rdS |dk    r	| j         rdS |                      |¦  «        rdS |                      ¦   «         sdS |                      ¦   «         }|dk    r|                      |d¦  «        S | j         rGt          |                      |¦  «        | j        ¦  «        }||k    rdS |                      |||¦  «        S |                      ||¦  «        sdS |  	                    ||¦  «        dk    rdS |dz
  }|                      |¦  «        p!| j
        |         p|                      |¦  «        S )Nr   Fr�   TrH  )rô   r‡  r…  r
  Ú_column_in_carryrž   rZ  rè   r^  rƒ  rî   r~  )rö   r”   r;  ra  Úlowers        r   r~  z%OdometerEngine._column_cascade_active   s_  € Ø�AŠ:ˆ:Ø�5à�AŠ:ˆ:˜$Ô+ˆ:Ø�5Ø×'Ò'¨Ñ.Ô.ð 	Ø�4Ø×'Ò'Ñ)Ô)ð 	Ø�5Ø×%Ò%Ñ'Ô'ˆØ�AŠ:ˆ:Ø×(Ò(¨°!Ñ4Ô4Ð4ð Ôð 	EÝ�d×.Ò.¨wÑ7Ô7¸Ô9LÑMÔMˆCØ�gŠ~ˆ~Ø�uØ×/Ò/°¸¸eÑDÔDÐDØ×$Ò$ W¨eÑ4Ô4ð 	Ø�5Ø×Ò ¨Ñ/Ô/°1Ò4Ð4Ø�4Ø˜‘	ˆà×(Ò(¨Ñ/Ô/ð 2ØÔ$ UÔ+ð2à×*Ò*¨5Ñ1Ô1ð	
r    c                ó4   — |                       |¦  «        sdS dS )Nr@   rI   )r~  rh  s     r   r  z*OdometerEngine._intermittent_scroll_target  s"   € Ø×*Ò*¨5Ñ1Ô1ð 	Ø�3Øˆsr    c                óf   — d|z  }t          | ¦  «        |z  |z  }t          ||z   dz
  ¦  «        dz   S )Nr¦   r�   gé!çýÿï?)r   r(   )ré   r”   r4  Útails       r   Ú_carry_window_capz OdometerEngine._carry_window_cap$  s=   € à�5‰yˆÝ�MÑ"Ô" dÑ*¨dÑ2ˆÝ�T˜D‘[ 1‘_Ñ%Ô%¨Ñ0Ð0r    úOptional[float]c                óh  — | j         rd S g }t          dt          ¦  «        D ]}|                      |¦  «        r*|                     |                      ||¦  «        ¦  «         ŒA|                      |¦  «        r)|                     |                      ||¦  «        ¦  «         Œ€|sd S t          |¦  «        S ©Nr�   )rô   r©   rª   r‡  rÆ   rŽ  r~  rž   )rö   ré   Úcapsr”   s       r   Ú_carry_display_hold_capz&OdometerEngine._carry_display_hold_cap*  sÁ   € àÔð 	Ø�4ØˆÝ˜1�kÑ*Ô*ð 	Jð 	JˆEØ×+Ò+¨EÑ2Ô2ð JØ—’˜D×2Ò2°=À%ÑHÔHÑIÔIÐIÐIØ×,Ò,¨UÑ3Ô3ð JØ—’˜D×2Ò2°=À%ÑHÔHÑIÔIÐIøØð 	Ø�4Ý�4‰yŒyÐr    c                óÚ  — t          |dz   t          ¦  «        D ]'}|                      |¦  «        s| j        |         r d S Œ(|                      ¦   «         }|| j        k    rd S | j        |z
  }|dk    r%|dz  dk    r|                      | j        ¦  «         d S d|z  }||z  |dz
  k     rd S t          ||z  |z  |z   | j        ¦  «        }||k    rt          |¦  «        | _	        d| _
        d S d S )Nr�   r¦   rH  r@   )r©   rª   r‡  rî   r
  rè   rÿ   rž   r(   ré   rò   )rö   r”   Úhigherr;  rI  r4  Úbumpeds          r   Ú_bump_display_after_carryz(OdometerEngine._bump_display_after_carry8  s$  € Ý˜E A™I¥{Ñ3Ô3ð 	ð 	ˆFØ×+Ò+¨FÑ3Ô3ð °tÔ7LÈVÔ7Tð Ø��ðà×%Ò%Ñ'Ô'ˆØ�dÔ)Ò)Ð)ØˆFØÔ! GÑ+ˆØ�!Š8ˆ8˜ 2™¨!Ò+Ð+Ø×/Ò/°Ô0CÑDÔDÐDØˆFØ�5‰yˆØ�d‰N˜d Q™hÒ&Ð&ØˆFÝ�g ‘o¨Ñ-°Ñ4°dÔ6IÑJÔJˆØ�GÒÐÝ!& v¡¤ˆDÔØ(+ˆDÔ%Ð%Ð%ð Ðr    c                ó†   — t          | j        ¦  «        }|                      | j        ¦  «        }|�t	          ||¦  «        }|S r   )r(   rè   r“  ré   rž   )rö   Úceilingr    s      r   r&  z,OdometerEngine._intermittent_display_ceilingK  sA   € Ý˜Ô+Ñ,Ô,ˆØ×*Ò*¨4Ô+=Ñ>Ô>ˆØˆ?Ý˜' 3Ñ'Ô'ˆGØˆr    r�   rx  c                ó>  — |dk    rd S t          dt          |¦  «        ¦  «        }| j        r!t          |                      ¦   «         ¦  «        nt          ¦   «         }t          |t          ¦  «        D �]ª}|                      ¦   «         d|z  z  dz  }| j        |         }|t          | j	        d¦  «        z  }|dk    rA| j        r||v rd| j        |<   Œa|  
                    |¦  «         |                      |¦  «         ŒŒ|                      |¦  «        }	| j        |         }
|	rX|
s
|| j        |<   d| j        |<   d| j        |<   |                      |¦  «        }||k    rt#          |||z   ¦  «        | j        |<   �Œd| j        |<   |dk    r}| j        |         �pd| j        |<   t#          d||z   ¦  «        }|| j        |<   |dk    rA| j        r||v rd| j        |<   �Œi|  
                    |¦  «         |                      |¦  «         �Œ•|  
                    |¦  «         �Œ¬d S )	Nr   r�   r¦   r�   rV  rI   TF)r   r   rô   Úsetrb  r©   rª   r
  rí   ró   rL  r—  r~  rð   rï   rî   r  rž   )rö   r=  rx  r÷   Úpending_dime_powersr”   r;  re  rW  Ú	cascadingÚwas_inrA  s               r   ry  z*OdometerEngine._update_intermittent_scrollR  sp  € Ø�Š7ˆ7ØˆFÝ�A•s˜9‘~”~Ñ&Ô&ˆà<@Ô<MÐX�C�×5Ò5Ñ7Ô7Ñ8Ô8Ð8ÕSVÑSXÔSXð 	õ ˜5¥+Ñ.Ô.ð $	,ñ $	,ˆEØ×*Ò*Ñ,Ô,°°U±Ñ;¸rÑAˆGØÔ,¨UÔ3ˆEØ�˜DÔ3°TÑ:Ô:Ñ:ˆDØ˜
Ò"Ð"ð Ô$ð ¨Ð2EÐ)EÐ)EØ69�DÔ,¨UÑ3ØØ×(Ò(¨Ñ/Ô/Ð/Ø×.Ò.¨uÑ5Ô5Ð5ØØ×3Ò3°EÑ:Ô:ˆIØÔ'¨Ô.ˆFØð Øð <Ø4;�DÔ*¨5Ñ1Ø,0�Ô" 5Ñ)Ø/4�Ô% eÑ,Ø×9Ò9¸%Ñ@Ô@�Ø˜E’>�>Ý69¸&À%È$Á,Ñ6OÔ6O�DÔ,¨UÑ3ÙØ(-ˆDÔ˜uÑ%Ø�tŠ|ˆ| Ô 6°uÔ =Ð IØ/3�Ô% eÑ,Ý˜C ¨¡Ñ.Ô.�Ø27�Ô(¨Ñ/Ø˜JÒ&Ð&ØÔ(ð !¨UÐ6IÐ-IÐ-IØ:=˜Ô0°Ñ7Ù Ø×,Ò,¨UÑ3Ô3Ð3Ø×2Ò2°5Ñ9Ô9Ð9ÙØ×$Ò$ UÑ+Ô+Ð+Ñ+ðI$	,ð $	,r    c                ó4   — |dk    rdS d|z  }| |z  |dz
  k    S )Nr   Fr¦   r�   rE   )r�  r”   Úmods      r   r‰  zOdometerEngine._column_in_carry  s-   € à�AŠ:ˆ:Ø�5Ø�%‰iˆØ Ñ#¨¨a©Ò/Ð/r    c                óD   — t          t          | j        ¦  «        ¦  «        S r   )r«   r   ré   r  s    r   Úget_display_digitsz!OdometerEngine.get_display_digits†  s   € Ý!¥# dÔ&8Ñ"9Ô"9Ñ:Ô:Ð:r    úTuple[int, float]c                ól  — |dk     s|t           k    rdS |dk    rC| j        �t          | j        ¦  «        dz  | j        fS |                      ¦   «         dz  | j        fS d|z  }|                      ¦   «         |z  dz  }| j        |         }|dk    r|dfS | j        |         }|€|}|t          |d¦  «        fS )Nr   )r   r@   r¦   r�   r@   rI   )rª   rõ   r   rò   r
  rí   rï   rž   )rö   r”   r4  r;  re  Ú
from_digits         r   Úget_column_drawzOdometerEngine.get_column_draw‰  sØ   € Ø�1Š9ˆ9˜¥Ò,Ð,Ø�6Ø�AŠ:ˆ:ØÔ)Ð5Ý˜4Ô5Ñ6Ô6¸Ñ;¸TÔ=VÐVÐVØ×&Ò&Ñ(Ô(¨2Ñ-¨tÔ/HÐHÐHØ�5‰yˆØ×&Ò&Ñ(Ô(¨DÑ0°BÑ6ˆØÔ(¨Ô/ˆØ�DŠ=ˆ=Ø˜C�<ÐØÔ+¨EÔ2ˆ
ØÐØ ˆJØ�3˜u c™?œ?Ð*Ð*r    c                ó8   — |                       |¦  «        d         S r‘  )r¦  rh  s     r   Úget_column_scrollz OdometerEngine.get_column_scrollš  s   € Ø×#Ò# EÑ*Ô*¨1Ô-Ð-r    c                óV   — t          d| j        |                      ¦   «         z
  ¦  «        S r—   )r   rè   r
  r  s    r   r•   zOdometerEngine.lag_pennies�  s&   € Ý�1�dÔ)¨D×,?Ò,?Ñ,AÔ,AÑAÑBÔBÐBr    r•   c                óV  — t          t          dt          |¦  «        ¦  «        | j        j        ¦  «        }| j        }|�!||k     r|                      ¦   «          d| _        t          d|                      ¦   «         |z   ¦  «        | _	        || _        t          j        ¦   «         | _        d S )Nr   r@   )rž   r   r   rã   r2   rñ   rz  rò   r
  rè   rê   rë   rì   )rö   r•   r™   rß   s       r   Úmaintain_lagzOdometerEngine.maintain_lag   sš   € Ý•#�a�˜[Ñ)Ô)Ñ*Ô*¨D¬KÔ,GÑHÔHˆØÔ,ˆØÐ C¨(¢N NØ×5Ò5Ñ7Ô7Ð7Ø(+ˆDÔ%Ý! ! T×%8Ò%8Ñ%:Ô%:¸SÑ%@ÑAÔAˆÔØ$'ˆÔ!Ý(,Ô(9Ñ(;Ô(;ˆÔ%Ð%Ð%r    c                óH   — |                       | j        ¦  «         d | _        d S r   )rÿ   rè   rñ   r  s    r   Úreset_display_to_targetz&OdometerEngine.reset_display_to_targetª  s'   € Ø×+Ò+¨DÔ,?Ñ@Ô@Ð@Ø$(ˆÔ!Ð!Ð!r    )NN)rã   rä   r¿   rå   )rè   rå   r   rù   )r  r   r   rù   )r   r   )r   r  )r   r   r   )r›   rå   r   r(   )r›   r   r   r(   )ré   r(   r”   r   r   r(   )r   rå   r   rù   )r   rù   )r=  r(   r   r(   )r=  r(   r   rù   )r;  rå   r   r   )r[  r   r\  r   r”   r   r   r  )r;  rå   r   r£   )r”   r   r   rù   )r�  r   r”   r   r   r   )r”   r   r   r  )r”   r   r   r(   )ré   r(   r   r�  )r   r(   )r�   )r=  r(   rx  r   r   rù   )r�  r   r”   r   r   r  )r   r£   )r”   r   r   r£  )r•   r   r   rù   )=r€   r�   r‚   rø   rý   r   r  r  r  Úpropertyr  r  r  r
  r  rû   r   r#  r)  rÅ   r%  r5  rÿ   r<  rD  rF  rJ  rT  rX  rZ  Ústaticmethodr^  rb  rf  ri  rl  ro  rq  rt  rv  rq   rL  r7  rz  rƒ  r…  r‡  r~  r  rŽ  r“  r—  r&  ry  r‰  r¢  r¦  r¨  r•   r«  r­  rE   r    r   rÃ   rÃ   C  s  € € € € € ð ,0Ø04ð9ð 9ð 9ð 9ð 9ð4*ð *ð *ð *ð/ð /ð /ð /ð0ð 0ð 0ð 0ðJð Jð Jð Jð0ð 0ð 0ð 0ð ð%ð %ð %ñ „Xð%ð
ð 
ð 
ð 
ð ð8ð 8ð 8ñ „Xð8ð'ð 'ð 'ð 'ðð ð ð ðð ð ð ð.ð .ð .ð .ð/ð /ð /ð /ð /ð
$ð $ð $ð $ð $ð"ð ð ð ð@
ð 
ð 
ð 
ð
-ð -ð -ð -ð'ð 'ð 'ð 'ð 'ð+ð +ð +ð +ð'ð 'ð 'ð 'ð*7ð 7ð 7ð 7ð/ð /ð /ð /ð
'(ð '(ð '(ð '(ðRTð Tð Tð Tð'ð 'ð 'ð 'ð 'ð ð[ð [ð [ñ „\ð[ð


ð 

ð 

ð 

ð 

ðð ð ð ð0ð 0ð 0ð 0ð
+ð 
+ð 
+ð 
+ð,ð ,ð ,ð ,ð>&ð &ð &ð &ðNð Nð Nð NðJð Jð Jð Jð>ð >ð >ð >ð8*ð *ð *ð *ð,ð ,ð ,ð ,ð9ð 9ð 9ð 9ð ð3ð 3ð 3ñ „\ð3ð&ð &ð &ð &ðUð Uð Uð Uð
ð 
ð 
ð 
ð>ð ð ð ð
 ð1ð 1ð 1ñ „\ð1ð
ð ð ð ð,ð ,ð ,ð ,ð&ð ð ð ð+,ð +,ð +,ð +,ð +,ðZ ð0ð 0ð 0ñ „\ð0ð;ð ;ð ;ð ;ð+ð +ð +ð +ð".ð .ð .ð .ðCð Cð Cð Cð<ð <ð <ð <ð)ð )ð )ð )ð )ð )r    rÃ   )r   r   r   r   )r   )r   r   r!   r   r   r   )rw   r1   r   r   )rw   r1   r   r(   )r“   )r”   r   rw   r1   r•   r   r   r(   )r›   r   rw   r1   r   r(   )r   r   r   r£   )r¬   r£   r   r   )rw   r1   r   r   )rÏ   r   r}   r   r   rF   )r›   r   rÝ   rF   r   r(   )#Ú
__future__r   r?  rê   Údataclassesr   Údecimalr   r   r   Útypingr   r	   r
   r   r   rª   r®   r   r(   Ú
CurvePointr   r/   r1   rŒ   r’   rš   r˜   r«   r¯   r½   rÎ   rt   r�   rÃ   rE   r    r   ú<module>rµ     s  ðØ "Ð "Ð "Ð "Ð "Ð "à €€€Ø €€€Ø !Ð !Ð !Ð !Ð !Ð !Ø <Ð <Ð <Ð <Ð <Ð <Ð <Ð <Ð <Ð <Ø 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3Ð 3à€ØÐ Ø�3˜�:Ô€
ð'ð 'ð 'ð 'ðð ð ð ð ð2 ðfð fð fð fð fñ fô fñ „ðfðR%ð %ð %ð %ðPð Pð Pð Pð 9;ð,ð ,ð ,ð ,ð ,ðð ð ð ðCð Cð Cð Cð
ð ð ð ð$ð $ð $ð $ðNð ð ð ðD)ð )ð )ð )ð@ð ð ð ði	)ð i	)ð i	)ð i	)ð i	)ñ i	)ô i	)ð i	)ð i	)ð i	)r    