§
    Îi»j[-  ã                   ó  — d Z ddlZddlZddlmZmZmZmZ ddlm	Z	m
Z
 ddlmZmZmZmZmZmZ ddlmZ  e	d¬¦  «         G d	„ d
¦  «        ¦   «         Z e	d¬¦  «         G d„ d¦  «        ¦   «         Z G d„ d¦  «        ZdS )u7  
End-of-Season Migration Pipeline (LuÃ¢n Há»“i Chuyá»ƒn Sinh) for FreeExile.
Orchestrates the atomic, non-destructive migration of expiring seasonal leagues to Standard:
1. Freezes trade and marketplace activity.
2. Cancels active listings on Universal Consignment Vault and refunds items.
3. Migrates shared stash tabs into Standard as 'Remove-Only' tabs.
4. Updates character realm affiliation from league_id to 'standard'.
5. Snapshots and persists the final Season Leaderboard (Hall of Fame).
6. Initializes and activates the new Season with clean slate economy.
é    N)ÚDictÚListÚOptionalÚAny)Ú	dataclassÚfield)Ú
LeagueTypeÚLeagueStatusÚSeasonLeagueManagerÚSeasonCharacterÚStashTabÚSeasonStashItem)ÚUniversalConsignmentVaultT)Úslotsc                   óV   — e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   eed<   dS )	ÚHallOfFameEntryÚrankÚcharacter_idÚcharacter_nameÚ
account_idÚmartial_classÚlevelÚsnapshot_timestamp_msN)Ú__name__Ú
__module__Ú__qualname__ÚintÚ__annotations__Ústr© ó    ú?C:\Projects\FreeExile\server\world\season_migration_pipeline.pyr   r      s]   € € € € € € à
€I€I�IØÐÐÑØÐÐÑØ€O€O�OØÐÐÑØ€J€J�JØÐÐÑÐÐr!   r   c                   ó¢   — e Zd ZU eed<   eed<   eed<   eed<   eed<   eed<   dZee         ed<   d	Z	e
ed
<    ee¬¦  «        Zee         ed<   dS )ÚMigrationReportÚsuccessÚexpiring_league_idÚcharacters_migratedÚvault_listings_canceledÚremove_only_tabs_createdÚleaderboard_snapshot_entriesNÚnext_season_idg        Úmigration_duration_ms)Údefault_factoryÚerrors)r   r   r   Úboolr   r   r   r+   r   r,   Úfloatr   Úlistr.   r   r    r!   r"   r$   r$   '   s�   € € € € € € à€M€M�MØÐÐÑØÐÐÑØ Ð Ð Ñ Ø!Ð!Ð!Ñ!Ø"%Ð%Ð%Ñ%Ø$(€N�H˜S”MÐ(Ð(Ñ(Ø#&Ð˜5Ð&Ð&Ñ&Ø˜¨dÐ3Ñ3Ô3€FˆD�ŒIÐ3Ð3Ñ3Ð3Ð3r!   r$   c                   óä   — e Zd ZdZ	 ddedee         ddfd„Z	 	 	 	 dded	ee         d
ee         dedee	eef                  de
fd„Zdedefd„Zdededefd„Zdedefd„Zdedee         fd„ZdS )ÚSeasonMigrationPipelinezŒ
    Automated Migration Orchestrator for Seasonal Big Updates.
    Guarantees zero-duplication, atomic settlement, and zero item loss.
    NÚleague_managerÚvaultÚreturnc                 ó0   — || _         || _        i | _        d S ©N)r4   r5   Úarchived_leaderboards)Úselfr4   r5   s      r"   Ú__init__z SeasonMigrationPipeline.__init__:   s"   € ð
 4BˆÔØ:?ˆŒ
àGIˆÔ"Ð"Ð"r!   úv1.1.0r&   r+   Únext_season_nameÚnext_season_versionÚnext_season_mechanicsc                 ó’  — t          j         ¦   «         }g }| j                             |¦  «        }|st          d|› d�¦  «        ‚|j        t
          j        k    rt          d¦  «        ‚| j                             |t          j
        ¦  «         d}	| j        r|                      |¦  «        }	| j                             |t          j        ¦  «         |                      ||j        ¦  «        }
|                      |¦  «        }|                      |¦  «        }| j                             |t          j        ¦  «         |r=|pd|› �}| j                             ||t
          j        t          j        ||pi ¬¦  «         t          j         ¦   «         |z
  dz  }t-          t/          |¦  «        dk    |||	|
t/          |¦  «        |||¬¦	  «	        S )	NzExpiring league 'z' does not existz,Standard realm cannot be expired or migratedr   u   MÃ¹a Giáº£i Má»›i: )Ú	league_idÚdisplay_nameÚleague_typeÚstatusÚversion_requirementÚmechanic_flagsg     @�@)	r%   r&   r'   r(   r)   r*   r+   r,   r.   )Útimer4   Ú
get_leagueÚKeyErrorrC   r	   ÚSTANDARDÚ
ValueErrorÚset_league_statusr
   ÚFREEZINGr5   Ú_refund_vault_listingsÚ	MIGRATINGÚ_migrate_stashes_to_standardrB   Ú_migrate_characters_to_standardÚ_archive_leaderboardÚARCHIVEDÚcreate_leagueÚ	CHALLENGEÚACTIVEr$   Úlen)r:   r&   r+   r=   r>   r?   Ú
start_timer.   Úexpiring_leagueÚcanceled_vault_countÚremove_only_tabs_countr'   Úladder_entriesrB   Úduration_mss                  r"   Úexecute_season_migrationz0SeasonMigrationPipeline.execute_season_migrationD   sô  € õ ”Y‘[”[ˆ
ØˆàÔ-×8Ò8Ð9KÑLÔLˆØð 	UÝÐSÐ/AÐSÐSÐSÑTÔTÐTØÔ&­*Ô*=Ò=Ð=ÝÐKÑLÔLÐLð
 	Ô×-Ò-Ð.@Å,ÔBWÑXÔXÐXð
  !ÐØŒ:ð 	SØ#'×#>Ò#>Ð?QÑ#RÔ#RÐ ð
 	Ô×-Ò-Ð.@Å,ÔBXÑYÔYÐYð
 "&×!BÒ!BÐCUÐWfÔWsÑ!tÔ!tÐð
 #×BÒBÐCUÑVÔVÐð
 ×2Ò2Ð3EÑFÔFˆð
 	Ô×-Ò-Ð.@Å,ÔBWÑXÔXÐXð
 ð 		Ø+ÐUÐ/UÀ^Ð/UÐ/UˆLØÔ×-Ò-Ø(Ø)Ý&Ô0Ý#Ô*Ø$7Ø4Ð:¸ð .ñ ô ð õ ”y‘{”{ ZÑ/°6Ñ9ˆåÝ˜‘K”K 1Ò$Ø1Ø 3Ø$8Ø%;Ý),¨^Ñ)<Ô)<Ø)Ø"-Øð

ñ 

ô 

ð 
	
r!   c           
      óx  — | j         sdS d}t          | j         j                             ¦   «         ¦  «        D �]�}|j        �svd|_        |dz  }t          | j         d¦  «        r\| j         j        rP| j         j        j                             |j	        ¦  «        }|r%|j
        j        |j        v r|j        |j
        j        = |j	        df}|| j        j        vrHt          dt!          j        ¦   «         j        dd…         › �|j	        dd	d
¬¦  «        g| j        j        |<   | j        j        |         d         }t'          |j
        j        |j
        j        |j
        j        t          |j
        j        d¦  «        r|j
        j        j        nt1          |j
        j        ¦  «        ¬¦  «        }||j        |j        <   �Œƒ|S )z˜
        Finds all active listings, marks them closed, and refunds items to
        the seller's Standard stash or temporary migration holding.
        r   Té   Úbuyout_engineÚstandardÚstash_Né   õ   Kho Chuáº©n StandardF©Útab_idr   rA   ÚnameÚis_remove_onlyÚvalue)Ú	item_uuidÚ	item_nameÚ
item_levelÚrarity)r5   r1   ÚlistingsÚvaluesÚis_soldÚhasattrra   ÚaccountsÚgetÚ	seller_idÚitemrk   Úitemsr4   Ústashesr   ÚuuidÚuuid4Úhexr   rl   rm   rn   rj   r   )r:   r&   Úcanceled_countÚlistingÚseller_stashÚstd_keyÚ
target_tabÚrefund_items           r"   rN   z.SeasonMigrationPipeline._refund_vault_listings–   sÍ  € ð
 Œzð 	Ø�1àˆÝ˜DœJÔ/×6Ò6Ñ8Ô8Ñ9Ô9ð 	Fñ 	FˆGØ”?ñ FØ"&�”Ø !Ñ#�õ ˜4œ: Ñ7Ô7ð G¸D¼JÔ<Tð GØ#'¤:Ô#;Ô#D×#HÒ#HÈÔIZÑ#[Ô#[�LØ#ð G¨¬Ô(>À,ÔBTÐ(TÐ(TØ(Ô.¨w¬|Ô/EÐFð #Ô,¨jÐ9�Ø $Ô"5Ô"=Ð=Ð=å Ø#B­D¬J©L¬LÔ,<¸R¸a¸RÔ,@Ð#BÐ#BØ'.Ô'8Ø&0Ø!7Ø+0ðñ ô ð<�DÔ'Ô/°Ñ8ð "Ô0Ô8¸ÔAÀ!ÔD�
Ý-Ø%œlÔ4Ø%œlÔ4Ø&œ|Ô6Ý8?ÀÄÔ@SÐU\Ñ8]Ô8]Ð{˜7œ<Ô.Ô4Ð4ÕcfÐgnÔgsÔgzÑc{Ôc{ð	ñ ô �ð ;F�
Ô  Ô!6Ñ7ùàÐr!   Úleague_display_namec                 óˆ  — d}t          | j        j                             ¦   «         ¦  «        D �]\  \  }}}||k    rŒ|df}|| j        j        vrCt	          dt          j        ¦   «         j        d d…         › �|ddd¬¦  «        g| j        j        |<   |D ]›}|                     ¦   «         rŒt	          dt          j        ¦   «         j        d d…         › �|dd	|› d
|j	        › �dd|j
        t          |j        ¦  «        ¬¦  «        }	| j        j        |                              |	¦  «         |dz  }Œœ| j        j        ||f= �Œ|S )Nr   rb   rc   rd   re   Frf   Úro_u   [Chá»‰ RÃºt - z] Tz#b45309)rg   r   rA   rh   ri   Ú	color_hexÚcapacityrw   r`   )r1   r4   rx   rw   r   ry   rz   r{   Úis_emptyrh   r†   ÚdictÚappend)
r:   r&   r‚   Úcreated_tabs_countr   rA   Útabsr   ÚtabÚmigrated_tabs
             r"   rP   z4SeasonMigrationPipeline._migrate_stashes_to_standardÁ   sŠ  € ØÐå-1°$Ô2EÔ2M×2SÒ2SÑ2UÔ2UÑ-VÔ-Vð #	Eñ #	EÑ)Ñ#ˆZ˜ TØÐ.Ò.Ð.Øà! :Ð.ˆGØ˜dÔ1Ô9Ð9Ð9åØ>­¬
©¬Ô(8¸¸!¸Ô(<Ð>Ð>Ø#-Ø",Ø3Ø',ðñ ô ð8�Ô#Ô+¨GÑ4ð ð (ð (�Ø—<’<‘>”>ð Øõ  (Ø7¥¤¡¤Ô!1°"°1°"Ô!5Ð7Ð7Ø)Ø(ØKÐ*=ÐKÐKÀÄÐKÐKØ#'Ø'Ø œ\Ý˜sœy™/œ/ð	 ñ 	 ô 	 �ð Ô#Ô+¨GÔ4×;Ò;¸LÑIÔIÐIØ" aÑ'Ð"Ð"ð Ô#Ô+¨Z¸Ð,CÐDÑDà!Ð!r!   c                 ó  — d}| j                              d¦  «        }| j         j                             ¦   «         D ]+}|j        |k    rd|_        |dz  }|r|xj        dz  c_        Œ,| j                              |¦  «        }|rd|_        |S )Nr   rb   r`   )r4   rH   Ú
charactersrp   rA   Úactive_characters_count)r:   r&   Úmigrated_countÚ
std_leagueÚcharrY   s         r"   rQ   z7SeasonMigrationPipeline._migrate_characters_to_standardë   s§   € ØˆØÔ(×3Ò3°JÑ?Ô?ˆ
àÔ'Ô2×9Ò9Ñ;Ô;ð 	<ð 	<ˆDØŒ~Ð!3Ò3Ð3Ø!+�”Ø !Ñ#�Øð <ØÐ6Ô6¸!Ñ;Ð6Ô6øàÔ-×8Ò8Ð9KÑLÔLˆØð 	8Ø67ˆOÔ3àÐr!   rA   c                 ó¬  ‡— ˆfd„| j         j                             ¦   «         D ¦   «         }|                     d„ d¬¦  «         t	          t          j        ¦   «         dz  ¦  «        }g }t          |d d…         d¬¦  «        D ]G\  }}|                     t          ||j	        |j
        |j        |j        |j        |¬	¦  «        ¦  «         ŒH|| j        ‰<   |S )
Nc                 ó@   •— g | ]}|j         ‰k    s|j         d k    ¯|‘ŒS )rb   )rA   )Ú.0ÚcrA   s     €r"   ú
<listcomp>z@SeasonMigrationPipeline._archive_leaderboard.<locals>.<listcomp>ý   sV   ø€ ð  Eð  Eð  E˜aÈaÌkÐ]fÒNfÐNfÐjkÔjuð  zDò  kDð  kD˜ð  kDð  kDð  kDr!   c                 ó    — | j         | j         fS r8   )r   Úcreated_at_ms)r—   s    r"   ú<lambda>z>SeasonMigrationPipeline._archive_leaderboard.<locals>.<lambda>ÿ   s   € ¨¬°1´?Ð2BÐ(C€ r!   T)ÚkeyÚreverseiè  éd   r`   )Ústart)r   r   r   r   r   r   r   )r4   r�   rp   Úsortr   rG   Ú	enumerater‰   r   r   rh   r   r   r   r9   )r:   rA   Úleague_charsÚnow_msÚentriesr   r“   s    `     r"   rR   z,SeasonMigrationPipeline._archive_leaderboardü   s  ø€ ð Eð  Eð  Eð  E 4Ô#6Ô#A×#HÒ#HÑ#JÔ#Jð  Eñ  Eô  Eˆà×ÒÐCÐCÈTÐÑRÔRÐRå•T”Y‘[”[ 4Ñ'Ñ(Ô(ˆØ)+ˆÝ# L°°#°Ô$6¸aÐ@Ñ@Ô@ð 	ð 	‰JˆD�$Ø�NŠNÝØØ!%Ô!2Ø#'¤9Ø#œØ"&Ô"4Øœ*Ø*0ðñ ô ñ
ô 
ð 
ð 
ð 18ˆÔ" 9Ñ-Øˆr!   r8   )NNr<   N)r   r   r   Ú__doc__r   r   r   r;   r   r   r$   r^   r   rN   rP   rQ   r   r   rR   r    r!   r"   r3   r3   4   s€  € € € € € ðð ð 6:ðJð Jà+ðJð Ð1Ô2ðJð 
ð	Jð Jð Jð Jð )-Ø*.Ø#+Ø:>ðP
ð P
àðP
ð ! œðP
ð # 3œ-ð	P
ð
 !ðP
ð  (¨¨S°#¨X¬Ô7ðP
ð 
ðP
ð P
ð P
ð P
ðd)¸ð )Àð )ð )ð )ð )ðV("¸sð ("ÐY\ð ("Ðadð ("ð ("ð ("ð ("ðTÀ#ð È#ð ð ð ð ð"¨cð °d¸?Ô6Kð ð ð ð ð ð r!   r3   )r¥   rG   ry   Útypingr   r   r   r   Údataclassesr   r   Úworld.season_league_managerr	   r
   r   r   r   r   Útrade.consignment_vaultr   r   r$   r3   r    r!   r"   ú<module>rª      sƒ  ðð	ð 	ð €€€Ø €€€Ø ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ð ,Ø (Ð (Ð (Ð (Ð (Ð (Ð (Ð (ðð ð ð ð ð ð ð ð ð ð ð ð ð ð ð ð >Ð =Ð =Ð =Ð =Ð =ð €�ÐÑÔðð ð ð ð ñ ô ñ Ôðð €�ÐÑÔð	4ð 	4ð 	4ð 	4ð 	4ñ 	4ô 	4ñ Ôð	4ð]ð ]ð ]ð ]ð ]ñ ]ô ]ð ]ð ]ð ]r!   