Documentation → Étape 4

Étape 4 — Téléchargement et extraction

748 rendus, 94 secondes, zéro échec — et 374 gabarits génériques reconstruits à partir d'une API qui ne les expose pas.

1. Compter les variantes avant de tirer

Un cosmétique n'est pas une variante. Trois paramètres le démultiplient : la morphologie (wide / slim) et, pour deux groupes, un alignement.

ParamètreValeursGroupes concernés
skin_typewide, slimdéterminé par mesure, voir ci-dessous
eyes_alignmenthigh, middle, loweyes_textures
mouth_alignmenthigh, lowmouth_textures

2. Quels groupes changent vraiment entre wide et slim ?

Doubler les 22 groupes « au cas où » aurait ajouté plusieurs centaines de requêtes inutiles. Un représentant par groupe, rendu dans les deux morphologies et comparé pixel à pixel, tranche la question pour 44 requêtes :

GroupeTémoinPixels différentsDécision
top_texturesbaseball_tee61wide + slim
outerwear_texturesalien_force125wide + slim
gloves_texturesfingerless_gloves82wide + slim
makeup_texturesadmin41wide + slim
base_texturesbear0wide seul
… et 17 autres groupes à 0 différence
Contre-intuitif

base_textures — le corps lui-même, donc les bras — ne change pas. Vérifié sur trois cosmétiques différents pour écarter un faux négatif. À l'inverse, makeup_textures, qui est sur le visage, change. L'anatomie n'était pas un bon guide : seule la mesure l'était.

3. Deux passes suffisent à tout décomposer

Chaque variante est rendue deux fois, avec des couleurs choisies pour être orthogonales :

PasseZone primaireZone secondaire
A$800000 rouge$000080 bleu
B$008000 vert$800000 rouge

La lecture croisée lève toute ambiguïté :

rouge puis vert   → zone primaire
bleu  puis rouge  → zone secondaire
identique         → pixel fixe

Les valeurs sont à 128 et non 255 : au-delà, le slot le plus clair dépasse la capacité d'un octet et l'information se perd dans l'écrêtage.

4. Politesse réseau

Le service appartient à un développeur solo qui sortait d'un burn-out, avec près de six mois d'indisponibilité derrière lui. Les garde-fous ne sont pas décoratifs :

Ce qui est imposé

  • 3 requêtes simultanées au maximum
  • 120 ms minimum entre deux départs, tous workers confondus
  • 4 tentatives maximum, backoff exponentiel
  • Retry-After respecté sur 429 et 5xx
  • User-Agent descriptif et identifiable

Détails d'implémentation

  • Le throttle est une chaîne de promesses partagée, pas un setTimeout par worker — sinon 3 workers émettraient 3 requêtes simultanées toutes les 120 ms.
  • Écriture en .part puis renommage atomique : une interruption ne laisse jamais un fichier tronqué qu'une reprise prendrait pour valide.
  • Un fichier non vide déjà présent est sauté.
  • Les 4xx autres que 429 ne sont pas réessayés : ce sont des réponses, pas des pannes.

5. Le téléchargement

Le passage à blanc, obligatoire avant tout tir réel :

374
variantes
748
fichiers
326
Kio estimés
1,5
min plancher

Résultat réel :

Terminé en 94 s
  téléchargés : 748   sautés : 0   échecs : 0

Soit 8,0 requêtes par seconde — exactement la cadence imposée par le throttle (3 workers ÷ 120 ms). Le serveur n'a jamais renvoyé un seul 429 ni 5xx.

6. Extraction des gabarits

Les paires de passes sont ensuite fusionnées en un gabarit générique par variante. Chaque pixel est attribué à une zone, et sa valeur comparée à la rampe de référence [96, 105, 114, 128, 138, 143, 148, 153] lue sur la bande de calibration.

79 162
px primaires
13 196
px secondaires
2 152
px fixes
0
non classés
Validation du modèle

Erreur maximale d'affectation : 0. Les 94 510 pixels colorisables tombent exactement sur l'une des 8 valeurs de la rampe, sans un seul pixel inclassable. Un modèle approximatif aurait produit des dizaines de résidus.

7. Format d'archive

Chaque gabarit est un PNG 64×64 RGBA où les canaux portent des index, pas des couleurs :

CanalContenu
Rzone — 0 = fixe, 1 = primaire, 2 = secondaire
Gindex de slot d'ombrage, 0 (plus sombre) à 7 (plus clair)
Binutilisé
Aalpha d'origine, conservé tel quel

Les pixels fixes conservent leur couleur littérale dans _fixed.json. L'arborescence sur disque suit la hiérarchie sémantique du manifest :

textures/<groupe>/<cosmétique>/<morphologie>[_<alignement>].png

textures/top_textures/chef_shirt/wide.png
textures/eyes_textures/big_ol_eyes/wide_middle.png
textures/outerwear_textures/alien_force/slim.png

Ces gabarits sont servis par ce site et alimentent directement la démo interactive.