§
    ‘Î½jæ4  ã                  ó�  — d Z ddlmZ ddlZddlmc mZ ddl	Z	ddl
Z
ddlZddlZddlZddlmZ ddlZ ee¦  «                             ¦   «         j        j        j        Zedz  dz  Zedz  dz  Zedz  d	z  Z G d
„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        Z G d„ d¦  «        ZdS )a  
Unit Test Suite for Milestone 2: Character Animation & Visceral Combat Feel Engine.
Tests:
1. 5-Phase Kinetic State Machine & Archetype Clips (animation_engine.js)
2. Micro Hit-Stop, Screen Shake Clamping, and Damage Number Ring Buffer (combat_feel_engine.js)
3. Weapon Swing Archetypes Catalog (weapon_swing_catalog.js)
4. Animation Cancelling & Weapon Swing Triggers (combat_skills.js)
5. Canvas Renderer Game Loop Wiring (canvas_renderer.js)
6. Strict Quantitative Line Length Hygiene Caps (GEMINI.md & PROJECT.md)
é    )ÚannotationsN)ÚPathÚclientÚwebappÚjsÚengineÚdatac                  óx   — 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d„ZdS )Ú!TestAnimationEngineKineticMachinezVVerifies 5-phase kinetic machine and archetype animation clips in animation_engine.js.T©ÚautouseÚreturnÚNonec                óL   — t           dz                       d¬¦  «        | _        d S )Núanimation_engine.jsúutf-8©Úencoding©Ú
ENGINE_DIRÚ	read_textÚcode©Úselfs    úEC:\Projects\FreeExile\tests\unit\test_m2_animation_and_combat_feel.pyÚ
setup_codez,TestAnimationEngineKineticMachine.setup_code   s$   € åÐ"7Ñ7×BÒBÈGÐBÑTÔTˆŒ	ˆ	ˆ	ó    c                óþ  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )zKVerifies attack_slash, attack_thrust, attack_slam, attack_bolt clips exist.zattack_slash:©Úin©z,%(py1)s in %(py5)s
{%(py5)s = %(py3)s.code
}r   ©Úpy1Úpy3Úpy5úassert %(py7)sÚpy7Nzattack_thrust:zattack_slam:zattack_bolt:©	r   Ú
@pytest_arÚ_call_reprcompareÚ	_safereprÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚAssertionErrorÚ_format_explanation©r   Ú@py_assert0Ú@py_assert4Ú@py_assert2Ú@py_format6Ú@py_format8s         r   Ú&test_archetype_animation_clips_definedzHTestAnimationEngineKineticMachine.test_archetype_animation_clips_defined"   s  € àÐ+ $¤)Ð+ˆ )Ð+Ð+Ð+Ð+Õ+Ô+Ð+Ð+Ð+Ð+ˆ )Ð+Ñ+Ô+Õ+Ô+ˆÑ+Ô+Ð+Õ+Ô+Ñ+Ô+Ð+Ð+Õ+Ô+ $Ñ+Ô+Ð+Õ+Ô+ $Ñ+Ô+Ð+Ð+Õ+Ô+ )Ñ+Ô+Ð+Ð+Ñ+Ð+Ð+Ð+Ð+Ð+Ñ+Ð+Õ+Õ+Ô+Ð+Ñ+Ô+Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+ØÐ, 4¤9Ð,Ð 9Ð,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð 9Ð,Ñ,Ô,Õ,Ô,ÐÑ,Ô,Ð,Õ,Ô,Ñ,Ô,Ð,Ð,Õ,Ô, 4Ñ,Ô,Ð,Õ,Ô, 4Ñ,Ô,Ð,Ð,Õ,Ô, 9Ñ,Ô,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,ØÐ* ¤Ð*ˆ~ Ð*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*ˆ~ Ð*Ñ*Ô*Õ*Ô*ˆ~Ñ*Ô*Ð*Õ*Ô*Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*ØÐ* ¤Ð*ˆ~ Ð*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*ˆ~ Ð*Ñ*Ô*Õ*Ô*ˆ~Ñ*Ô*Ð*Õ*Ô*Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*r   c                óh  — g }d}| j         }||v }|}|sd}| j         }||v }|}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }	dd|	iz  }
|                     |
¦  «         |sžt          j        d|fd	||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        d
œz  }dd|iz  }|                     |¦  «         t          j        |d¦  «        i z  }dd|iz  }t          t          j
        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }	t          t          j
        |	¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }	t          t          j
        |	¦  «        ¦  «        ‚dx}x}}dS )zSVerifies hit_frame defined and atlas_clip aliased to prevent sprite index overflow.zatlas_clip: 'attack_slash'zatlas_clip: "attack_slash"r   ©z,%(py3)s in %(py7)s
{%(py7)s = %(py5)s.code
}r   ©r$   r%   r'   ú%(py9)sÚpy9©z0%(py12)s in %(py16)s
{%(py16)s = %(py14)s.code
}©Úpy12Úpy14Úpy16ú%(py18)sÚpy18é   úassert %(py21)sÚpy21Nzhit_frame: 2r!   r"   r&   r'   zhit_frame: 3©r   r)   r*   r+   r,   r-   r.   ÚappendÚ_format_boolopr/   r0   ©r   Ú@py_assert1r4   Ú@py_assert6r3   r2   Ú@py_assert11Ú@py_assert15Ú@py_assert13r6   Ú@py_format10Ú@py_format17Ú@py_format19Ú@py_format20Ú@py_format22r5   s                   r   Ú+test_archetype_hit_frame_and_atlas_aliasingzMTestAnimationEngineKineticMachine.test_archetype_hit_frame_and_atlas_aliasing)   sé  € àeÐeÐ+Ðe¨t¬yÐeÐ+¨yÐ8ÐeÐeÐeÐeÐeÐ<XÐeÐ\`Ô\eÐeÐ<XÐ\eÐ<eÐeÐeÐeÐeÑeÕeÔeÐeÐeÐeÐeÐ+¨yÐeÑeÔeÕeÔeÐ+ÑeÔeÐeÕeÔeÑeÔeÐeÐeÕeÔe¨tÑeÔeÐeÕeÔe¨tÑeÔeÐeÐeÕeÔe¨yÑeÔeÐeÐeÑeÐeÐeÐeÐeÐeÑeÐeÐe×eÒeÐeÑeÔeÐeÐeÐeÕeÔeÐeÐeÐeÐeÐ<XÐ\eÐeÑeÔeÕeÔeÐ<XÑeÔeÐeÕeÔeÑeÔeÐeÐeÕeÔeÐ\`ÑeÔeÐeÕeÔeÐ\`ÑeÔeÐeÐeÕeÔeÐ\eÑeÔeÐeÐeÑeÐeÐeÐeÐeÐeÑeÐeÐe×eÒeÐeÑeÔeÐeÕeÔeÐeÐeÑeÔeÐeÑeÐeÐeÐeÐeÐeÑeÐeÕeÕeÔeÐeÑeÔeÑeÔeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeÐeàÐ* ¤Ð*ˆ~ Ð*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*ˆ~ Ð*Ñ*Ô*Õ*Ô*ˆ~Ñ*Ô*Ð*Õ*Ô*Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*ØÐ* ¤Ð*ˆ~ Ð*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*ˆ~ Ð*Ñ*Ô*Õ*Ô*ˆ~Ñ*Ô*Ð*Õ*Ô*Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ð*r   c                óZ  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	D ]è}| j         }||v }|sÕt          j        d|fd
||f¦  «        dt	          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }	dd|	iz  }
t          t          j        |
¦  «        ¦  «        ‚dx}}ŒédS )z;Verifies KINETIC_PHASES enum contains all canonical phases.ÚKINETIC_PHASESr   r!   r   r"   r&   r'   N)ÚidleÚrunÚwind_upÚimpactÚrecoveryÚhit_stopÚdodge©z,%(py0)s in %(py4)s
{%(py4)s = %(py2)s.code
}Úphase©Úpy0Úpy2Úpy4úassert %(py6)sÚpy6r(   )r   r2   r3   r4   r5   r6   r`   Ú@py_assert3rK   Ú@py_format5Ú@py_format7s              r   Ú'test_kinetic_phases_constant_and_valueszITestAnimationEngineKineticMachine.test_kinetic_phases_constant_and_values0   sü  € àÐ, 4¤9Ð,Ð 9Ð,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð 9Ð,Ñ,Ô,Õ,Ô,ÐÑ,Ô,Ð,Õ,Ô,Ñ,Ô,Ð,Ð,Õ,Ô, 4Ñ,Ô,Ð,Õ,Ô, 4Ñ,Ô,Ð,Ð,Õ,Ô, 9Ñ,Ô,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,ØZð 	&ð 	&ˆEØ œIÐ%�5˜IÐ%Ð%Ð%Ð%Õ%Ô%Ð%Ð%Ð%Ð%�5˜IÐ%Ñ%Ô%Ð%Õ%Ô%Ñ%Ô%Ð%Ð%Õ%Ô%�5Ñ%Ô%Ð%Õ%Ô%�5Ñ%Ô%Ð%Ð%Ð%Õ%Ô%Ñ%Ô%Ð%Ð%Õ%Ô%˜DÑ%Ô%Ð%Õ%Ô%˜DÑ%Ô%Ð%Ð%Õ%Ô%˜IÑ%Ô%Ð%Ð%Ñ%Ð%Ð%Ð%Ð%Ð%Ñ%Ð%Õ%Õ%Ô%Ð%Ñ%Ô%Ñ%Ô%Ð%Ð%Ð%Ð%Ð%Ð%ð	&ð 	&r   c                óx
  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )zVVerifies updateAnimation continuously computes state.kineticPhase across all 5 phases.z#animState.kineticPhase = 'hit_stop'r   r!   r   r"   r&   r'   Nz"animState.kineticPhase = 'wind_up'z!animState.kineticPhase = 'impact'z#animState.kineticPhase = 'recovery'zanimState.kineticPhase = 'run'zanimState.kineticPhase = 'idle'z animState.kineticPhase = 'dodge'r(   r1   s         r   Ú)test_continuous_kinetic_phase_computationzKTestAnimationEngineKineticMachine.test_continuous_kinetic_phase_computation6   s(  € à4ÐA¸¼	ÐAÐ4¸	ÐAÐAÐAÐAÕAÔAÐAÐAÐAÐAÐ4¸	ÐAÑAÔAÕAÔAÐ4ÑAÔAÐAÕAÔAÑAÔAÐAÐAÕAÔA¸ÑAÔAÐAÕAÔA¸ÑAÔAÐAÐAÕAÔA¸	ÑAÔAÐAÐAÑAÐAÐAÐAÐAÐAÑAÐAÕAÕAÔAÐAÑAÔAÑAÔAÐAÐAÐAÐAÐAÐAÐAØ3Ð@°t´yÐ@Ð3°yÐ@Ð@Ð@Ð@Õ@Ô@Ð@Ð@Ð@Ð@Ð3°yÐ@Ñ@Ô@Õ@Ô@Ð3Ñ@Ô@Ð@Õ@Ô@Ñ@Ô@Ð@Ð@Õ@Ô@°tÑ@Ô@Ð@Õ@Ô@°tÑ@Ô@Ð@Ð@Õ@Ô@°yÑ@Ô@Ð@Ð@Ñ@Ð@Ð@Ð@Ð@Ð@Ñ@Ð@Õ@Õ@Ô@Ð@Ñ@Ô@Ñ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@Ð@Ø2Ð?°d´iÐ?Ð2°iÐ?Ð?Ð?Ð?Õ?Ô?Ð?Ð?Ð?Ð?Ð2°iÐ?Ñ?Ô?Õ?Ô?Ð2Ñ?Ô?Ð?Õ?Ô?Ñ?Ô?Ð?Ð?Õ?Ô?°dÑ?Ô?Ð?Õ?Ô?°dÑ?Ô?Ð?Ð?Õ?Ô?°iÑ?Ô?Ð?Ð?Ñ?Ð?Ð?Ð?Ð?Ð?Ñ?Ð?Õ?Õ?Ô?Ð?Ñ?Ô?Ñ?Ô?Ð?Ð?Ð?Ð?Ð?Ð?Ð?Ø4ÐA¸¼	ÐAÐ4¸	ÐAÐAÐAÐAÕAÔAÐAÐAÐAÐAÐ4¸	ÐAÑAÔAÕAÔAÐ4ÑAÔAÐAÕAÔAÑAÔAÐAÐAÕAÔA¸ÑAÔAÐAÕAÔA¸ÑAÔAÐAÐAÕAÔA¸	ÑAÔAÐAÐAÑAÐAÐAÐAÐAÐAÑAÐAÕAÕAÔAÐAÑAÔAÑAÔAÐAÐAÐAÐAÐAÐAÐAØ/Ð<°4´9Ð<Ð/°9Ð<Ð<Ð<Ð<Õ<Ô<Ð<Ð<Ð<Ð<Ð/°9Ð<Ñ<Ô<Õ<Ô<Ð/Ñ<Ô<Ð<Õ<Ô<Ñ<Ô<Ð<Ð<Õ<Ô<°4Ñ<Ô<Ð<Õ<Ô<°4Ñ<Ô<Ð<Ð<Õ<Ô<°9Ñ<Ô<Ð<Ð<Ñ<Ð<Ð<Ð<Ð<Ð<Ñ<Ð<Õ<Õ<Ô<Ð<Ñ<Ô<Ñ<Ô<Ð<Ð<Ð<Ð<Ð<Ð<Ð<Ø0Ð=°D´IÐ=Ð0°IÐ=Ð=Ð=Ð=Õ=Ô=Ð=Ð=Ð=Ð=Ð0°IÐ=Ñ=Ô=Õ=Ô=Ð0Ñ=Ô=Ð=Õ=Ô=Ñ=Ô=Ð=Ð=Õ=Ô=°DÑ=Ô=Ð=Õ=Ô=°DÑ=Ô=Ð=Ð=Õ=Ô=°IÑ=Ô=Ð=Ð=Ñ=Ð=Ð=Ð=Ð=Ð=Ñ=Ð=Õ=Õ=Ô=Ð=Ñ=Ô=Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=Ð=Ø1Ð>°T´YÐ>Ð1°YÐ>Ð>Ð>Ð>Õ>Ô>Ð>Ð>Ð>Ð>Ð1°YÐ>Ñ>Ô>Õ>Ô>Ð1Ñ>Ô>Ð>Õ>Ô>Ñ>Ô>Ð>Ð>Õ>Ô>°TÑ>Ô>Ð>Õ>Ô>°TÑ>Ô>Ð>Ð>Õ>Ô>°YÑ>Ô>Ð>Ð>Ñ>Ð>Ð>Ð>Ð>Ð>Ñ>Ð>Õ>Õ>Ô>Ð>Ñ>Ô>Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ð>r   c                ó€  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )z@Verifies cancelAction function resets action lock and callbacks.zfunction cancelActionr   r!   r   r"   r&   r'   NÚcancelActionzisActionLocked = falser(   r1   s         r   Ú)test_cancel_action_resets_locks_and_phasezKTestAnimationEngineKineticMachine.test_cancel_action_resets_locks_and_phase@   s¥  € à&Ð3¨$¬)Ð3Ð&¨)Ð3Ð3Ð3Ð3Õ3Ô3Ð3Ð3Ð3Ð3Ð&¨)Ð3Ñ3Ô3Õ3Ô3Ð&Ñ3Ô3Ð3Õ3Ô3Ñ3Ô3Ð3Ð3Õ3Ô3¨$Ñ3Ô3Ð3Õ3Ô3¨$Ñ3Ô3Ð3Ð3Õ3Ô3¨)Ñ3Ô3Ð3Ð3Ñ3Ð3Ð3Ð3Ð3Ð3Ñ3Ð3Õ3Õ3Ô3Ð3Ñ3Ô3Ñ3Ô3Ð3Ð3Ð3Ð3Ð3Ð3Ð3ØÐ* ¤Ð*ˆ~ Ð*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*ˆ~ Ð*Ñ*Ô*Õ*Ô*ˆ~Ñ*Ô*Ð*Õ*Ô*Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ø'Ð4¨4¬9Ð4Ð'¨9Ð4Ð4Ð4Ð4Õ4Ô4Ð4Ð4Ð4Ð4Ð'¨9Ð4Ñ4Ô4Õ4Ô4Ð'Ñ4Ô4Ð4Õ4Ô4Ñ4Ô4Ð4Ð4Õ4Ô4¨4Ñ4Ô4Ð4Õ4Ô4¨4Ñ4Ô4Ð4Ð4Õ4Ô4¨9Ñ4Ô4Ð4Ð4Ñ4Ð4Ð4Ð4Ð4Ð4Ñ4Ð4Õ4Õ4Ô4Ð4Ñ4Ô4Ñ4Ô4Ð4Ð4Ð4Ð4Ð4Ð4Ð4Ð4Ð4r   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
zKVerifies AnimationEngine exports cancelAction and KINETIC_PHASES to window.zcancelAction,r   r!   r   r"   r&   r'   NzKINETIC_PHASES,r(   r1   s         r   Ú$test_animation_engine_window_exportszFTestAnimationEngineKineticMachine.test_animation_engine_window_exportsF   sÅ  € àÐ+ $¤)Ð+ˆ )Ð+Ð+Ð+Ð+Õ+Ô+Ð+Ð+Ð+Ð+ˆ )Ð+Ñ+Ô+Õ+Ô+ˆÑ+Ô+Ð+Õ+Ô+Ñ+Ô+Ð+Ð+Õ+Ô+ $Ñ+Ô+Ð+Õ+Ô+ $Ñ+Ô+Ð+Ð+Õ+Ô+ )Ñ+Ô+Ð+Ð+Ñ+Ð+Ð+Ð+Ð+Ð+Ñ+Ð+Õ+Õ+Ô+Ð+Ñ+Ô+Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+Ø Ð- D¤IÐ-Ð  IÐ-Ð-Ð-Ð-Õ-Ô-Ð-Ð-Ð-Ð-Ð  IÐ-Ñ-Ô-Õ-Ô-Ð Ñ-Ô-Ð-Õ-Ô-Ñ-Ô-Ð-Ð-Õ-Ô- DÑ-Ô-Ð-Õ-Ô- DÑ-Ô-Ð-Ð-Õ-Ô- IÑ-Ô-Ð-Ð-Ñ-Ð-Ð-Ð-Ð-Ð-Ñ-Ð-Õ-Õ-Ô-Ð-Ñ-Ô-Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-Ð-Ð-Ð-r   N©r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚpytestÚfixturer   r7   rU   rj   rl   ro   rq   © r   r   r   r      sÄ   € € € € € Ø`Ð`à€V„^˜DÐ!Ñ!Ô!ðUð Uð Uñ "Ô!ðUð+ð +ð +ð +ð+ð +ð +ð +ð&ð &ð &ð &ð?ð ?ð ?ð ?ð5ð 5ð 5ð 5ð.ð .ð .ð .ð .ð .r   r   c                  óˆ   — 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d„Zdd„Zdd„ZdS )ÚTestCombatFeelEnginezaVerifies hit-stop, camera shake clamping, and damage number ring buffer in combat_feel_engine.js.Tr   r   r   c                óL   — t           dz                       d¬¦  «        | _        d S )Núcombat_feel_engine.jsr   r   r   r   s    r   r   zTestCombatFeelEngine.setup_codeO   s$   € åÐ"9Ñ9×DÒDÈgÐDÑVÔVˆŒ	ˆ	ˆ	r   c                óh  — g }d}| j         }||v }|}|sd}| j         }||v }|}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }	dd|	iz  }
|                     |
¦  «         |sžt          j        d|fd	||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        d
œz  }dd|iz  }|                     |¦  «         t          j        |d¦  «        i z  }dd|iz  }t          t          j
        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }	t          t          j
        |	¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }	t          t          j
        |	¦  «        ¦  «        ‚dx}x}}dS )zJVerifies isHitStopped guards against NaN / undefined dt with safe default.zisHitStopped(dt = 0.016)zisHitStopped(dt=0.016)r   r9   r   r:   r;   r<   r=   r>   rB   rC   rD   rE   rF   Nz	isNaN(dt)r!   r"   r&   r'   zhitStopTimer -= actualDtrG   rJ   s                   r   Ú#test_hit_stop_dt_safety_and_defaultz8TestCombatFeelEngine.test_hit_stop_dt_safety_and_defaultS   sì  € à_Ð_Ð)Ð_¨T¬YÐ_Ð)¨YÐ6Ð_Ð_Ð_Ð_Ð_Ð:RÐ_ÐVZÔV_Ð_Ð:RÐV_Ð:_Ð_Ð_Ð_Ð_Ñ_Õ_Ô_Ð_Ð_Ð_Ð_Ð)¨YÐ_Ñ_Ô_Õ_Ô_Ð)Ñ_Ô_Ð_Õ_Ô_Ñ_Ô_Ð_Ð_Õ_Ô_¨TÑ_Ô_Ð_Õ_Ô_¨TÑ_Ô_Ð_Ð_Õ_Ô_¨YÑ_Ô_Ð_Ð_Ñ_Ð_Ð_Ð_Ð_Ð_Ñ_Ð_Ð_×_Ò_Ð_Ñ_Ô_Ð_Ð_Ð_Õ_Ô_Ð_Ð_Ð_Ð_Ð:RÐV_Ð_Ñ_Ô_Õ_Ô_Ð:RÑ_Ô_Ð_Õ_Ô_Ñ_Ô_Ð_Ð_Õ_Ô_ÐVZÑ_Ô_Ð_Õ_Ô_ÐVZÑ_Ô_Ð_Ð_Õ_Ô_ÐV_Ñ_Ô_Ð_Ð_Ñ_Ð_Ð_Ð_Ð_Ð_Ñ_Ð_Ð_×_Ò_Ð_Ñ_Ô_Ð_Õ_Ô_Ð_Ð_Ñ_Ô_Ð_Ñ_Ð_Ð_Ð_Ð_Ð_Ñ_Ð_Õ_Õ_Ô_Ð_Ñ_Ô_Ñ_Ô_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_Ð_ØÐ'˜dœiÐ'ˆ{˜iÐ'Ð'Ð'Ð'Õ'Ô'Ð'Ð'Ð'Ð'ˆ{˜iÐ'Ñ'Ô'Õ'Ô'ˆ{Ñ'Ô'Ð'Õ'Ô'Ñ'Ô'Ð'Ð'Õ'Ô'˜dÑ'Ô'Ð'Õ'Ô'˜dÑ'Ô'Ð'Ð'Õ'Ô'˜iÑ'Ô'Ð'Ð'Ñ'Ð'Ð'Ð'Ð'Ð'Ñ'Ð'Õ'Õ'Ô'Ð'Ñ'Ô'Ñ'Ô'Ð'Ð'Ð'Ð'Ð'Ð'Ð'Ø)Ð6¨T¬YÐ6Ð)¨YÐ6Ð6Ð6Ð6Õ6Ô6Ð6Ð6Ð6Ð6Ð)¨YÐ6Ñ6Ô6Õ6Ô6Ð)Ñ6Ô6Ð6Õ6Ô6Ñ6Ô6Ð6Ð6Õ6Ô6¨TÑ6Ô6Ð6Õ6Ô6¨TÑ6Ô6Ð6Ð6Õ6Ô6¨YÑ6Ô6Ð6Ð6Ñ6Ð6Ð6Ð6Ð6Ð6Ñ6Ð6Õ6Õ6Ô6Ð6Ñ6Ô6Ñ6Ô6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ð6r   c                ó„  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )	zMVerifies triggerHitStop computes duration = max(0.016 * frames, durationSec).z%Math.max(0.016 * frames, durationSec)r   r!   r   r"   r&   r'   Nr(   r1   s         r   Útest_hit_stop_duration_formulaz3TestCombatFeelEngine.test_hit_stop_duration_formulaY   sè   € à6ÐC¸$¼)ÐCÐ6¸)ÐCÐCÐCÐCÕCÔCÐCÐCÐCÐCÐ6¸)ÐCÑCÔCÕCÔCÐ6Ñ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ÐCÑCÐCÕCÕCÔCÐCÑCÔCÑCÔCÐCÐCÐCÐCÐCÐCÐCÐCÐCr   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
z=Verifies triggerHitStop pauses both attacker.anim and target.zattacker.anim.hitStopTimerr   r!   r   r"   r&   r'   Nztarget.hitStopTimerr(   r1   s         r   Ú.test_hit_stop_affects_both_attacker_and_targetzCTestCombatFeelEngine.test_hit_stop_affects_both_attacker_and_target]   sÈ  € à+Ð8¨t¬yÐ8Ð+¨yÐ8Ð8Ð8Ð8Õ8Ô8Ð8Ð8Ð8Ð8Ð+¨yÐ8Ñ8Ô8Õ8Ô8Ð+Ñ8Ô8Ð8Õ8Ô8Ñ8Ô8Ð8Ð8Õ8Ô8¨tÑ8Ô8Ð8Õ8Ô8¨tÑ8Ô8Ð8Ð8Õ8Ô8¨yÑ8Ô8Ð8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Õ8Õ8Ô8Ð8Ñ8Ô8Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ø$Ð1¨¬	Ð1Ð$¨	Ð1Ð1Ð1Ð1Õ1Ô1Ð1Ð1Ð1Ð1Ð$¨	Ð1Ñ1Ô1Õ1Ô1Ð$Ñ1Ô1Ð1Õ1Ô1Ñ1Ô1Ð1Ð1Õ1Ô1¨Ñ1Ô1Ð1Õ1Ô1¨Ñ1Ô1Ð1Ð1Õ1Ô1¨	Ñ1Ô1Ð1Ð1Ñ1Ð1Ð1Ð1Ð1Ð1Ñ1Ð1Õ1Õ1Ô1Ð1Ñ1Ô1Ñ1Ô1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1r   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
zSVerifies screen shake intensity clamped to [2.5, 8.5] and duration to [0.12, 0.45].z'Math.min(8.5, Math.max(2.5, intensity))r   r!   r   r"   r&   r'   Nz+Math.min(0.45, Math.max(0.12, durationSec))r(   r1   s         r   Ú#test_screen_shake_clamping_to_specsz8TestCombatFeelEngine.test_screen_shake_clamping_to_specsb   sÈ  € à8ÐE¸D¼IÐEÐ8¸IÐEÐEÐEÐEÕEÔEÐEÐEÐEÐEÐ8¸IÐEÑEÔEÕEÔEÐ8ÑEÔEÐEÕEÔEÑEÔEÐEÐEÕEÔE¸DÑEÔEÐEÕEÔE¸DÑEÔEÐEÐEÕEÔE¸IÑEÔEÐEÐEÑEÐEÐEÐEÐEÐEÑEÐEÕEÕEÔEÐEÑEÔEÑEÔEÐEÐEÐEÐEÐEÐEÐEØ<ÐIÀÄ	ÐIÐ<À	ÐIÐIÐIÐIÕIÔIÐIÐIÐIÐIÐ<À	ÐIÑIÔIÕIÔIÐ<ÑIÔIÐIÕIÔIÑIÔIÐIÐIÕIÔIÀÑIÔIÐIÕIÔIÀÑIÔIÐIÐIÕIÔIÀ	ÑIÔIÐIÐIÑIÐIÐIÐIÐIÐIÑIÐIÕIÕIÔIÐIÑIÔIÑIÔIÐIÐIÐIÐIÐIÐIÐIÐIÐIr   c                ó€  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )zYVerifies triggerScreenShake synchronizes with global screenShake in iso_math.js / window.z1screenShake.intensity = this.screenShakeIntensityr   r!   r   r"   r&   r'   Nz/screenShake.duration = this.screenShakeDurationz)screenShake.timer = this.screenShakeTimerr(   r1   s         r   Ú#test_screen_shake_syncs_with_globalz8TestCombatFeelEngine.test_screen_shake_syncs_with_globalg   s¨  € àBÐOÀdÄiÐOÐBÀiÐOÐOÐOÐOÕOÔOÐOÐOÐOÐOÐBÀiÐOÑOÔOÕOÔOÐBÑOÔOÐOÕOÔOÑOÔOÐOÐOÕOÔOÀdÑOÔOÐOÕOÔOÀdÑOÔOÐOÐOÕOÔOÀiÑOÔOÐOÐOÑOÐOÐOÐOÐOÐOÑOÐOÕOÕOÔOÐOÑOÔOÑOÔOÐOÐOÐOÐOÐOÐOÐOØ@ÐMÀDÄIÐMÐ@ÀIÐMÐMÐMÐMÕMÔMÐMÐMÐMÐMÐ@ÀIÐMÑMÔMÕMÔMÐ@ÑMÔMÐMÕMÔMÑMÔMÐMÐMÕMÔMÀDÑMÔMÐMÕMÔMÀDÑMÔMÐMÐMÕMÔMÀIÑMÔMÐMÐMÑMÐMÐMÐMÐMÐMÑMÐMÕMÕMÔMÐMÑMÔMÑMÔMÐMÐMÐMÐMÐMÐMÐMØ:ÐG¸d¼iÐGÐ:¸iÐGÐGÐGÐGÕGÔGÐGÐGÐGÐGÐ:¸iÐGÑGÔGÕGÔGÐ:ÑGÔGÐGÕGÔGÑGÔGÐGÐGÕGÔG¸dÑGÔGÐGÕGÔG¸dÑGÔGÐGÐGÕGÔG¸iÑGÔGÐGÐGÑGÐGÐGÐGÐGÐGÑGÐGÕGÕGÔGÐGÑGÔGÑGÔGÐGÐGÐGÐGÐGÐGÐGÐGÐGr   c                óh  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}g }d
}| j         }||v }|}|rd}| j         }	||	v }
|
}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }| 	                    |¦  «         |ržt          j        d|
fd||	f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |	¦  «        dœz  }dd|iz  }| 	                    |¦  «         t          j
        |d¦  «        i z  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}
}	dS )zKVerifies directional shake applies vector decomposition along strike angle.zMath.cos(this.shakeAngle)r   r!   r   r"   r&   r'   NzMath.sin(this.shakeAngle)ÚshakeOffsetXÚshakeOffsetYr9   r:   r;   r<   r=   r>   rB   rC   r   rE   rF   ©r   r)   r*   r+   r,   r-   r.   r/   r0   rH   rI   ©r   r2   r3   r4   r5   r6   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   s                   r   Ú$test_directional_shake_decompositionz9TestCombatFeelEngine.test_directional_shake_decompositionm   sà  € à*Ð7¨d¬iÐ7Ð*¨iÐ7Ð7Ð7Ð7Õ7Ô7Ð7Ð7Ð7Ð7Ð*¨iÐ7Ñ7Ô7Õ7Ô7Ð*Ñ7Ô7Ð7Õ7Ô7Ñ7Ô7Ð7Ð7Õ7Ô7¨dÑ7Ô7Ð7Õ7Ô7¨dÑ7Ô7Ð7Ð7Õ7Ô7¨iÑ7Ô7Ð7Ð7Ñ7Ð7Ð7Ð7Ð7Ð7Ñ7Ð7Õ7Õ7Ô7Ð7Ñ7Ô7Ñ7Ô7Ð7Ð7Ð7Ð7Ð7Ð7Ð7Ø*Ð7¨d¬iÐ7Ð*¨iÐ7Ð7Ð7Ð7Õ7Ô7Ð7Ð7Ð7Ð7Ð*¨iÐ7Ñ7Ô7Õ7Ô7Ð*Ñ7Ô7Ð7Õ7Ô7Ñ7Ô7Ð7Ð7Õ7Ô7¨dÑ7Ô7Ð7Õ7Ô7¨dÑ7Ô7Ð7Ð7Õ7Ô7¨iÑ7Ô7Ð7Ð7Ñ7Ð7Ð7Ð7Ð7Ð7Ñ7Ð7Õ7Õ7Ô7Ð7Ñ7Ô7Ñ7Ô7Ð7Ð7Ð7Ð7Ð7Ð7Ð7ØJÐJˆ~ÐJ ¤ÐJˆ~ Ð*ÐJÐJÐJÐJÐJ¨~ÐJÀÄÐJ¨~ÀÐ/JÐJÐJÐJÐJÑJÕJÔJÐJÐJÐJÐJˆ~ ÐJÑJÔJÕJÔJˆ~ÑJÔJÐJÕJÔJÑJÔJÐJÐJÕJÔJ ÑJÔJÐJÕJÔJ ÑJÔJÐJÐJÕJÔJ ÑJÔJÐJÐJÑJÐJÐJÐJÐJÐJÑJÐJÐJ×JÒJÐJÑJÔJÐJÐJÐJÕJÔJÐJÐJÐJÐJ¨~ÀÐJÑJÔJÕJÔJ¨~ÑJÔJÐJÕJÔJÑJÔJÐJÐJÕJÔJÀÑJÔJÐJÕJÔJÀÑJÔJÐJÐJÕJÔJÀÑJÔJÐJÐJÑJÐJÐJÐJÐJÐJÑJÐJÐJ×JÒJÐJÑJÔJÐJÕJÔJÐJÐJÑJÔJÐJÑJÐJÐJÐJÐJÐJÑJÐJÕJÕJÔJÐJÑJÔJÑJÔJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJÐJr   c                óP  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}g }d	}| j         }||v }|}|rd
}| j         }	||	v }
|
}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }| 	                    |¦  «         |ržt          j        d|
fd||	f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |	¦  «        dœz  }dd|iz  }| 	                    |¦  «         t          j
        |d¦  «        i z  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}
}	g }d}| j         }||v }|}|rd}| j         }	||	v }
|
}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }| 	                    |¦  «         |ržt          j        d|
fd||	f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |	¦  «        dœz  }dd|iz  }| 	                    |¦  «         t          j
        |d¦  «        i z  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}
}	dS )z]Verifies pop-in bounce: standard 1.6x->1.0x (1.6 - p * 0.6), crit 2.0x->1.2x (2.0 - p * 0.8).z this.scale = isCrit ? 2.0 : 1.6;r   r!   r   r"   r&   r'   Nz1.6z0.6r9   r:   r;   r<   r=   r>   rB   rC   r   rE   rF   z2.0z0.8r‹   rŒ   s                   r   Ú&test_damage_number_pop_in_bounce_scalez;TestCombatFeelEngine.test_damage_number_pop_in_bounce_scales   s  € à1Ð>°T´YÐ>Ð1°YÐ>Ð>Ð>Ð>Õ>Ô>Ð>Ð>Ð>Ð>Ð1°YÐ>Ñ>Ô>Õ>Ô>Ð1Ñ>Ô>Ð>Õ>Ô>Ñ>Ô>Ð>Ð>Õ>Ô>°TÑ>Ô>Ð>Õ>Ô>°TÑ>Ô>Ð>Ð>Õ>Ô>°YÑ>Ô>Ð>Ð>Ñ>Ð>Ð>Ð>Ð>Ð>Ñ>Ð>Õ>Õ>Ô>Ð>Ñ>Ô>Ñ>Ô>Ð>Ð>Ð>Ð>Ð>Ð>Ð>Ø8Ð8ˆuÐ8˜œ	Ð8ˆu˜	Ð!Ð8Ð8Ð8Ð8Ð8 eÐ8¨t¬yÐ8 e¨yÐ&8Ð8Ð8Ð8Ð8Ñ8Õ8Ô8Ð8Ð8Ð8Ð8ˆu˜	Ð8Ñ8Ô8Õ8Ô8ˆuÑ8Ô8Ð8Õ8Ô8Ñ8Ô8Ð8Ð8Õ8Ô8˜Ñ8Ô8Ð8Õ8Ô8˜Ñ8Ô8Ð8Ð8Õ8Ô8˜	Ñ8Ô8Ð8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Ð8×8Ò8Ð8Ñ8Ô8Ð8Ð8Ð8Õ8Ô8Ð8Ð8Ð8Ð8 e¨yÐ8Ñ8Ô8Õ8Ô8 eÑ8Ô8Ð8Õ8Ô8Ñ8Ô8Ð8Ð8Õ8Ô8¨tÑ8Ô8Ð8Õ8Ô8¨tÑ8Ô8Ð8Ð8Õ8Ô8¨yÑ8Ô8Ð8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Ð8×8Ò8Ð8Ñ8Ô8Ð8Õ8Ô8Ð8Ð8Ñ8Ô8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Õ8Õ8Ô8Ð8Ñ8Ô8Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ø8Ð8ˆuÐ8˜œ	Ð8ˆu˜	Ð!Ð8Ð8Ð8Ð8Ð8 eÐ8¨t¬yÐ8 e¨yÐ&8Ð8Ð8Ð8Ð8Ñ8Õ8Ô8Ð8Ð8Ð8Ð8ˆu˜	Ð8Ñ8Ô8Õ8Ô8ˆuÑ8Ô8Ð8Õ8Ô8Ñ8Ô8Ð8Ð8Õ8Ô8˜Ñ8Ô8Ð8Õ8Ô8˜Ñ8Ô8Ð8Ð8Õ8Ô8˜	Ñ8Ô8Ð8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Ð8×8Ò8Ð8Ñ8Ô8Ð8Ð8Ð8Õ8Ô8Ð8Ð8Ð8Ð8 e¨yÐ8Ñ8Ô8Õ8Ô8 eÑ8Ô8Ð8Õ8Ô8Ñ8Ô8Ð8Ð8Õ8Ô8¨tÑ8Ô8Ð8Õ8Ô8¨tÑ8Ô8Ð8Ð8Õ8Ô8¨yÑ8Ô8Ð8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Ð8×8Ò8Ð8Ñ8Ô8Ð8Õ8Ô8Ð8Ð8Ñ8Ô8Ð8Ñ8Ð8Ð8Ð8Ð8Ð8Ñ8Ð8Õ8Õ8Ô8Ð8Ñ8Ô8Ñ8Ô8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8Ð8r   c                ó€  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )zGVerifies pre-allocated 64-slot Ring Buffer without dynamic allocations.zMAX_DAMAGE_NUMBERS = 64r   r!   r   r"   r&   r'   Nz;this.damagePool = Array.from({ length: MAX_DAMAGE_NUMBERS }z8this.poolHead = (this.poolHead + 1) % MAX_DAMAGE_NUMBERSr(   r1   s         r   Ú%test_static_ring_buffer_pool_capacityz:TestCombatFeelEngine.test_static_ring_buffer_pool_capacityy   s¯  € à(Ð5¨D¬IÐ5Ð(¨IÐ5Ð5Ð5Ð5Õ5Ô5Ð5Ð5Ð5Ð5Ð(¨IÐ5Ñ5Ô5Õ5Ô5Ð(Ñ5Ô5Ð5Õ5Ô5Ñ5Ô5Ð5Ð5Õ5Ô5¨DÑ5Ô5Ð5Õ5Ô5¨DÑ5Ô5Ð5Ð5Õ5Ô5¨IÑ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Ð5ØLÐYÐPTÔPYÐYÐLÐPYÐYÐYÐYÐYÕYÔYÐYÐYÐYÐYÐLÐPYÐYÑYÔYÕYÔYÐLÑYÔYÐYÕYÔYÑYÔYÐYÐYÕYÔYÐPTÑYÔYÐYÕYÔYÐPTÑYÔYÐYÐYÕYÔYÐPYÑYÔYÐYÐYÑYÐYÐYÐYÐYÐYÑYÐYÕYÕYÔYÐYÑYÔYÑYÔYÐYÐYÐYÐYÐYÐYÐYØIÐVÈTÌYÐVÐIÈYÐVÐVÐVÐVÕVÔVÐVÐVÐVÐVÐIÈYÐVÑVÔVÕVÔVÐIÑVÔVÐVÕVÔVÑVÔVÐVÐVÕVÔVÈTÑVÔVÐVÕVÔVÈTÑVÔVÐVÐVÕVÔVÈYÑVÔVÐVÐVÑVÐVÐVÐVÐVÐVÑVÐVÕVÕVÔVÐVÑVÔVÑVÔVÐVÐVÐVÐVÐVÐVÐVÐVÐVr   Nrr   )rs   rt   ru   rv   rw   rx   r   r   r�   rƒ   r…   r‡   r�   r�   r‘   ry   r   r   r{   r{   L   s  € € € € € ØkÐkà€V„^˜DÐ!Ñ!Ô!ðWð Wð Wñ "Ô!ðWð7ð 7ð 7ð 7ðDð Dð Dð Dð2ð 2ð 2ð 2ð
Jð Jð Jð Jð
Hð Hð Hð HðKð Kð Kð Kð9ð 9ð 9ð 9ðWð Wð Wð Wð Wð Wr   r{   c                  óh   — 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S )ÚTestWeaponSwingCatalogz8Verifies 4 weapon archetypes in weapon_swing_catalog.js.Tr   r   r   c                óL   — t           dz                       d¬¦  «        | _        d S )Núweapon_swing_catalog.jsr   r   )ÚDATA_DIRr   r   r   s    r   r   z!TestWeaponSwingCatalog.setup_codeƒ   s$   € åÐ 9Ñ9×DÒDÈgÐDÑVÔVˆŒ	ˆ	ˆ	r   c                óÜ  — dD ]è}| j         }||v }|sÕt          j        d|fd||f¦  «        dt          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        nddt          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚d	x}}Œéd	S )
zAVerifies SLASH, THRUST, SLAM, and BOLT archetypes are configured.)zSLASH:zTHRUST:zSLAM:zBOLT:r   r_   Úarchr   ra   re   rf   N)	r   r)   r*   r,   r-   r.   r+   r/   r0   )r   r˜   rg   rK   rh   ri   s         r   Ú%test_all_four_weapon_archetypes_existz<TestWeaponSwingCatalog.test_all_four_weapon_archetypes_exist‡   s  € à;ð 	%ð 	%ˆDØœ9Ð$�4˜9Ð$Ð$Ð$Ð$Õ$Ô$Ð$Ð$Ð$Ð$�4˜9Ð$Ñ$Ô$Ð$Õ$Ô$Ñ$Ô$Ð$Ð$Õ$Ô$�4Ñ$Ô$Ð$Õ$Ô$�4Ñ$Ô$Ð$Ð$Ð$Õ$Ô$Ñ$Ô$Ð$Ð$Õ$Ô$˜4Ñ$Ô$Ð$Õ$Ô$˜4Ñ$Ô$Ð$Ð$Õ$Ô$˜9Ñ$Ô$Ð$Ð$Ñ$Ð$Ð$Ð$Ð$Ð$Ñ$Ð$Õ$Õ$Ô$Ð$Ñ$Ô$Ñ$Ô$Ð$Ð$Ð$Ð$Ð$Ð$ð	%ð 	%r   c                óþ  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )z@Verifies style arc, cone, radial, and beam for the 4 archetypes.zstyle: 'arc'r   r!   r   r"   r&   r'   Nzstyle: 'cone'zstyle: 'radial'zstyle: 'beam'r(   r1   s         r   Útest_archetype_stylesz,TestWeaponSwingCatalog.test_archetype_stylesŒ   s  € àÐ* ¤Ð*ˆ~ Ð*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*ˆ~ Ð*Ñ*Ô*Õ*Ô*ˆ~Ñ*Ô*Ð*Õ*Ô*Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*ØÐ+ $¤)Ð+ˆ )Ð+Ð+Ð+Ð+Õ+Ô+Ð+Ð+Ð+Ð+ˆ )Ð+Ñ+Ô+Õ+Ô+ˆÑ+Ô+Ð+Õ+Ô+Ñ+Ô+Ð+Ð+Õ+Ô+ $Ñ+Ô+Ð+Õ+Ô+ $Ñ+Ô+Ð+Ð+Õ+Ô+ )Ñ+Ô+Ð+Ð+Ñ+Ð+Ð+Ð+Ð+Ð+Ñ+Ð+Õ+Õ+Ô+Ð+Ñ+Ô+Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+Ø Ð- D¤IÐ-Ð  IÐ-Ð-Ð-Ð-Õ-Ô-Ð-Ð-Ð-Ð-Ð  IÐ-Ñ-Ô-Õ-Ô-Ð Ñ-Ô-Ð-Õ-Ô-Ñ-Ô-Ð-Ð-Õ-Ô- DÑ-Ô-Ð-Õ-Ô- DÑ-Ô-Ð-Ð-Õ-Ô- IÑ-Ô-Ð-Ð-Ñ-Ð-Ð-Ð-Ð-Ð-Ñ-Ð-Õ-Õ-Ô-Ð-Ñ-Ô-Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-Ð-ØÐ+ $¤)Ð+ˆ )Ð+Ð+Ð+Ð+Õ+Ô+Ð+Ð+Ð+Ð+ˆ )Ð+Ñ+Ô+Õ+Ô+ˆÑ+Ô+Ð+Õ+Ô+Ñ+Ô+Ð+Ð+Õ+Ô+ $Ñ+Ô+Ð+Õ+Ô+ $Ñ+Ô+Ð+Ð+Õ+Ô+ )Ñ+Ô+Ð+Ð+Ñ+Ð+Ð+Ð+Ð+Ð+Ñ+Ð+Õ+Õ+Ô+Ð+Ñ+Ô+Ñ+Ô+Ð+Ð+Ð+Ð+Ð+Ð+Ð+Ð+Ð+r   c                ó8
  — g }d}| j         }||v }|}|rd}| j         }||v }|}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }	dd|	iz  }
|                     |
¦  «         |ržt          j        d|fd	||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        d
œz  }dd|iz  }|                     |¦  «         t          j        |d¦  «        i z  }dd|iz  }t          t          j
        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}}g }d}| j         }||v }|}|rd}| j         }||v }|}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }	dd|	iz  }
|                     |
¦  «         |ržt          j        d|fd	||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        d
œz  }dd|iz  }|                     |¦  «         t          j        |d¦  «        i z  }dd|iz  }t          t          j
        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}}g }d}| j         }||v }|}|rd}| j         }||v }|}|�s~t          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }	dd|	iz  }
|                     |
¦  «         |ržt          j        d|fd	||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        d
œz  }dd|iz  }|                     |¦  «         t          j        |d¦  «        i z  }dd|iz  }t          t          j
        |¦  «        ¦  «        ‚dx}x}x}x}x}x}x}}dS )z:Verifies hitStopFrames and hitStopDuration for archetypes.zhitStopFrames: 3zhitStopDuration: 0.05r   r9   r   r:   r;   r<   r=   r>   rB   rC   r   rE   rF   NzhitStopFrames: 2zhitStopDuration: 0.035zhitStopFrames: 4zhitStopDuration: 0.066rG   )r   rK   r4   rL   r3   r2   rM   rN   rO   r6   rP   rQ   rR   rS   rT   s                  r   Útest_archetype_hit_stop_timingsz6TestWeaponSwingCatalog.test_archetype_hit_stop_timings“   sh  € àWÐWÐ!ÐW T¤YÐWÐ! YÐ.ÐWÐWÐWÐWÐWÐ3JÐWÈdÌiÐWÐ3JÈiÐ3WÐWÐWÐWÐWÑWÕWÔWÐWÐWÐWÐWÐ! YÐWÑWÔWÕWÔWÐ!ÑWÔWÐWÕWÔWÑWÔWÐWÐWÕWÔW TÑWÔWÐWÕWÔW TÑWÔWÐWÐWÕWÔW YÑWÔWÐWÐWÑWÐWÐWÐWÐWÐWÑWÐWÐW×WÒWÐWÑWÔWÐWÐWÐWÕWÔWÐWÐWÐWÐWÐ3JÈiÐWÑWÔWÕWÔWÐ3JÑWÔWÐWÕWÔWÑWÔWÐWÐWÕWÔWÈdÑWÔWÐWÕWÔWÈdÑWÔWÐWÐWÕWÔWÈiÑWÔWÐWÐWÑWÐWÐWÐWÐWÐWÑWÐWÐW×WÒWÐWÑWÔWÐWÕWÔWÐWÐWÑWÔWÐWÑWÐWÐWÐWÐWÐWÑWÐWÕWÕWÔWÐWÑWÔWÑWÔWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWÐWØXÐXÐ!ÐX T¤YÐXÐ! YÐ.ÐXÐXÐXÐXÐXÐ3KÐXÈtÌyÐXÐ3KÈyÐ3XÐXÐXÐXÐXÑXÕXÔXÐXÐXÐXÐXÐ! YÐXÑXÔXÕXÔXÐ!ÑXÔXÐXÕXÔXÑXÔXÐXÐXÕXÔX TÑXÔXÐXÕXÔX TÑXÔXÐXÐXÕXÔX YÑXÔXÐXÐXÑXÐXÐXÐXÐXÐXÑXÐXÐX×XÒXÐXÑXÔXÐXÐXÐXÕXÔXÐXÐXÐXÐXÐ3KÈyÐXÑXÔXÕXÔXÐ3KÑXÔXÐXÕXÔXÑXÔXÐXÐXÕXÔXÈtÑXÔXÐXÕXÔXÈtÑXÔXÐXÐXÕXÔXÈyÑXÔXÐXÐXÑXÐXÐXÐXÐXÐXÑXÐXÐX×XÒXÐXÑXÔXÐXÕXÔXÐXÐXÑXÔXÐXÑXÐXÐXÐXÐXÐXÑXÐXÕXÕXÔXÐXÑXÔXÑXÔXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXØXÐXÐ!ÐX T¤YÐXÐ! YÐ.ÐXÐXÐXÐXÐXÐ3KÐXÈtÌyÐXÐ3KÈyÐ3XÐXÐXÐXÐXÑXÕXÔXÐXÐXÐXÐXÐ! YÐXÑXÔXÕXÔXÐ!ÑXÔXÐXÕXÔXÑXÔXÐXÐXÕXÔX TÑXÔXÐXÕXÔX TÑXÔXÐXÐXÕXÔX YÑXÔXÐXÐXÑXÐXÐXÐXÐXÐXÑXÐXÐX×XÒXÐXÑXÔXÐXÐXÐXÕXÔXÐXÐXÐXÐXÐ3KÈyÐXÑXÔXÕXÔXÐ3KÑXÔXÐXÕXÔXÑXÔXÐXÐXÕXÔXÈtÑXÔXÐXÕXÔXÈtÑXÔXÐXÐXÕXÔXÈyÑXÔXÐXÐXÑXÐXÐXÐXÐXÐXÑXÐXÐX×XÒXÐXÑXÔXÐXÕXÔXÐXÐXÑXÔXÐXÑXÐXÐXÐXÐXÐXÑXÐXÕXÕXÔXÐXÑXÔXÑXÔXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXÐXr   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
zUVerifies getWeaponSwingArchetype provides case-insensitive lookup and SLASH fallback.z'export function getWeaponSwingArchetyper   r!   r   r"   r&   r'   NzWEAPON_SWING_ARCHETYPES.SLASHr(   r1   s         r   Ú&test_get_archetype_lookup_and_fallbackz=TestWeaponSwingCatalog.test_get_archetype_lookup_and_fallback™   sÈ  € à8ÐE¸D¼IÐEÐ8¸IÐEÐEÐEÐEÕEÔEÐEÐEÐEÐEÐ8¸IÐEÑEÔEÕEÔEÐ8ÑEÔEÐEÕEÔEÑEÔEÐEÐEÕEÔE¸DÑEÔEÐEÕEÔE¸DÑEÔEÐEÐEÕEÔE¸IÑEÔEÐEÐEÑEÐEÐEÐEÐEÐEÑEÐEÕEÕEÔEÐEÑEÔEÑEÔEÐEÐEÐEÐEÐEÐEÐEØ.Ð;°$´)Ð;Ð.°)Ð;Ð;Ð;Ð;Õ;Ô;Ð;Ð;Ð;Ð;Ð.°)Ð;Ñ;Ô;Õ;Ô;Ð.Ñ;Ô;Ð;Õ;Ô;Ñ;Ô;Ð;Ð;Õ;Ô;°$Ñ;Ô;Ð;Õ;Ô;°$Ñ;Ô;Ð;Ð;Õ;Ô;°)Ñ;Ô;Ð;Ð;Ñ;Ð;Ð;Ð;Ð;Ð;Ñ;Ð;Õ;Õ;Ô;Ð;Ñ;Ô;Ñ;Ô;Ð;Ð;Ð;Ð;Ð;Ð;Ð;Ð;Ð;r   Nrr   )rs   rt   ru   rv   rw   rx   r   r™   r›   r�   rŸ   ry   r   r   r“   r“   €   s    € € € € € ØBÐBà€V„^˜DÐ!Ñ!Ô!ðWð Wð Wñ "Ô!ðWð%ð %ð %ð %ð
,ð ,ð ,ð ,ðYð Yð Yð Yð<ð <ð <ð <ð <ð <r   r“   c                  óh   — 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S )Ú*TestCombatSkillsAnimationCancellingAndFeelzHVerifies animation cancelling and visceral triggers in combat_skills.js.Tr   r   r   c                óL   — t           dz                       d¬¦  «        | _        d S )Núcombat_skills.jsr   r   r   r   s    r   r   z5TestCombatSkillsAnimationCancellingAndFeel.setup_code¢   s$   € åÐ"4Ñ4×?Ò?ÈÐ?ÑQÔQˆŒ	ˆ	ˆ	r   c                ó€  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )zEVerifies doDodge immediately cancels attack wind-up and action locks.zplayer.attackTimer = 0;r   r!   r   r"   r&   r'   Nrn   zplayer.animState = 'dodge';r(   r1   s         r   Ú!test_dodge_cancels_attack_wind_upzLTestCombatSkillsAnimationCancellingAndFeel.test_dodge_cancels_attack_wind_up¦   s¥  € à(Ð5¨D¬IÐ5Ð(¨IÐ5Ð5Ð5Ð5Õ5Ô5Ð5Ð5Ð5Ð5Ð(¨IÐ5Ñ5Ô5Õ5Ô5Ð(Ñ5Ô5Ð5Õ5Ô5Ñ5Ô5Ð5Ð5Õ5Ô5¨DÑ5Ô5Ð5Õ5Ô5¨DÑ5Ô5Ð5Ð5Õ5Ô5¨IÑ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Ð5ØÐ* ¤Ð*ˆ~ Ð*Ð*Ð*Ð*Õ*Ô*Ð*Ð*Ð*Ð*ˆ~ Ð*Ñ*Ô*Õ*Ô*ˆ~Ñ*Ô*Ð*Õ*Ô*Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Õ*Ô* Ñ*Ô*Ð*Ð*Ñ*Ð*Ð*Ð*Ð*Ð*Ñ*Ð*Õ*Õ*Ô*Ð*Ñ*Ô*Ñ*Ô*Ð*Ð*Ð*Ð*Ð*Ð*Ð*Ø,Ð9°´	Ð9Ð,°	Ð9Ð9Ð9Ð9Õ9Ô9Ð9Ð9Ð9Ð9Ð,°	Ð9Ñ9Ô9Õ9Ô9Ð,Ñ9Ô9Ð9Õ9Ô9Ñ9Ô9Ð9Ð9Õ9Ô9°Ñ9Ô9Ð9Õ9Ô9°Ñ9Ô9Ð9Ð9Õ9Ô9°	Ñ9Ô9Ð9Ð9Ñ9Ð9Ð9Ð9Ð9Ð9Ñ9Ð9Õ9Õ9Ô9Ð9Ñ9Ô9Ñ9Ô9Ð9Ð9Ð9Ð9Ð9Ð9Ð9Ð9Ð9r   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
z7Verifies dodge charges decrement properly when dodging.zdodgeCharges--;r   r!   r   r"   r&   r'   Nz#window.dodgeCharges = dodgeCharges;r(   r1   s         r   Ú#test_dodge_charges_budget_decrementzNTestCombatSkillsAnimationCancellingAndFeel.test_dodge_charges_budget_decrement¬   sÈ  € à Ð- D¤IÐ-Ð  IÐ-Ð-Ð-Ð-Õ-Ô-Ð-Ð-Ð-Ð-Ð  IÐ-Ñ-Ô-Õ-Ô-Ð Ñ-Ô-Ð-Õ-Ô-Ñ-Ô-Ð-Ð-Õ-Ô- DÑ-Ô-Ð-Õ-Ô- DÑ-Ô-Ð-Ð-Õ-Ô- IÑ-Ô-Ð-Ð-Ñ-Ð-Ð-Ð-Ð-Ð-Ñ-Ð-Õ-Õ-Ô-Ð-Ñ-Ô-Ñ-Ô-Ð-Ð-Ð-Ð-Ð-Ð-Ð-Ø4ÐA¸¼	ÐAÐ4¸	ÐAÐAÐAÐAÕAÔAÐAÐAÐAÐAÐ4¸	ÐAÑAÔAÕAÔAÐ4ÑAÔAÐAÕAÔAÑAÔAÐAÐAÕAÔA¸ÑAÔAÐAÕAÔA¸ÑAÔAÐAÐAÕAÔA¸	ÑAÔAÐAÐAÑAÐAÐAÐAÐAÐAÑAÐAÕAÕAÔAÐAÑAÔAÑAÔAÐAÐAÐAÐAÐAÐAÐAÐAÐAr   c                óþ  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d
}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )zPVerifies primary attack and skills trigger SLASH, BOLT, THRUST, SLAM archetypes.ztriggerSwing('SLASH'r   r!   r   r"   r&   r'   NztriggerSwing('BOLT'ztriggerSwing('THRUST'ztriggerSwing('SLAM'r(   r1   s         r   Ú/test_skills_trigger_respective_swing_archetypeszZTestCombatSkillsAnimationCancellingAndFeel.test_skills_trigger_respective_swing_archetypes±   sˆ  € à%Ð2¨¬Ð2Ð%¨Ð2Ð2Ð2Ð2Õ2Ô2Ð2Ð2Ð2Ð2Ð%¨Ð2Ñ2Ô2Õ2Ô2Ð%Ñ2Ô2Ð2Õ2Ô2Ñ2Ô2Ð2Ð2Õ2Ô2¨Ñ2Ô2Ð2Õ2Ô2¨Ñ2Ô2Ð2Ð2Õ2Ô2¨Ñ2Ô2Ð2Ð2Ñ2Ð2Ð2Ð2Ð2Ð2Ñ2Ð2Õ2Õ2Ô2Ð2Ñ2Ô2Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Ð2Ð2Ø$Ð1¨¬	Ð1Ð$¨	Ð1Ð1Ð1Ð1Õ1Ô1Ð1Ð1Ð1Ð1Ð$¨	Ð1Ñ1Ô1Õ1Ô1Ð$Ñ1Ô1Ð1Õ1Ô1Ñ1Ô1Ð1Ð1Õ1Ô1¨Ñ1Ô1Ð1Õ1Ô1¨Ñ1Ô1Ð1Ð1Õ1Ô1¨	Ñ1Ô1Ð1Ð1Ñ1Ð1Ð1Ð1Ð1Ð1Ñ1Ð1Õ1Õ1Ô1Ð1Ñ1Ô1Ñ1Ô1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ø&Ð3¨$¬)Ð3Ð&¨)Ð3Ð3Ð3Ð3Õ3Ô3Ð3Ð3Ð3Ð3Ð&¨)Ð3Ñ3Ô3Õ3Ô3Ð&Ñ3Ô3Ð3Õ3Ô3Ñ3Ô3Ð3Ð3Õ3Ô3¨$Ñ3Ô3Ð3Õ3Ô3¨$Ñ3Ô3Ð3Ð3Õ3Ô3¨)Ñ3Ô3Ð3Ð3Ñ3Ð3Ð3Ð3Ð3Ð3Ñ3Ð3Õ3Õ3Ô3Ð3Ñ3Ô3Ñ3Ô3Ð3Ð3Ð3Ð3Ð3Ð3Ð3Ø$Ð1¨¬	Ð1Ð$¨	Ð1Ð1Ð1Ð1Õ1Ô1Ð1Ð1Ð1Ð1Ð$¨	Ð1Ñ1Ô1Õ1Ô1Ð$Ñ1Ô1Ð1Õ1Ô1Ñ1Ô1Ð1Ð1Õ1Ô1¨Ñ1Ô1Ð1Õ1Ô1¨Ñ1Ô1Ð1Ð1Õ1Ô1¨	Ñ1Ô1Ð1Ð1Ñ1Ð1Ð1Ð1Ð1Ð1Ñ1Ð1Õ1Õ1Ô1Ð1Ñ1Ô1Ñ1Ô1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1Ð1r   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
z=Verifies hitMonster triggers micro hit-stop freeze on impact.ÚtriggerHitStopr   r!   r   r"   r&   r'   Nzplayer.anim.hitStopTimerr(   r1   s         r   Ú"test_hit_monster_triggers_hit_stopzMTestCombatSkillsAnimationCancellingAndFeel.test_hit_monster_triggers_hit_stop¸   sÈ  € àÐ, 4¤9Ð,Ð 9Ð,Ð,Ð,Ð,Õ,Ô,Ð,Ð,Ð,Ð,Ð 9Ð,Ñ,Ô,Õ,Ô,ÐÑ,Ô,Ð,Õ,Ô,Ñ,Ô,Ð,Ð,Õ,Ô, 4Ñ,Ô,Ð,Õ,Ô, 4Ñ,Ô,Ð,Ð,Õ,Ô, 9Ñ,Ô,Ð,Ð,Ñ,Ð,Ð,Ð,Ð,Ð,Ñ,Ð,Õ,Õ,Ô,Ð,Ñ,Ô,Ñ,Ô,Ð,Ð,Ð,Ð,Ð,Ð,Ð,Ø)Ð6¨T¬YÐ6Ð)¨YÐ6Ð6Ð6Ð6Õ6Ô6Ð6Ð6Ð6Ð6Ð)¨YÐ6Ñ6Ô6Õ6Ô6Ð)Ñ6Ô6Ð6Õ6Ô6Ñ6Ô6Ð6Ð6Õ6Ô6¨TÑ6Ô6Ð6Õ6Ô6¨TÑ6Ô6Ð6Ð6Õ6Ô6¨YÑ6Ô6Ð6Ð6Ñ6Ð6Ð6Ð6Ð6Ð6Ñ6Ð6Õ6Õ6Ô6Ð6Ñ6Ô6Ñ6Ô6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ð6Ð6r   Nrr   )rs   rt   ru   rv   rw   rx   r   r¥   r§   r©   r¬   ry   r   r   r¡   r¡   Ÿ   s    € € € € € ØRÐRà€V„^˜DÐ!Ñ!Ô!ðRð Rð Rñ "Ô!ðRð:ð :ð :ð :ðBð Bð Bð Bð
2ð 2ð 2ð 2ð7ð 7ð 7ð 7ð 7ð 7r   r¡   c                  ó`   — e Zd ZdZ ej        d¬¦  «        dd„¦   «         Zdd„Zdd„Zdd	„Z	d
S )ÚTestCanvasRendererWiringz0Verifies game loop wiring in canvas_renderer.js.Tr   r   r   c                óL   — t           dz                       d¬¦  «        | _        d S )Núcanvas_renderer.jsr   r   r   r   s    r   r   z#TestCanvasRendererWiring.setup_codeÁ   s$   € åÐ"6Ñ6×AÒAÈ7ÐAÑSÔSˆŒ	ˆ	ˆ	r   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
zXVerifies canvas_renderer invokes combatFeelEngine.update and weaponSwingRenderer.update.z"window.combatFeelEngine.update(dt)r   r!   r   r"   r&   r'   Nz%window.weaponSwingRenderer.update(dt)r(   r1   s         r   Ú*test_combat_feel_and_swing_updates_in_loopzCTestCanvasRendererWiring.test_combat_feel_and_swing_updates_in_loopÅ   sÈ  € à3Ð@°t´yÐ@Ð3°yÐ@Ð@Ð@Ð@Õ@Ô@Ð@Ð@Ð@Ð@Ð3°yÐ@Ñ@Ô@Õ@Ô@Ð3Ñ@Ô@Ð@Õ@Ô@Ñ@Ô@Ð@Ð@Õ@Ô@°tÑ@Ô@Ð@Õ@Ô@°tÑ@Ô@Ð@Ð@Õ@Ô@°yÑ@Ô@Ð@Ð@Ñ@Ð@Ð@Ð@Ð@Ð@Ñ@Ð@Õ@Õ@Ô@Ð@Ñ@Ô@Ñ@Ô@Ð@Ð@Ð@Ð@Ð@Ð@Ð@Ø6ÐC¸$¼)ÐCÐ6¸)ÐCÐCÐCÐCÕCÔCÐCÐCÐCÐCÐ6¸)ÐCÑCÔCÕCÔCÐ6Ñ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ÐCÑCÐCÕCÕCÔCÐCÑCÔCÑCÔCÐCÐCÐCÐCÐCÐCÐCÐCÐCr   c                ó  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}dS )
zBVerifies canvas_renderer renders weapon swings and damage numbers.z.window.weaponSwingRenderer.render(ctx, player)r   r!   r   r"   r&   r'   Nz0window.combatFeelEngine.renderDamageNumbers(ctx)r(   r1   s         r   Ú-test_weapon_swing_and_damage_numbers_renderedzFTestCanvasRendererWiring.test_weapon_swing_and_damage_numbers_renderedÊ   sÈ  € à?ÐLÀ4Ä9ÐLÐ?À9ÐLÐLÐLÐLÕLÔLÐLÐLÐLÐLÐ?À9ÐLÑLÔLÕLÔLÐ?ÑLÔLÐLÕLÔLÑLÔLÐLÐLÕLÔLÀ4ÑLÔLÐLÕLÔLÀ4ÑLÔLÐLÐLÕLÔLÀ9ÑLÔLÐLÐLÑLÐLÐLÐLÐLÐLÑLÐLÕLÕLÔLÐLÑLÔLÑLÔLÐLÐLÐLÐLÐLÐLÐLØAÐNÀTÄYÐNÐAÀYÐNÐNÐNÐNÕNÔNÐNÐNÐNÐNÐAÀYÐNÑNÔNÕNÔNÐAÑNÔNÐNÕNÔNÑNÔNÐNÐNÕNÔNÀTÑNÔNÐNÕNÔNÀTÑNÔNÐNÐNÕNÔNÀYÑNÔNÐNÐNÑNÐNÐNÐNÐNÐNÑNÐNÕNÕNÔNÐNÑNÔNÑNÔNÐNÐNÐNÐNÐNÐNÐNÐNÐNr   c                ó^  — d}| j         }||v }|sªt          j        d|fd||f¦  «        t          j        |¦  «        dt	          j        ¦   «         v st          j        | ¦  «        rt          j        | ¦  «        ndt          j        |¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}d	}d
|› d�}t          j
        ddd|gt          t          ¦  «        dd¬¦  «        }|j        }	d}|	|k    }
|
sÇt          j        d|
fd|	|f¦  «        dt	          j        ¦   «         v st          j        |¦  «        rt          j        |¦  «        ndt          j        |	¦  «        t          j        |¦  «        dœz  }t          j        d|j        › �¦  «        dz   d|iz  }t          t          j        |¦  «        ¦  «        ‚dx}	x}
}t!          j        |j                             ¦   «         ¦  «        }|d         }d}
||
u }|slt          j        d|fd||
f¦  «        t          j        |¦  «        t          j        |
¦  «        dœz  }dd|iz  }t          t          j        |¦  «        ¦  «        ‚dx}x}}
|d         }	t(          t*          f}
t-          |	|
¦  «        }|s¨dd t	          j        ¦   «         v st          j        t,          ¦  «        rt          j        t,          ¦  «        nd t          j        |	¦  «        t          j        |
¦  «        t          j        |¦  «        d!œz  }t          t          j        |¦  «        ¦  «        ‚dx}	x}
}|d"         }	t(          t*          f}
t-          |	|
¦  «        }|s¨dd t	          j        ¦   «         v st          j        t,          ¦  «        rt          j        t,          ¦  «        nd t          j        |	¦  «        t          j        |
¦  «        t          j        |¦  «        d!œz  }t          t          j        |¦  «        ¦  «        ‚dx}	x}
}dS )#zTVerifies camera shake applies combat feel shake offset and executes runtime methods.zcombatFeelEngine.getShakeOffsetr   r!   r   r"   r&   r'   Naõ  
        const { CombatFeelEngine } = await import('./client/webapp/js/engine/combat_feel_engine.js');
        const cfe = new CombatFeelEngine();
        cfe.triggerScreenShake(5.0, 0.25, 0.785);
        cfe.update(0.016);
        const offset = cfe.getShakeOffset();
        console.log(JSON.stringify({
            hasMethod: typeof cfe.getShakeOffset === 'function',
            offset: offset,
            x: offset ? offset.x : null,
            y: offset ? offset.y : null
        }));
        zb
        globalThis.window = globalThis;
        (async () => {
            try {
                z†
            } catch (err) {
                console.error(err);
                process.exit(1);
            }
        })();
        Únodez--input-type=modulez-eT)ÚcwdÚcapture_outputÚtextr   )ú==)z2%(py2)s
{%(py2)s = %(py0)s.returncode
} == %(py5)sÚres)rb   rc   r%   zNode execution failed:
z
>assert %(py7)sÚ	hasMethod)Úis)z%(py1)s is %(py4)s)r#   rd   re   rf   Úxz5assert %(py6)s
{%(py6)s = %(py0)s(%(py2)s, %(py4)s)
}Ú
isinstance)rb   rc   rd   rf   Úy)r   r)   r*   r+   r,   r-   r.   r/   r0   Ú
subprocessrY   ÚstrÚPROJECT_ROOTÚ
returncodeÚ_format_assertmsgÚstderrÚjsonÚloadsÚstdoutÚstripÚintÚfloatr¿   )r   r2   r3   r4   r5   r6   Újs_codeÚrunnerr»   rK   rg   r	   rh   ri   Ú@py_assert5s                  r   Ú)test_camera_shake_uses_combat_feel_offsetzBTestCanvasRendererWiring.test_camera_shake_uses_combat_feel_offsetÏ   s“  € à0Ð=°D´IÐ=Ð0°IÐ=Ð=Ð=Ð=Õ=Ô=Ð=Ð=Ð=Ð=Ð0°IÐ=Ñ=Ô=Õ=Ô=Ð0Ñ=Ô=Ð=Õ=Ô=Ñ=Ô=Ð=Ð=Õ=Ô=°DÑ=Ô=Ð=Õ=Ô=°DÑ=Ô=Ð=Ð=Õ=Ô=°IÑ=Ô=Ð=Ð=Ñ=Ð=Ð=Ð=Ð=Ð=Ñ=Ð=Õ=Õ=Ô=Ð=Ñ=Ô=Ñ=Ô=Ð=Ð=Ð=Ð=Ð=Ð=Ð=ðˆð
ð ð	
ð 
ð 
ˆõ ŒnØÐ*¨D°&Ð9Ý•LÑ!Ô!ØØð	
ñ 
ô 
ˆð Œ~ÐK ÐKˆ~ Ò"ÐKÐKÐKÕKÔKÐKÐKÐKÐKˆ~ ÐKÑKÔKÐKÕKÔKÑKÔKÐKÐKÕKÔKˆsÑKÔKÐKÕKÔKˆsÑKÔKÐKÐKÕKÔKˆ~ÑKÔKÕKÔK ÑKÔKÐKÐKÑKÐKÕKÔKÐ$K¸s¼zÐ$KÐ$KÑKÔKÐKÑKÐKÐKÐKÑKÐKÕKÕKÔKÐKÑKÔKÑKÔKÐKÐKÐKÐKÐKÐKÐKÝŒz˜#œ*×*Ò*Ñ,Ô,Ñ-Ô-ˆØ�KÔ Ð( DÐ(Ð  DÐ(Ð(Ð(Ð(Õ(Ô(Ð(Ð(Ð(Ð(Ð  DÐ(Ñ(Ô(Õ(Ô(Ð Ñ(Ô(Õ(Ô( DÑ(Ô(Ð(Ð(Ñ(Ð(Ð(Ð(Ð(Ð(Ñ(Ð(Õ(Õ(Ô(Ð(Ñ(Ô(Ñ(Ô(Ð(Ð(Ð(Ð(Ð(Ð(Ð(Ø˜sœ)Ð2¥c­5 \Ð2�z˜) \Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Õ2Ô2Ñ2Ô2Ð2Ð2Õ2Ô2�zÑ2Ô2Ð2Õ2Ô2�zÑ2Ô2Ð2Ð2Õ2Ô2˜)Ñ2Ô2Õ2Ô2 \Ñ2Ô2Õ2Ô2Ð2Ñ2Ô2Ð2Ð2Ñ2Ð2Õ2Õ2Ô2Ð2Ñ2Ô2Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Ð2Ð2Ø˜sœ)Ð2¥c­5 \Ð2�z˜) \Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Õ2Ô2Ñ2Ô2Ð2Ð2Õ2Ô2�zÑ2Ô2Ð2Õ2Ô2�zÑ2Ô2Ð2Ð2Õ2Ô2˜)Ñ2Ô2Õ2Ô2 \Ñ2Ô2Õ2Ô2Ð2Ñ2Ô2Ð2Ð2Ñ2Ð2Õ2Õ2Ô2Ð2Ñ2Ô2Ñ2Ô2Ð2Ð2Ð2Ð2Ð2Ð2Ð2Ð2Ð2r   Nrr   )
rs   rt   ru   rv   rw   rx   r   r²   r´   rÐ   ry   r   r   r®   r®   ¾   s�   € € € € € Ø:Ð:à€V„^˜DÐ!Ñ!Ô!ðTð Tð Tñ "Ô!ðTðDð Dð Dð Dð
Oð Oð Oð Oð
%3ð %3ð %3ð %3ð %3ð %3r   r®   c                  ó:   — e Zd ZdZd
d„Zd
d„Zd
d„Zd
d„Zd
d„Zd	S )ÚTestCodeHygieneLineCapszLEnforces strict quantitative line length limits from GEMINI.md & PROJECT.md.r   r   c                óx  — t          t          dz                       d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d
�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )z6animation_engine.js: <= 350 soft cap, <= 500 hard cap.r   r   r   é^  ©ú<=©z%(py0)s <= %(py3)sÚlines©rb   r$   zanimation_engine.js has ú lines (exceeds 350 soft cap)ú
>assert %(py5)sr%   Néô  ú lines (exceeds 500 hard cap)©Úlenr   r   Ú
splitlinesr)   r*   r,   r-   r.   r+   rÅ   r/   r0   ©r   rØ   r4   rK   Ú@py_format4r5   s         r   Útest_animation_engine_line_capsz7TestCodeHygieneLineCaps.test_animation_engine_line_capsú   sô  € å•ZÐ"7Ñ7×BÒBÈGÐBÑTÔT×_Ò_ÑaÔaÑbÔbˆØÐ\ˆu˜Š|Ð\Ð\Ð\Õ\Ô\Ð\Ð\Ð\Ð\ˆu˜Ð\Ñ\Ô\Ð\Õ\Ô\Ñ\Ô\Ð\Ð\Õ\Ô\ˆuÑ\Ô\Ð\Õ\Ô\ˆuÑ\Ô\Ð\Ð\Õ\Ô\˜Ñ\Ô\Ð\Ð\Ñ\Ð\Õ\Ô\Ð\¸Ð\Ð\Ð\Ñ\Ô\Ð\Ñ\Ð\Ð\Ð\Ñ\Ð\Õ\Õ\Ô\Ð\Ñ\Ô\Ñ\Ô\Ð\Ð\Ð\Ð\Ð\ØÐ\ˆu˜Š|Ð\Ð\Ð\Õ\Ô\Ð\Ð\Ð\Ð\ˆu˜Ð\Ñ\Ô\Ð\Õ\Ô\Ñ\Ô\Ð\Ð\Õ\Ô\ˆuÑ\Ô\Ð\Õ\Ô\ˆuÑ\Ô\Ð\Ð\Õ\Ô\˜Ñ\Ô\Ð\Ð\Ñ\Ð\Õ\Ô\Ð\¸Ð\Ð\Ð\Ñ\Ô\Ð\Ñ\Ð\Ð\Ð\Ñ\Ð\Õ\Õ\Ô\Ð\Ñ\Ô\Ñ\Ô\Ð\Ð\Ð\Ð\Ð\Ð\Ð\r   c                óx  — t          t          dz                       d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d
�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )z8combat_feel_engine.js: <= 350 soft cap, <= 500 hard cap.r}   r   r   rÔ   rÕ   r×   rØ   rÙ   zcombat_feel_engine.js has rÚ   rÛ   r%   NrÜ   rÝ   rÞ   rá   s         r   Ú!test_combat_feel_engine_line_capsz9TestCodeHygieneLineCaps.test_combat_feel_engine_line_caps   sô  € å•ZÐ"9Ñ9×DÒDÈgÐDÑVÔV×aÒaÑcÔcÑdÔdˆØÐ^ˆu˜Š|Ð^Ð^Ð^Õ^Ô^Ð^Ð^Ð^Ð^ˆu˜Ð^Ñ^Ô^Ð^Õ^Ô^Ñ^Ô^Ð^Ð^Õ^Ô^ˆuÑ^Ô^Ð^Õ^Ô^ˆuÑ^Ô^Ð^Ð^Õ^Ô^˜Ñ^Ô^Ð^Ð^Ñ^Ð^Õ^Ô^Ð^¸%Ð^Ð^Ð^Ñ^Ô^Ð^Ñ^Ð^Ð^Ð^Ñ^Ð^Õ^Õ^Ô^Ð^Ñ^Ô^Ñ^Ô^Ð^Ð^Ð^Ð^Ð^ØÐ^ˆu˜Š|Ð^Ð^Ð^Õ^Ô^Ð^Ð^Ð^Ð^ˆu˜Ð^Ñ^Ô^Ð^Õ^Ô^Ñ^Ô^Ð^Ð^Õ^Ô^ˆuÑ^Ô^Ð^Õ^Ô^ˆuÑ^Ô^Ð^Ð^Õ^Ô^˜Ñ^Ô^Ð^Ð^Ñ^Ð^Õ^Ô^Ð^¸%Ð^Ð^Ð^Ñ^Ô^Ð^Ñ^Ð^Ð^Ð^Ñ^Ð^Õ^Õ^Ô^Ð^Ñ^Ô^Ñ^Ô^Ð^Ð^Ð^Ð^Ð^Ð^Ð^r   c                óü  — t          t          dz                       d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d
�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )z+combat_skills.js: strictly <= 500 hard cap.r£   r   r   rÜ   rÕ   r×   rØ   rÙ   zcombat_skills.js has rÝ   rÛ   r%   NrÞ   rá   s         r   Útest_combat_skills_line_capsz4TestCodeHygieneLineCaps.test_combat_skills_line_caps  s  € å•ZÐ"4Ñ4×?Ò?ÈÐ?ÑQÔQ×\Ò\Ñ^Ô^Ñ_Ô_ˆØÐYˆu˜Š|ÐYÐYÐYÕYÔYÐYÐYÐYÐYˆu˜ÐYÑYÔYÐYÕYÔYÑYÔYÐYÐYÕYÔYˆuÑYÔYÐYÕYÔYˆuÑYÔYÐYÐYÕYÔY˜ÑYÔYÐYÐYÑYÐYÕYÔYÐY°UÐYÐYÐYÑYÔYÐYÑYÐYÐYÐYÑYÐYÕYÕYÔYÐYÑYÔYÑYÔYÐYÐYÐYÐYÐYÐYÐYr   c                óx  — t          t          dz                       d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d
�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )z5canvas_renderer.js: <= 350 soft cap, <= 500 hard cap.r°   r   r   rÔ   rÕ   r×   rØ   rÙ   zcanvas_renderer.js has rÚ   rÛ   r%   NrÜ   rÝ   rÞ   rá   s         r   Útest_canvas_renderer_line_capsz6TestCodeHygieneLineCaps.test_canvas_renderer_line_caps  sô  € å•ZÐ"6Ñ6×AÒAÈ7ÐAÑSÔS×^Ò^Ñ`Ô`ÑaÔaˆØÐ[ˆu˜Š|Ð[Ð[Ð[Õ[Ô[Ð[Ð[Ð[Ð[ˆu˜Ð[Ñ[Ô[Ð[Õ[Ô[Ñ[Ô[Ð[Ð[Õ[Ô[ˆuÑ[Ô[Ð[Õ[Ô[ˆuÑ[Ô[Ð[Ð[Õ[Ô[˜Ñ[Ô[Ð[Ð[Ñ[Ð[Õ[Ô[Ð[°uÐ[Ð[Ð[Ñ[Ô[Ð[Ñ[Ð[Ð[Ð[Ñ[Ð[Õ[Õ[Ô[Ð[Ñ[Ô[Ñ[Ô[Ð[Ð[Ð[Ð[Ð[ØÐ[ˆu˜Š|Ð[Ð[Ð[Õ[Ô[Ð[Ð[Ð[Ð[ˆu˜Ð[Ñ[Ô[Ð[Õ[Ô[Ñ[Ô[Ð[Ð[Õ[Ô[ˆuÑ[Ô[Ð[Õ[Ô[ˆuÑ[Ô[Ð[Ð[Õ[Ô[˜Ñ[Ô[Ð[Ð[Ñ[Ð[Õ[Ô[Ð[°uÐ[Ð[Ð[Ñ[Ô[Ð[Ñ[Ð[Ð[Ð[Ñ[Ð[Õ[Õ[Ô[Ð[Ñ[Ô[Ñ[Ô[Ð[Ð[Ð[Ð[Ð[Ð[Ð[r   c                óx  — t          t          dz                       d¬¦  «                             ¦   «         ¦  «        }d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d
�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}d}||k    }|s°t	          j        d|fd||f¦  «        dt          j        ¦   «         v st	          j        |¦  «        rt	          j	        |¦  «        ndt	          j	        |¦  «        dœz  }t	          j
        d	|› d�¦  «        dz   d|iz  }t          t	          j        |¦  «        ¦  «        ‚dx}}dS )z;weapon_swing_catalog.js: <= 700 soft cap, <= 1000 hard cap.r•   r   r   i¼  rÕ   r×   rØ   rÙ   zweapon_swing_catalog.js has z lines (exceeds 700 soft cap)rÛ   r%   Niè  z lines (exceeds 1000 hard cap))rß   r–   r   rà   r)   r*   r,   r-   r.   r+   rÅ   r/   r0   rá   s         r   Ú#test_weapon_swing_catalog_line_capsz;TestCodeHygieneLineCaps.test_weapon_swing_catalog_line_caps  sô  € å•XÐ 9Ñ9×DÒDÈgÐDÑVÔV×aÒaÑcÔcÑdÔdˆØÐ`ˆu˜Š|Ð`Ð`Ð`Õ`Ô`Ð`Ð`Ð`Ð`ˆu˜Ð`Ñ`Ô`Ð`Õ`Ô`Ñ`Ô`Ð`Ð`Õ`Ô`ˆuÑ`Ô`Ð`Õ`Ô`ˆuÑ`Ô`Ð`Ð`Õ`Ô`˜Ñ`Ô`Ð`Ð`Ñ`Ð`Õ`Ô`Ð`¸EÐ`Ð`Ð`Ñ`Ô`Ð`Ñ`Ð`Ð`Ð`Ñ`Ð`Õ`Õ`Ô`Ð`Ñ`Ô`Ñ`Ô`Ð`Ð`Ð`Ð`Ð`ØÐbˆu˜Š}ÐbÐbÐbÕbÔbÐbÐbÐbÐbˆu˜ÐbÑbÔbÐbÕbÔbÑbÔbÐbÐbÕbÔbˆuÑbÔbÐbÕbÔbˆuÑbÔbÐbÐbÕbÔb˜ÑbÔbÐbÐbÑbÐbÕbÔbÐb¸UÐbÐbÐbÑbÔbÐbÑbÐbÐbÐbÑbÐbÕbÕbÔbÐbÑbÔbÑbÔbÐbÐbÐbÐbÐbÐbÐbr   Nrr   )	rs   rt   ru   rv   rã   rå   rç   ré   rë   ry   r   r   rÒ   rÒ   ÷   s”   € € € € € ØVÐVð]ð ]ð ]ð ]ð_ð _ð _ð _ðZð Zð Zð Zð
\ð \ð \ð \ðcð cð cð cð cð cr   rÒ   )rv   Ú
__future__r   Úbuiltinsr,   Ú_pytest.assertion.rewriteÚ	assertionÚrewriter)   rÇ   ÚmathÚosÚrerÁ   Úpathlibr   rw   Ú__file__ÚresolveÚparentrÃ   Ú
WEBAPP_DIRr   r–   r   r{   r“   r¡   r®   rÒ   ry   r   r   ú<module>rù      sæ  ðð	ð 	ð #Ð "Ð "Ð "Ð "Ð "Ø  € € € € € € € € € € € € €€€€Ø €€€Ø 	€	€	€	Ø 	€	€	€	Ø Ð Ð Ð Ø Ð Ð Ð Ð Ð Ø €€€àˆt�H‰~Œ~×%Ò%Ñ'Ô'Ô.Ô5Ô<€Ø˜HÑ$ xÑ/€
Ø˜$Ñ Ñ)€
Ø˜Ñ˜vÑ%€ð..ð ..ð ..ð ..ð ..ñ ..ô ..ð ..ðb1Wð 1Wð 1Wð 1Wð 1Wñ 1Wô 1Wð 1Wðh<ð <ð <ð <ð <ñ <ô <ð <ð>7ð 7ð 7ð 7ð 7ñ 7ô 7ð 7ð>63ð 63ð 63ð 63ð 63ñ 63ô 63ð 63ðrcð cð cð cð cñ cô cð cð cð cr   