§
    A¿j*  ã                  óÂ   — d Z ddlmZ ddlZddlmZ ej        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d„Zdd„Zdd„Zdd„Zdd„Zdd„Zdd„ZdS )z¼
Unit Tests for FreeExile Game Design Matrix Service & Integrity Engine.
Verifies cross-cutting queries, DAG cycle detection, foreign key enforcement,
and automated anti-drift validation.
é    )ÚannotationsN)ÚGameDesignMatrixServicec               #  ó†   K  — t          d¬¦  «        } |                      d¬¦  «         | V — |                      ¦   «          dS )zCProvides an in-memory matrix service populated with canonical data.z:memory:)Údb_pathT)ÚforceN)r   Úseed_canonical_dataÚclose)Úservices    ú;C:\Projects\FreeExile\tests\unit\test_game_design_matrix.pyÚmatrix_servicer      sI   è è € õ &¨jÐ9Ñ9Ô9€GØ×Ò dÐÑ+Ô+Ð+Ø
€M€M€MØ‡M‚M�O„O€O€O€Oó    r   r   c                ób  — |                       ¦   «         }|j        du sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j	        dk    sJ ‚|j
        dk    sJ ‚t          |j        ¦  «        dk    sJ ‚d	S )
zKVerifies that all core tables are populated with expected canonical counts.Té   é   é
   é2   é   éd   r   N)Úvalidate_game_design_integrityÚis_validÚ
total_actsÚtotal_zonesÚ
total_npcsÚtotal_questsÚtotal_monstersÚtotal_skillsÚtotal_weaponsÚtotal_affixesÚtotal_relationsÚlenÚ
violations)r   Úreports     r   Útest_canonical_seeding_countsr#      sü   € à×:Ò:Ñ<Ô<€FØŒ?˜dÐ"Ð"Ð"Ð"ØÔ Ò!Ð!Ð!Ð!ØÔ Ò"Ð"Ð"Ð"ØÔ Ò!Ð!Ð!Ð!ØÔ "Ò$Ð$Ð$Ð$ØÔ  BÒ&Ð&Ð&Ð&ØÔ "Ò$Ð$Ð$Ð$ØÔ 2Ò%Ð%Ð%Ð%ØÔ 3Ò&Ð&Ð&Ð&ØÔ! RÒ'Ð'Ð'Ð'ÝˆvÔ Ñ!Ô! QÒ&Ð&Ð&Ð&Ð&Ð&r   c                ó
  — |                       d¦  «        }|€J ‚|d         d         dk    sJ ‚d|d         d         v sJ ‚|d         d         dk    sJ ‚|d         d	         d
k    sJ ‚t          |d         ¦  «        dk    sJ ‚dS )z4Tests fetching complete narrative context of an Act.ÚACT_I_HUNGERNÚactÚact_idu   Ä�Ã¡y Vá»±c Ä�Ã³i RÃ©tÚtitleÚprimary_zone_idÚzone_tang_kiem_nhaiÚclimax_boss_idÚboss_strand_executionerÚquestsr   )Úget_act_narrative_contextr    )r   Úcontexts     r   Ú test_act_narrative_context_queryr0   %   s±   € à×6Ò6°~ÑFÔF€GØÐÐÐØ�5Œ>˜(Ô# ~Ò5Ð5Ð5Ð5Ø# w¨u¤~°gÔ'>Ð>Ð>Ð>Ð>Ø�5Œ>Ð+Ô,Ð0EÒEÐEÐEÐEØ�5Œ>Ð*Ô+Ð/HÒHÐHÐHÐHÝˆw�xÔ Ñ!Ô! AÒ%Ð%Ð%Ð%Ð%Ð%r   c                óÒ   — |                       d¦  «        }|€J ‚|d         d         dk    sJ ‚t          |d         ¦  «        dk    sJ ‚d„ |d         D ¦   «         }d|v sd	|v sJ ‚dS dS )
z?Tests retrieving full zone ecosystem including NPCs and quests.Úzone_boundless_sanctuaryNÚzoneÚzone_idÚnpcsé   c                ó   — h | ]
}|d          ’ŒS )Úrole© )Ú.0Únpcs     r   ú	<setcomp>z,test_zone_ecosystem_query.<locals>.<setcomp>7   s   € Ð0Ð0Ð0˜SˆS�Œ[Ð0Ð0Ð0r   ÚBONE_BLACKSMITHÚBLOOD_SHAMAN)Úget_zone_ecosystemr    )r   ÚecoÚroless      r   Útest_zone_ecosystem_queryrB   0   s•   € à
×
+Ò
+Ð,FÑ
GÔ
G€CØˆ?ˆ?ˆ?ØˆvŒ;�yÔ!Ð%?Ò?Ð?Ð?Ð?Ýˆs�6Œ{ÑÔ˜qÒ Ð Ð Ð à0Ð0 C¨¤KÐ0Ñ0Ô0€EØ Ð%Ð%¨¸5Ð)@Ð)@Ð)@Ð@Ð%Ð%Ð)@Ð)@r   c                ó®   — |                       d¦  «        }|€J ‚|d         dk    sJ ‚|d         dk    sJ ‚|                      d¦  «        }|g d¢k    sJ ‚dS )z?Tests quest ecosystem view and prerequisite chain backtracking.Ú quest_norm_04_diet_u_hon_kiem_noNr'   ÚACT_II_MIASMAÚprerequisite_quest_idÚ!quest_norm_03_luyen_khi_hoa_thach)rG   Ú!quest_norm_02_khai_thong_dan_dienÚ!quest_norm_01_thuc_tinh_tang_kiem)Úget_quest_contextÚget_quest_dependency_chain)r   Úq_ctxÚchains      r   Ú'test_quest_context_and_dependency_chainrN   ;   s•   € à×,Ò,Ð-OÑPÔP€EØÐÐÐØ�Œ?˜oÒ-Ð-Ð-Ð-ØÐ(Ô)Ð-PÒPÐPÐPÐPð ×5Ò5Ð6XÑYÔY€EØð ð ð ò ð ð ð ð ð r   c                ó  — |                       d¦  «        }|€J ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|                       d¦  «        }|€J ‚|j        dk    sJ ‚|j        |j        k    sJ ‚|j        dk    sJ ‚dS )z1Tests mathematical progression milestone lookups.é   Ng      Y@é   éU   )Úget_level_progression_benchmarkÚlevelÚplayer_base_hpÚmax_affix_tier_allowed)r   Úb_lvl1Úb_lvl85s      r   Ú test_level_progression_benchmarkrY   K   s¿   € à×;Ò;¸AÑ>Ô>€FØÐÐÐØŒ<˜1ÒÐÐÐØÔ  EÒ)Ð)Ð)Ð)ØÔ(¨BÒ.Ð.Ð.Ð.à×<Ò<¸RÑ@Ô@€GØÐÐÐØŒ=˜BÒÐÐÐØÔ! FÔ$9Ò9Ð9Ð9Ð9ØÔ)¨QÒ.Ð.Ð.Ð.Ð.Ð.r   c                ó.  — |                       ¦   «         5 }|                     ¦   «         }|                     d¦  «         ddd¦  «         n# 1 swxY w Y   |                      ¦   «         }|j        du sJ ‚t          d„ |j        D ¦   «         ¦  «        sJ ‚dS )zUVerifies that an intentional circular dependency in quests causes validation to FAIL.z²
            UPDATE quests 
            SET prerequisite_quest_id = 'quest_norm_03_luyen_khi_hoa_thach' 
            WHERE quest_id = 'quest_norm_01_thuc_tinh_tang_kiem'
        NFc              3  ó   K  — | ]}d |v V — Œ	dS )z Circular Dependency in Quest DAGNr9   ©r:   Úvs     r   ú	<genexpr>z3test_dag_cycle_detection_failure.<locals>.<genexpr>g   s(   è è € ÐRÐR¸1Ð1°QÐ6ÐRÐRÐRÐRÐRÐRr   ©Ú_get_connectionÚcursorÚexecuter   r   Úanyr!   ©r   ÚconnÚcurr"   s       r   Ú test_dag_cycle_detection_failurerg   Z   sà   € à	×	'Ò	'Ñ	)Ô	)ð ¨TØ�kŠk‰mŒmˆà�Šð ñ 	ô 	ð 	ðð ð ñ ô ð ð ð ð ð ð øøøð ð ð ð ð ×:Ò:Ñ<Ô<€FØŒ?˜eÐ#Ð#Ð#Ð#ÝÐRÐRÀÔ@QÐRÑRÔRÑRÔRÐRÐRÐRÐRÐRs   •*AÁAÁAc                ó‚  — |                       ¦   «         5 }|                     ¦   «         }|                     d¦  «         |                     d¦  «         |                     d¦  «         ddd¦  «         n# 1 swxY w Y   |                      ¦   «         }|j        du sJ ‚t          d„ |j        D ¦   «         ¦  «        sJ ‚dS )zQVerifies that referencing a non-existent prerequisite quest triggers a violation.zPRAGMA foreign_keys = OFFz±
            UPDATE quests 
            SET prerequisite_quest_id = 'quest_non_existent_phantom_ghost' 
            WHERE quest_id = 'quest_norm_01_thuc_tinh_tang_kiem'
        zPRAGMA foreign_keys = ONNFc              3  ó   K  — | ]}d |v V — Œ	dS )zBroken Quest PrerequisiteNr9   r\   s     r   r^   z5test_broken_prerequisite_detection.<locals>.<genexpr>y   s(   è è € ÐKÐK°AÐ*¨aÐ/ÐKÐKÐKÐKÐKÐKr   r_   rd   s       r   Ú"test_broken_prerequisite_detectionrj   j   s  € à	×	'Ò	'Ñ	)Ô	)ð 	0¨TØ�kŠk‰mŒmˆà�ŠÐ/Ñ0Ô0Ð0Ø�Šð ñ 	ô 	ð 	ð
 	�ŠÐ.Ñ/Ô/Ð/ð	0ð 	0ð 	0ñ 	0ô 	0ð 	0ð 	0ð 	0ð 	0ð 	0ð 	0øøøð 	0ð 	0ð 	0ð 	0ð ×:Ò:Ñ<Ô<€FØŒ?˜eÐ#Ð#Ð#Ð#ÝÐKÐK¸Ô9JÐKÑKÔKÑKÔKÐKÐKÐKÐKÐKs   •AA5Á5A9Á<A9c                óŽ   — |                       dd¬¦  «        }t          |¦  «        dk    sJ ‚d„ |D ¦   «         }d|v sJ ‚d|v sJ ‚dS )	z4Tests querying cross-relationships by source entity.ÚACTr%   )Úsource_typeÚ	source_idr6   c                ó   — h | ]
}|d          ’ŒS )Úrelation_typer9   )r:   Úrs     r   r<   z-test_cross_relations_query.<locals>.<setcomp>€   s   € Ð.Ð.Ð. AˆQˆÔÐ.Ð.Ð.r   ÚACT_CONTAINS_ZONEÚBOSS_CLIMAX_FOR_ACTN)Úquery_cross_relationsr    )r   ÚrelsÚtypess      r   Útest_cross_relations_queryrw   |   sh   € à×/Ò/¸EÈ^Ð/Ñ\Ô\€DÝˆt‰9Œ9˜Š>ˆ>ˆ>ˆ>Ø.Ð.¨Ð.Ñ.Ô.€EØ %Ð'Ð'Ð'Ð'Ø  EÐ)Ð)Ð)Ð)Ð)Ð)r   c                óø  — |                       d¦  «        }|€J ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|                       d¦  «        }|€J ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        d	k    sJ ‚|j        d	k    sJ ‚|j        dk    sJ ‚|j        dk    sJ ‚|                       d
¦  «        �J ‚|                      ¦   «         }t          |¦  «        dk    sJ ‚t          t          |¦  «        dz
  ¦  «        D ]e}||dz            j        ||         j        k    sJ ‚||dz            j        ||         j        k    sJ ‚||dz            j        ||         j        k    sJ ‚ŒfdS )zATests party scaling lookup from size 1 to 6 and monotonic growth.rP   Ng      ð?ç        g      .@é   ç      @g     Àb@g     @o@éc   )
Úget_party_scalingÚhp_multiplierÚexp_bonus_pctÚitem_quantity_bonus_pctÚnearby_radiusÚcurrency_quantity_bonus_pctÚrarity_bonus_pctÚget_all_party_scalingsr    Úrange)r   ÚsoloÚ	max_partyÚscalingsÚis        r   Ú2test_party_scaling_matrix_queries_and_monotonicityrŠ   …   sê  € à×+Ò+¨AÑ.Ô.€DØÐÐÐØÔ Ò$Ð$Ð$Ð$ØÔ Ò$Ð$Ð$Ð$ØÔ'¨3Ò.Ð.Ð.Ð.ØÔ Ò%Ð%Ð%Ð%à×0Ò0°Ñ3Ô3€IØÐ Ð Ð ØÔ" cÒ)Ð)Ð)Ð)ØÔ" eÒ+Ð+Ð+Ð+ØÔ,°Ò5Ð5Ð5Ð5ØÔ0°EÒ9Ð9Ð9Ð9ØÔ%¨Ò.Ð.Ð.Ð.ØÔ" dÒ*Ð*Ð*Ð*ð ×+Ò+¨BÑ/Ô/Ð7Ð7Ð7ð ×4Ò4Ñ6Ô6€HÝˆx‰=Œ=˜AÒÐÐÐÝ•3�x‘=”= 1Ñ$Ñ%Ô%ð ]ð ]ˆØ˜˜A™ŒÔ,¨x¸¬{Ô/HÒHÐHÐHÐHØ˜˜A™ŒÔ,¨x¸¬{Ô/HÒHÐHÐHÐHØ˜˜A™ŒÔ6¸À!¼Ô9\Ò\Ð\Ð\Ð\Ð\ð]ð ]r   c                ó¬  — |                       d¦  «        }|€J ‚|j        du sJ ‚|j        dk    sJ ‚|                       d¦  «        }|€J ‚|j        du sJ ‚|j        dk    sJ ‚|                       d¦  «        }|€J ‚|j        du sJ ‚|j        dk    sJ ‚|                       d	¦  «        �J ‚|                      ¦   «         }t	          |¦  «        d
k    sJ ‚dS )zETests querying 3 canonical loot allocation modes and timeout configs.Ú	PERMANENTNTry   ÚSHORTFg      @ÚFREE_FOR_ALLÚNON_EXISTENTé   )Úget_loot_allocation_modeÚis_permanentÚtimeout_secondsÚget_all_loot_allocation_modesr    )r   ÚpermÚ
short_modeÚffaÚ	all_modess        r   Ú"test_loot_allocation_modes_queriesr™   £   s  € à×2Ò2°;Ñ?Ô?€DØÐÐÐØÔ Ð$Ð$Ð$Ð$ØÔ 3Ò&Ð&Ð&Ð&à×8Ò8¸ÑAÔA€JØÐ!Ð!Ð!ØÔ" eÐ+Ð+Ð+Ð+ØÔ%¨Ò,Ð,Ð,Ð,à
×
1Ò
1°.Ñ
AÔ
A€CØˆ?ˆ?ˆ?ØÔ˜uÐ$Ð$Ð$Ð$ØÔ #Ò%Ð%Ð%Ð%à×2Ò2°>ÑBÔBÐJÐJÐJØ×<Ò<Ñ>Ô>€IÝˆy‰>Œ>˜QÒÐÐÐÐÐr   c                ó6  — |                       d¦  «        }|€J ‚|j        dk    sJ ‚|j        dk    sJ ‚|j        du sJ ‚|j        du sJ ‚|                       d¦  «        }|€J ‚|j        dk    sJ ‚|                      ¦   «         }t          |¦  «        dk    sJ ‚dS )z7Tests teleport config queries and safety channel flags.ÚPARTY_MEMBERNr{   g      $@TÚTOWN_PORTALr   )Úget_teleport_configÚcast_time_secondsÚcooldown_secondsÚcancel_on_movementÚcancel_on_damageÚget_all_teleport_configsr    )r   Ú
party_teleÚportal_teleÚall_configss       r   Útest_teleport_configs_queriesr¦   ¹   sÔ   € à×3Ò3°NÑCÔC€JØÐ!Ð!Ð!ØÔ'¨3Ò.Ð.Ð.Ð.ØÔ&¨$Ò.Ð.Ð.Ð.ØÔ(¨DÐ0Ð0Ð0Ð0ØÔ&¨$Ð.Ð.Ð.Ð.à ×4Ò4°]ÑCÔC€KØÐ"Ð"Ð"ØÔ(¨CÒ/Ð/Ð/Ð/à ×9Ò9Ñ;Ô;€KÝˆ{ÑÔ˜qÒ Ð Ð Ð Ð Ð r   c                ó¦  — |                       d¦  «        }|€J ‚|j        du sJ ‚|j        du sJ ‚|j        dk    sJ ‚|                       d¦  «        }|€J ‚|j        du sJ ‚|j        du sJ ‚|j        dk    sJ ‚|                       d¦  «        }|€J ‚|j        du sJ ‚|j        du sJ ‚|                      ¦   «         }t          |¦  «        d	k    sJ ‚dS )
zOTests quarantine rules for wilderness, dungeon, secret chamber, and safe haven.Ú
WILDERNESSNTrz   ÚSECRET_CHAMBERr   Ú
SAFE_HAVENFr   )Úget_portal_quarantine_ruleÚboss_lockoutÚsecret_chamber_lockoutÚmax_portalsÚget_all_portal_quarantine_rulesr    )r   Ú	wild_ruleÚsecret_ruleÚ
haven_ruleÚ	all_ruless        r   Ú$test_portal_quarantine_rules_queriesr´   Ê   s.  € à×9Ò9¸,ÑGÔG€IØÐ Ð Ð ØÔ! TÐ)Ð)Ð)Ð)ØÔ+¨tÐ3Ð3Ð3Ð3ØÔ  AÒ%Ð%Ð%Ð%à ×;Ò;Ð<LÑMÔM€KØÐ"Ð"Ð"ØÔ# tÐ+Ð+Ð+Ð+ØÔ-°Ð5Ð5Ð5Ð5ØÔ" aÒ'Ð'Ð'Ð'à×:Ò:¸<ÑHÔH€JØÐ!Ð!Ð!ØÔ" eÐ+Ð+Ð+Ð+ØÔ,°Ð5Ð5Ð5Ð5à×>Ò>Ñ@Ô@€IÝˆy‰>Œ>˜QÒÐÐÐÐÐr   c                ó*  — |                       ¦   «         5 }|                     ¦   «                              d¦  «         ddd¦  «         n# 1 swxY w Y   |                      ¦   «         }|j        du sJ ‚t          d„ |j        D ¦   «         ¦  «        sJ ‚dS )zJVerifies that non-monotonic party scaling triggers an integrity violation.zHUPDATE party_scaling_matrix SET hp_multiplier = 1.2 WHERE party_size = 3NFc              3  ó   K  — | ]}d |v V — Œ	dS )zParty Scaling HP non-monotonicNr9   r\   s     r   r^   z=test_party_scaling_non_monotonic_detection.<locals>.<genexpr>ç   s(   è è € ÐPÐP¸Ð/°1Ð4ÐPÐPÐPÐPÐPÐPr   r_   ©r   re   r"   s      r   Ú*test_party_scaling_non_monotonic_detectionr¸   á   sã   € à	×	'Ò	'Ñ	)Ô	)ð j¨TØ�Š‰Œ×ÒÐhÑiÔiÐiðjð jð jñ jô jð jð jð jð jð jð jøøøð jð jð jð jà×:Ò:Ñ<Ô<€FØŒ?˜eÐ#Ð#Ð#Ð#ÝÐPÐP¸fÔ>OÐPÑPÔPÑPÔPÐPÐPÐPÐPÐPó   •(A	Á	AÁAc                ó*  — |                       ¦   «         5 }|                     ¦   «                              d¦  «         ddd¦  «         n# 1 swxY w Y   |                      ¦   «         }|j        du sJ ‚t          d„ |j        D ¦   «         ¦  «        sJ ‚dS )zDVerifies that invalid SHORT timeout triggers an integrity violation.zNUPDATE loot_allocation_modes SET timeout_seconds = 2.0 WHERE mode_id = 'SHORT'NFc              3  ó   K  — | ]}d |v V — Œ	dS )z+Loot Allocation SHORT timeout expected 5.0sNr9   r\   s     r   r^   zAtest_loot_allocation_invalid_timeout_detection.<locals>.<genexpr>ð   s(   è è € Ð]Ð]ÀaÐ<ÀÐAÐ]Ð]Ð]Ð]Ð]Ð]r   r_   r·   s      r   Ú.test_loot_allocation_invalid_timeout_detectionr¼   ê   sã   € à	×	'Ò	'Ñ	)Ô	)ð p¨TØ�Š‰Œ×ÒÐnÑoÔoÐoðpð pð pñ pô pð pð pð pð pð pð pøøøð pð pð pð pà×:Ò:Ñ<Ô<€FØŒ?˜eÐ#Ð#Ð#Ð#ÝÐ]Ð]È6ÔK\Ð]Ñ]Ô]Ñ]Ô]Ð]Ð]Ð]Ð]Ð]r¹   c                ó*  — |                       ¦   «         5 }|                     ¦   «                              d¦  «         ddd¦  «         n# 1 swxY w Y   |                      ¦   «         }|j        du sJ ‚t          d„ |j        D ¦   «         ¦  «        sJ ‚dS )zIVerifies that altered teleport cast time triggers an integrity violation.zVUPDATE teleport_configs SET cast_time_seconds = 1.0 WHERE action_type = 'PARTY_MEMBER'NFc              3  ó   K  — | ]}d |v V — Œ	dS )z&Teleport Config 'PARTY_MEMBER' invalidNr9   r\   s     r   r^   zCtest_teleport_config_invalid_cast_time_detection.<locals>.<genexpr>ù   s(   è è € ÐXÐXÀÐ7¸1Ð<ÐXÐXÐXÐXÐXÐXr   r_   r·   s      r   Ú0test_teleport_config_invalid_cast_time_detectionr¿   ó   sã   € à	×	'Ò	'Ñ	)Ô	)ð x¨TØ�Š‰Œ×ÒÐvÑwÔwÐwðxð xð xñ xô xð xð xð xð xð xð xøøøð xð xð xð xà×:Ò:Ñ<Ô<€FØŒ?˜eÐ#Ð#Ð#Ð#ÝÐXÐXÀfÔFWÐXÑXÔXÑXÔXÐXÐXÐXÐXÐXr¹   )r   r   )Ú__doc__Ú
__future__r   ÚpytestÚ'server.world.game_design_matrix_servicer   Úfixturer   r#   r0   rB   rN   rY   rg   rj   rw   rŠ   r™   r¦   r´   r¸   r¼   r¿   r9   r   r   ú<module>rÅ      s¯  ððð ð #Ð "Ð "Ð "Ð "Ð "Ø €€€Ø KÐ KÐ KÐ KÐ KÐ Kð „ðð ñ „ðð'ð 'ð 'ð 'ð &ð &ð &ð &ðAð Að Að Aðð ð ð ð /ð /ð /ð /ðSð Sð Sð Sð Lð Lð Lð Lð$*ð *ð *ð *ð]ð ]ð ]ð ]ð<ð ð ð ð,!ð !ð !ð !ð"ð ð ð ð.Qð Qð Qð Qð^ð ^ð ^ð ^ðYð Yð Yð Yð Yð Yr   