Ë
    cõãjMÓ  ã                   óþ  — d Z ddlZddl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	m
Z
 ddlmZ ddlmZ ej                  j                  dd¬«        ee«      j#                  «       j$                  j$                  Zej(                  j+                  d e ee«      j#                  «       j$                  «      «       ed	z  Z ee«      ej(                  vr"ej(                  j+                  d ee«      «       ddlZdd
lmZ ddlmZ ddlmZmZ ddl m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z) ddl*m+Z+ ddl,m-Z- dZ.ej^                  ja                  dd«      Z1edz  dz  Z2edz  dz  Z3ed	z  dz  Z4ed	z  dz  Z5ed	z  dz  Z6e4dz  e5dz  e6dz  ge4dz  e5dz  e6dz  ge4dz  e5dz  e6dz  gdœZ7ed	z  dz  dz  Z8ed	z  dz  dz  Z9dd d!dœZ:d"d#d$dœZ;d%Z< e=h d&£«      Z> e=h d'£«      Z? e=h d(£«      Z@ ej‚                  d)«      ZBd*efd+„ZCd*efd,„ZDe	 G d-„ d.«      «       ZEd*eFfd/„ZGd*eFfd0„ZHd[d*eFfd1„ZId*eFfd2„ZJd*eKfd3„ZLd4„ ZMh d5£h d5£h d5£h d6£h d7£h d8£d9œZNh d:£ZOd;„ ZPd[d<„ZQd=„ ZR	 d[d*eFfd>„ZS	 d[d*eFfd?„ZTd@„ ZUe9fd*eKfdA„ZVd*eKfdB„ZWdC„ ZXdD„ ZYd*efdE„ZZdF„ Z[d\dG„Z\dH„ Z]d*edz  fdI„Z^dJ„ Z_dK„ Z`	 	 	 	 d]d*eFfdL„Zad*efdM„Zbd*efdN„Zcd*eKfdO„Zdd*efdP„Zed*eKfdQ„ZfdR„ Zgd*ehfdS„Zid*ejfdT„Zkd*efdU„Zld*efdV„Zm	 	 d^d*eKfdW„Zn	 d_d*eofdX„ZpdY„ ZqerdZk(  r eq«        yy)`a;  
pack_builder: PLANIFICADOR y GENERADOR de packs de contenido.

Coge el banco de poses validadas (pose_bank) + los pools de exploracion
(wildcards_harvest / wildcards_danbooru / danbooru) y compone la lista de trabajos
(quotas por nivel, poses aprobadas + exploracion controlada, un angulo de
camara por job). El prompt de cada job se monta con build_prompt() de
test_blocks.py, asi que el MASTER, el BREAK y los 5 LoRAs de estilo quedan
intactos.

    # Planificar (no toca Forge): imprime el plan y sale.
    python Engine/pack_builder.py --char Furina --theme playa --dry-run
    python Engine/pack_builder.py --char Furina --theme playa --target 45         --levels 15,16,14 --explore 0.2 --max-variants 2 --dry-run

    # Generar un piloto pequeno (N imagenes) en Output/pilots/<stamp>/
    python Engine/pack_builder.py --pilot 3 --char Furina

    # Generar un pack completo en Output/packs/<clave>_<tema>/
    python Engine/pack_builder.py --pack --char Furina --theme playa --target 45

    # La seed es aleatoria por imagen. --seed N la fija: usalo solo para
    # reproducir o corregir una imagen concreta, no para un pack entero.

El banco se lee de Archivos/pose_bank/ salvo que exista PLUMLOOM_BANK_DIR
(lo usan las verificaciones para no tocar el banco real). Forge se lee de
PLUMLOOM_FORGE (default http://127.0.0.1:7860).
é    N)Ú	dataclassÚfield)Údatetime)ÚPathúutf-8Úbackslashreplace)ÚencodingÚerrorsÚArchivos)Ústrip_scene_tags)ÚPromptBuilder)Úload_affinityÚvalidate_pose_scene)	ÚSTAGE_LEVELÚSTAGESÚdress_for_stageÚdress_negativeÚforce_nude_forÚload_stage_camerasÚparse_stage_quotasÚstage_allows_poseÚstage_for_record)Úbuild_prompt)Úwatermark_dir)Ú	sugerenteÚspicyÚ	explicitoÚPLUMLOOM_FORGEzhttp://127.0.0.1:7860ÚOutputÚpilotsÚpacksÚwildcards_harvestÚwildcards_danbooruÚdanbooruzbloques_sfw.txtzbloques_spicy.txtzbloques_explicit.txtÚprogression_wildcardszcameras.txtzthemes.jsoné   é   é   ÚdressedÚ	strippingÚnudeznipples, topless>   úno braú
no pantiesúbreasts outúclothed sexúnaked towelúcompletely nudeúcovered nipplesúpartially undressedÚbrar+   ÚnakedÚtowelÚbikiniÚclothedÚnipplesÚpantiesÚtoplessÚswimsuitÚ	underwearÚ
bottomlessÚ
undressing>   úclose-upú	full bodyú	wide shotú
foot focusú
from belowú
from frontú
lower bodyú
upper bodyúcowboy shotúdutch angleúcleavage focusÚthighsÚcloseupÚmidriffÚportraitú	ass focusú	from sideú
from aboveúfrom behind>   úon bedúgrey backgroundúblack backgroundúwhite backgroundúsimple backgroundúgradient backgroundÚbedÚdayÚskyÚdoorÚfireÚtreeÚwallÚfloorÚgrassÚnightÚwaterÚcandleÚpillowÚwindowÚbathtubÚblanketÚceilingÚindoorsÚcurtainsÚoutdoorsz\(([^():]+):[0-9.]+\)Úreturnc                 óÚ   — t         j                  dt        | «      «      }|j                  «       j                  d«      j                  «       }|j	                  dd«      j                  «       S )z:Tag sin pesos ni parentesis, `_`->espacio y en minusculas.z\1z()[]{}Ú_Ú )Ú
_WEIGHT_REÚsubÚstrÚstripÚreplaceÚlower)ÚtokenÚtexts     úEngine/pack_builder.pyÚ	_bare_tagrz   v   sO   € ä�>‰>˜%¤ U£Ó,€DØ�:‰:‹<×Ñ˜hÓ'×-Ñ-Ó/€DØ�<‰<˜˜SÓ!×'Ñ'Ó)Ð)ó    c                 ó€  — t        «       }| j                  r	|t        z  }| j                  r	|t        z  }| j
                  r	|t        z  }|s| j                  S g }| j                  xs dj                  d«      D ]3  }|j                  «       }|rt        |«      |v rŒ#|j                  |«       Œ5 dj                  |«      S )zBPose sin los tags que contradicen el stage o el tema (solo quita).Ú Ú,ú, )ÚsetÚcameraÚ_CLEAN_FRAMINGÚoutfit_lineÚ_CLEAN_STATEÚ
scene_lineÚ_CLEAN_PLACEÚ	pose_lineÚsplitrt   rz   ÚappendÚjoin)ÚjobÚdropÚkeptrw   rx   s        ry   Úclean_pose_linerŽ   }   s¤   € ä‹5€DØ
‡z‚zØ”ÑˆØ
‡‚Ø”ÑˆØ
‡~‚~Ø”ÑˆÙØ�}‰}ÐØ€DØ—-‘-Ò% 2×,Ñ,¨SÖ1ˆØ�{‰{‹}ˆÙ”y “¨$Ñ.ØØ�‰�DÕð	 2ð
 �9‰9�T‹?Ðr{   c                   ó@  — e Zd ZU eed<   eed<   eed<   edz  ed<   ee   ed<   eed<   dZeed	<   dZeed
<   dZeed<   dZ	eed<    e
e¬«      Zeed<   dZeed<   dZedz  ed<   dZedz  ed<   dZedz  ed<   dZeed<    e
e¬«      Zeed<   dZeed<   dZedz  ed<   y)ÚJobÚnivelr‡   ÚoriginNÚpose_idÚtemar�   r}   rƒ   r…   Ú
light_lineÚautoÚdress)Údefault_factoryÚvariant_keysÚ
props_lineÚstageÚoutfit_baseÚ
outfit_keyFÚoutfit_fallbackÚpose_scene_warningsÚclean_posesÚseed)Ú__name__Ú
__module__Ú__qualname__rs   Ú__annotations__Úlistrƒ   r…   r•   r—   r   Údictr™   rš   r›   rœ   r�   rž   ÚboolrŸ   r    r¡   Úint© r{   ry   r�   r�   ‘   sÆ   … àƒJØƒNØƒKØ�4‰ZÓØ
ˆs‰)ƒOØƒKà€K�ÓØ€J�ÓØ€J�ÓØ€Eˆ3ÓÙ¨tÔ4€L�$Ó4Ø€J�ÓØ€Eˆ3�‰:ÓØ"€K��t‘Ó"Ø!€J��d‘
Ó!Ø!€O�TÓ!Ù %°dÔ ;Ð˜Ó;Ø€K�ÓØ€Dˆ#�‰*Ôr{   r�   c                  óô   — t         j                  «       sg S g } t         j                  d¬«      j                  «       D ]8  }|j	                  «       }|sŒ|j                  d«      rŒ(| j                  |«       Œ: | S )zCAngulos/encuadres de cameras.txt, sin comentarios ni lineas vacias.r   ©r	   Ú#)ÚCAMERAS_FILEÚexistsÚ	read_textÚ
splitlinesrt   Ú
startswithr‰   )ÚoutÚlines     ry   Úload_camerasrµ   ©   sf   € ä×ÑÔ Øˆ	Ø
€CÜ×&Ñ&°Ð&Ó8×CÑCÖEˆØ�z‰z‹|ˆÚ˜Ÿ™¨Õ,Ø�J‰J�tÕð Fð €Jr{   c                 óV  — g }t        «       }t        j                  | g «      D ]ƒ  }|j                  «       sŒ|j	                  d¬«      j                  «       D ]M  }|j                  «       }|r|j                  d«      rŒ'||vsŒ,|j                  |«       |j                  |«       ŒO Œ… |S )zELineas de bloque de los dos pools del nivel (dedup, sin # ni vacias).r   r¬   r­   )
r€   ÚLEVEL_POOLSÚgetr¯   r°   r±   rt   r²   Úaddr‰   )r‘   r³   ÚseenÚpathr´   s        ry   Úload_pool_linesr¼   µ   s�   € à
€CÜ‹5€DÜ—‘  rÖ*ˆØ�{‰{Œ}ØØ—N‘N¨G�NÓ4×?Ñ?ÖAˆDØ—:‘:“<ˆDÙ˜4Ÿ?™?¨3Ô/ØØ˜4ÒØ—‘˜”Ø—
‘
˜4Õ ñ Bð +ð €Jr{   c                 óÚ  — |dk  rg S t        dt        |«      «      }g }|�|ni }t        |«      |k  r²|j                  «       D ��	ch c]  \  }}	|	|k\  sŒ|’Œ }
}}	|t        |«      z
  }t	        j
                  | ||
||¬«      }|s	 |S |D ]I  }|j                  |«       |j                  |j                  d«      d«      dz   ||j                  d«      <   ŒK t        |«      |k  rŒ²|S c c}	}w )zàHasta n entradas del banco (nivel), cada pose reutilizable max_variants
    veces. `sample` ya excluye avoid y los ids que se le pasan. `used` permite
    compartir el contador entre varias llamadas (stages del mismo nivel).r   é   )r‘   Úexclude_idsÚnÚrngÚid)Úmaxr©   ÚlenÚitemsÚ	pose_bankÚsampler‰   r¸   )Úbankr‘   rÀ   Úmax_variantsrÁ   ÚusedÚchosenÚusageÚeidÚcÚexcludeÚneedÚgotÚes                 ry   Ú
_take_bankrÓ   Æ   só   € ð 	ˆA‚vØˆ	Ü�qœ#˜lÓ+Ó,€LØ€FØÐ$‰D¨"€EÜ
ˆf‹+˜Š/Ø%*§[¡[¤]ÔH¡]™6˜3 °a¸<Ó6G’3 ]ˆÑHØ”3�v“;‰ˆÜ×Ñ˜t¨5¸gØ!%¨3ô0ˆáØð €Mó ˆAØ�M‰M˜!ÔØ!&§¡¨1¯5©5°«;¸Ó!:¸QÑ!>ˆE�!—%‘%˜“+Òð ô ˆf‹+˜‹/ð €Mùó Is   ÁC'ÁC'c                 óP  — |dk  rg S | D �cg c]  }t        j                  ||«      rŒ|‘Œ }}|sg S |t        |«      k  r|j                  ||«      S g }t        |«      |k  r<t	        |«      }|j                  |«       |j                  |«       t        |«      |k  rŒ<|d| S c c}w )zIn lineas al azar (sin repetir si alcanza; ciclando si no). Excluye avoid.r   N)rÆ   Ú
is_avoidedrÄ   rÇ   r¦   ÚshuffleÚextend)ÚlinesÚavoidrÀ   rÁ   ÚlnÚeligibler³   Úchunks           ry   Ú_take_explorerÝ   Ü   s§   € àˆA‚vØˆ	Ù"ÓJ™U�r¬)×*>Ñ*>¸rÀ5Õ*I’˜U€HÐJÙØˆ	ØŒC�‹MÒØ�z‰z˜( AÓ&Ð&Ø
€CÜ
ˆc‹(�QŠ,Ü�X“ˆØ�‰�EÔØ�
‰
�5Ôô ˆc‹(�Q‹,ð ˆr�ˆ7€Nùò Ks
   ŒB#¨B#c                 ó  — |si S | D �ci c]  }|j                  d«      |“Œ }}i }|D ]T  }|j                  |«      }|st        d|› d�«      ‚|j                  |j                  d«      g «      j                  |«       ŒV |S c c}w )z;`--bank-ids` -> {nivel: [entrada, ...]} en el orden pedido.rÂ   z[!] --bank-ids: 'z' no existe en el bancor‘   )r¸   Ú
SystemExitÚ
setdefaultr‰   )rÈ   Úbank_idsrÒ   Úby_idr³   ÚpidÚentrys          ry   Ú_pinned_by_levelrå   í   s�   € áØˆ	Ù%)Ó*¡T ˆQ�U‰U�4‹[˜!‰^ T€EÐ*Ø
€CÛˆØ—	‘	˜#“ˆÙÜÐ0°°Ð5LÐMÓNÐNØ�‰�u—y‘y Ó)¨2Ó.×5Ñ5°eÕ<ð	 ð
 €Jùò +s   ‰Bc                 ó^   — | j                  «       j                  dd«      j                  «       S )Nro   rp   )rv   ru   rt   )rx   s    ry   Ú	_norm_tagrç   û   s$   € Ø�:‰:‹<×Ñ  SÓ)×/Ñ/Ó1Ð1r{   >   rO   ú	back viewrR   >   úover the shoulderrO   rè   rR   >   ÚlegsrO   rè   rQ   >   Úprofilerè   rP   rR   )Úlyingúon sidezon backÚ
missionaryúagainst wallÚpov>   rì   rî   rí   rï   c                 óÜ   — |j                  d«      D �ch c]  }t        |«      ’Œ }}t        | «      }|t        z  rd|v ryt        j	                  «       D ]  \  }}||v sŒ||v sŒ y yc c}w )zFEvita que el angulo final anule la pose (p.ej. back_view sobre lying).r~   rP   TF)rˆ   rç   Ú
FORCE_SIDEÚCAMERA_BLOCKSrÅ   )r�   r‡   ÚtÚtoksÚcamÚtagÚblockeds          ry   Ú	camera_okrù   
  sr   € à"+§/¡/°#Ô"6Ó7Ñ"6˜QŒI�a�LÐ"6€DÐ7Ü
�FÓ
€CØŒjÒ˜[¨CÑ/ØÜ%×+Ñ+Ö-‰ˆˆWØ�$Š;˜3 'š>Ùð .ð ùò 8s   ”A)c                 óh  — t        | «      D ]¤  \  }}|xs g }|j                  r|�|j                  |v r||j                     }|sd|_        ŒA|t        |«      z  }t	        t        |«      «      D ]5  }|||z   t        |«      z     }t        ||j                  «      sŒ.||_         Œš ||   |_        Œ¦ y)z;Asigna camara por stage (o general) sin forzar `from side`.Nr}   )Ú	enumerater›   r�   rÄ   Úrangerù   r‡   )	ÚjobsÚcamerasÚstage_camerasÚir‹   ÚpoolÚstartÚkrö   s	            ry   Úassign_camerasr    s«   € ä˜D–/‰ˆˆ3ØŠ}˜"ˆØ�9Š9˜Ð2°s·y±yÀMÑ7QØ  §¡Ñ+ˆDÙØˆCŒJØØ”C˜“I‘ˆÜ”s˜4“yÖ!ˆAØ˜ ™	¤S¨£YÑ.Ñ/ˆCÜ˜˜cŸm™mÕ,Ø �”
Ùð	 "ð ˜e™ˆC�Jñ "r{   c                 óà  — |syt        | «      D ]Ø  \  }}|j                  j                  d«      D �ch c]  }t        |«      ’Œ }}|t        z  r5|D ]  }t        |«      dk(  sŒ||_         n ||t        |«      z     |_        Œu|t        |«      z  }t        t        |«      «      D ]5  }|||z   t        |«      z     }t        ||j                  «      sŒ.||_         ŒÎ ||   |_        ŒÚ yc c}w )zMComportamiento legacy de `compose_jobs`: prioriza from side en ciertas poses.Nr~   rP   )	rû   r‡   rˆ   rç   rò   r�   rÄ   rü   rù   )	rý   rþ   r   r‹   rô   rõ   rö   r  r  s	            ry   Ú_assign_cameras_legacyr  )  så   € áØÜ˜D–/‰ˆˆ3Ø&)§m¡m×&9Ñ&9¸#Ô&>Ó?Ñ&> ”	˜!•Ð&>ˆÐ?Ø”*ÒÛ�Ü˜S“> [Ó0Ø!$�C”JÙð ð
 % Q¬¨W«Ñ%5Ñ6�”
ØØ”C˜“LÑ ˆÜ”s˜7“|Ö$ˆAØ˜5 1™9¬¨G«Ñ4Ñ5ˆCÜ˜˜cŸm™mÕ,Ø �”
Ùð	 %ð ! ™ˆC�Jñ# "ùÚ?s   ²C+c
                 ó|  — t         D �
ci c]  }
|
t        |j                  |
d«      «      “Œ  }}
t        |j	                  «       «      }t        ||	«      }g }t         D �]G  }|dkD  rt        | ||   z  |z  «      }nd}|dk  rŒ&t        ||z  «      }||z
  }|j                  |«      r-||   }t        |«      D �cg c]  }||t        |«      z     ‘Œ }}nt        |||||«      }|D ]]  }|j                  t        ||j                  dd«      d|j                  d«      t        |j                  d«      xs g «      d¬«      «       Œ_ |t        |«      z
  }|t        d|«      z   }t        |j                  |g «      |||«      D ]"  }|j                  t        ||dd	g d¬«      «       Œ$ �ŒJ t        ||«       |S c c}
w c c}w )
a4  Compone la lista de Job: quotas por nivel, poses del banco + exploracion.

    Regla: por nivel, count = round(target * quotas[nivel] / sum(quotas));
    explore_n = round(count * explore); bank_n = count - explore_n. Si el banco
    da menos de bank_n, el resto se rellena desde pools[nivel] (explore).
    r   r‡   r}   rÈ   rÂ   r”   )r‘   r‡   r’   r“   r”   r�   ÚexploreN)ÚLEVELSr©   r¸   ÚsumÚvaluesrå   Úroundrü   rÄ   rÓ   r‰   r�   r¦   rÃ   rÝ   r  )ÚtargetÚquotasr  rÈ   rÙ   Úpoolsrþ   rÉ   rÁ   rá   ÚlvÚtotalÚpinnedrý   r‘   ÚcountÚ	explore_nÚbank_nÚcycler   Úbank_entriesrÒ   Ú	shortfallÚ	n_explorer´   s                            ry   Úcompose_jobsr  A  sÆ  € õ 4:Ó:±6¨Rˆb”#�f—j‘j  QÓ'Ó(Ñ(°6€FÐ:Ü�—‘“Ó €EÜ˜d HÓ-€FØ€Dß�ˆØ�1Š9Ü˜& 6¨%¡=Ñ0°5Ñ8Ó9‰EàˆEØ�AŠ:ØÜ˜% '™/Ó*ˆ	Ø˜Ñ"ˆà�:‰:�eÔØ˜5‘MˆEÜ;@À¼=ÓI¹=°a˜E !¤c¨%£j¡.Ó1¸=ˆLÑIä% d¨E°6¸<ÈÓMˆLÛˆAØ�K‰KœØØŸ%™% ¨RÓ0ØØŸ™˜d›Ü˜!Ÿ%™% ›-Ò-¨2Ó.Øôõ ð ð œS Ó.Ñ.ˆ	Ø¤ A yÓ 1Ñ1ˆ	Ü! %§)¡)¨E°2Ó"6¸¸yÈ#ÖNˆDØ�K‰KœØØØ ØØØôõ ò Oð7 ôJ ˜4 Ô)Ø€KùòU ;ùò  Js   ‰#F4Â7F9c	                 ó„  — t         D �	ci c]"  }	|	t        |xs i j                  |	d«      «      “Œ$ }
}	t        |
j	                  «       «      }t        ||«      }i }g }t         D �]Â  }	|dkD  rt        | |
|	   z  |z  «      nd}|dk  rŒ%t        |	   }t        ||z  «      }||z
  }|D �cg c]   }t        |	|j                  dd«      «      r|‘Œ" }}|j                  |g «      D �cg c]   }t        |	|j                  dd«      «      r|‘Œ" }}|r*|}t        |«      D �cg c]  }||t        |«      z     ‘Œ }}nt        ||||||¬«      }|D ]^  }|j                  t        ||j                  dd«      d|j                  d«      t        |j                  d«      xs g «      d|	¬«      «       Œ` |t        |«      z
  }|t        d|«      z   }|j                  |g «      D �cg c]  }t        |	|«      r|‘Œ }}t!        ||||«      D ]#  }|j                  t        ||d	d
g d|	¬«      «       Œ% �ŒÅ |S c c}	w c c}w c c}w c c}w c c}w )zšCompone jobs por stage (5 etapas), compartiendo el uso del banco por nivel.

    No asigna camara: eso lo hace `assign_cameras` en un paso posterior.
    r   r‡   r}   )rÊ   rÈ   rÂ   r”   )r‘   r‡   r’   r“   r”   r�   r›   r  N)r   r©   r¸   r
  r  rå   r  r   r   rü   rÄ   rÓ   r‰   r�   r¦   rÃ   rÝ   )r  Ústage_quotasr  rÈ   rÙ   r  rÉ   rÁ   rá   r›   r  r  r  rÊ   rý   r  Úlevelr  r  rä   Úeligible_bankÚpinned_entriesr  r   r  r  r  r´   Úeligible_poolss                                ry   Úcompose_stage_jobsr!  v  s„  € õ "ó#Ù!�%ð ”S˜,Ò,¨"×1Ñ1°%¸Ó;Ó<Ñ<Ø!ð ð #ä�—‘“Ó €EÜ˜d HÓ-€FØ€DØ€Dß�ˆØ9>Àº”�f˜v e™}Ñ,¨uÑ4Ô5ÈˆØ�AŠ:ØÜ˜EÑ"ˆÜ˜% '™/Ó*ˆ	Ø˜Ñ"ˆá,0ó R©D 5Ü-¨e°U·Y±Y¸{ÈBÓ5OÔPò ¨Dˆð Rà-3¯Z©Z¸¸rÔ-Bó SÑ-B EÜ.¨u°e·i±iÀÈRÓ6PÔQò  Ð-Bˆð SáØ"ˆEÜ;@À¼=ÓI¹=°a˜E !¤c¨%£j¡.Ó1¸=ˆLÑIä% m°U¸FØ&2°C¸dôDˆLã!ˆEØ�K‰KœØØŸ)™) K°Ó4ØØŸ	™	 $›Ü˜%Ÿ)™) FÓ+Ò1¨rÓ2ØØôõ ð "ð œS Ó.Ñ.ˆ	Ø¤ A yÓ 1Ñ1ˆ	Ø+0¯9©9°U¸BÔ+?ó =Ñ+? 4Ü.¨u°dÔ;ò Ð+?ˆð =ä! .°%¸ÀCÖHˆDØ�K‰KœØØØ ØØØØôõ ò IðC ðV €Kùòc#ùòRùòSùò Jùò"=s   ‰'H)Â&%H.Ã!%H3ÄH8ÇH=c                 ó–  — t        | |||||||	|¬«	      }|dk(  }|xs i }|s|dk7  rt        d|z  «       |€
t        «       }i }|
D ]n  \  }}|rd||<   Œ|j                  d«      }t	        |t
        «      r|s|rd||<   Œ9t        d|z  «      ‚	 t        ||j                  d	«      |	«      \  }}||df||<   Œp i }g }t        |«      D �]Í  \  }}|
|t        |
«      z     \  }}||   \  }}}|rd} nt        |j                  |dk(  rd n|«      } d }!d}"|rn�| dk(  rn{|r_t        ||j                  «      }#t        |#|j                  d	«      |	d¬«      }!|!r$dj!                  |#j                  |!«      xs g «      nd}"|!}n|}!t#        |||j                  |«      }"t%        |d|j                  d«      |||df|	«      \  }$}%|rd\  }&}'n%t%        |d|j                  d«      |||df|	«      \  }&}'t%        |d|j                  d«      |||df|	«      \  }(})|g|_        |"|_        ||_        |!|_        ||_        |$|_        |&|_        |(|_        | |_        |!|%|)|'dœ|_        t;        |j<                  |$|«      |_        |r|j>                  r�Œ½|jA                  |«       �ŒÐ tC        |||xs i «       |S # t        $ r}t        d
|›d|›�«      ‚d }~ww xY w)N©rá   Úfreer–   z+[!] --dress %s se aplica a todos los stages)NNFÚoutfit_story)NNTz^[!] tema '%s' sin outfit_story; usa --allow-legacy-outfit o define outfit_story en themes.jsonÚoutfitz[!] outfit_story de 'z': Fr}   r+   T©Úwarnr   Úscene©r}   NÚpropsÚlighting©r&  r)  r,  r+  )"r!  Úprintr   r¸   Ú
isinstancer§   rß   Úchoose_outfit_storyÚ
ValueErrorrû   rÄ   r   r›   Ú_outfit_mappingr‘   Ú_choose_keyrŠ   Úoutfit_line_for_stageÚ
_axis_liner”   rƒ   rœ   r�   rž   r…   rš   r•   r—   r™   r   r‡   rŸ   r‰   r  )*r  r  Ú	variationÚvariantsr—   r  rÈ   rÙ   r  rÁ   ÚresolvedrÉ   rá   Úallow_legacy_outfitÚstrict_sceneÚaffinityrþ   rÿ   rý   r$  Úoutfit_stateÚnameÚthemeÚstoryÚbaserä   ÚexcÚcacher�   r   r‹   ÚfallbackÚ	job_dressr�   rƒ   Úmappingr…   Ú	scene_keyrš   Ú	props_keyr•   Ú	light_keys*                                             ry   Ú_compose_stage_theme_jobsrI  °  sQ  € ô ˜f l°G¸TÀ5Ø# \°3ÀôK€Dà�V‰O€DØŠ~˜2€Há�E˜V’OÜÐ;¸eÑCÔDØÐÜ “?ˆà€LÛ‰ˆˆeÙØ!4ˆL˜ÑØØ—	‘	˜.Ó)ˆÜ˜%¤Ô&©eÙ"Ø%7�˜TÑ"ØÜð7Ø9=ñ>ó?ð ?ð	KÜ-¨e°X·\±\À(Ó5KÈSÓQ‰KˆD�%ð # E¨5Ð1ˆ�TÒð!  ð$ €EØ€DÜ˜D—/‰ˆˆ3Ø˜q¤3 x£=Ñ0Ñ1‰ˆˆeØ ,¨TÑ 2Ñˆˆe�XÙØ‰Iä'Ø—	‘	 5¨F¢?™4¸ó?ˆIð ˆ
ØˆÙØØ˜&Ò ð ÙÜ% e¨S¯Y©YÓ7ˆGÜ$ W¨h¯l©l¸8Ó.DÀcØ*.ô0ˆJñ )ð  Ÿ9™9 W§[¡[°Ó%<Ò%BÀÔCØ.0ð à‰DàˆJÜ/°°t¸S¿Y¹YÈÓNˆKä *Ø�7˜HŸL™L¨Ó1°9¸eØ�7ˆO˜Só!"Ñˆ
�Iñ Ø$,Ñ!ˆJ™	ä$.Ø�w §¡¨WÓ 5°yÀ%Ø�w� ó%&Ñ!ˆJ˜	ô !+Ø�:˜xŸ|™|¨JÓ7¸ÀEØ�:Ð ó!%Ñˆ
�Ið �6ˆŒØ%ˆŒØˆŒØ#ˆŒØ&ˆÔØ#ˆŒØ#ˆŒØ#ˆŒØˆŒ	Ø&0¸9Ø(1¸IñGˆÔä"5Ø�M‰M˜: xó#1ˆÔá˜C×3Ò3ÙØ�‰�CÖðs "ôt �4˜ -Ò"5°2Ô6Ø€KøôC ò 	KÝºtÁSÐIÓJÐJûð	Kús   ÂJ)Ê)	KÊ2KËKc                 ó>  — t        | «      } | j                  «       st        d| › d�«       i S 	 t        j                  | j                  d¬«      «      }t        |t        «      st        d| › d	�«       i S |S # t        $ r}t        d| › d|› �«       i cY d}~S d}~ww xY w)
z«Lee `themes.json` -> `{nombre: tema}`. `{}` si falta o es ilegible.

    No aborta: los flags de tema son los que dan el error claro si el tema
    pedido no aparece.
    z[i] no existe z; sin temas disponiblesz	utf-8-sigr¬   z[!] no se pudo leer ú: Nú[!] z no es un objeto JSON de temas)	r   r¯   r.  ÚjsonÚloadsr°   Ú	Exceptionr/  r§   )r»   ÚdatarÒ   s      ry   Úload_themesrQ    s    € ô �‹:€DØ�;‰;Œ=Ü�˜t˜fÐ$;Ð<Ô=Øˆ	ðÜ�z‰z˜$Ÿ.™.°+˜.Ó>Ó?ˆô �dœDÔ!Ü��T�FÐ8Ð9Ô:Øˆ	Ø€Køô ò ÜÐ$ T F¨"¨Q¨CÐ0Ô1Ø�	ûðús   ®%A6 Á6	BÁ?BÂBÂBc                 ó¢   — | j                  d«      xs i }|j                  |«      r||   S t        D ]  }|j                  |«      sŒ||   c S  i S )zGVariantes de outfit del nivel; si no hay, cae al primer nivel con ropa.r&  )r¸   r	  )r>  r  r&  r  s       ry   r2  r2  &  sQ   € à�Y‰Y�xÓ Ò& B€FØ‡z�z�%ÔØ�e‰}ÐßˆØ�:‰:�b�>Ø˜"‘:Òð ð €Ir{   c                 ó°   — | j                  d«      xs i }dD ]/  }|j                  |«      xs i }||v sŒt        ||   xs g «      c S  t        d|z  «      ‚)Nr&  )r   r   zoutfit base '%s' no tiene tags)r¸   r¦   r1  )r>  r@  r&  r  rE  s        ry   Ú_story_base_tagsrT  1  s`   € Ø�Y‰Y�xÓ Ò& B€FÛ'ˆØ—*‘*˜UÓ#Ò) rˆØ�7Š?Ü˜ ™Ò+¨Ó,Ò,ð (ô Ð5¸Ñ<Ó
=Ð=r{   c                 óÚ   — g }t        «       }| xs g D ]U  }t        |«      j                  «       }|j                  «       }|sŒ/||vsŒ4|j	                  |«       |j                  |«       ŒW |S ©N)r€   rs   rt   rv   r¹   r‰   )Útagsr³   rº   r÷   rx   Úkeys         ry   Ú_dedupe_tagsrY  :  s`   € Ø
€CÜ‹5€DØŠz�rŠzˆÜ�3‹x�~‰~ÓˆØ�j‰j‹lˆÚ�C˜t’OØ�H‰H�SŒMØ�J‰J�tÕð ð €Jr{   c                 óp   — t        | «      j                  «       j                  dd«      j                  «       S )zKClave de comparacion: `_` y espacios son lo mismo (`fur_trim`==`fur trim`).ro   rp   )rs   rt   ru   rv   )r÷   s    ry   Ú_tag_keyr[  F  s)   € äˆs‹8�>‰>Ó×#Ñ# C¨Ó-×3Ñ3Ó5Ð5r{   c                 óŠ  — | xs i j                  |«      }|€g g fS t        |t        «      rt        |«      g fS t        |t        «      rn|j                  d«      xs g }|j                  d«      xs g }t        |t        «      rt        |t        «      st	        d|z  «      ‚t        |«      t        |«      fS t	        d|z  «      ‚)a  (add, remove) de un stage del outfit_story.

    Acepta la forma legacy (lista = solo anadir) y la forma con retirada:
    `{"add": [...], "remove": [...]}`. `remove` se aplica sobre los tags
    acumulados hasta ese stage, asi que cada stage solo declara su delta.
    r¹   Úremovez3outfit_story['%s']: 'add'/'remove' deben ser listasz1outfit_story['%s'] debe ser lista o {add, remove})r¸   r/  r¦   r§   r1  )rä   r›   Úvaluer¹   r]  s        ry   Ú_story_deltar_  K  sÂ   € ð Š[�b×Ñ˜eÓ$€EØ€}Ø�2ˆvˆÜ�%œÔÜ�E‹{˜BˆÐÜ�%œÔØ�i‰i˜ÓÒ$ "ˆØ—‘˜8Ó$Ò*¨ˆÜ˜#œtÔ$¬J°v¼tÔ,DÜØEÈÑMóOð Oä�C‹yœ$˜v›,Ð&Ð&Ü
Ø;¸eÑCóEð Er{   c                 óÌ  — | j                  d«      xs i }t        |t        «      r|st        d«      ‚|�||vrt        d|z  «      ‚|}n1|€t	        t        |«      «      }n|j                  t        |«      «      }|j                  |«      }t        |t        «      st        d|z  «      ‚dD ]'  }t        ||«      \  }}|rŒ|rŒt        d|›d|›�«      ‚ t        | |«       ||fS )Nr%  zel tema no tiene outfit_storyzoutfit base desconocido: %rz"outfit_story['%s'] no es un objeto)Úspicy1Úspicy2Ú	explicit1zoutfit_story['z'] no tiene )
r¸   r/  r§   r1  ÚnextÚiterÚchoicer¦   r_  rT  )	r>  Ú	preferredrÁ   r?  r@  rä   r›   r¹   r]  s	            ry   r0  r0  b  sã   € Ø�I‰I�nÓ%Ò+¨€EÜ�eœTÔ"©%ÜÐ8Ó9Ð9ØÐØ˜EÑ!ÜÐ:¸YÑFÓGÐGØ‰Ø	ˆÜ”D˜“KÓ ‰à�z‰zœ$˜u›+Ó&ˆØ�I‰I�d‹O€EÜ�eœTÔ"ÜÐ=ÀÑDÓEÐEÛ2ˆÜ" 5¨%Ó0‰ˆˆVÚš6ÝÂÁuÐMÓNÐNð 3ô �U˜DÔ!Ø�ˆ;Ðr{   c                 ó¾  — |t         vrt        d|z  «      ‚|dk(  ry|xs i }t        | |«      }|j                  d«      rt         D �cg c]
  }|dk7  sŒ	|‘Œ }}n|g}|D ]T  }t	        ||«      \  }	}
||	z   }|
r5|
D �ch c]  }t        |«      ’Œ }}|D �cg c]  }t        |«      |vsŒ|‘Œ }}||k(  sŒT n dj                  t        |«      «      S c c}w c c}w c c}w )a·  Ropa del stage: base + deltas del stage.

    `explicit2` devuelve "" (el stage va desnudo y el ensamblador anade los
    NUDE_TAGS). Por defecto solo se aplica el delta del stage actual (forma
    legacy: `oficina` y los packs ya generados no cambian). Con
    `"inherit": true` en la entrada del outfit los `add`/`remove` se acumulan
    desde `sugerente` hasta el stage pedido, que es lo que hace falta para
    desnudar por capas.
    zstage desconocido: %rÚ	explicit2r}   Úinheritr   )r   r1  rT  r¸   r_  r[  rŠ   rY  )r>  r@  r›   Ústory_entryrä   rW  ÚsÚsequenceÚcurrentr¹   r]  rô   rŒ   s                ry   r4  r4  y  s÷   € ð ”FÑÜÐ0°5Ñ8Ó9Ð9Ø�ÒØØÒ˜2€EÜ˜E 4Ó(€DØ‡y�y�ÔÝ%Ó:™v˜!¨¨kÓ)9’A˜vˆÑ:à�7ˆÛˆÜ" 5¨'Ó2‰ˆˆVØ�c‰zˆÙÙ)/Ó0© A”H˜Q•K¨ˆDÐ0Ù#Ó?™t˜!¤x°£{¸$Ò'>’A˜tˆDÐ?Ø�eÓÙð ð �9‰9”\ $Ó'Ó(Ð(ùò ;ùò 1ùÚ?s   Á
CÁCÁ<CÂCÂ'Cc                 óž   — t        | xs i «      }|sy|�"|| v r|S |rt        d|› d|d   › d�«       |d   S |€|d   S |j                  |«      S )z€Clave de variante: `key` si existe, si no la primera (aviso opcional) o
    una al azar con `rng` (determinista con `rng=None`).Nz[!] variante 'z' no existe; uso 'r   Ú')r¦   r.  rf  )rE  rX  rÁ   r(  Úkeyss        ry   r3  r3  ˜  sn   € ô �’˜2Ó€DÙØØ
€Ø�'‰>ØˆJÙÜ�N 3 %Ð'9¸$¸q¹'¸À!ÐDÔEØ�A‰wˆØ
€{Ø�A‰wˆØ�:‰:�dÓÐr{   c                 óŽ   — | sy|dk(  rt        | |dd¬«      S |dk(  r||vrt        | ||d¬«      ||<   ||   S t        | ||d¬«      S )z¹Resuelve la clave de un eje segun el modo de variacion.

    per-image: cada job tira la suya. per-pack: una sola tirada compartida
    (cache). fixed: la de `--variant eje=clave`.
    NÚfixedTr'  úper-pack)r3  )rE  Ú	fixed_keyr6  rB  Ú	cache_keyrÁ   s         ry   Ú	_axis_keyrw  ©  sd   € ñ ØØ�GÒÜ˜7 I¨t¸$Ô?Ð?Ø�JÒØ˜EÑ!Ü*¨7°I¸sÈÔNˆE�)ÑØ�YÑÐÜ�w 	¨3°TÔ:Ð:r{   c                 óª   — | j                  |«      xs i }|syt        ||||||«      }|r&dj                  |j                  |«      xs g «      |fS d|fS )zE-> (linea de tags, clave elegida) para un eje plano (scene/lighting).r*  r   r}   )r¸   rw  rŠ   )	r>  Úaxisru  r6  rB  rv  rÁ   rE  rX  s	            ry   r5  r5  º  s\   € à�i‰i˜‹oÒ# €GÙØÜ
�G˜Y¨	°5¸)ÀSÓ
I€CÙ14ˆD�I‰I�g—k‘k #Ó&Ò,¨"Ó-¸sÐBÐB¸"¸sÐBÐBr{   c                 óš  — |dk(  }|€
t        «       }g }| xs g D ]T  }|xs dj                  «       }|sŒ|j                  |«      }|st        d|› dt        › �«      ‚|j                  ||f«       ŒV |sk|�Tt        ||||||	|||¬«	      }|D ](  }|rdnt        |j                  |dk(  rdn|«      |_	        Œ* t        ||
|xs i «       |S t        ||||||	|
|||¬«
      S |�t        |||||||||	||||||||
|«      S |xs i }t        ||||||	|
|||¬«
      }i }t        |«      D �]£  \  }}||t        |«      z     \  }}|j                  }|rd}n|dk(  rt         j                  |d«      }n|}d\  }}|s¥|d	v r¡t#        ||«      } |d
k(  rH|df}!|!|vr!t%        | |j                  d«      |d¬«      ||!<   ||!   }|| vr8t'        t)        | «      d«      }n"t+        | |j                  d«      |||d|f|«      }|r$dj-                  | j                  |«      xs g «      }t/        |d|j                  d«      |||df|«      \  }"}#|rd\  }$}%n%t/        |d|j                  d«      |||df|«      \  }$}%t/        |d|j                  d«      |||df|«      \  }&}'|g|_        ||_        |"|_        |$|_        |&|_        ||_	        ||#|'|%dœ|_        �Œ¦ |S )aÒ  Como `compose_jobs`, pero pega los ejes del tema a cada Job.

    `theme_names` = [--theme NAME] + [--themes a,b]; con varios temas se reparten
    por job (round-robin). `dress` es el flag `--dress` o el centinela `"free"`.
    `variants` = {eje: clave} de `--variant eje=clave`. Lanza `SystemExit(1)` si
    un tema pedido no existe (no inventa un pack sin tema). Con `stage_quotas`
    entra el modo de 5 etapas; sin el, se mantiene el modo legacy por nivel.
    r$  Nr}   z
[!] tema 'z' no encontrado en r#  r–   r*  )r)   r*   rt  r&  Tr'  r   r)  r+  r,  r-  )rQ  rt   r¸   rß   ÚTHEMES_FILEr‰   r!  r   r›   r—   r  r  rI  rû   rÄ   r‘   ÚLEVEL_DRESSr2  r3  rd  re  rw  rŠ   r5  r”   rƒ   r…   rš   r•   r™   )(Útheme_namesr  r  r6  r7  r—   r  rÈ   rÙ   r  rþ   rÁ   ÚthemesrÉ   rá   r  r9  r:  r;  rÿ   r$  r8  r=  r>  rý   r‹   rB  r   r  rD  rƒ   r�   rE  Úpack_keyr…   rF  rš   rG  r•   rH  s(                                           ry   Úcompose_theme_jobsr€  Ã  s‰  € ð �V‰O€DØ€~Ü“ˆà€HØÒ" Ò"ˆØ’
˜×!Ñ!Ó#ˆÙØØ—
‘
˜4Ó ˆÙÜ˜z¨$¨Ð/BÄ;À-ÐPÓQÐQØ�‰˜˜u˜Õ&ð #ñ ØÐ#Ü% f¨l¸GÀTØ&+¨U°LÀ#Ø/7ô9ˆDó �Ù'+™VÜ,¨S¯Y©YØ5:¸f²_©TÈ%óQð •	ð ô ˜4 ¨-Ò*=¸2Ô>ØˆKÜ˜F F¨G°T¸5À%ÈØ(¨#¸ôBð 	Bð ÐÜ(Ø�L )¨X°u¸gÀtØ�5˜#˜x¨°xØ ¨x¸Øó	ð 	ð Š~˜2€HÜ˜ ¨°°u¸eÀWØ$ c°Hô>€Dð €EÜ˜D—/‰ˆˆ3Ø˜q¤3 x£=Ñ0Ñ1‰ˆˆeØ—	‘	ˆáØ‰IØ�fŠ_Ü#Ÿ™¨¨vÓ6‰IàˆIà"*Ñˆ�Zñ ˜	Ð%=Ñ=Ü% e¨UÓ3ˆGØ˜JÒ&ð ! (Ð+�Ø 5Ñ(Ü&1Ø §¡¨hÓ!7¸À4ô'I�E˜(‘Oà" 8™_�
Ø WÑ,Ü!%¤d¨7£m°TÓ!:‘Jä&Ø˜XŸ\™\¨(Ó3°YÀØ˜8 UÐ+¨Só2�
ñ Ø"Ÿi™i¨¯©°JÓ(?Ò(EÀ2ÓF�ä *¨5°'¸8¿<¹<ÈÓ;PØ+4°e¸dÀG¸_Ècó!SÑˆ
�Iñ Ø$,Ñ!ˆJ™	ä$.Ø�w §¡¨WÓ 5°yÀ%Ø�w� ó%&Ñ!ˆJ˜	ô !+Ø�:˜xŸ|™|¨JÓ7¸ÀEØ�:Ð ó!%Ñˆ
�Ið �6ˆŒØ%ˆŒØ#ˆŒØ#ˆŒØ#ˆŒØˆŒ	Ø&0¸9Ø(1¸IñGˆÖðm "ðp €Kr{   c                 ó   — t        | «      S )zI`--dress`/nivel -> force_nude del ensamblador (nude=always, resto never).)r   )r—   s    ry   Ú_force_nude_forr‚  3  s   € ä˜%Ó Ð r{   c                 óJ   — t        | j                  «      }|s|S |r|› d|› �S |S )z>Negative del job: anade el bloque de vestuario segun el dress.r   )r   r—   )r‹   Úbase_negÚextras      ry   Útheme_negativer†  8  s0   € ä˜3Ÿ9™9Ó%€EÙØˆÙ%-ˆhˆZ�r˜%˜Ð!Ð8°5Ð8r{   c                 óÎ   — i }| xs g D ]Y  }d|vrt        d|› d�«      ‚|j                  dd«      \  }}|j                  «       ||j                  «       j                  «       <   Œ[ |S )z'`["eje=clave", ...]` -> `{eje: clave}`.Ú=z*[!] --variant espera eje=clave, recibido 'rp  r¾   )rß   rˆ   rt   rv   )rÅ   r³   Úitemry  rX  s        ry   Úparse_variantsrŠ  @  sm   € à
€CØ’˜’ˆØ�d‰?ÜÐIÈ$ÈÈqÐQÓRÐRØ—J‘J˜s AÓ&‰	ˆˆcØ$'§I¡I£KˆˆD�J‰J‹L×ÑÓ Ò!ð	 ð
 €Jr{   c           	      óŠ  — |}|j                   r|› d|j                   › �}|j                  }t        |dd«      rt        |«      }|j                  rt        |«      }||j                  |j                  |j                  |j                  g}dj                  d„ |D «       «      }t        | ||dt        |j                  «      ¬«      S )zçPrompt positivo ensamblado: ropa en la chica, escena+props+luz en el bloque.

    Sin tema (`job.outfit_line`/`scene_line`/`props_line`/`light_line` vacios y
    dress auto) el resultado es identico al de antes: pose + camara.
    r   r    Fc              3   ó&   K  — | ]	  }|sŒ|–— Œ y ­wrV  rª   )Ú.0Úps     ry   Ú	<genexpr>z#build_run_prompt.<locals>.<genexpr>]  s   è ø€ Ð,¡˜Aª!”a¡ùs   ‚Š)Úage_upÚ
force_nude)rƒ   r‡   ÚgetattrrŽ   r…   r   rš   r•   r�   rŠ   r   r‚  r—   )ÚmasterÚ	char_liner‹   ÚgirlÚblockÚpartss         ry   Úbuild_run_promptr˜  K  s¬   € ð €DØ
‡‚Ø�˜B˜sŸ™Ð/Ð0ˆà�M‰M€EÜˆs�M 5Ô)Ü Ó$ˆØ
‡~‚~ô ! Ó'ˆØ�C—N‘N C§N¡N°C·N±NÀCÇJÁJÐO€EØ�I‰IÑ,¡Ó,Ó,€EÜ˜  e°EÜ#2°3·9±9Ó#=ô?ð ?r{   c                 ó°  — | €t        t        «      S | j                  d«      D �cg c]  }|j                  «       ‘Œ }}t	        |«      t	        t
        «      k7  r't        dt	        t
        «      › dt	        |«      › �«      ‚	 |D �cg c]  }t        |«      ‘Œ }}t        t        t
        |«      «      S c c}w c c}w # t        $ r t        d| › d�«      ‚w xY w)zD'18,20,17' -> dict por nivel, en el orden sugerente,spicy,explicito.r~   z[!] --levels necesita z0 valores (sugerente,spicy,explicito), recibidos z [!] --levels debe ser enteros: 'rp  )
r§   ÚDEFAULT_QUOTASrˆ   rt   rÄ   r	  rß   r©   r1  Úzip)rx   rŽ  r—  r  s       ry   Úparse_levelsrœ  b  sÔ   € à€|Ü”NÓ#Ð#Ø $§
¡
¨3¤Ó0¡˜1ˆQ�W‰W�Y €EÐ0Ü
ˆ5ƒz”Sœ“[Ò ÜØ$¤S¬£[ Mð 26Ü69¸%³j°\ðCóDð 	DðEÙ"'Ó(¡%˜Q”#�a•& %ˆÐ(ô ””F˜FÓ#Ó$Ð$ùò 1ùò )øÜò EÜÐ;¸D¸6ÀÐCÓDÐDðEús#   ¥B2ÂB< ÂB7ÂB< Â7B< Â<Cc                 ój   — 	 ddl m}  || «       y# t        $ r}t        d|z  «       Y d}~yd}~ww xY w)zBAviso por Telegram; nunca rompe la corrida si no esta configurado.r   )Úsend_telegram_msgz![i] aviso Telegram no enviado: %sN)Únotifierrž  rO  r.  )Úmessagerž  rÒ   s      ry   Únotifyr¡  r  s3   € ð7Ý.Ù˜'Õ"øÜò 7ÜÐ1°AÑ5×6Ñ6ûð7ús   ‚ ‘	2š-­2c                  ó|   — ddl } 	 | j                  t        › d�d¬«      }|j                  dk(  S # t        $ r Y yw xY w)z9True si Forge responde a /sdapi/v1/options (timeout 15s).r   Nz/sdapi/v1/optionsr&   )ÚtimeoutéÈ   F)Úrequestsr¸   ÚFORGEÚstatus_coderO  )r¥  Úrs     ry   Úforge_availabler©  {  sE   € ãðØ�L‰LœE˜7Ð"3Ð4¸bˆLÓAˆØ�}‰} Ñ#Ð#øÜò Ùðús   †(/ ¯	;º;c                 ó�   — t        j                  d| xs d«      }|sy	 t        |j                  d«      «      S # t        $ r Y yw xY w)zCPeso del <lora:...:W> de la linea (1.0 si falta). Solo informativo.z<lora:[^:>]+:([^>]*)>r}   g      ð?r¾   )ÚreÚsearchÚfloatÚgroupr1  )r”  Úms     ry   Ú_lora_weightr°  …  sG   € ä
�	‰	Ð*¨IªO¸Ó<€AÙØðÜ�Q—W‘W˜Q“ZÓ Ð øÜò Ùðús   Ÿ9 ¹	AÁAc                 ó„   — | r| S t        j                  d|xs d«      }|r|j                  d«      j                  «       S dS )zCClave del personaje; si no se pasa, el nombre del LoRA de la linea.z<lora:([^:>]+):[^>]*>r}   r¾   )r«  r¬  r®  rt   )Úcharr”  r¯  s      ry   Ú
_char_namer³  �  s=   € áØˆÜ
�	‰	Ð*¨IªO¸Ó<€AÙ!"ˆ1�7‰7�1‹:×ÑÓÐ*¨Ð*r{   c                 ó¦   — |j                   xs |j                  }|j                  dk(  r|j                  r|j                  nd}| d›d|› d|› d|› d�S )NrÈ   ÚnewÚ02dro   Ú_sz.png)r›   r‘   r’   r“   )Úorderr‹   r¡   r÷   Úposeids        ry   Ú_image_namerº  ˜  sQ   € Ø
�)‰)Ò
 �s—y‘y€CØ ŸZ™Z¨6Ò1°c·k²kˆS�[Š[È€FØ�Cˆ[˜˜#˜˜a ˜x r¨$¨¨tÐ4Ð4r{   c           
      ó|  — t         D �ci c]  }|d“Œ }}t        D �ci c]  }|d“Œ }}| D ]N  }	|	j                  d«      }|j                  |d«      dz   ||<   t        |	«      }|j                  |d«      dz   ||<   ŒP d}
|�@t         D �ci c]1  }|t	        |j                  |d«      «      |j                  |d«      z
  “Œ3 }
}d}|�@t        D �ci c]1  }|t	        |j                  |d«      «      |j                  |d«      z
  “Œ3 }}t        | «      t	        |«      d||t        |«      |
|dœS c c}w c c}w c c}w c c}w )ab  Metricas de la corrida a partir de los records generados.

    `records` solo lleva las imagenes guardadas; `failed` se pasa aparte (una
    imagen fallida no tiene fichero, asi que no genera record). `planned` es el
    reparto por nivel deseado (de los jobs) para calcular el faltante.
    `planned_stage` anade el reparto por stage y su faltante.
    r   r‘   r¾   N)Ú	generatedÚfailedÚ	keep_rateÚby_levelÚby_stageÚ
budget_hitr  Úshortfall_stage)r	  r   r¸   r   r©   rÄ   r¨   )ÚrecordsÚplannedr½  rÁ  Úplanned_stager  r¿  r›   rÀ  Úrecr  rÂ  s               ry   Úcompute_metricsrÇ  ž  sw  € õ !'Ó'¡˜"��A‘ €HÐ'Ý&,Ó-¡f˜U��q‘ f€HÐ-ÛˆØ�W‰W�WÓˆØ—|‘| B¨Ó*¨QÑ.ˆ�‰Ü  Ó%ˆØ"Ÿ,™, u¨aÓ0°1Ñ4ˆ�Šð	 ð
 €IØÐå%ó'Ù%˜ð œ˜WŸ[™[¨¨QÓ/Ó0°8·<±<ÀÀAÓ3FÑFÑFØ%ð 	ð 'à€OØÐ åAGóIÙAG¸ð !¤# m×&7Ñ&7¸¸qÓ&AÓ"BØ%Ÿ\™\¨%°Ó3ñ#4ñ 4ØAGð 	ð Iô ˜“\Ü�f“+ØØØÜ˜:Ó&ØØ*ñ	ð 	ùò (ùÚ-ùò'ùòIs   ‰
D*�
D/Â6D4Ã6D9c
                 ó8
  — ddl }
t        |«      }|j                  dd¬«       i }i }| D ]g  }|j                  |j                  d«      dz   ||j                  <   |j
                  sŒ<|j                  |j
                  d«      dz   ||j
                  <   Œi t        ||«      }t        |«      }g }d}d}d}d}|du}t        d„ | D «       «      }|rt        d«       nt        d	|rd
t        |«      z   nd› �«       t        | d«      D �]²  \  }}||k\  rd} �n¥|	�& |	«       rd}t        d|› dt        | «      › �«        �n}|�6 |d|t        | «      |j                  |j
                  |j                  dœ«       |j                  �t        |j                  «      }n|r|nt!        j"                  dd«      }t%        |||«      }t'        ||«      }d}d}dD ]{  }|dz  }|dk(  r$|j                  €|st!        j"                  dd«      }	 ||ddddddd|ddœ}|
j)                  t*        › d�|d¬«      }|j-                  «        |j/                  «       } n |€�|dz  }t        d|› dt        | «      › d|j                  › d |j2                  › d!|› d"�«       |�@ |d#|t        | «      |j                  |j
                  |j                  t        |«      d$œ«       �ŒÍ	 t/        j4                  |j                  d%d&«      «      j                  d'|«      }!t7        |||!«      }"||"z  j9                  t;        j<                  |d(   d   «      «       |j?                  i d)d*|"› �“d+|j                  “d,|j                  “d-|j
                  “d.tA        |jB                  «      “d/|“d'|!“d0|“d1|“d2|jD                  “d3|j2                  “d4|jF                  “d5|jB                  r|jB                  d   nd“d6|jH                  “d7|jJ                  “d8|jL                  “d9tA        |jN                  «      “tQ        |jR                  «      |jT                  |jV                  dg d:œ¥«       t        d|› dt        | «      › d|j                  › d |j2                  › d;|"› d<|!› d"�«       |€�Œ� |d=|t        | «      |d>   t        ||"z  «      d?œ«       �Œµ tY        |||||xs d¬@«      }#||#dA<   ||#fS # t0        $ r} | }t        d|› d| › �«       Y d} ~ nd} ~ ww xY w||k\  s�Œ7d} �Œ¾# t0        $ r |}!Y �Œw xY w)BaÕ  Llama a Forge txt2img job a job y escribe los PNG en `out_dir`.

    -> (records, metrics). `records` es la lista de dicts del manifest (solo
    imagenes guardadas; su `file` es SIEMPRE img/<nombre>, segun el ruling).
    Reintenta una vez por imagen; si el 2do intento falla, cuenta en
    metrics["failed"] y sigue (no aborta). `budget` limita los intentos totales
    (incluidos reintentos); si se agota antes de acabar, budget_hit=True.

    `on_image` y `should_stop` son opcionales (los usa la UI, no el CLI): el
    primero recibe un dict por evento (`start`, `done`, `fail`) y el segundo se
    consulta antes de cada imagen para poder cancelar. Con los defaults el
    comportamiento es identico al de siempre.
    r   NT©ÚparentsÚexist_okr¾   Fc              3   ó8   K  — | ]  }|j                   d u–— Œ y ­wrV  )r¡   )r�  r‹   s     ry   r�  zgenerate.<locals>.<genexpr>æ  s   è ø€ Ð<±t°�s—x‘x tÔ+±tùs   ‚z-[-] semilla: una por job (distinta por stage)z[-] semilla: zfija zaleatoria por imagenz![!] cancelado antes de la imagen Ú/r  )ÚeventÚindexr  r‘   r›   r“   l   ÿÿ )r¾   é   rÐ  i@  iÀ  é   g      @zDPM++ 2M Karras)ÚpromptÚnegative_promptÚwidthÚheightÚstepsÚ	cfg_scaleÚsampler_nameÚ
batch_sizeÚn_iterr¡   Ú	clip_skipz/sdapi/v1/txt2imgi,  )rM  r£  z
    [FAIL z/2] Ú[ú] rp   z -> FALLO (Ú)Úfail)rÎ  rÏ  r  r‘   r›   r“   ÚerrorÚinfoz{}r¡   ÚimagesÚfilezimg/r“   r‘   r›   r”   r²  Úlora_weightrÒ  r‡   r’   r�   r>  rœ   r�   rž   rŸ   )r7  r—   r    ÚverdictÚmotivosz -> z (seed=Údoneéÿÿÿÿ)rÎ  rÏ  r  Úrecordr»   )rÄ  r½  rÁ  rÅ  Ústopped)-r¥  r   Úmkdirr¸   r‘   r›   r³  r°  Úanyr.  rs   rû   rÄ   r“   r¡   r©   ÚrandomÚrandintr˜  r†  Úpostr¦  Úraise_for_statusrM  rO  r’   rN  rº  Úwrite_bytesÚbase64Ú	b64decoder‰   r¦   r”   r‡   r�   rœ   r�   rž   rŸ   r§   r™   r—   r    rÇ  )$rý   r”  r“  ÚnegÚout_dirr¡   Úbudgetr²  Úon_imageÚshould_stopr¥  rÄ  rÅ  r‹   Úrec_charrä  rÃ  r½  ÚattemptsrÁ  rê  Ú
fixed_seedÚper_job_seedr   Újob_seedrÒ  Újob_negrP  rà  ÚattemptÚpayloadÚresprÒ   Ú	used_seedr=  Úmetricss$                                       ry   Úgenerater  Â  s¤  € ó ä�7‹m€GØ‡M�M˜$¨€MÔ.à€GØ€MÛˆØ$Ÿ[™[¨¯©°AÓ6¸Ñ:ˆ�—	‘	ÑØ�9‹9Ø'4×'8Ñ'8¸¿¹ÀAÓ'FÈÑ'JˆM˜#Ÿ)™)Ò$ð ô
 ˜$ 	Ó*€HÜ˜yÓ)€Kà€GØ€FØ€HØ€JØ€GØ˜TÐ!€JÜÑ<±tÓ<Ó<€LÙÜÐ=Õ>ä�±Z˜g¬¨D«	Ò1ÐE[Ð\Ð]Ô^ä˜D !×$‰ˆˆ3Ø�vÒØˆJÚØÐ"¡{¤}ØˆGÜÐ5°a°S¸¼#¸d»)¸ÐEÔFÚØÐÙ˜w°¼SÀ»YØ"Ÿy™y°3·9±9Ø!$§¡ñ.ô /ð �8‰8ÐÜ˜3Ÿ8™8“}‰Há)‘t¬v¯~©~¸aÀÓ/KˆHÜ! &¨)°SÓ9ˆÜ   cÓ*ˆØˆØˆÛˆGØ˜‰MˆHØ˜!Š| §¡Ð!5¹ZÜ!Ÿ>™>¨!¨YÓ7�ð5à$¸Ø ¨D¸2ÈCØ$5ÀQØ¨Àñ	�ð  —}‘}¬ wÐ.?Ð%@ÀwØ-0ð %ó 2�à×%Ñ%Ô'Ø—y‘y“{�Ùð ð. ˆ<Ø�a‰KˆFÜ�A�a�S˜œ#˜d›)˜ B s§y¡y k°°3·:±:°,ð ?Ø�W˜Aðô  àÐ#Ù 6°AÄÀDÃ	Ø#&§9¡9°s·y±yØ%(§[¡[¼3¸u»:ñGô Hñ ð	!ÜŸ
™
 4§8¡8¨F°DÓ#9Ó:×>Ñ>¸vÀxÓPˆIô ˜1˜c 9Ó-ˆØ	�4‰×$Ñ$¤V×%5Ñ%5°d¸8±nÀQÑ6GÓ%HÔIØ�‰ð 
Ø�d˜4˜&�Mð
à�s—{‘{ð
ð �S—Y‘Yð
ð �S—Y‘Yð	
ð
 ”D˜Ÿ™“Nð
ð �Hð
ð �Ið
ð ˜;ð
ð �fð
ð ˜Ÿ™ð
ð �c—j‘jð
ð �c—j‘jð
ð  C§H¢H�S—X‘X˜a’[°$ð
ð ˜3Ÿ?™?ð
ð ˜#Ÿ.™.ð
ð  ˜s×2Ñ2ð!
ð" "¤4¨×(?Ñ(?Ó#@ð#
ô$ ˜S×-Ñ-Ó.Ø—Y‘YØŸ?™?ØØò-
ô 	ô0 	��!��A”c˜$“i�[  3§9¡9 +¨Q¨s¯z©z¨l¸$¸t¸fð EØ �k ð$ô 	%àÒÙ˜v°¼CÀ»IØ '¨¡Ü! '¨D¡.Ó1ñ3ö 4ðo %ôv ˜g¨w¸vØ)3Ø,9Ò,A¸TôC€Gð !€GˆIÑØ�GÐÐøôu ò 5Ø�Ü˜
 7 )¨4°¨sÐ3×4Ñ4ûð5úð ˜6Ô!Ø!�
Úøô ò 	!Ø ‹Ið	!ús+   È A	SË5T
Ó	S;ÓS6Ó6S;Ô
TÔTc                  ó2  ‡'‡(— t        j                  d¬«      } | j                  ddd¬«       | j                  dd d¬	«       | j                  d
d d¬	«       | j                  dg d¢dd¬«       | j                  ddd dd¬«       | j                  dg d¢dd¬«       | j                  ddd¬«       | j                  dt        dd ¬!«       | j                  d"d d#¬	«       | j                  d$d d%¬	«       | j                  d&dd'¬«       | j                  d(dd)¬«       | j                  d*dd+¬«       | j                  d,t        d-d.¬!«       | j                  d/t        d0d1¬!«       | j                  d2t        d d3¬!«       | j                  d4dd5¬«       | j                  d6d d7d8¬9«       | j                  d:dd;¬«       | j                  d<t        d d=d>¬?«       | j                  d@ddA¬«       | j                  dBd dCdD¬9«       | j                  dEt        d dF¬!«       | j                  «       }|j                  �|j                  rt        dG«      ‚|j                  s#|j                  €|j                  st        dH«      ‚|j                  �|j                  �t        dI«      ‚|j                  d u }|rF	 t        |j                  «      }t        t        «      }t!        «       }t#        |¬K«      }t%        «       }n%d }d }d }t'        |j                  «      }t!        «       }t(        D �	ci c]  }	|	t+        |	«      “Œ }
}	t-        j.                  «       }t-        j0                  «       }t3        t5        t6        «      «      }|j9                  |j:                  «      }|st        dL|j:                  › dM�«      ‚|dN   }|j                  �|j                  n|j<                  }g }|j>                  r|jA                  |j>                  «       |jB                  r1|jE                  dO„ |jB                  jG                  dP«      D «       «       |jH                  rH|jH                  jG                  dP«      D �cg c]#  }|jK                  «       sŒ|jK                  «       ‘Œ% c}nd }tM        jN                  |jP                  «      }|jR                  rdQn|jT                  }|r tW        |jX                  «      }|rQt[        ||||j\                  |||j^                  |||
|||j`                  |||jb                  |jd                  ||¬R«      }nèt[        ||||j\                  |||j^                  |||
|||j`                  |¬S«      }n°|r…tg        |||j^                  |||
|j`                  ||¬T«	      }|D ]F  }|jR                  rdn0ti        |jj                  |jT                  dk(  rd n|jT                  «      |_*        ŒH tm        |||xs i «       n)to        |||j^                  |||
||j`                  ||¬T«
      }|j                  �|d |j                   }|D ]  }|jp                  |_8        Œ |jr                  rì|jP                  �|jP                  ntM        jt                  dUdV«      Š'i }tw        |«      D ]w  \  }}|jj                  r\|jy                  |jj                  dW«      }|dUz   ||jj                  <   ‰'t{        j|                  |jj                  «      dXz  z   |z   |_(        Œn‰'|z   |_(        Œy t        dY‰'› dZ�d[j�                  ˆ'fd\„tw        tz        «      D «       «      z   «       |j                  �rët        d]tƒ        |«      › d^|j:                  › d_|j>                  › �«       t        d`tƒ        |«      › datƒ        |«      › �«       t(        D �	ci c]  }	|	dW“Œ }}	tz        D �ci c]  }|dW“Œ c}Š(tw        |dU«      D �]  \  }}|jy                  |j„                  dW«      dUz   ||j„                  <   |jj                  r,‰(jy                  |jj                  dW«      dUz   ‰(|jj                  <   t‡        |jˆ                  ||«      }t        db|› dctƒ        |«      › dd|j„                  › de|jŠ                  › de|jŒ                  › df|jj                  xs dg› dh|jŽ                  › �|jP                  �di|jP                  › �ndjz   «       t        dk|d dl › �«       |j�                  s$|j’                  s|j”                  s|j–                  r dej�                  dm„ |j˜                  j›                  «       D «       «      }t        dn|jœ                  › do|jT                  › dp|jž                  › dq|j�                  › dr|j’                  › ds|j”                  › dt|j–                  › �|rdu|› �ndjz   «       |j                   s�Œît        dvduj�                  |j                   «      z   «       �Œ t        dw|dx   › dy|dz   › d{|d|   › �«       |r*t        d}d~j�                  ˆ(fd„tz        D «       «      z   «       y t£        «       s1d€t¤        › d��} t        d‚| › �«       t§        dƒ| › �«       t        dU«      ‚|j                  �0t¨        t«        j¬                  «       j¯                  d„«      z  }!|!d…z  }"n+t°        |j:                  › d†|j>                  xs d‡› �z  }!|!dˆz  }"|!j³                  dd¬‰«       |j´                  �|j´                  n|dŠz  }#t·        |||jˆ                  |j¸                  |"|jP                  |#|j:                  ¬‹«      \  }$}%|%dŒ   dWkD  r,|!d�z  j»                  t½        j¾                  |$dŽdU¬�«      d�¬‘«       |!d’z  j»                  t½        j¾                  |%dŽdU¬�«      d�¬‘«       |j                  rO|%dŒ   dWkD  rGtÁ        |"|!d…z  |jÂ                  xs dj«      }&t        d“tƒ        |&«      › d”�|jÂ                  rd•nd–z   «       t        d—|%dŒ   › d˜|%d™   › dš|!› �«       |%d›   rt        dœ|#› d�|%dž   › �«       |%dŒ   dWkD  rt        dŸ«       nt        d «       t§        d¡|%dŒ   › d¢|!› �«       y # t        $ r}t        dJ|z  «      ‚d }~ww xY wc c}	w c c}w c c}	w c c}w )£NzPlanificador de packs PlumLoom)Údescriptionz--charTz$clave del personaje (personajes.txt))ÚrequiredÚhelpz--themez7tema del pack (nombre en Archivos/danbooru/themes.json))Údefaultr  z--themesz&varios temas separados por comas (a,b)z--variation)ú	per-imagert  rs  r
  z=variacion de variantes por job/pack/fijas (default per-image))Úchoicesr	  r  z	--variantr‰   z	EJE=CLAVEzNcon --variation fixed: variante por eje (repetible). Ej: --variant scene=shore)Úactionr	  Úmetavarr  z--dress)r–   r)   r*   Úlingerier8   r+   r–   zEauto (stage->dress) | dressed | stripping | lingerie | clothed | nudez--freeÚ
store_truez;sin outfit: el tema solo sesga escena/luz (force_nude auto))r  r  z--targeté-   zimagenes objetivo (default 45))Útyper	  r  z--levelsz:quotas legacy sugerente,spicy,explicito (default 15,16,14)z--stageszPquotas por stage sugerente,spicy1,spicy2,explicit1,explicit2 (default 9,9,9,9,9)z--allow-legacy-outfitz6permite temas sin outfit_story (modo legacy por nivel)z--strict-scenez5descarta jobs con choque pose/escena (default: avisa)z--clean-poseszYquita de la pose los tags que contradicen el stage/tema (estado de ropa, encuadre, fondo)z	--exploregš™™™™™É?zratio exploracion (default 0.2)z--max-variantsrÐ  z0reusos maximos de una pose del banco (default 2)z--seedzRsemilla fija (default: aleatoria por imagen; fijala solo para corregir una imagen)z--seed-per-stagezncada stage usa su propia semilla (base + stage*1000003 + i); evita que el mismo seed repita poses entre stagesz
--bank-idszID[,ID]zWfija poses del banco (p.ej. pb0001,pb0008,pb0011); util para variar la pose entre temas)r	  r  r  z	--dry-runzimprime el plan sin tocar Forgez--pilotÚNz8genera un piloto de N imagenes en Output/pilots/<stamp>/)r  r	  r  r  z--packz.genera un pack en Output/packs/<clave>_<tema>/z--watermarkÚTEXTOzDtexto de la marca de agua para img/ en --pack (sin el = copia plana)z--budgetz4maximo de intentos de generacion (default 3x target)z$[!] elige --pilot o --pack, no ambosz.[!] elige --pilot N o --pack (o usa --dry-run)z0[!] no se pueden usar --levels y --stages juntosz[!] --stages: %s)rC  z[!] personaje 'z' no esta en personajes.txtr@  c              3   ó^   K  — | ]%  }|j                  «       sŒ|j                  «       –— Œ' y ­wrV  )rt   )r�  rô   s     ry   r�  zmain.<locals>.<genexpr>®  s!   è ø€ ÐRÑ.D¨ÈÏÉÍ	˜1Ÿ7™7Ÿ9Ñ.Dùs   ‚-˜-r~   r$  )rÉ   rá   r  r9  r:  r;  rÿ   )rÉ   rá   r#  r¾   iÿÿÿr   éCB z[-] semillas por stage desde rK  r   c              3   ó>   •K  — | ]  \  }}|› d ‰|dz  z   › �–— Œ y­w)rp   r  Nrª   )r�  r   Ústr@  s      €ry   r�  zmain.<locals>.<genexpr>è  s2   øè ø€ ð :Ù'8™e˜a ð  ˜D  $¨¨W©Ñ"4Ð!5Ô6Ù'8ùs   ƒz
[-] plan: z jobs | personaje z | tema z[-] banco: z poses | camaras: rÜ  rÍ  rÝ  rp   z	 | stage:Ú-z | cam:z | seed:r}   z    prompt: é–   c              3   ó4   K  — | ]  \  }}|r	|› d |› �–— Œ y­w)rˆ  Nrª   )r�  r  Úvs      ry   r�  zmain.<locals>.<genexpr>û  s)   è ø€ ð  &Ñ7O©t¨q°!Ù#$ð $% # Q q c¤
Ñ7Oùs   ‚z    tema  : z	 | dress:z | outfit_base:z
 | outfit:z	 | scene:z	 | props:z	 | light:z | z    aviso : z
[OK] quota: sugerente r   z	 / spicy r   u    / explÃ­cito r   z[OK] stages: z / c              3   ó2   •K  — | ]  }|› d ‰|   › �–— Œ y­w)rp   Nrª   )r�  r›   Ú	per_stages     €ry   r�  zmain.<locals>.<genexpr>  s'   øè ø€ ð /CÙ;A°%�5�'˜˜9 UÑ+Ð,Ô-¹6ùs   ƒzForge NO responde en z. Arranca webui-user.bat --apirL  u   â�Œ z%Y%m%d_%H%M%SÚimgro   Úsin_temaÚrawrÉ  é   )r²  r¼  zpack_manifest.jsonF)Úensure_asciiÚindentr   r¬   zmetrics.jsonz[OK] img/: z	 ficherosz (marca de agua)z (copia plana)z
[OK] z imagenes generadas (r½  z fallidas) -> rÁ  z[!] budget agotado (z); faltante por nivel: r  z/[OK] pack_manifest.json + metrics.json escritosz3[!] nada generado; NO se escribe pack_manifest.jsonu   âœ… Generadas u    imÃ¡genes -> )bÚargparseÚArgumentParserÚadd_argumentr©   r­  Ú
parse_argsÚpilotÚpackrß   Údry_runÚlevelsÚstagesr   r1  r§   rš  rµ   r   r   rœ  r	  r¼   rÆ   Ú	load_bankÚ
load_avoidr   rs   ÚBASE_DIRÚget_characterr²  r  r>  r‰   r~  r×   rˆ   rá   rt   rí  ÚRandomr¡   r$  r—   rŠ  Úvariantr€  r6  r  rÉ   r9  r:  r!  r   r›   r  r  r    Úseed_per_stagerî  rû   r¸   r   rÏ  r.  rŠ   rÄ   r‘   r˜  Úmaster_promptr’   r‡   r�   rƒ   r…   rš   r•   r™   rÅ   r”   rœ   rŸ   r©  r¦  r¡  Ú
PILOTS_DIRr   ÚnowÚstrftimeÚ	PACKS_DIRrë  rö  r  rÓ  Ú
write_textrM  Údumpsr   Ú	watermark))rŽ  ÚargsÚ
stage_moder  rA  r  rþ   rÿ   r;  r  r  rÈ   rÙ   ÚBr²  r”  r  r}  Úxrá   rÁ   Ú	dress_argr7  rý   r‹   Úcountersr   ÚidxÚ	per_levelr›   Úposrq  ÚmsgÚrun_dirÚimg_dirrö  rÃ  r  Úmader@  r  s)                                          @@ry   ÚmainrI  N  s>  ù€ Ü×ÑÐ,LÔM€AØ‡N�N�8 dÐ1W€NÔXØ‡N�N�9 dØQð ô Sà‡N�N�: tØ@ð ô Bà‡N�N�=Ò*LØ&ØWð ô Yð ‡N�N�; x¸À{ð4ð ô 5ð ‡N�N�9ò 'Fà!ð)ð ô *ð
 ‡N�N�8 LØUð ô Wà‡N�N�:¤C°Ð:Z€NÔ[Ø‡N�N�: tØTð ô Và‡N�N�: tð8ð ô 9ð ‡N�NÐ*°<ØPð ô Rà‡N�NÐ#¨LØOð ô Qà‡N�N�?¨<ð<ð ô =ð ‡N�N�;¤U°CÐ>_€NÔ`Ø‡N�NÐ#¬#°qØJð ô Là‡N�N�8¤#¨tØlð ô nà‡N�NÐ%¨lðLð ô Mð ‡N�N�<¨°yð?ð ô @ð ‡N�N�; |Ø9ð ô ;à‡N�N�9¤3°¸cØRð ô Tà‡N�N�8 LØHð ô Jà‡N�N�=¨$¸ð1ð ô 2ð ‡N�N�:¤C°ØNð ô Pà�<‰<‹>€Dà‡z�zÐ $§)¢)ÜÐ?Ó@Ð@Ø�<Š<˜DŸJ™JÐ.°t·y²yÜÐIÓJÐJØ‡{�{Ð 4§;¡;Ð#:ÜÐKÓLÐLà—‘ Ð$€JÙð	7Ü-¨d¯k©kÓ:ˆLô ”nÓ%ˆÜ“.ˆÜ*°GÔ<ˆÜ “?‰àˆØˆØˆÜ˜dŸk™kÓ*ˆÜ“.ˆÝ/5Ó6©v¨ˆR” Ó$Ñ$¨v€EÐ6Ü×ÑÓ €DÜ× Ñ Ó"€Eä”cœ(“mÓ$€AØ�?‰?˜4Ÿ9™9Ó%€DÙÜ˜?¨4¯9©9¨+Ð5PÐQÓRÐRØ�V‘€IàŸ:™:Ð1ˆT�ZŠZ°t·{±{€Fà€KØ‡z‚zØ×Ñ˜4Ÿ:™:Ô&Ø‡{‚{Ø×ÑÑR¨d¯k©k×.?Ñ.?ÀÔ.DÓRÔRð —=’=ð %)§M¡M×$7Ñ$7¸Ô$<ÓJÑ$<˜qÀÇÁÅ	�—‘•Ð$<ÒJØ&*ð ä
�-‰-˜Ÿ	™	Ó
"€CØŸ)š)‘¨¯©€IÙÜ! $§,¡,Ó/ˆÙÜ%Ø˜V V¨T¯^©^¸XØ˜4Ÿ<™<¨¨u°e¸WÀcØ!×.Ñ.¸Ø)Ø$(×$<Ñ$<Ø!×.Ñ.¸Ø+ô-‰Dô &Ø˜V V¨T¯^©^¸XØ˜4Ÿ<™<¨¨u°e¸WÀcØ!×.Ñ.¸ôC‰Dñ 
Ü! &¨,¸¿¹ÀdØ"'¨°×0AÑ0AÀ3Ø+3ô5ˆó ˆCØ#'§9¢9™Ü(¨¯©Ø15·±¸vÒ1E©Ø.2¯j©jó:ð �Ið ô
 	�t˜W mÒ&9°rÕ:ä˜F F¨D¯L©L¸$ÀÀuØ# T×%6Ñ%6¸ÀhôPˆð
 ‡z�zÐØ�K�T—Z‘ZÐ ˆãˆØ×*Ñ*ˆ�ð ð ×ÒØ ŸI™IÐ1ˆt�yŠy´v·~±~ÀaÈÓ7SˆØˆÜ –o‰FˆAˆsØ�yŠyà—l‘l 3§9¡9¨aÓ0�Ø&)¨A¡g�˜Ÿ™Ñ#Ø¤&§,¡,¨s¯y©yÓ"9¸GÑ"CÑCÀcÑI�•ð   !™8�•ð &ô 	Ð-¨d¨V°2Ð6Ø—	‘	ó :Ü'0´Ô'8ó:ó :ñ:ô 	;ð ‡|ƒ|Ü�
œ3˜t›9˜+Ð%7¸¿	¹	°{À(È4Ï:É:È,ÐWÔXÜ�œC ›I˜;Ð&8¼¸W»¸ÐGÔHå%+Ó,¡V˜r�R˜‘U Vˆ	Ð,Ý+1Ó2©6 %�U˜A‘X¨6Ñ2ˆ	Ü  a×(‰FˆAˆsØ#,§=¡=°·±¸AÓ#>ÀÑ#BˆI�c—i‘iÑ Ø�yŠyØ'0§}¡}°S·Y±YÀÓ'BÀQÑ'F�	˜#Ÿ)™)Ñ$Ü" 1§?¡?°I¸sÓCˆCÜ�A�a�S˜œ#˜d›)˜ B s§y¡y k°°3·:±:°,¸aÀÇÁ¸ð OØ ŸY™YÒ-¨#Ð.¨g°c·j±j°\ðCà.1¯h©hÐ.B�x §¡˜zÑ*ÈñLô Mô �L  T c  Ð,Ô-Ø�Š #§.¢.°C·N²NÀcÇnÂnØ—x‘xñ  &°s×7GÑ7G×7MÑ7MÔ7Oó  &ó &�ä˜ S§X¡X J¨i¸¿	¹	°{ð C'Ø'*§¡Ð&7ð 8"Ø"%§/¡/Ð!2°)¸C¿N¹NÐ;Kð L!Ø!$§¡Ð 0°	¸#¿.¹.Ð9IðKñ *.˜3˜t˜f™°2ñ	7ô 8ð
 ×&Ô&Ü�n u§z¡z°#×2IÑ2IÓ'JÑJÖKð% )ô( 	Ð(¨°;Ñ)?Ð(@ð AØ  Ñ)Ð*¨.¸À;Ñ9OÐ8PðRô 	SáÜ�/ E§J¡Jó /CÝ;Aó/Có %Cñ Cô Dàô ÔØ%¤e WÐ,JÐKˆÜ��S�EˆlÔÜ��c�Uˆ|ÔÜ˜‹mÐà‡z�zÐÜœxŸ|™|›~×6Ñ6°ÓGÑGˆØ˜E‘/‰ä §¡ ¨1¨T¯Z©ZÒ-E¸:Ð,FÐGÑGˆØ˜E‘/ˆØ‡M�M˜$¨€MÔ.à ŸK™KÐ3ˆT�[Š[¸À!¹€Fä  i°·±Ø !× 1Ñ 1°7¸D¿I¹IÀvØ%)§Y¡Yô0Ñ€GˆWð ˆ{Ñ˜aÒØ	Ð'Ñ	'×3Ñ3Ü�J‰J�w¨U¸1Ô=Èð 	4ô 	Qàˆ~Ñ×)Ñ)Ü�
‰
�7¨°qÔ9ÀGð *ô Mð ‡y‚y�W˜[Ñ)¨AÒ-Ü˜W g°¡o°t·~±~Ò7KÈÓLˆÜ�œC ›I˜; iÐ0Ø'+§~¢~Ñ#Ð;KñMô 	Nô 
ˆG�G˜KÑ(Ð)ð *Ø�hÑÐ  ¨w¨ið9ô :àˆ|ÒÜÐ$ V HÐ,CØ˜Ñ%Ð&ð(ô 	)àˆ{Ñ˜aÒÜÐ?Õ@äÐCÔDÜ
ˆ^˜G KÑ0Ð1°À¸yÐIÕJøôS ò 	7ÜÐ/°#Ñ5Ó6Ð6ûð	7üò 7ùò$ Kùò~ -ùÚ2s6   Ê$q& ÌrÑr
Ñ/r
Þ%
rÞ9
rñ&	rñ/q=ñ=rÚ__main__rV  )NN)NrÐ  NNFFNN)Nr   FN)r}   NN)sÚ__doc__r$  rò  rM  Úosrí  r«  ÚsysÚdataclassesr   r   r   Úpathlibr   ÚstdoutÚreconfigureÚ__file__ÚresolveÚparentr/  r»   Úinsertrs   ÚARCHIVOSrÆ   Údanbooru_harvestr   Úprompt_builderr   Ú
pose_scener   r   r,  r   r   r   r   r   r   r   r   r   Útest_blocksr   r;  r   r	  Úenvironr¸   r¦  r5  r8  ÚHARVESTÚDANBOORUÚEJE_Ar·   r®   r{  rš  r|  Ú	DRESS_NEGÚ	frozensetr„   r‚   r†   Úcompilerq   rz   rŽ   r�   r¦   rµ   r¼   rÓ   rÝ   r§   rå   rç   ró   rò   rù   r  r  r  r!  rI  rQ  r2  rT  rY  r[  r_  r0  r4  r3  rw  r5  r€  r‚  r†  rŠ  r˜  rœ  r¡  r¨   r©  r­  r°  r³  rº  rÇ  Útupler  rI  r¢   rª   r{   ry   Ú<module>rc     sA  ðñó8 Û Û Û 	Û Û 	Û 
ß (Ý Ý à ‡
�
× Ñ  Ð0BÐ Ô Cá�‹>×!Ñ!Ó#×*Ñ*×1Ñ1€Ø ‡�‡��‘3‘t˜H“~×-Ñ-Ó/×6Ñ6Ó7Ô 8ð �jÑ €Ù€xƒ=˜Ÿ™Ñ Ø‡H�H‡O�O�A‘s˜8“}Ô%ã Ý -Ý (ß 9÷9÷ 9õ 9õ %Ý #à	,€à
�
‰
�‰Ð'Ð)@ÓA€à˜Ñ  8Ñ+€
Ø�xÑ 'Ñ)€	à
�ZÑ
Ð"5Ñ
5€Ø�jÑ Ð#7Ñ7€Ø�:Ñ 
Ñ*€ð Ð-Ñ-¨xÐ:KÑ/KÈUÐUfÑMfÐgØÐ+Ñ+¨XÐ8KÑ-KÈUÐUhÑMhÐiØÐ2Ñ2°HÐ?UÑ4UÐW\Ð_uÑWuÐvñ€ð ˜*Ñ$Ð'>Ñ>ÀÑN€à˜Ñ# jÑ0°=Ñ@€à!¨B¸RÑ@€ð &°È&ÑQ€ð
 €	ñ
 ò ó €ñ ò ó €ñ ò ó €ð ˆR�Z‰ZÐ0Ó1€
ð*˜ó *ð˜Có ð( ÷ð ó ðð.	�dó 	ð˜dó ñ"Àó ð,¨4ó ð"¨ó ò2ò
 7Ú8Ú8ÚPÚDÚ?ñ€ò @€
ò	ó%ò&(ð2 .2ñ2Ø6:ó2ðl 48ñ7Ø<@ó7òt^ðB !ñ  Tó ð* Tó ò>ò	ð6�Só 6ò
Eó.ò.)ð>¨C°$©Jó ò";ò"Cð >BØ>CØ48Ø%)ñmð
 /3ómð`!˜có !ð
9 Só 9ð˜Tó ð?°ó ?ð.%˜$ó %ò 7ð˜ó ð˜uó ð+ 3ó +ð5 Só 5ð AFØ"&ñ!Ø+/ó!ðJ 26ñIØ:?óIòXmKð` ˆzÒÙ…Fð r{   