
    %ie/                         S r SSKrSSKJs  Jr  SSKJr  SSK	J
r
Jr  SSKrSSKJr  SSKJr  SSKJr  SSKJrJrJrJr   " S	 S
5      r " S S5      r " S S5      rg)z+Integration tests for end-to-end workflows.    N)dateMockpatch)DataQualityValidator)RatingEngine)PredictionEngine)
EntityTypeMeetingRaceStarterc                   T    \ rS rSrSr\R                  S 5       rS rS r	S r
S rSrg	)
TestDataQualityIntegration   z.Integration tests for data quality validation.c                     [        5       $ zCreate mock database session.r   selfs    ;/root/tipsharks/tipsharks-elo-api/tests/test_integration.pymock_session'TestDataQualityIntegration.mock_session        v    c                    [        U5      nSo2ULoD(       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.-  nSSU0-  n[        [        R                  " U5      5      eS=pCUR                  oDU:H  ow(       d  [        R                  " SU4S	XA4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
S.-  nSSU0-  n	[        [        R                  " U	5      5      eS=pGg)z.Test that DataQualityValidator can be created.Nis notz%(py0)s is not %(py3)s	validatorpy0py3assert %(py5)spy5==)z/%(py2)s
{%(py2)s = %(py0)s.session
} == %(py4)sr   r!   py2py4assert %(py6)spy6)
r   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationsession)
r   r   r   @py_assert2@py_assert1@py_format4@py_format6@py_assert3@py_format5@py_format7s
             r   $test_data_quality_validator_creation?TestDataQualityIntegration.test_data_quality_validator_creation   s    (6	 $$$$$$$y$$$$$$y$$$$y$$$$$$$$$$  0L00000 000000y0000y000 000000L0000L0000000r   c                 \   [        U5      n[        [        S9nSUl        [        [        SSSSSSSSS9	[        [        S	S
SSS	SS	SS9	/nUR                  X45      nU Vs/ s H  ofR                  S:X  d  M  UPM     n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[        [        R                  " U5      5      eS=n=pgs  snf )z Test validation of a valid race.spec   d      ,  r   F	r@   idhorse_id	driver_id
trainer_idbarrier
handicap_mplacingdid_not_finish   e      -  errorr%   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenerrorsr!   py1r"   r+   assert %(py8)spy8N)r   r   r   rF   r   validate_raceseverityrS   r,   r-   r.   r/   r0   r1   r2   r3   )r   r   r   	mock_racestartersissuesirT   r5   @py_assert5@py_assert4r;   @py_format9s                r   "test_validate_race_with_valid_data=TestDataQualityIntegration.test_validate_race_with_valid_data   s4   (6	dO		 $
 $

2 ((= $=VzzW'<!V=6{aa{ss66{a >s   F)6F)c                    [        U5      n[        [        S9nSUl        [        [        SSSSSSSSS9	[        [        S	S
SSS	SSSS9	/nUR                  X45      nU Vs/ s H(  ofR                  S:X  d  M  UR                  S:X  d  M&  UPM*     nn[        U5      nSoU	:  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[        [        R                   " U5      5      eS=n=pSoS   oR"                  oU	;   o(       d  [        R                  " SU4SX4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=pgs  snf )z+Test detection of duplicate placing values.r?   rA   rB   rC   rD   r   FrE   rN   rO   rP   rQ   rR   rL   >)z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} > %(py6)srS   rT   rU   rW   rX   N	Duplicate)in)z/%(py1)s in %(py6)s
{%(py6)s = %(py4)s.message
}rV   r)   r+   )r   r   r   rF   r   rY   rZ   categoryrS   r,   r-   r.   r/   r0   r1   r2   r3   message)r   r   r   r[   r\   r]   r^   rT   r5   r_   r`   r;   ra   @py_assert0r9   s                  r   *test_validate_race_with_duplicate_placingsETestDataQualityIntegration.test_validate_race_with_duplicate_placingsB   s   (6	dO		 $
 $

2 ((= 
!w!6A1::;RAv 	 
 6{QQ{ss66{Q/Qi//////////{///{///i///////////	
s   I!6I!I!c                 Z   [        U5      n[        [        S9nSUl        [        [        SSSSSSSSS9	/nUR                  X45      nU Vs/ s H)  nUR                  S:X  d  M  UR                  S	:X  d  M'  UPM+     nn[        U5      nS
oU	:  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[        [        R                   " U5      5      eS=n=pgs  snf )zTest detection of missing data.r?   rA   rB   Nr   FrE   warningmissing_datarN   )>=)z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} >= %(py6)srS   warningsrU   rW   rX   )r   r   r   rF   r   rY   rZ   rj   rS   r,   r-   r.   r/   r0   r1   r2   r3   )r   r   r   r[   r\   r]   r^   rs   r5   r_   r`   r;   ra   s                r   $test_validate_race_with_missing_data?TestDataQualityIntegration.test_validate_race_with_missing_datak   s1   (6	dO		 $

 ((=
 
zzY& +,::+G  	 

 8}!!!!!!!}!!!!!!s!!!!s!!!!!!8!!!!8!!!}!!!!!!!!!!
s   F(#F(5F( N)__name__
__module____qualname____firstlineno____doc__pytestfixturer   r<   rb   rm   rt   __static_attributes__rv   r   r   r   r      s1    8^^ 1$ L'0R"r   r   c                   x    \ rS rSrSr\R                  S 5       r\R                  S 5       rS r	S r
S rS rS	rg
)TestPredictionIntegration   z(Integration tests for prediction engine.c                     [        5       $ r   r   r   s    r   r   &TestPredictionIntegration.mock_session   r   r   c                 h    [        S5         [        U5      nUsSSS5        $ ! , (       d  f       g= f)zCreate prediction engine..packages.core.ratings.predictions.RatingEngineN)r   r	   )r   r   engines      r   prediction_engine+TestPredictionIntegration.prediction_engine   s'     CD%l3F EDDs   #
1c                    [        S5         [        U5      nSo2ULoD(       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.-  nSSU0-  n[        [        R                  " U5      5      eS=pCSSS5        g! , (       d  f       g= f)	z*Test that PredictionEngine can be created.r   Nr   r   r   r    r#   r$   )
r   r	   r,   r-   r.   r/   r0   r1   r2   r3   )r   r   r   r5   r6   r7   r8   s          r   test_prediction_engine_creation9TestPredictionIntegration.test_prediction_engine_creation   s}    CD%l3F!%%%%%%%6%%%%%%6%%%%6%%%%%%%%%% EDDs   B?C
C"c                 2   SSSS.nUR                  U5      nUR                  oD" 5       n[        U5      nSovU-
  n[        U5      n	SoU
:  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                  " [        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      [        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=n=n	=pUS   oS   oNU:  o(       do  [        R
                  " SU4SX45      [        R                  " U5      [        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS=n=pUS   oS   oNU:  o(       do  [        R
                  " SU4SX45      [        R                  " U5      [        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS=n=pUR                  5        H  nSoU:*  nSnUU:*  oO(       a  U(       d  [        R
                  " SX4SUUU45      [        R                  " U5      S[        R                  " 5       ;   d  [        R                  " U5      (       a  [        R                  " U5      OS[        R                  " U5      S.-  nSSU0-  n[        [        R                  " U5      5      eS=n=n=pEM     g)z!Test win probability computation.      @     p@     @rA   rN            ?gMbP?<)z%(py13)s
{%(py13)s = %(py0)s((%(py8)s
{%(py8)s = %(py1)s(%(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py2)s.values
}()
})
} - %(py10)s))
} < %(py16)sabssumprobs)	r!   rV   r(   r)   r+   rX   py10py13py16zassert %(py18)spy18NrA   rN   re   z%(py1)s > %(py4)srV   r)   r*   r+   r           <=r   z%(py1)s <= %(py4)sz%(py4)s <= %(py6)sprobri   rW   rX   )_compute_win_probabilitiesvaluesr   r   r,   r-   r.   r/   r0   r1   r2   r3   )r   r   effective_ratingsr   r9   r_   @py_assert7@py_assert9@py_assert11@py_assert12@py_assert15@py_assert14@py_format17@py_format19rl   r5   r:   r;   r   ra   s                       r   test_compute_win_probabilities8TestPredictionIntegration.test_compute_win_probabilities   sf    
 "<<=NO ||5|~53~&55,5s,-5555555-555555s5555s555555355553555555u5555u555|555~555&555555-55555555555 Qx"("("""""x"""x"""("""""""Qx"("("""""x"""x"""(""""""" LLND%$%%#%$#%%%%%%3$#%%%3%%%%%%$%%%%$%%%#%%%%%%% #r   c           	      0   SSSS.nUR                  USS9nUS   oCS   oTU:  of(       do  [        R                  " SU4S	XE45      [        R                  " U5      [        R                  " U5      S
.-  nSSU0-  n[	        [        R
                  " U5      5      eS=n=peUS   oCS   oTU:  of(       do  [        R                  " SU4S	XE45      [        R                  " U5      [        R                  " U5      S
.-  nSSU0-  n[	        [        R
                  " U5      5      eS=n=peUR                  5        H  n	SoDU	:*  nSoU
:*  oV(       a  U(       d  [        R                  " SXe4SXIU
45      [        R                  " U5      S[        R                  " 5       ;   d  [        R                  " U	5      (       a  [        R                  " U	5      OS[        R                  " U
5      S.-  nSSU0-  n[	        [        R
                  " U5      5      eS=n=n=pZM     g)z#Test place probability computation.r   r   r   r   rN   )top_nrA   re   r   r   r*   r+   Nr   r   r   r   r   r   ri   rW   rX   )
_compute_place_probabilitiesr,   r-   r1   r2   r3   r   r.   r/   r0   )r   r   r   r   rl   r9   r5   r:   r;   r   r_   ra   s               r    test_compute_place_probabilities:TestPredictionIntegration.test_compute_place_probabilities   s[    
 ">>Q ? 

 Qx"("("""""x"""x"""("""""""Qx"("("""""x"""x"""(""""""" LLND%$%%#%#%%%%%%3#%%%3%%%%%%$%%%%$%%%#%%%%%%% #r   c           
        ^^ SSK JmJn  T" [        S9nSUl        [        SSS5      Ul        T" [        S9nSUl        SUl	        SUl
        X4l        T" [        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
Ul        T" [        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
Ul        U4S jmU" SSU4S jjS9   U" S/ S9   U" S/ S9   [+        U5      nUR,                  " USSSS.S9   UR/                  XEU/5      nS
S
S
5        S
S
S
5        S
S
S
5        S
S
S
5        WR0                   V	s0 s H  oR2                  U	R4                  _M     n
n	XR                     oUR                     oU:  o(       do  [6        R8                  " SU4SX45      [6        R:                  " U5      [6        R:                  " U5      S.-  nSSU0-  n[=        [6        R>                  " U5      5      eS
=n=pg
! , (       d  f       N= f! , (       d  f       N= f! , (       d  f       GN= f! , (       d  f       GN= fs  sn	f )z1Test predictions reflect latest rating snapshots.r   r   r?   z
Test Venue  rA   
     rB   NrN   rC   c                 P   > T" 5       nU S:X  a  SOSUl         SUl        S Ul        U$ )NrB   g     @g     P@g      Y@)ratingrdrace)	entity_idsnapshotr   s     r   snapshot_forSTestPredictionIntegration.test_prediction_uses_latest_ratings.<locals>.snapshot_for   s-    vH(1S(8ffHOHK HMOr   zLpackages.core.ratings.predictions.RatingSnapshotRepository.get_latest_ratingc                    > T" U5      $ Nrv   )r4   entity_typer   before_race_idr   s       r   <lambda>OTestPredictionIntegration.test_prediction_uses_latest_ratings.<locals>.<lambda>   s    UaVr   )side_effectz@packages.core.ratings.engine.BarrierAdjustmentRepository.get_all)return_valuezApackages.core.ratings.engine.HandicapAdjustmentRepository.get_all_get_recent_finish_statsgQ?g      ?)	top3_rateconsistencyre   r   r   r*   r+   r   ) unittest.mockr   r   r   venuer   meeting_dater   rF   race_number
distance_mmeetingr   rG   rH   rI   rJ   rK   horsedrivertrainerr	   objectpredict_racepredictions
starter_idwin_probabilityr,   r-   r1   r2   r3   )r   r   r   mock_meetingr[   starter1starter2r   
predictionp	win_probsrl   r9   r5   r:   r;   r   r   s                   @@r   #test_prediction_uses_latest_ratings=TestPredictionIntegration.test_prediction_uses_latest_ratings   s0   -))$(q!$4!dO		 !	#	(W%!""W%!""	 Z
 R W!# .l;F237%L
 &,%8%8%(';&
	
0 ?I>T>TU>T\\1#4#44>T	U%>(++(>>(>>>>>>%>>>%>>>(>>>>>>>>  	 
 
0 VsZ   8I I
!H9)H(	=H9I
I+ I.(
H62H99
II


I	I
I+rv   N)rw   rx   ry   rz   r{   r|   r}   r   r   r   r   r   r   r~   rv   r   r   r   r      sH    2^^  ^^ &&*&(D?r   r   c                   H    \ rS rSrSr\R                  S 5       rS rS r	Sr
g)TestRatingEngineIntegrationi  z$Integration tests for rating engine.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       $ )
z(Create rating engine with test settings.HRNZ_USERNAMEtestHRNZ_PASSWORDDATABASE_URLzpostgresql://test	ENABLE_RDfalser   reload_settings)setenvpackages.core.common.settingsr   r   )r   monkeypatchr   s      r   r   "TestRatingEngineIntegration.engine  sV     	?F3?F3>+>?;0A~r   c                 R   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=pgUR#                  [
        R                  S5      nUR$                  n/ n['        S5       H0  nUR)                  [
        R                  SSU[+        SSS5      US9  M2     UR$                  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      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=pUR	                  [
        R                  S5      nUU:  o(       d  [        R                  " SU4SUU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 that RD-based K-factor works correctly.r   true
INITIAL_RDz350.0r   r   rA   g      8@r%   )zL%(py0)s == %(py8)s
{%(py8)s = %(py4)s
{%(py4)s = %(py2)s.approx
}(%(py6)s)
}k1r|   )r!   r(   r)   r+   rX   zassert %(py10)sr   Nr   g      @r      )deltarace_id	race_dateupdatesr   )z)%(py2)s
{%(py2)s = %(py0)s.rd
} < %(py4)sstate
initial_rdr'   r*   r+   )z%(py0)s < %(py2)sk2)r!   r(   zassert %(py4)sr)   )r   r   r   r   get_effective_k_factorr
   HORSEr|   approxr,   r-   r.   r/   r0   r1   r2   r3   get_or_init_ratingr   range_apply_updater   )r   r   r   r   r   r9   r_   r   r6   ra   @py_format11r   r   r   r^   r:   r;   r   @py_format3s                      r   #test_rating_engine_with_rd_k_factor?TestRatingEngineIntegration.test_rating_engine_with_rd_k_factor!  sL   ;/<1A **:+;+;Q?]](4(]4((((((((r((((((r((((r((((((V((((V(((](((4((((((((((( ))**:*:A>XX
rA    tQ+ !   xx$*$$$$$x$$$$$$u$$$$u$$$x$$$$$$*$$$$*$$$$$$$ **:+;+;Q?BwrBrrBBr   c                    SSK JnJnJn  [	        US9nSUl        [        SSS5      Ul        [	        US9nSUl        SUl	        S	Ul
        XVl        [	        U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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        Xx/n	UR'                  [(        R*                  S
5        UR'                  [(        R*                  S5        UR-                  Xi5      n
[/        S U
 5       5      n[1        U5      nSoU:  o(       Gd  [2        R4                  " SU4SX45      S[6        R8                  " 5       ;   d  [2        R:                  " [0        5      (       a  [2        R<                  " [0        5      OSS[6        R8                  " 5       ;   d  [2        R:                  " U5      (       a  [2        R<                  " U5      OS[2        R<                  " U5      [2        R<                  " U5      S.-  nSSU0-  n[?        [2        R@                  " U5      5      eS=n=pU
 Vs/ s H  nURB                  S
:X  d  M  UPM     snS   nURD                  nSnUU:  nU(       d  [2        R4                  " SU4SUU45      S[6        R8                  " 5       ;   d  [2        R:                  " U5      (       a  [2        R<                  " U5      OS[2        R<                  " U5      [2        R<                  " U5      S.-  nSSU0-  n[?        [2        R@                  " U5      5      eS=n=nnU
 Vs/ s H  nURB                  S:X  d  M  UPM     snS   nURD                  nSnUU:  nU(       d  [2        R4                  " SU4SUU45      S[6        R8                  " 5       ;   d  [2        R:                  " U5      (       a  [2        R<                  " U5      OS[2        R<                  " U5      [2        R<                  " U5      S.-  nSSU0-  n[?        [2        R@                  " U5      5      eS=n=nngs  snf s  snf ) z9Test that rating changes sum to zero in a two-horse race.r   )r   r   r   r?   Testr   rA   r   r   mobilerB   NFrN   rC   c              3   8   #    U  H  oR                   v   M     g 7fr   )r   ).0us     r   	<genexpr>KTestRatingEngineIntegration.test_two_horse_race_zero_sum.<locals>.<genexpr>t  s     37a''7s   g{Gz?r   )z/%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} < %(py6)sr   total_deltarU   rW   rX   re   )z,%(py2)s
{%(py2)s = %(py0)s.delta
} > %(py5)swinner_update)r!   r(   r$   zassert %(py7)spy7)z,%(py2)s
{%(py2)s = %(py0)s.delta
} < %(py5)sloser_update)#packages.core.storage.modelsr   r   r   r   r   r   r   rF   r   
start_typer   rG   rH   rI   rJ   rK   rL   rM   r   r
   r   process_racer   r   r,   r-   r.   r/   r0   r1   r2   r3   r   r   )r   r   r   r   r   r   r[   r   r   r\   r   r  r5   r_   r`   r;   ra   r  r  r6   r9   r8   @py_format8r  s                           r   test_two_horse_race_zero_sum8TestRatingEngineIntegration.test_two_horse_race_zero_sumF  s   GG )#$(q"$5!dO		#	'	( W%!""'W%!""'' 	!!*"2"2C8!!*"2"2C8 %%i: 3733;&$&$&&&&&&&&&&&s&&&&s&&&&&&;&&&&;&&&&&&$&&&&&&& %,BGqq{{c/AGB1E""&Q&"Q&&&&&"Q&&&&&&}&&&&}&&&"&&&Q&&&&&&& $+A7aakkS.@7A!D!!%A%!A%%%%%!A%%%%%%|%%%%|%%%!%%%A%%%%%%% C Bs   'Q*?Q**Q/Q/rv   N)rw   rx   ry   rz   r{   r|   r}   r   r  r  r~   rv   r   r   r   r     s&    .^^ #J7&r   r   )r{   builtinsr.   _pytest.assertion.rewrite	assertionrewriter,   datetimer   r   r   r   r|   !packages.core.common.data_qualityr   packages.core.ratings.enginer   !packages.core.ratings.predictionsr	   r  r
   r   r   r   r   r   r   rv   r   r   <module>r!     sK    1     %  B 5 > K Kz" z"zB? B?Jm& m&r   