§
    Í½j  ã                  óê  — d Z ddlmZ ddlZddlZddlZddlmZ ddlZ ee	¦  «         
                    ¦   «         j        j        j        Zedz  Z ee¦  «        ej        vr$ej                             d ee¦  «        ¦  «          ee¦  «        ej        vr$ej                             d ee¦  «        ¦  «         ddlmZmZmZ ddlmZ  G d„ d	¦  «        Z G d
„ d¦  «        Z G d„ d¦  «        ZdS )aê  
Empirical Adversarial Stress Test Suite for Milestone 2:
- Exact 250ms i-frame boundaries (t=0ms, 249ms, 250ms evaded; 251ms damaged; negative timestamps rejected)
- Sequential dodge resets and extension logic
- Animation cancelling during attack wind-up and action locks
- 3-charge pool budgeting, depletion lockout, and multi-tier recharge
- 4 Weapon swing archetypes parameter verification (SLASH, THRUST, SLAM, BOLT)
- Execution of Node.js empirical runtime harness for client modules
é    )ÚannotationsN)ÚPathÚserver)ÚCombatEngineÚCombatActorÚDamageEventResult)ÚFiveElementsc                  óŠ   — e Zd ZdZej        dd„¦   «         Zej                             dg d¢¦  «        dd„¦   «         Z	dd„Z
dS )ÚTestExactIFrameBoundariesServerz=Adversarial stress-testing of server-side i-frame boundaries.Úreturnú-tuple[CombatEngine, CombatActor, CombatActor]c                óò   — t          ¦   «         }t          ddt          j        d¬¦  «        }t          ddt          j        dd¬¦  «        }|                     |¦  «         |                     |¦  «         |||fS )	Né   ÚSavageHellhoundg      ^@)Úbase_attacké   Ú
PrimalHeroç     @@)Ú
current_hpÚmax_hp)r   r   r	   ÚHOAÚKIMÚregister_actor)ÚselfÚengineÚattackerÚdefenders       úGC:\Projects\FreeExile\tests\unit\test_challenger_m2_empirical_stress.pyÚsetup_combatz,TestExactIFrameBoundariesServer.setup_combat    sw   € å‘”ˆÝ˜qÐ"3µ\Ô5EÐSXÐYÑYÔYˆÝ˜q ,µÔ0@ÈUÐ[`ÐaÑaÔaˆØ×Ò˜hÑ'Ô'Ð'Ø×Ò˜hÑ'Ô'Ð'Ø�x Ð)Ð)ó    zdelta_ms, should_evade))r   T)r   T)é2   T)é}   T)éø   T)éù   T)éú   T)éû   F)éü   F)i,  F)iô  F)éÿÿÿÿF)iÎÿÿÿFr   Údelta_msÚintÚshould_evadeÚboolÚNonec                óÜ  — |\  }}}d}|                      |j        |¦  «         ||z   }|                     |j        |j        dt          j        |¦  «        }	|rK|	j        du sJ d|› d�¦   «         ‚|	j        dk    sJ d|	j        › �¦   «         ‚|j        dk    s
J d	¦   «         ‚dS |	j        d
u sJ d|› d�¦   «         ‚|	j        dk    sJ d|	j        › �¦   «         ‚|j        dk     s
J d¦   «         ‚dS )z_Verifies damage is evaded at t=0ms, 249ms, 250ms, and damage is taken at t=251ms and negatives.é@B ç      Y@TzAttack at delta=zms should be evaded!ç        z'Evaded attack must yield 0 damage, got r   z.Defender HP must not decrease on evaded attackFzms should NOT be evaded!z,Non-evaded attack must yield >0 damage, got z Defender HP must decrease on hitN)Útrigger_phantom_evasionÚactor_idÚcalculate_damager	   r   Ú	is_evadedÚfinal_damager   )
r   r   r)   r+   r   r   r   Út0Úhit_timeÚress
             r   Útest_exact_iframe_boundariesz<TestExactIFrameBoundariesServer.test_exact_iframe_boundaries)   sL  € ð, &2Ñ"ˆ�˜(ØˆØ×&Ò& xÔ'8¸"Ñ=Ô=Ð=Ø˜‘=ˆà×%Ò% hÔ&7¸Ô9JÈEÕS_ÔScÐemÑnÔnˆØð 	SØ”= DÐ(Ð(Ð(Ð*[¸XÐ*[Ð*[Ð*[Ñ(Ô(Ð(ØÔ# sÒ*Ð*Ð*Ð,hÐVYÔVfÐ,hÐ,hÑ*Ô*Ð*ØÔ&¨%Ò/Ð/Ð/Ð1aÑ/Ô/Ð/Ð/Ð/à”= EÐ)Ð)Ð)Ð+`¸hÐ+`Ð+`Ð+`Ñ)Ô)Ð)ØÔ# cÒ)Ð)Ð)Ð+lÐZ]ÔZjÐ+lÐ+lÑ)Ô)Ð)ØÔ&¨Ò.Ð.Ð.Ð0RÑ.Ô.Ð.Ð.Ð.r    c                óz  — |\  }}}d}|                      |j        |¦  «         |                     |j        |j        dt          j        |dz   ¦  «        }|j        du sJ ‚|                      |j        |dz   ¦  «         |                     |j        |j        dt          j        |dz   ¦  «        }|j        du sJ ‚|                     |j        |j        dt          j        |dz   ¦  «        }|j        du sJ ‚|                     |j        |j        dt          j        |dz   ¦  «        }	|	j        du sJ ‚|	j        d	k    sJ ‚d
S )zCSecond dodge during active i-frame resets the 250ms window forward.r/   r0   éÈ   Ti�  iÂ  iÃ  Fr1   N)r2   r3   r4   r	   r   r5   r6   )
r   r   r   r   r   r7   Úres1Úres2Úres3Úres4s
             r   Ú/test_sequential_dodge_resets_and_extends_iframezOTestExactIFrameBoundariesServer.test_sequential_dodge_resets_and_extends_iframeN   sk  € ð
 &2Ñ"ˆ�˜(ØˆØ×&Ò& xÔ'8¸"Ñ=Ô=Ð=ð ×&Ò& xÔ'8¸(Ô:KÈUÕT`ÔTdÐfhÐknÑfnÑoÔoˆØŒ~ Ð%Ð%Ð%Ð%ð 	×&Ò& xÔ'8¸"¸s¹(ÑCÔCÐCð ×&Ò& xÔ'8¸(Ô:KÈUÕT`ÔTdÐfhÐknÑfnÑoÔoˆØŒ~ Ð%Ð%Ð%Ð%ð ×&Ò& xÔ'8¸(Ô:KÈUÕT`ÔTdÐfhÐknÑfnÑoÔoˆØŒ~ Ð%Ð%Ð%Ð%ð ×&Ò& xÔ'8¸(Ô:KÈUÕT`ÔTdÐfhÐknÑfnÑoÔoˆØŒ~ Ð&Ð&Ð&Ð&ØÔ  3Ò&Ð&Ð&Ð&Ð&Ð&r    N)r   r   )r   r   r)   r*   r+   r,   r   r-   )r   r   r   r-   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚpytestÚfixturer   ÚmarkÚparametrizer:   rA   © r    r   r   r      s™   € € € € € ØGÐGà„^ð*ð *ð *ñ „^ð*ð „[×ÒÐ5ð 8ð 8ð 8ñ ô ðSð Sð Sñô ðSð,'ð 'ð 'ð 'ð 'ð 'r    r   c                  óp   — e Zd ZdZ ej        d¬¦  «        dd„¦   «         Zdd„Zdd„Zdd	„Z	dd
„Z
dd„ZdS )Ú TestWeaponSwingArchetypesCatalogzWVerifies all 4 weapon swing archetypes and their parameters in weapon_swing_catalog.js.T)Úautouser   r-   c                óh   — t           dz  dz  dz  dz  dz  }|                     d¬¦  «        | _        d S )NÚclientÚwebappÚjsÚdatazweapon_swing_catalog.jszutf-8)Úencoding)ÚPROJECT_ROOTÚ	read_textÚcode)r   Úcatalog_paths     r   Úload_catalogz-TestWeaponSwingArchetypesCatalog.load_catalogo   s=   € å# hÑ.°Ñ9¸DÑ@À6ÑIÐLeÑeˆØ ×*Ò*°GÐ*Ñ<Ô<ˆŒ	ˆ	ˆ	r    c                ó>   — dD ]}|| j         v sJ d|› d�¦   «         ‚Œd S )N)zSLASH:zTHRUST:zSLAM:zBOLT:z
Archetype z must exist in catalog©rV   )r   Úarchs     r   Útest_four_archetype_ids_existz>TestWeaponSwingArchetypesCatalog.test_four_archetype_ids_existt   sI   € Ø;ð 	Pð 	PˆDØ˜4œ9Ð$Ð$Ð$Ð&O°4Ð&OÐ&OÐ&OÑ$Ô$Ð$Ð$ð	Pð 	Pr    c                ó    — d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d S )Nzid: 'SLASH'zstyle: 'arc'zhitStopFrames: 3zhitStopDuration: 0.05zsweepAngleDeg: 135zreachRadius: 56zparticleType: 'fire'rZ   ©r   s    r   Útest_slash_archetype_specsz;TestWeaponSwingArchetypesCatalog.test_slash_archetype_specsx   s�   € Ø ¤	Ð)Ð)Ð)Ð)Ø ¤Ð*Ð*Ð*Ð*Ø! T¤YÐ.Ð.Ð.Ð.Ø&¨$¬)Ð3Ð3Ð3Ð3Ø# t¤yÐ0Ð0Ð0Ð0Ø  D¤IÐ-Ð-Ð-Ð-Ø%¨¬Ð2Ð2Ð2Ð2Ð2Ð2r    c                ó    — d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d S )Nzid: 'THRUST'zstyle: 'cone'úhitStopFrames: 2úhitStopDuration: 0.035zsweepAngleDeg: 35zreachRadius: 84zparticleType: 'thunder'rZ   r^   s    r   Útest_thrust_archetype_specsz<TestWeaponSwingArchetypesCatalog.test_thrust_archetype_specs�   s�   € Ø ¤Ð*Ð*Ð*Ð*Ø $¤)Ð+Ð+Ð+Ð+Ø! T¤YÐ.Ð.Ð.Ð.Ø'¨4¬9Ð4Ð4Ð4Ð4Ø" d¤iÐ/Ð/Ð/Ð/Ø  D¤IÐ-Ð-Ð-Ð-Ø(¨D¬IÐ5Ð5Ð5Ð5Ð5Ð5r    c                ó    — d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d S )Nz
id: 'SLAM'zstyle: 'radial'zhitStopFrames: 4zhitStopDuration: 0.066zsweepAngleDeg: 360zreachRadius: 76zparticleType: 'earth'rZ   r^   s    r   Útest_slam_archetype_specsz:TestWeaponSwingArchetypesCatalog.test_slam_archetype_specsŠ   s�   € Ø˜tœyÐ(Ð(Ð(Ð(Ø  D¤IÐ-Ð-Ð-Ð-Ø! T¤YÐ.Ð.Ð.Ð.Ø'¨4¬9Ð4Ð4Ð4Ð4Ø# t¤yÐ0Ð0Ð0Ð0Ø  D¤IÐ-Ð-Ð-Ð-Ø&¨$¬)Ð3Ð3Ð3Ð3Ð3Ð3r    c                ó    — d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d| j         v sJ ‚d S )Nz
id: 'BOLT'zstyle: 'beam'ra   rb   zsweepAngleDeg: 20zreachRadius: 180zparticleType: 'phantom'rZ   r^   s    r   Útest_bolt_archetype_specsz:TestWeaponSwingArchetypesCatalog.test_bolt_archetype_specs“   s�   € Ø˜tœyÐ(Ð(Ð(Ð(Ø $¤)Ð+Ð+Ð+Ð+Ø! T¤YÐ.Ð.Ð.Ð.Ø'¨4¬9Ð4Ð4Ð4Ð4Ø" d¤iÐ/Ð/Ð/Ð/Ø! T¤YÐ.Ð.Ð.Ð.Ø(¨D¬IÐ5Ð5Ð5Ð5Ð5Ð5r    N©r   r-   )rB   rC   rD   rE   rF   rG   rX   r\   r_   rc   re   rg   rJ   r    r   rL   rL   l   s°   € € € € € ØaÐaà€V„^˜DÐ!Ñ!Ô!ð=ð =ð =ñ "Ô!ð=ðPð Pð Pð Pð3ð 3ð 3ð 3ð6ð 6ð 6ð 6ð4ð 4ð 4ð 4ð6ð 6ð 6ð 6ð 6ð 6r    rL   c                  ó   — e Zd ZdZdd„ZdS )Ú#TestNodeJsEmpiricalHarnessExecutionzRExecutes the full Node.js runtime stress harness to empirically verify JS modules.r   r-   c                óº  — t          t          ¦  «        j        dz  }|                     ¦   «         s
J d¦   «         ‚t	          j        dt          |¦  «        gddt          t          ¦  «        ¬¦  «        }|j        dk    sJ d|j	        › d|j
        › �¦   «         ‚d	|j	        v sJ ‚d
|j	        v sJ ‚d|j	        v sJ ‚d|j	        v sJ ‚d|j	        v sJ ‚d|j	        v sJ ‚d S )Nzharness_m2_empirical.mjsz#harness_m2_empirical.mjs must existÚnodeT)Úcapture_outputÚtextÚcwdr   z*Node.js empirical harness failed:
STDOUT:
z	
STDERR:
z-=== ALL 5 EMPIRICAL HARNESS CHECKS PASSED ===z-PASS: Animation cancelling interrupts wind-upzLPASS: Client i-frame bounds strictly: evaded at 0ms, 249ms; damaged at 251msz-PASS: 3-charge pool limits, depletion lockoutz2PASS: All 4 archetypes (SLASH, THRUST, SLAM, BOLT)z+PASS: Hit-stop freeze, NaN/undefined safety)r   Ú__file__ÚparentÚexistsÚ
subprocessÚrunÚstrrT   Ú
returncodeÚstdoutÚstderr)r   Úharness_pathÚprocs      r   Útest_run_nodejs_stress_harnesszBTestNodeJsEmpiricalHarnessExecution.test_run_nodejs_stress_harness    s  € Ý�H‘~”~Ô,Ð/IÑIˆØ×"Ò"Ñ$Ô$ÐKÐKÐ&KÑKÔKÐ$åŒ~Ø•S˜Ñ&Ô&Ð'ØØÝ•LÑ!Ô!ð	
ñ 
ô 
ˆð Œ !Ò#Ð#Ð#Ð%yÐTXÔT_Ð%yÐ%yÐlpÔlwÐ%yÐ%yÑ#Ô#Ð#Ø>À$Ä+ÐMÐMÐMÐMØ>À$Ä+ÐMÐMÐMÐMØ]ÐaeÔalÐlÐlÐlÐlØ>À$Ä+ÐMÐMÐMÐMØCÀtÄ{ÐRÐRÐRÐRØ<ÀÄÐKÐKÐKÐKÐKÐKr    Nrh   )rB   rC   rD   rE   r{   rJ   r    r   rj   rj   �   s4   € € € € € Ø\Ð\ðLð Lð Lð Lð Lð Lr    rj   )rE   Ú
__future__r   Úosrs   ÚsysÚpathlibr   rF   rp   Úresolverq   rT   Ú
SERVER_DIRru   ÚpathÚinsertÚworld.combat_enginer   r   r   Úworld.martial_matrixr	   r   rL   rj   rJ   r    r   ú<module>r†      s¸  ððð ð #Ð "Ð "Ð "Ð "Ð "Ø 	€	€	€	Ø Ð Ð Ð Ø 
€
€
€
Ø Ð Ð Ð Ð Ð Ø €€€àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€Ø˜HÑ$€
Ø€3€z�?„?˜#œ(Ð"Ð"Ø„H‡O‚O�A�s�s˜:‘”Ñ'Ô'Ð'Ø€3€|ÑÔ˜CœHÐ$Ð$Ø„H‡O‚O�A�s�s˜<Ñ(Ô(Ñ)Ô)Ð)à LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LÐ LØ -Ð -Ð -Ð -Ð -Ð -ðL'ð L'ð L'ð L'ð L'ñ L'ô L'ð L'ð^.6ð .6ð .6ð .6ð .6ñ .6ô .6ð .6ðbLð Lð Lð Lð Lñ Lô Lð Lð Lð Lr    