§
    `ÁjeE  ã                  ó¼   — d Z ddlmZ ddlZddlZddlZddlmZ ddlm	Z	m
Z
mZmZmZmZ ddlmZmZmZmZmZmZmZ ddlmZmZmZ ddlmZmZ  G d	„ d
¦  «        ZdS )a   
FreeExile Skill & Gem Database Service (PoE2 Multi-Tier Tag Architecture).
Manages SQLite persistence, tag validation, PoE2 combo synergies, and build archetype matching.
Follows Clean Architecture, high-density queries, and zero-leak connection pooling.
é    )ÚannotationsN)Úcontextmanager)ÚAnyÚDictÚListÚOptionalÚSetÚTuple)ÚSkillTagÚTagCategoryÚAttributeAffinityÚ	ComboRoleÚFiveElementsÚMartialSectÚWeaponCategory)Úget_canonical_skill_tagsÚget_canonical_build_archetypesÚget_canonical_passive_nodes)Úcreate_standard_active_skillsÚcreate_standard_augment_sigilsc                  ó„   — e Zd Zd,d-d„Zed„ ¦   «         Zd.d„Zd.d	„Zd/d0d„Zd1d„Z		 	 	 	 	 d2d3d„Z
d4d „Zd5d$„Zd6d(„Zd7d+„ZdS )8ÚSkillDatabaseServiceNÚdb_pathúOptional[str]c                ó&  — |s—t           j                             t           j                             t           j                             t
          ¦  «        ddd¦  «        ¦  «        }t          j        |d¬¦  «         t           j                             |d¦  «        }|| _        | j        dk    rJt          j	        d¦  «        | _
        t          j        | j
        _        | j
                             d¦  «         nd | _
        |                      ¦   «          d S )Nz..ÚdataT)Úexist_okzmartial_database.dbz:memory:úPRAGMA foreign_keys = ON)ÚosÚpathÚabspathÚjoinÚdirnameÚ__file__Úmakedirsr   Úsqlite3ÚconnectÚ_memory_connÚRowÚrow_factoryÚexecuteÚ_init_database)Úselfr   Úbase_dirs      ú<C:\Projects\FreeExile\server\world\skill_database_service.pyÚ__init__zSkillDatabaseService.__init__#   sÛ   € Øð 	DÝ”w—’¥r¤w§|¢|µB´G·O²OÅHÑ4MÔ4MÈtÐUYÐ[aÑ'bÔ'bÑcÔcˆHÝŒK˜¨4Ð0Ñ0Ô0Ð0Ý”g—l’l 8Ð-BÑCÔCˆGØˆŒØŒ<˜:Ò%Ð%Ý '¤°
Ñ ;Ô ;ˆDÔÝ,3¬KˆDÔÔ)ØÔ×%Ò%Ð&@ÑAÔAÐAÐAà $ˆDÔØ×ÒÑÔÐÐÐó    c              #  ó´  K  — | j         �$| j         V — | j                              ¦   «          d S t          j        | j        ¦  «        }t          j        |_        |                     d¦  «         	 |V — |                     ¦   «          n## t          $ r | 	                    ¦   «          ‚ w xY w	 | 
                    ¦   «          d S # | 
                    ¦   «          w xY w)Nr   )r(   Úcommitr&   r'   r   r)   r*   r+   Ú	ExceptionÚrollbackÚclose©r-   Úconns     r/   Ú_get_connectionz$SkillDatabaseService._get_connection1   sÙ   è è € àÔÐ(ØÔ#Ð#Ð#Ð#ØÔ×$Ò$Ñ&Ô&Ð&Ð&Ð&å”? 4¤<Ñ0Ô0ˆDÝ&œ{ˆDÔØ�LŠLÐ3Ñ4Ô4Ð4ðØ�
�
�
Ø—’‘”��øÝð ð ð Ø—’‘”�Øðøøøð ð
 —
’
‘”���ø�—
’
‘”��øøøs   Á.B ÂC Â B'Â'C ÃCÚreturnÚNonec                óX   — | j         �"| j                              ¦   «          d | _         d S d S ©N)r(   r6   )r-   s    r/   r6   zSkillDatabaseService.closeC   s6   € ØÔÐ(ØÔ×#Ò#Ñ%Ô%Ð%Ø $ˆDÔÐÐð )Ð(r1   c                óŠ   — |                       ¦   «         5 }|                     d¦  «         ddd¦  «         dS # 1 swxY w Y   dS )u@   Khá»Ÿi táº¡o toÃ n bá»™ cáº¥u trÃºc báº£ng SQLite chuáº©n má»±c.az  
                CREATE TABLE IF NOT EXISTS skill_tags (
                    tag_id TEXT PRIMARY KEY,
                    category TEXT NOT NULL,
                    name_vi TEXT NOT NULL,
                    name_en TEXT NOT NULL,
                    description TEXT NOT NULL,
                    affected_modifiers TEXT NOT NULL
                );

                CREATE TABLE IF NOT EXISTS skills (
                    skill_id INTEGER PRIMARY KEY,
                    skill_name TEXT NOT NULL,
                    element TEXT NOT NULL,
                    sect TEXT NOT NULL,
                    attribute_affinity TEXT NOT NULL,
                    weapon_requirement TEXT NOT NULL,
                    base_damage REAL NOT NULL,
                    energy_cost INTEGER NOT NULL,
                    cooldown_ms INTEGER NOT NULL,
                    cast_time_ms INTEGER NOT NULL,
                    animation_lock_ms INTEGER NOT NULL,
                    combo_role TEXT NOT NULL,
                    upside_desc TEXT NOT NULL,
                    downside_desc TEXT NOT NULL,
                    tags_json TEXT NOT NULL
                );

                CREATE TABLE IF NOT EXISTS support_gems (
                    sigil_id INTEGER PRIMARY KEY,
                    sigil_name TEXT NOT NULL,
                    augment_type TEXT NOT NULL,
                    attribute_affinity TEXT NOT NULL,
                    required_tags_json TEXT NOT NULL,
                    excluded_tags_json TEXT NOT NULL,
                    damage_multiplier REAL NOT NULL,
                    energy_cost_multiplier REAL NOT NULL,
                    projectile_bonus INTEGER NOT NULL,
                    aoe_radius_multiplier REAL NOT NULL,
                    upside_desc TEXT NOT NULL,
                    downside_desc TEXT NOT NULL
                );

                CREATE TABLE IF NOT EXISTS build_archetypes (
                    archetype_id TEXT PRIMARY KEY,
                    name_vi TEXT NOT NULL,
                    name_en TEXT NOT NULL,
                    primary_attribute TEXT NOT NULL,
                    element TEXT NOT NULL,
                    playstyle_summary TEXT NOT NULL,
                    core_tags_json TEXT NOT NULL,
                    recommended_skills_json TEXT NOT NULL,
                    recommended_gems_json TEXT NOT NULL,
                    combo_guide TEXT NOT NULL
                );

                CREATE TABLE IF NOT EXISTS passive_nodes (
                    node_id INTEGER PRIMARY KEY,
                    name_vi TEXT NOT NULL,
                    affected_tags_json TEXT NOT NULL,
                    damage_multiplier REAL NOT NULL,
                    crit_chance_bonus REAL NOT NULL,
                    attack_speed_bonus REAL NOT NULL,
                    area_radius_multiplier REAL NOT NULL,
                    special_mechanic TEXT NOT NULL
                );
            N)r9   Úexecutescriptr7   s     r/   r,   z#SkillDatabaseService._init_databaseH   s©   € à×!Ò!Ñ#Ô#ð C	 tØ×Òð B ñ Bô Bð BðC	ð C	ð C	ñ C	ô C	ð C	ð C	ð C	ð C	ð C	ð C	ð C	øøøð C	ð C	ð C	ð C	ð C	ð C	s   •8¸<¿<FÚforceÚboolc                óª  — |                       ¦   «         5 }|                     ¦   «         }|sA|                     d¦  «         |                     ¦   «         d         dk    r	 ddd¦  «         dS |                     d¦  «         |                     d¦  «         |                     d¦  «         |                     d¦  «         |                     d	¦  «         t	          ¦   «                              ¦   «         D ]X}|                     d
|j        j        |j        j        |j	        |j
        |j        t          j        |j        ¦  «        f¦  «         ŒYt          ¦   «                              ¦   «         D ]©}d„ |j        D ¦   «         }|                     d|j        |j        |j        j        |j        j        |j        j        |j        j        |j        |j        |j        |j        |j        |j        j        |j        |j        t          j        |¦  «        f¦  «         Œªt?          ¦   «                              ¦   «         D ]Ê}d„ |j         D ¦   «         }tC          |d¦  «        rd„ |j"        D ¦   «         ng }	|                     d|j#        |j$        |j%        j        tC          |d¦  «        r|j        j        ndt          j        |¦  «        t          j        |	¦  «        |j&        |j'        |j(        |j)        |j        |j        f¦  «         ŒËtU          ¦   «                              ¦   «         D ] }
d„ |
j+        D ¦   «         }|                     d|
j,        |
j	        |
j
        |
j-        j        |
j        j        |
j.        t          j        |¦  «        t          j        |
j/        ¦  «        t          j        |
j0        ¦  «        |
j1        f
¦  «         Œ¡te          ¦   «         D ]f}d„ |j3        D ¦   «         }|                     d|j4        |j	        t          j        |¦  «        |j&        |j5        |j6        |j7        |j8        f¦  «         Œg	 ddd¦  «         dS # 1 swxY w Y   dS )uB   Náº¡p dá»¯ liá»‡u máº«u háº¡t giá»‘ng chuáº©n má»±c vÃ o database.z&SELECT COUNT(*) as cnt FROM skill_tagsÚcntr   NzDELETE FROM skill_tagszDELETE FROM skillszDELETE FROM support_gemszDELETE FROM build_archetypeszDELETE FROM passive_nodesz0INSERT INTO skill_tags VALUES (?, ?, ?, ?, ?, ?)c                ó   — g | ]	}|j         ‘Œ
S © ©Úvalue©Ú.0Úts     r/   ú
<listcomp>z<SkillDatabaseService.seed_canonical_data.<locals>.<listcomp>¨   s   € Ð4Ð4Ð4¨˜AœGÐ4Ð4Ð4r1   zGINSERT INTO skills VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)c                ó   — g | ]	}|j         ‘Œ
S rE   rF   rH   s     r/   rK   z<SkillDatabaseService.seed_canonical_data.<locals>.<listcomp>´   ó   € Ð=Ð=Ð=¨˜AœGÐ=Ð=Ð=r1   Úexcluded_tagsc                ó   — g | ]	}|j         ‘Œ
S rE   rF   rH   s     r/   rK   z<SkillDatabaseService.seed_canonical_data.<locals>.<listcomp>µ   s   € Ð<Ð<Ð< q˜1œ7Ð<Ð<Ð<r1   zDINSERT INTO support_gems VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)Úattribute_affinityÚ	UNIVERSALc                ó   — g | ]	}|j         ‘Œ
S rE   rF   rH   s     r/   rK   z<SkillDatabaseService.seed_canonical_data.<locals>.<listcomp>Á   s   € Ð:Ð:Ð:¨˜QœWÐ:Ð:Ð:r1   zBINSERT INTO build_archetypes VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)c                ó   — g | ]	}|j         ‘Œ
S rE   rF   rH   s     r/   rK   z<SkillDatabaseService.seed_canonical_data.<locals>.<listcomp>Ë   rM   r1   z9INSERT INTO passive_nodes VALUES (?, ?, ?, ?, ?, ?, ?, ?))9r9   Úcursorr+   Úfetchoner   ÚvaluesÚtagrG   ÚcategoryÚname_viÚname_enÚdescriptionÚjsonÚdumpsÚaffected_modifiersr   ÚtagsÚskill_idÚ
skill_nameÚelementÚsectrP   Úweapon_requirementÚbase_damageÚenergy_costÚcooldown_msÚcast_time_msÚanimation_lock_msÚ
combo_roleÚupside_descÚdownside_descr   Úrequired_tagsÚhasattrrN   Úsigil_idÚ
sigil_nameÚaugment_typeÚdamage_multiplierÚenergy_cost_multiplierÚprojectile_bonusÚaoe_radius_multiplierr   Ú	core_tagsÚarchetype_idÚprimary_attributeÚplaystyle_summaryÚrecommended_skillsÚrecommended_gemsÚcombo_guider   Úaffected_tagsÚnode_idÚcrit_chance_bonusÚattack_speed_bonusÚarea_radius_multiplierÚspecial_mechanic)r-   r@   r8   ÚcurÚtag_defÚsÚtags_strÚgÚreq_tagsÚex_tagsÚarv   ÚpÚaff_tagss                 r/   Úseed_canonical_dataz(SkillDatabaseService.seed_canonical_data�   s‰  € à×!Ò!Ñ#Ô#ð ?	 tØ—+’+‘-”-ˆCØð Ø—’ÐDÑEÔEÐEØ—<’<‘>”> %Ô(¨1Ò,Ð,Øð?	ð ?	ð ?	ñ ?	ô ?	ð ?	ð ?	ð ?	ð �KŠKÐ0Ñ1Ô1Ð1Ø�KŠKÐ,Ñ-Ô-Ð-Ø�KŠKÐ2Ñ3Ô3Ð3Ø�KŠKÐ6Ñ7Ô7Ð7Ø�KŠKÐ3Ñ4Ô4Ð4õ 4Ñ5Ô5×<Ò<Ñ>Ô>ð ð �Ø—’ØFØ”[Ô&¨Ô(8Ô(>ÀÄØ”_ gÔ&9½4¼:ÀgÔF`Ñ;aÔ;aðcñô ð ð õ 3Ñ4Ô4×;Ò;Ñ=Ô=ð 	ð 	�Ø4Ð4¨Q¬VÐ4Ñ4Ô4�Ø—’Ø]Ø”Z ¤¨q¬y¬ÀÄÄØÔ)Ô/°Ô1EÔ1KØ”] A¤M°1´=À!Ä.ØÔ(¨!¬,Ô*<¸a¼mØ”_¥d¤j°Ñ&:Ô&:ð	<ñô ð ð õ 4Ñ5Ô5×<Ò<Ñ>Ô>ð 
ð 
�Ø=Ð=¨Q¬_Ð=Ñ=Ô=�Ý@GÈÈ?Ñ@[Ô@[ÐcÐ<Ð<¨A¬OÐ<Ñ<Ô<Ð<Ðac�Ø—’ØZØ”Z ¤¨q¬~Ô/CÝ3:¸1Ð>RÑ3SÔ3SÐd�QÔ)Ô/Ð/ÐYdÝ”Z Ñ)Ô)­4¬:°gÑ+>Ô+>ÀÔ@SØÔ-¨qÔ/AÀ1ÔCZØ”] A¤Oð	5ñô ð ð õ 4Ñ5Ô5×<Ò<Ñ>Ô>ð ð �Ø:Ð:¨a¬kÐ:Ñ:Ô:�	Ø—’ØXØ”^ Q¤Y°´	¸1Ô;NÔ;TØ”Y”_ aÔ&9½4¼:ÀiÑ;PÔ;PÝ”Z Ô 4Ñ5Ô5µt´zÀ!ÔBTÑ7UÔ7UÐWXÔWdðfñô ð ð õ 1Ñ2Ô2ð ð �Ø=Ð=¨Q¬_Ð=Ñ=Ô=�Ø—’ØOØ”Y ¤	­4¬:°hÑ+?Ô+?ÀÔATØÔ(¨!Ô*>ÀÔ@XÐZ[ÔZlðnñô ð ð ððs?	ð ?	ð ?	ñ ?	ô ?	ð ?	ð ?	ð ?	ð ?	ð ?	ð ?	ð ?	øøøð ?	ð ?	ð ?	ð ?	ð ?	ð ?	s   •AQÁ-OQÑQÑQr`   ÚintúOptional[Dict[str, Any]]c                ó,  — |                       ¦   «         5 }|                     d|f¦  «                             ¦   «         }|s	 ddd¦  «         dS t          |¦  «        }t	          j        |d         ¦  «        |d<   |cddd¦  «         S # 1 swxY w Y   dS )u'   Láº¥y thÃ´ng tin chiÃªu thá»©c theo ID.z'SELECT * FROM skills WHERE skill_id = ?NÚ	tags_jsonr_   )r9   r+   rU   Údictr\   Úloads)r-   r`   r8   ÚrowÚress        r/   Ú	get_skillzSkillDatabaseService.get_skillÒ   sò   € à×!Ò!Ñ#Ô#ð 	 tØ—,’,ÐHÈ8È+ÑVÔV×_Ò_ÑaÔaˆCØð Øð	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	õ �s‘)”)ˆCÝœ* S¨Ô%5Ñ6Ô6ˆC�‰KØð	ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   •-B	Á-B	Â	BÂBr_   úOptional[Set[SkillTag]]rb   úOptional[FiveElements]Ú	attributeúOptional[AttributeAffinity]ÚweaponúOptional[WeaponCategory]rj   úOptional[ComboRole]úList[Dict[str, Any]]c                óà  — d}g }|r|dz  }|                      |j        ¦  «         |r|dz  }|                      |j        ¦  «         |r/|t          j        k    r|dz  }|                      |j        ¦  «         |r|dz  }|                      |j        ¦  «         |                      ¦   «         5 }|                     ||¦  «                             ¦   «         }	g }
|	D ]z}t          |¦  «        }t          j	        |d         ¦  «        |d<   |r5d„ |D ¦   «         }| 
                    t          |d         ¦  «        ¦  «        sŒe|
                      |¦  «         Œ{|
cd	d	d	¦  «         S # 1 swxY w Y   d	S )
uF   Truy váº¥n tÃ¬m kiáº¿m chiÃªu thá»©c theo ma tráº­n lá»�c linh hoáº¡t.zSELECT * FROM skills WHERE 1=1z AND element = ?z AND attribute_affinity = ?z; AND (weapon_requirement = ? OR weapon_requirement = 'ANY')z AND combo_role = ?r‘   r_   c                ó   — h | ]	}|j         ’Œ
S rE   rF   rH   s     r/   ú	<setcomp>z5SkillDatabaseService.search_skills.<locals>.<setcomp>û   s   € Ð6Ð6Ð6¨A ¤Ð6Ð6Ð6r1   N)ÚappendrG   r   ÚANYr9   r+   Úfetchallr’   r\   r“   ÚissubsetÚset)r-   r_   rb   r™   r›   rj   ÚqueryÚparamsr8   ÚrowsÚresultsÚrÚitemÚtag_valss                 r/   Úsearch_skillsz"SkillDatabaseService.search_skillsÜ   sÙ  € ð 1ˆØˆØð 	)ØÐ'Ñ'ˆEØ�MŠM˜'œ-Ñ(Ô(Ð(Øð 	+ØÐ2Ñ2ˆEØ�MŠM˜)œ/Ñ*Ô*Ð*Øð 	(�f¥Ô 2Ò2Ð2ØÐRÑRˆEØ�MŠM˜&œ,Ñ'Ô'Ð'Øð 	,ØÐ*Ñ*ˆEØ�MŠM˜*Ô*Ñ+Ô+Ð+à×!Ò!Ñ#Ô#ð 	 tØ—<’<  vÑ.Ô.×7Ò7Ñ9Ô9ˆDØ,.ˆGØð %ð %�Ý˜A‘w”w�Ý#œz¨$¨{Ô*;Ñ<Ô<��V‘Øð !Ø6Ð6°Ð6Ñ6Ô6�HØ#×,Ò,­S°°f´Ñ->Ô->Ñ?Ô?ð !Ø Ø—’˜tÑ$Ô$Ð$Ð$Øð	ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   Â-B)E#Å#E'Å*E'ro   úTuple[bool, str]c                ó
  — |                       |¦  «        }|sdd|› �fS |                      ¦   «         5 }|                     d|f¦  «                             ¦   «         }|sdd|› �fcddd¦  «         S t	          |¦  «        }t          t          j        |d         ¦  «        ¦  «        }t          t          j        |d         ¦  «        ¦  «        }t          |d         ¦  «        }	|r3||	z  r.t          ||	z  ¦  «        }
dd	|d
         › d|
› �fcddd¦  «         S |rC| 	                    |	¦  «        s.t          ||	z
  ¦  «        }dd	|d
         › d|› �fcddd¦  «         S dd|d
         › d�fcddd¦  «         S # 1 swxY w Y   dS )uN   Kiá»ƒm tra tÃ­nh há»£p lá»‡ khi liÃªn káº¿t Gem Há»— Trá»£ vÃ o ChiÃªu Thá»©c.Fu!   KhÃ´ng tÃ¬m tháº¥y chiÃªu thá»©c z-SELECT * FROM support_gems WHERE sigil_id = ?u(   KhÃ´ng tÃ¬m tháº¥y Dá»‹ Biáº¿n TÃ  áº¤n NÚrequired_tags_jsonÚexcluded_tags_jsonr_   u   Dá»‹ Biáº¿n TÃ  áº¤n 'rp   u   ' xung Ä‘á»™t vá»›i tag: u   ' thiáº¿u tag báº¯t buá»™c: Tu"   LiÃªn káº¿t Dá»‹ Biáº¿n TÃ  áº¤n 'u   ' thÃ nh cÃ´ng)
r–   r9   r+   rU   r’   r¦   r\   r“   Úlistr¥   )r-   r`   ro   Úskillr8   r”   Úgemrˆ   r‰   Ú
skill_tagsÚconflictÚmissings               r/   Úvalidate_gem_linkz&SkillDatabaseService.validate_gem_link  s�  € à—’˜xÑ(Ô(ˆØð 	IØÐH¸hÐHÐHÐHÐHØ×!Ò!Ñ#Ô#ð 	` tØ—,’,ÐNÐQYÐP[Ñ\Ô\×eÒeÑgÔgˆCØð TØÐSÈÐSÐSÐSð	`ð 	`ð 	`ð 	`ñ 	`ô 	`ð 	`ð 	`õ �s‘)”)ˆCÝ�4œ: cÐ*>Ô&?Ñ@Ô@ÑAÔAˆHÝ�$œ* SÐ)=Ô%>Ñ?Ô?Ñ@Ô@ˆGÝ˜U 6œ]Ñ+Ô+ˆJàð n˜G jÑ0ð nÝ ¨*Ñ 4Ñ5Ô5�ØÐm°s¸<Ô7HÐmÐmÐckÐmÐmÐmð	`ð 	`ð 	`ð 	`ñ 	`ô 	`ð 	`ð 	`ð ð p × 1Ò 1°*Ñ =Ô =ð pÝ˜x¨*Ñ4Ñ5Ô5�ØÐo°s¸<Ô7HÐoÐoÐfmÐoÐoÐoð	`ð 	`ð 	`ð 	`ñ 	`ô 	`ð 	`ð 	`ð Ð_¸cÀ,Ô>OÐ_Ð_Ð_Ð_ð	`ð 	`ð 	`ð 	`ñ 	`ô 	`ð 	`ð 	`ð 	`ð 	`ð 	`ð 	`øøøð 	`ð 	`ð 	`ð 	`ð 	`ð 	`s$   ³2E8Á2BE8Ä8E8ÅE8Å8E<Å?E<Ú
starter_idÚfinisher_idúDict[str, Any]c                óô  — |                       |¦  «        }|                       |¦  «        }|r|sdddœS t          |d         ¦  «        }t          |d         ¦  «        }g }d}t          j        j        |v p|d         t
          j        j        k    }	t          j        j        |v p|d         t
          j        j        k    }
|	r|
r|dz  }|                     d¦  «         t          j        j        |v r-t          j	        j        |v r|d	z  }|                     d
¦  «         t          j
        j        |v r@t          j        j        |v r-t          j        j        |v r|dz  }|                     d¦  «         t          j        j        |v rSt          j        j        |v s&t          j        j        |v st          j        j        |v r|dz  }|                     d¦  «         t#          |¦  «        dk    |||d         |d         dœS )uN   Ä�Ã¡nh giÃ¡ hiá»‡p Ä‘á»“ng Combo PoE2 giá»¯a Ä‘Ã²n Starter vÃ  Ä‘Ã²n Finisher.Fu    ChiÃªu thá»©c khÃ´ng tá»“n táº¡i)Úsynergy_activeÚreasonr_   ç      ð?rj   g      ø?uh   Chuá»—i Combo PoE2: Khai ChiÃªu Má»“i Báº«y -> KÃ­ch Ná»• Tuyá»‡t SÃ¡t (+150% SÃ¡t thÆ°Æ¡ng bá»™c phÃ¡t)g      à?uq   Hiá»‡p Ä‘á»“ng BÄƒng PhÃ¡ch & Trá»�ng KÃ­ch: Ä�áº­p vá»¡ má»¥c tiÃªu Ä‘Ã³ng bÄƒng gÃ¢y ná»• vá»¥n bÄƒng (Shatter)g333333ã?un   Hiá»‡p Ä‘á»“ng Há»§ Ä�á»™c & Ná»• XÃ¡c: KÃ­ch ná»• dá»‹ch Ä‘á»™c lÃ¢y lan toÃ n báº£n Ä‘á»“ (Toxin Detonation)gš™™™™™Ù?um   Hiá»‡p Ä‘á»“ng PhÃ¡ GiÃ¡p & CÆ°Æ¡ng KÃ¬nh: XÃ© toáº¡c da thá»‹t gÃ¢y Xuáº¥t Huyáº¿t gáº¥p Ä‘Ã´i (Armor Shred)r   ra   )r¾   Úcombo_multiplierÚ	synergiesÚstarter_nameÚfinisher_name)r–   r¦   r   ÚCOMBO_STARTERrG   r   ÚCOMBO_FINISHERr¢   ÚCOLDÚSLAMÚPOISONÚAOEÚCORPSEÚARMOR_BREAKÚPHYSICALÚPHYSIQUE_ALIGNEDÚMELEEÚlen)r-   rº   r»   ÚstarterÚfinisherÚs_tagsÚf_tagsrÂ   Ú
multiplierÚhas_starterÚhas_finishers              r/   Úevaluate_combo_synergyz+SkillDatabaseService.evaluate_combo_synergy  sF  € à—.’. Ñ,Ô,ˆØ—>’> +Ñ.Ô.ˆØð 	[˜hð 	[Ø&+Ð7YÐZÐZÐZå�W˜V”_Ñ%Ô%ˆÝ�X˜fÔ%Ñ&Ô&ˆØ!ˆ	Øˆ
õ Ô,Ô2°fÐ<ÐvÀÈÔ@UÕYbÔYpÔYvÒ@vˆÝÔ.Ô4¸Ð>ÐzÀ(È<ÔBXÕ\eÔ\tÔ\zÒBzˆØð 	I˜<ð 	IØ˜#ÑˆJØ×Òð  Hñ  Iô  Ið  Iõ Œ=Ô &Ð(Ð(­X¬]Ô-@ÀFÐ-JÐ-JØ˜#ÑˆJØ×Òð  Qñ  Rô  Rð  RÝŒ?Ô  FÐ*Ð*­x¬|Ô/AÀVÐ/KÐ/KÕPXÔP_ÔPeÐioÐPoÐPoØ˜#ÑˆJØ×Òð  Nñ  Oô  Oð  OÝÔÔ%¨Ð/Ð/ÝÔÔ# vÐ-Ð-ÝÔ(Ô.°&Ð8Ð8ÝŒ~Ô# vÐ-Ð-à˜#ÑˆJØ×Òð  Mñ  Nô  Nð  Nõ " )™nœn¨qÒ0Ø *Ø"Ø# LÔ1Ø% lÔ3ð
ð 
ð 	
r1   Ú	skill_idsú	List[int]Úgem_idsc                ó  — t          ¦   «         }|D ]4}|                      |¦  «        }|r|                     |d         ¦  «         Œ5|                      ¦   «         5 }|                     d¦  «                             ¦   «         }g }|D ]Í}	t          |	¦  «        }
t          t          j        |
d         ¦  «        ¦  «        }||z  }|rt          |¦  «        t          |¦  «        z  nd}|dk    rg| 
                    |
d         |
d         |
d         |
d	         |
d
         t          |dz  d¦  «        t          |¦  «        |
d         |
d         dœ	¦  «         ŒÎ|                     d„ d¬¦  «         |cddd¦  «         S # 1 swxY w Y   dS )uP   Ä�á»‘i chiáº¿u loadout cá»§a ngÆ°á»�i chÆ¡i vá»›i 6 HÆ°á»›ng Build kinh Ä‘iá»ƒn.r_   zSELECT * FROM build_archetypesÚcore_tags_jsonç        gffffffÖ?rw   rY   rZ   rb   rx   éd   é   ry   r|   )	rw   rY   rZ   rb   rx   Úmatch_score_percentÚmatched_tagsry   r|   c                ó   — | d         S )Nrá   rE   )Úxs    r/   ú<lambda>z=SkillDatabaseService.match_build_archetypes.<locals>.<lambda>a  s   €  qÐ)>Ô'?€ r1   T)ÚkeyÚreverseN)r¦   r–   Úupdater9   r+   r¤   r’   r\   r“   rÐ   r¢   Úroundr³   Úsort)r-   rÙ   rÛ   Úcombined_tagsÚsidr…   r8   r©   rª   r«   r¬   rv   ÚintersectionÚscores                 r/   Úmatch_build_archetypesz+SkillDatabaseService.match_build_archetypesA  sã  € õ #&¡%¤%ˆØð 	0ð 	0ˆCØ—’˜sÑ#Ô#ˆAØð 0Ø×$Ò$ Q v¤YÑ/Ô/Ð/øà×!Ò!Ñ#Ô#ð 	 tØ—<’<Ð @ÑAÔA×JÒJÑLÔLˆDØˆGØð ð �Ý˜A‘w”w�Ý¥¤
¨4Ð0@Ô+AÑ BÔ BÑCÔC�	Ø,¨yÑ8�Ø>GÐP�˜LÑ)Ô)­C°	©N¬NÑ:Ð:ÈS�Ø˜D’=�=Ø—N’NØ(,¨^Ô(<Ø#'¨	¤?Ø#'¨	¤?Ø#'¨	¤?Ø-1Ð2EÔ-FÝ/4°U¸S±[À!Ñ/DÔ/DÝ(,¨\Ñ(:Ô(:Ø-1Ð2EÔ-FØ'+¨MÔ':ð
$ð 
$ñ 
ô 
ð 
øð �LŠLÐ?Ð?ÈˆLÑNÔNÐNØð+	ð 	ð 	ð 	ñ 	ô 	ð 	ð 	ð 	ð 	ð 	ð 	øøøð 	ð 	ð 	ð 	ð 	ð 	s   ÁDE:Å:E>ÆE>Únode_idsúDict[str, float]c                ó°  — |                       |¦  «        }|r|sdddddœS t          |d         ¦  «        }d}d}d}d}|                      ¦   «         5 }	d                     dt	          |¦  «        z  ¦  «        }
|	                     d|
› d�|¦  «                             ¦   «         }|D ]Z}t          t          j        |d	         ¦  «        ¦  «        }||z  r,||d
         z  }||d         z  }||d         z  }||d         z  }Œ[	 ddd¦  «         n# 1 swxY w Y   t          |d¦  «        t          |d¦  «        t          |d¦  «        t          |d¦  «        dœS )ug   TÃ­nh toÃ¡n tá»•ng chá»‰ sá»‘ khuáº¿ch Ä‘áº¡i tá»« cÃ¡c Ä‘iá»ƒm Huyáº¿t Cá»‘t Ma Ä�á»“ dá»±a trÃªn Tag.rÀ   rÞ   )rr   r€   r   r�   r_   ú,Ú?z.SELECT * FROM passive_nodes WHERE node_id IN (ú)Úaffected_tags_jsonrr   r€   r   r�   Né   )
r–   r¦   r9   r"   rÐ   r+   r¤   r\   r“   ré   )r-   r`   rð   r´   rÓ   Údmg_multÚ	spd_bonusÚ
crit_bonusÚ	area_multr8   Úplaceholdersr©   r«   Úp_tagss                 r/   Úcalculate_passive_bonusz,SkillDatabaseService.calculate_passive_bonusd  sÚ  € à—’˜xÑ(Ô(ˆØð 	B˜Hð 	BØ),ÀCÐ^að  ~Að  Bð  Bð  Bå�U˜6”]Ñ#Ô#ˆØˆØˆ	Øˆ
Øˆ	à×!Ò!Ñ#Ô#ð 		= tØŸ8š8 C­#¨h©-¬-Ñ$7Ñ8Ô8ˆLØ—<’<Ð `ÐQ]Ð `Ð `Ð `ÐbjÑkÔk×tÒtÑvÔvˆDØð =ð =�Ý�TœZ¨Ð*>Ô(?Ñ@Ô@ÑAÔA�Ø˜F‘?ð =Ø Ð"5Ô 6Ñ6�HØ Ð#7Ô!8Ñ8�IØ !Ð$7Ô"8Ñ8�JØ Ð#;Ô!<Ñ<�Iøð=ð		=ð 		=ð 		=ñ 		=ô 		=ð 		=ð 		=ð 		=ð 		=ð 		=ð 		=øøøð 		=ð 		=ð 		=ð 		=õ "' x°Ñ!3Ô!3Ý"'¨	°1Ñ"5Ô"5Ý!& z°1Ñ!5Ô!5Ý&+¨I°qÑ&9Ô&9ð	
ð 
ð 	
s   ÁB/DÄDÄDr=   )r   r   )r:   r;   )F)r@   rA   r:   r;   )r`   rŽ   r:   r�   )NNNNN)r_   r—   rb   r˜   r™   rš   r›   rœ   rj   r�   r:   rž   )r`   rŽ   ro   rŽ   r:   r¯   )rº   rŽ   r»   rŽ   r:   r¼   )rÙ   rÚ   rÛ   rÚ   r:   rž   )r`   rŽ   rð   rÚ   r:   rñ   )Ú__name__Ú
__module__Ú__qualname__r0   r   r9   r6   r,   r�   r–   r®   r¹   rØ   rï   rþ   rE   r1   r/   r   r   "   s)  € € € € € ðð ð ð ð ð ðð ñ „^ðð"%ð %ð %ð %ð
Eð Eð Eð EðNAð Að Að Að AðFð ð ð ð )-Ø*.Ø15Ø+/Ø*.ð#ð #ð #ð #ð #ðJ`ð `ð `ð `ð,(
ð (
ð (
ð (
ðT!ð !ð !ð !ðF
ð 
ð 
ð 
ð 
ð 
r1   r   )Ú__doc__Ú
__future__r   r\   r   r&   Ú
contextlibr   Útypingr   r   r   r   r	   r
   Úserver.world.martial_typesr   r   r   r   r   r   r   Úserver.world.skill_tag_catalogr   r   r   Úserver.world.martial_catalogr   r   r   rE   r1   r/   ú<module>r	     sp  ððð ð #Ð "Ð "Ð "Ð "Ð "Ø €€€Ø 	€	€	€	Ø €€€Ø %Ð %Ð %Ð %Ð %Ð %Ø 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8Ð 8ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ðð ð ð ð ð ð ð ð ð ð
ð ð ð ð ð ð ð ð^
ð ^
ð ^
ð ^
ð ^
ñ ^
ô ^
ð ^
ð ^
ð ^
r1   