
    ciR                     ~    S r SSKrSSKJs  Jr  SSKJr  SSK	J
r
  SSKrSSKJrJr  SSKJrJrJrJr   " S S5      rg)	zTests for rating engine.    N)date)Mock)RatingEngineRatingState)
EntityTypeMeetingRaceStarterc                       \ rS rSrSr\R                  S 5       rS rS r	S r
S rS rS	 rS
 rS rS rS rS rS rS rS rS rS rS rS rS rSrg)TestRatingEngine   z)Tests for multi-runner Elo rating engine.c                 t   UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS	5        UR                  S
S5        UR                  SS5        UR                  SS5        UR                  SS5        SSKJn  U" 5         [        5       $ )z(Create rating engine with test settings.HRNZ_USERNAMEtestHRNZ_PASSWORDDATABASE_URLpostgresql://testELO_SCALE_C400.0
ELO_K_BASE24.0INITIAL_RATINGz1500.0ENABLE_DRIVERfalseENABLE_TRAINERENABLE_ADJUSTMENTSr   reload_settings)setenvpackages.core.common.settingsr   r   )selfmonkeypatchr   s      =/root/tipsharks/tipsharks-elo-api/tests/test_rating_engine.pyengineTestRatingEngine.engine   s     	?F3?F3>+>?='2<0+X6?G4+W5/9A~    c                 `   UR                   nSo2" U5      nSoTU:H  of(       d  [        R                  " SU4SXE45      S[        R                  " 5       ;   d  [        R
                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS	=n=n=n=peUR                   nS
o2" U5      nSoTU:  of(       d  [        R                  " SU4SXE45      S[        R                  " 5       ;   d  [        R
                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS	=n=n=n=peUR                   nS
o3* oB" U5      n	SoU
:  oU(       d  [        R                  " SU4SX45      S[        R                  " 5       ;   d  [        R
                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      [        R                  " U	5      [        R                  " U
5      S.-  nSSU0-  n[        [        R                  " U5      5      eS	=n=n=n=n	=pZg	)zTest sigmoid function.g        g      ?==)zM%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.sigmoid
}(%(py4)s)
} == %(py9)sr$   )py0py2py4py6py9zassert %(py11)spy11Ng     @@gGz?>)zL%(py6)s
{%(py6)s = %(py2)s
{%(py2)s = %(py0)s.sigmoid
}(%(py4)s)
} > %(py9)s{Gz?<)zN%(py7)s
{%(py7)s = %(py2)s
{%(py2)s = %(py0)s.sigmoid
}(-%(py4)s)
} < %(py10)s)r*   r+   r,   py7py10zassert %(py12)spy12)	sigmoid
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)r!   r$   @py_assert1@py_assert3@py_assert5@py_assert8@py_assert7@py_format10@py_format12@py_assert6@py_assert9@py_format11@py_format13s                r#   test_sigmoidTestRatingEngine.test_sigmoid"   s   ~~)c)~c")c)c)))))"))))))v))))v)))~)))c)))")))c)))))))~~,f,~f%,,,,,,,%,,,,,,v,,,,v,,,~,,,f,,,%,,,,,,,,,,~~-v-g-~g&-------&------v----v---~---v---&-----------r&   c                    UR                  [        R                  S5      nUR                  nSoCU:H  oU(       d  [        R
                  " SU4SX445      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS	=n=pTUR                  nS
oCU:H  oU(       d  [        R
                  " SU4SX445      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      [        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS	=n=pTUR                  [        R                  S5      nX(L o3(       d  [        R
                  " SU4SX(45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS.-  n	SSU	0-  n
[        [        R                  " U
5      5      eS	ng	)zTest rating initialization.{        p@r(   z.%(py2)s
{%(py2)s = %(py0)s.rating
} == %(py5)sstater*   r+   py5assert %(py7)sr5   Nr   )z2%(py2)s
{%(py2)s = %(py0)s.race_count
} == %(py5)s)is)z%(py0)s is %(py2)sstate2)r*   r+   zassert %(py4)sr,   )get_or_init_ratingr   HORSEratingr9   r:   r;   r<   r=   r>   r?   r@   
race_count)r!   r$   rR   rA   @py_assert4rB   @py_format6@py_format8rW   @py_format3@py_format5s              r#   test_get_or_init_rating(TestRatingEngine.test_get_or_init_rating(   s   ))**:*:C@||%v%v%%%%%|%%%%%%u%%%%u%%%|%%%v%%%%%%%$1$1$$$$$$$$$$$u$$$$u$$$$$$1$$$$$$$ **:+;+;SAuuur&   c           
         [        [        S9nSUl        [        [        S9nSUl        X#l        SUl        SUl        [        [        S9nSUl        SUl	        SUl
        SUl        SUl        SUl        SUl        SUl        [        [        S9nS	Ul        S
Ul	        SUl
        SUl        SUl        SUl        S	Ul        SUl        UR!                  X4U/5      n[#        U5      nS	oU:H  o(       Gd  [$        R&                  " SU	4SXx45      S[(        R*                  " 5       ;   d  [$        R,                  " ["        5      (       a  [$        R.                  " ["        5      OSS[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U5      S.-  n
SSU
0-  n[1        [$        R2                  " U5      5      eS=n=pU Vs/ s H  oR4                  S:X  d  M  UPM     snS   nUR6                  nSoU	:  o(       d  [$        R&                  " SU4SX45      S[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U	5      S.-  nSSU0-  n[1        [$        R2                  " U5      5      eS=n=pUR8                  nSoU	:  o(       d  [$        R&                  " SU4SX45      S[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U	5      S.-  nSSU0-  n[1        [$        R2                  " U5      5      eS=n=pU Vs/ s H  oR4                  S
:X  d  M  UPM     snS   nUR6                  nSoU	:  o(       d  [$        R&                  " SU4SX45      S[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U	5      S.-  nSSU0-  n[1        [$        R2                  " U5      5      eS=n=pUR8                  nSoU	:  o(       d  [$        R&                  " SU4SX45      S[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U	5      S.-  nSSU0-  n[1        [$        R2                  " U5      5      eS=n=pUR6                  nUR6                  oU-   n[;        U5      nSnUU:  nU(       Gd  [$        R&                  " SU4S UU45      S![(        R*                  " 5       ;   d  [$        R,                  " [:        5      (       a  [$        R.                  " [:        5      OS!S[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      S[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U5      [$        R.                  " U5      S".-  nS#S$U0-  n[1        [$        R2                  " U5      5      eS=n=n=n=n=nngs  snf s  snf )%zjTest 2-runner race with equal ratings.

When ratings are equal, winner should gain and loser should lose.
spec
Test Track     mobilee   NF   f   r(   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenupdatesr*   py1py3r-   assert %(py8)spy8r   r0   z,%(py2)s
{%(py2)s = %(py0)s.delta
} > %(py5)swinner_updaterS   rU   r5   rP   )z1%(py2)s
{%(py2)s = %(py0)s.new_rating
} > %(py5)sr3   z,%(py2)s
{%(py2)s = %(py0)s.delta
} < %(py5)sloser_update)z1%(py2)s
{%(py2)s = %(py0)s.new_rating
} < %(py5)sr2   )zr%(py9)s
{%(py9)s = %(py0)s((%(py3)s
{%(py3)s = %(py1)s.delta
} + %(py6)s
{%(py6)s = %(py4)s.delta
}))
} < %(py12)sabs)r*   rq   rr   r,   r-   r.   r7   assert %(py14)spy14)r   r   venuer	   idmeeting
distance_m
start_typer
   horse_id	driver_id
trainer_idbarrier
handicap_mplacingdid_not_finishprocess_racern   r9   r:   r;   r<   r=   r>   r?   r@   	entity_iddelta
new_ratingry   )r!   r$   r~   racestarter1starter2ro   @py_assert2rC   r\   @py_format7@py_format9urv   rA   rB   r]   r^   rx   rE   rD   @py_assert11@py_assert10rK   @py_format15s                            r#   "test_two_runner_race_equal_ratings3TestRatingEngine.test_two_runner_race_equal_ratings3   s    G$$" W%!"""'W%!"""' %%dx,@A 7| q q     |      s    s      7    7   |   q        %,BGq{{c/AGB1E""&Q&Q&&&&&"&&&&&&}&&&&}&&&"&&&Q&&&&&&&''0&0&00000'000000}0000}000'000&0000000 $+A7akkS.@7A!D!!%A%A%%%%%!%%%%%%|%%%%|%%%!%%%A%%%%%%%&&///////&//////|////|///&////////// !&&C););C);;Cs;<CtC<tCCCCC<tCCCCCCsCCCCsCCCCCC=CCCC=CCC&CCCCCCCCCCCCC);CCC<CCCtCCCCCCCC C
 Bs   ]4]4]94]9c                    [        SS9UR                  [        R                  S4'   [        SS9UR                  [        R                  S4'   [	        [
        S9nSUl        [	        [        S9nSUl        X#l	        S	Ul
        S
Ul        [	        [        S9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        [	        [        S9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        UR)                  X4U/5      nU Vs/ s H  owR*                  S:X  d  M  UPM     snS   nSoR,                  oU
:  nSoU:  o(       a  U(       d  [.        R0                  " SX4SXU45      [.        R2                  " U	5      S[4        R6                  " 5       ;   d  [.        R8                  " U5      (       a  [.        R2                  " U5      OS[.        R2                  " U
5      [.        R2                  " U5      S.-  nSSU0-  n[;        [.        R<                  " U5      5      eS=n	=n=n=p[        SS9UR                  [        R                  S4'   [        SS9UR                  [        R                  S4'   SUl        SUl        SUl        UR)                  X4U/5      nU Vs/ s H  owR*                  S:X  d  M  UPM     snS   nUR,                  nSnUU:  o(       d  [.        R0                  " SU4SUU45      S[4        R6                  " 5       ;   d  [.        R8                  " U5      (       a  [.        R2                  " U5      OS[.        R2                  " U5      [.        R2                  " U5      S.-  nSSU0-  n[;        [.        R<                  " U5      5      eS=n=nngs  snf s  snf )zpTest 2-runner race with unequal ratings.

Favorite wins: small rating change
Underdog wins: large rating change
g     @)rZ      g     P@   rd   rf   rk   rh   ri   rg   NFr   g      @)r4   r4   )z,%(py1)s < %(py6)s
{%(py6)s = %(py4)s.delta
}z,%(py6)s
{%(py6)s = %(py4)s.delta
} < %(py8)sfavorite_update)rq   r,   r-   rt   assert %(py10)sr6      g      .@r0   ru   underdog_updaterS   rU   r5   )r   statesr   rY   r   r   r|   r	   r}   r~   r   r   r
   r   r   r   r   r   r   r   r   r   r   r9   r:   r>   r;   r<   r=   r?   r@   )r!   r$   r~   r   starter_strongstarter_weakro   r   r   @py_assert0rC   r   rE   rB   r   rJ   r   rA   r\   r]   r^   s                        r#   $test_two_runner_race_unequal_ratings5TestRatingEngine.test_two_runner_race_unequal_ratingsj   s    2=F1Kz''-.1<F1Kz''-.G$$" 7+"%#' $(!!%$(!!"(-%) #!%"&#"& &+#%%d\,JK '.Dg1C1gDQG.((.(..3.3......q3...q......?....?...(...3....... 2=F1Kz''-.1<F1Kz''-. "# %%d\,JK '.Dg1C1gDQG$$+t+$t+++++$t+++++++++++++$+++t+++++++! E Es   *O O OOc                 	   [        [        S9nSUl        [        [        S9nSUl        X#l        SUl        SUl        / n[        S5       H^  n[        [        S9nXVl        SU-   Ul
        SUl        SUl        SUl        SUl        US-   Ul        S	Ul        UR#                  U5        M`     UR%                  X45      n['        U5      nSoU	:H  o(       Gd  [(        R*                  " S
U
4SX45      S[,        R.                  " 5       ;   d  [(        R0                  " [&        5      (       a  [(        R2                  " [&        5      OSS[,        R.                  " 5       ;   d  [(        R0                  " U5      (       a  [(        R2                  " U5      OS[(        R2                  " U5      [(        R2                  " U	5      S.-  nSSU0-  n[5        [(        R6                  " U5      5      eS=n=pUS   nUR8                  nSoU
:  o(       d  [(        R*                  " SU4SX45      S[,        R.                  " 5       ;   d  [(        R0                  " U5      (       a  [(        R2                  " U5      OS[(        R2                  " U5      [(        R2                  " U
5      S.-  nSSU0-  n[5        [(        R6                  " U5      5      eS=n=pUS   nUR8                  nSoU
:  o(       d  [(        R*                  " SU4SX45      S[,        R.                  " 5       ;   d  [(        R0                  " U5      (       a  [(        R2                  " U5      OS[(        R2                  " U5      [(        R2                  " U
5      S.-  nSSU0-  n[5        [(        R6                  " U5      5      eS=n=p[;        S U 5       5      n[=        U5      nSoU	:  o(       Gd  [(        R*                  " SU
4SX45      S[,        R.                  " 5       ;   d  [(        R0                  " [<        5      (       a  [(        R2                  " [<        5      OSS [,        R.                  " 5       ;   d  [(        R0                  " U5      (       a  [(        R2                  " U5      OS [(        R2                  " U5      [(        R2                  " U	5      S.-  nSSU0-  n[5        [(        R6                  " U5      5      eS=n=pg)!zcTest race with 10 runners.

Rating updates should sum to approximately zero (no rating inflation).
rd   rf   
   rh   ri   i  Nrg   Fr(   rm   rn   ro   rp   rs   rt   r   r0   ru   rv   rS   rU   r5   r3   rw   last_updatec              3   8   #    U  H  oR                   v   M     g 7f)N)r   .0r   s     r#   	<genexpr>:TestRatingEngine.test_multi_runner_race.<locals>.<genexpr>   s     37a''7s         ?)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} < %(py6)sry   total_delta)r   r   r|   r	   r}   r~   r   r   ranger
   r   r   r   r   r   r   r   appendr   rn   r9   r:   r;   r<   r=   r>   r?   r@   r   sumry   )r!   r$   r~   r   startersistarterro   r   rC   r\   r   r   rv   rA   rB   r]   r^   r   r   s                       r#   test_multi_runner_race'TestRatingEngine.test_multi_runner_race   s   
 G$$" rA(GJ#axG $G!%G"GO!%G!eGO%*G"OOG$  %%d5 7|!r!r!!!!!|!!!!!!s!!!!s!!!!!!7!!!!7!!!|!!!r!!!!!!!  
""&Q&Q&&&&&"&&&&&&}&&&&}&&&"&&&Q&&&&&&& bk  $1$1$$$$$ $$$$$${$$$${$$$ $$$1$$$$$$$ 3733;%#%#%%%%%%%%%%%s%%%%s%%%%%%;%%%%;%%%%%%#%%%%%%%r&   c                 ~   [        [        S9nSUl        [        [        S9nSUl        X#l        SUl        SUl        [        [        S9nSUl        SUl	        SUl
        SUl        SUl        SUl        SUl        S	Ul        UR!                  X4/5      n[#        U5      nS
ovU:H  o(       Gd  [$        R&                  " SU4SXg45      S[(        R*                  " 5       ;   d  [$        R,                  " ["        5      (       a  [$        R.                  " ["        5      OSS[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U5      S.-  n	SSU	0-  n
[1        [$        R2                  " U
5      5      eS=n=pg)z8Test that races with fewer than 2 finishers are skipped.rd   rf      rh   ri   rg   i-  NFr   r(   rm   rn   ro   rp   rs   rt   )r   r   r|   r	   r}   r~   r   r   r
   r   r   r   r   r   r   r   r   rn   r9   r:   r;   r<   r=   r>   r?   r@   )r!   r$   r~   r   r   ro   r   rC   r\   r   r   s              r#   test_incomplete_race_skipped-TestRatingEngine.test_incomplete_race_skipped   s$   G$$" G$
 !!!&%%dI6 7| q q     |      s    s      7    7   |   q       r&   c                    [        [        S9nSUl        [        [        S9nSUl        X#l        SUl        SUl        [        [        S9nSUl        SUl	        SUl
        SUl        SUl        SUl        SUl        S	Ul        [        [        S9nS
Ul        SUl	        SUl
        SUl        SUl        SUl        S
Ul        S	Ul        [        [        S9nSUl        SUl	        SUl
        SUl        SUl        SUl        SUl        SUl        UR!                  X4XV/5      n[#        U5      nS
oU	:H  o(       Gd  [$        R&                  " SU
4SX45      S[(        R*                  " 5       ;   d  [$        R,                  " ["        5      (       a  [$        R.                  " ["        5      OSS[(        R*                  " 5       ;   d  [$        R,                  " U5      (       a  [$        R.                  " U5      OS[$        R.                  " U5      [$        R.                  " U	5      S.-  nSSU0-  n[1        [$        R2                  " U5      5      eS=n=pS U 5       n[5        U5      o(       d  SS[(        R*                  " 5       ;   d  [$        R,                  " [4        5      (       a  [$        R.                  " [4        5      OS[$        R.                  " U5      [$        R.                  " U5      S.-  n[1        [$        R2                  " U5      5      eS=pg)z8Test that DNF starters are excluded from rating updates.rd   rf      rh   ri   rg     NFrk     r   i  Tr(   rm   rn   ro   rp   rs   rt   c              3   >   #    U  H  oR                   S ;   v   M     g7f))r   r   N)r   r   s     r#   r   GTestRatingEngine.test_dnf_excluded_from_calculations.<locals>.<genexpr>  s     >g;;*,gs   z,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}all)r*   r+   r,   )r   r   r|   r	   r}   r~   r   r   r
   r   r   r   r   r   r   r   r   rn   r9   r:   r;   r<   r=   r>   r?   r@   r   )r!   r$   r~   r   r   r   starter3ro   r   rC   r\   r   r   rA   rB   r`   s                   r#   #test_dnf_excluded_from_calculations4TestRatingEngine.test_dnf_excluded_from_calculations   s"   G$$" W%!"""'W%!"""' W%!"""&%%dx,JK 7| q q     |      s    s      7    7   |   q       >g>>s>>>>>>>>>>s>>>>s>>>>>>>>>>>>>>r&   c                    UR                  [        R                  SSSS9  UR                  [        R                  S5      nUR                  nSoCU:H  oU(       d  [
        R                  " SU4SX445      S[        R                  " 5       ;   d  [
        R                  " U5      (       a  [
        R                  " U5      OS[
        R                  " U5      [
        R                  " U5      S.-  nS	S
U0-  n[        [
        R                  " U5      5      eS=n=pTUR                  nSoCU:H  oU(       d  [
        R                  " SU4SX445      S[        R                  " 5       ;   d  [
        R                  " U5      (       a  [
        R                  " U5      OS[
        R                  " U5      [
        R                  " U5      S.-  nS	S
U0-  n[        [
        R                  " U5      5      eS=n=pTg)z#Test loading existing rating state.i  g     ș@g     @o@rZ   rdr(   rQ   rR   rS   rU   r5   N)z*%(py2)s
{%(py2)s = %(py0)s.rd
} == %(py5)s)load_rating_stater   rY   rX   rZ   r9   r:   r;   r<   r=   r>   r?   r@   r   )r!   r$   rR   rA   r\   rB   r]   r^   s           r#   test_load_existing_rating*TestRatingEngine.test_load_existing_rating   s     !1!13v% P))**:*:C@||%v%v%%%%%|%%%%%%u%%%%u%%%|%%%v%%%%%%%xx 5 5     x      u    u   x   5       r&   c                    UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        UR                  S	S
5        SSKJn  U" 5         [        5       nUR	                  [
        R                  S5      n[        R                  nSoe" U5      otU:H  o(       Gd"  [        R                  " SU4SXG45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS[        R                  " 5       ;   d  [        R                  " [        5      (       a  [        R                  " [        5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  n	SSU	0-  n
[        [        R                   " U
5      5      eS=n=n=pgg)zTest K-factor clamping.r   r   	ENABLE_RDr   r   r   	ELO_K_MINz12.0	ELO_K_MAXz20.0r   r   rg   g      4@r(   zL%(py0)s == %(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s.approx
}(%(py6)s)
}k_effpytestr*   r+   r,   r-   rt   r   r6   N)r   r    r   r   get_effective_k_factorr   rY   r   approxr9   r:   r;   r<   r=   r>   r?   r@   r!   r"   r   r$   r   rB   rC   rE   rA   r   rJ   s              r#   test_k_factor_clamps%TestRatingEngine.test_k_factor_clamps(  s#   >+>?;0<0;/;/A--j.>.>B+d+d++++++++u++++++u++++u++++++++++++++++d+++++++++++r&   c                     UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        UR                  S	S
5        SSKJn  U" 5         [        5       nUR	                  [
        R                  SSSS9  UR                  [
        R                  S5      n[        R                  nSoe" U5      otU:H  o(       Gd"  [        R                  " SU4SXG45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS[        R                  " 5       ;   d  [        R                  " [        5      (       a  [        R                  " [        5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  n	SSU	0-  n
[!        [        R"                  " U
5      5      eS=n=n=pgg)z!Test square-root RD scaling mode.r   r   r   truer   r   
INITIAL_RDr   RD_SCALING_MODEsqrtr   r   rg   rP         Y@r   g      (@r(   r   r   r   r   r   r6   Nr   r    r   r   r   r   rY   r   r   r   r9   r:   r;   r<   r=   r>   r?   r@   r   s              r#   test_rd_scaling_sqrt%TestRatingEngine.test_rd_scaling_sqrt8  A   >+>?;/<0<1,f5A  !1!11V N--j.>.>B+d+d++++++++u++++++u++++u++++++++++++++++d+++++++++++r&   c                     UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        UR                  S	S
5        SSKJn  U" 5         [        5       nUR	                  [
        R                  SSSS9  UR                  [
        R                  S5      n[        R                  nSoe" U5      otU:H  o(       Gd"  [        R                  " SU4SXG45      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OSS[        R                  " 5       ;   d  [        R                  " [        5      (       a  [        R                  " [        5      OS[        R                  " U5      [        R                  " U5      [        R                  " U5      S.-  n	SSU	0-  n
[!        [        R"                  " U
5      5      eS=n=n=pgg)z;Test RD scaling disabled while RD tracking remains enabled.r   r   r   r   r   r   r   z350.0r   noner   r   rg   rP   r   r   g      8@r(   r   r   r   r   r   r6   Nr   r   s              r#   test_rd_scaling_none%TestRatingEngine.test_rd_scaling_noneI  r   r&   c                 R   UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        S	S
KJn  U" 5         [        5       n[	        [
        S9nSUl        [	        [        S9nSUl        XEl	        SUl
        SUl        [	        [        S9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        [	        [        S9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        [	        [        S9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        UR)                  XVXx/5      n	[+        U	5      n
SoU:H  o(       Gd  [,        R.                  " SU4SX45      S[0        R2                  " 5       ;   d  [,        R4                  " [*        5      (       a  [,        R6                  " [*        5      OSS[0        R2                  " 5       ;   d  [,        R4                  " U	5      (       a  [,        R6                  " U	5      OS[,        R6                  " U
5      [,        R6                  " U5      S.-  nSSU0-  n[9        [,        R:                  " U5      5      eS=n
=pg)z.Test comparisons normalizer with skipped ties.r   r   PAIRWISE_NORMALIZERcomparisonsTIE_HANDLINGskipr   r   r   r   rd   rf   (   rh   ri   rg   i  NFrk   i  r   i  r(   rm   rn   ro   rp   rs   rt   r   r    r   r   r   r   r|   r	   r}   r~   r   r   r
   r   r   r   r   r   r   r   r   rn   r9   r:   r;   r<   r=   r>   r?   r@   )r!   r"   r   r$   r~   r   r   r   r   ro   r   rC   r\   r   r   s                  r#   .test_pairwise_normalizer_comparisons_with_ties?TestRatingEngine.test_pairwise_normalizer_comparisons_with_tiesZ  s
   >+>?0-@>62/9AG$$"W%!"""'W%!"""'W%!"""'%%dx,JK7| q q     |      s    s      7    7   |   q       r&   c                    UR                  SS5        UR                  SS5        UR                  SS5        SSKJn  U" 5         [        5       n[	        [
        S	9nS
Ul        [	        [        S	9nSUl        XEl	        SUl
        SUl        [	        [        S	9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        [	        [        S	9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        UR)                  XVU/5      n[+        U5      n	SoU
:H  o(       Gd  [,        R.                  " SU4SX45      S[0        R2                  " 5       ;   d  [,        R4                  " [*        5      (       a  [,        R6                  " [*        5      OSS[0        R2                  " 5       ;   d  [,        R4                  " U5      (       a  [,        R6                  " U5      OS[,        R6                  " U	5      [,        R6                  " U
5      S.-  nSSU0-  n[9        [,        R:                  " U5      5      eS=n	=pg)z*Test normalizing by n in pairwise updates.r   r   r   nr   r   r   r   rd   rf   *   rh   ri   rg   i  NFrk   i  r(   rm   rn   ro   rp   rs   rt   r   r!   r"   r   r$   r~   r   r   r   ro   r   rC   r\   r   r   s                 r#   test_pairwise_normalizer_n+TestRatingEngine.test_pairwise_normalizer_n  s   >+>?0#6/9AG$$"W%!"""'W%!"""'%%dx,@A7| q q     |      s    s      7    7   |   q       r&   c                    UR                  SS5        UR                  SS5        UR                  SS5        SSKJn  U" 5         [        5       n[	        [
        S	9nS
Ul        [	        [        S	9nSUl        XEl	        SUl
        SUl        [	        [        S	9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        [	        [        S	9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        UR)                  XVU/5      n[+        U5      n	SoU
:H  o(       Gd  [,        R.                  " SU4SX45      S[0        R2                  " 5       ;   d  [,        R4                  " [*        5      (       a  [,        R6                  " [*        5      OSS[0        R2                  " 5       ;   d  [,        R4                  " U5      (       a  [,        R6                  " U5      OS[,        R6                  " U	5      [,        R6                  " U
5      S.-  nSSU0-  n[9        [,        R:                  " U5      5      eS=n	=pg)zTest half-score tie handling.r   r   r   halfr   r   r   r   rd   rf   +   rh   ri   rg   i!  NFrk   i"  r(   rm   rn   ro   rp   rs   rt   r   r   s                 r#   test_tie_handling_half'TestRatingEngine.test_tie_handling_half  s   >+>?>62/9AG$$"W%!"""'W%!"""'%%dx,@A7| q q     |      s    s      7    7   |   q       r&   c           	      f   UR                  SS5        UR                  SS5        UR                  SS5        SSKJn  U" 5         [        5       n/ nUR	                  [
        R                  S	S
SSUS9  US   oUR                  n[        R                  nSo" U5      oU	:H  o(       Gd  [        R                  " SU
4SXi45      [        R                  " U5      [        R                  " U5      S[        R                  " 5       ;   d  [        R                  " [        5      (       a  [        R                  " [        5      OS[        R                  " U5      [        R                  " U5      [        R                  " U	5      S.-  nSSU0-  n[!        [        R"                  " U5      5      eS=n=n=n
=n=pg)zTest rating min/max bounds.r   r   
RATING_MINz1400.0
RATING_MAXz1600.0r   r   iX  g      i@rg   Nr   race_id	race_datero   g      @r(   )zn%(py3)s
{%(py3)s = %(py1)s.new_rating
} == %(py11)s
{%(py11)s = %(py7)s
{%(py7)s = %(py5)s.approx
}(%(py9)s)
}r   )rq   rr   rT   r5   r.   r/   zassert %(py13)spy13)r   r    r   r   _apply_updater   rY   r   r   r   r9   r:   r>   r;   r<   r=   r?   r@   )r!   r"   r   r$   ro   r   r   rH   rD   r   r\   rG   @py_format14s                r#   test_rating_bounds#TestRatingEngine.test_rating_bounds  s(   >+>?<2<2A 	 	
 qz=$$==f=f(==(======$===z===$================f===(=========r&   c                    UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        S	S
KJn  U" 5         [        5       nUR	                  [
        R                  S5      nUR                  n/ nUR                  [
        R                  SSS[        SSS5      US9  UR                  n[        R                  nSoU	-
  o" U
5      oU:H  o(       Gd  [        R                  " SU4SX{45      S[        R                  " 5       ;   d  [        R                   " U5      (       a  [        R"                  " U5      OS[        R"                  " U5      S[        R                  " 5       ;   d  [        R                   " [        5      (       a  [        R"                  " [        5      OS[        R"                  " U5      S[        R                  " 5       ;   d  [        R                   " U5      (       a  [        R"                  " U5      OS[        R"                  " U	5      [        R"                  " U5      S.-  nSSU0-  n[%        [        R&                  " U5      5      eS=n=n=n=n	=pg)zTest RD decay floor is applied.r   r   r   r   RD_DECAY_PER_RACEz0.0RD_DECAY_FLOORz5.0r   r   rg   r        r   g      @r(   )zr%(py2)s
{%(py2)s = %(py0)s.rd
} == %(py12)s
{%(py12)s = %(py6)s
{%(py6)s = %(py4)s.approx
}((%(py7)s - %(py9)s))
}rR   r   
initial_rd)r*   r+   r,   r-   r5   r.   r7   rz   r{   N)r   r    r   r   rX   r   rY   r   r  r   r   r   r9   r:   r;   r<   r=   r>   r?   r@   )r!   r"   r   r$   rR   r  ro   rA   rC   rD   r   r   rB   rK   r   s                  r#   test_rd_decay_floor$TestRatingEngine.test_rd_decay_floor  s   >+>?;/.6+U3A))**:*:A>XX
4B' 	 	
 xx:6==:c:c)9:=)9::::::::x::::::u::::u:::x::::::6::::6:::=:::::::::::::c::::::::::::r&   c                     UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        S	S
KJn  U" 5         [        5       nUR	                  [
        R                  S5      n[        SSS5      Ul        / nUR                  [
        R                  SSS[        SSS5      US9  UR                  ocR                  owR                  oU:*  o(       Gd  [        R                  " SU	4SXh45      S[        R                   " 5       ;   d  [        R"                  " U5      (       a  [        R$                  " U5      OS[        R$                  " U5      S[        R                   " 5       ;   d  [        R"                  " U5      (       a  [        R$                  " U5      OS[        R$                  " U5      [        R$                  " U5      S.-  n
SSU
0-  n['        [        R(                  " U5      5      eS=n=n	=pxg)zTest RD inflation cap days.r   r   r   r   RD_INFLATION_PER_DAY1.0RD_INFLATION_CAP_DAYS10r   r   rk   r	  rg   r   r   )<=)zd%(py2)s
{%(py2)s = %(py0)s.rd
} <= %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s.settings
}.rd_max
}rR   r$   r   r   r6   N)r   r    r   r   rX   r   rY   r   last_race_dater  r   settingsrd_maxr9   r:   r;   r<   r=   r>   r?   r@   )r!   r"   r   r$   rR   ro   rA   rC   rE   rB   r   rJ   s               r#   test_rd_inflation_cap_days+TestRatingEngine.test_rd_inflation_cap_days  sb   >+>?;/1592D9A))**:*:A>#D!Q/4A& 	 	
 xx1??1111111111x111111u1111u111x111111611116111?11111111111r&   c                 (   UR                  SS5        UR                  SS5        UR                  SS5        UR                  SS5        S	S
KJn  U" 5         [        5       n[	        [
        S9nSUl        [	        [        S9nSUl        XEl	        SUl
        SUl        [	        [        S9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        [	        [        S9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        UR)                  XVU/5      nU V	s/ s H$  oR*                  [,        R.                  :X  d  M"  U	PM&     n
n	U V	s/ s H$  oR*                  [,        R0                  :X  d  M"  U	PM&     nn	U
(       dp  SSS[2        R4                  " 5       ;   d  [6        R8                  " U
5      (       a  [6        R:                  " U
5      OS0-  n[=        [6        R>                  " U5      5      eU(       dp  SSS[2        R4                  " 5       ;   d  [6        R8                  " U5      (       a  [6        R:                  " U5      OS0-  n[=        [6        R>                  " U5      5      egs  sn	f s  sn	f )zTest entity-specific K scaling.r   r   HORSE_K_SCALEr  DRIVER_K_SCALEz2.0TRAINER_K_SCALEz0.5r   r   rd   rf   ,   rh   ri   rg   i  i  iM  NFrk   i  i  iN  zassert %(py0)sr*   driver_updatestrainer_updates) r   r    r   r   r   r   r|   r	   r}   r~   r   r   r
   r   r   r   r   r   r   r   r   entity_typer   DRIVERTRAINERr;   r<   r9   r=   r>   r?   r@   )r!   r"   r   r$   r~   r   r   r   ro   r   r  r  @py_format1s                r#   test_entity_k_scales%TestRatingEngine.test_entity_k_scales1  s   >+>??E2+U3,e4AG$$"W%!"""'W%!"""'%%dx,@A%,SWARAR0R!WS&-Ug*BTBT1T1gU~~ TUs   =!J
"J
.!JJc                    UR                  SS5        UR                  SS5        UR                  SS5        SSKJn  U" 5         [        5       n[	        [
        S	9nS
Ul        [	        [        S	9nSUl        XEl	        SUl
        SUl        [	        [        S	9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        [	        [        S	9nSUl        SUl        SUl        SUl        SUl        SUl        SUl        SUl        UR)                  XVU/5      n[+        U5      n	SoU
:H  o(       Gd  [,        R.                  " SU4SX45      S[0        R2                  " 5       ;   d  [,        R4                  " [*        5      (       a  [,        R6                  " [*        5      OSS[0        R2                  " 5       ;   d  [,        R4                  " U5      (       a  [,        R6                  " U5      OS[,        R6                  " U	5      [,        R6                  " U
5      S.-  nSSU0-  n[9        [,        R:                  " U5      5      eS=n	=pg)z/Test DNF treated as last for minimum finishers.r   r   MIN_FINISHERS2DNF_TREATED_AS_LASTr   r   r   rd   rf   )   rh   ri   rg   iY  NFrk   iZ  Tr(   rm   rn   ro   rp   rs   rt   r   )r!   r"   r   r$   r~   r   finisherdnfro   r   rC   r\   r   r   s                 r#   #test_min_finishers_with_dnf_as_last4TestRatingEngine.test_min_finishers_with_dnf_as_lasta  s   >+>??C00&9AG$$"W%!"""' !%%dsO<7| q q     |      s    s      7    7   |   q       r&    N)__name__
__module____qualname____firstlineno____doc__r   fixturer$   rL   ra   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r$  r-  __static_attributes__r/  r&   r#   r   r      s    3^^ $.	5Dn;,z+&Z!6/?b!, ,","5!n*!X*!X>,;222.`*!r&   r   )r4  builtinsr;   _pytest.assertion.rewrite	assertionrewriter9   datetimer   unittest.mockr   r   packages.core.ratings.enginer   r   packages.core.storage.modelsr   r   r	   r
   r   r/  r&   r#   <module>r?     s+           B K K	! 	!r&   