← back to Wallco Ai
Interior-designer naming: motif-aware pattern names (parse hero animal from Motif: clause) + curated colorway palette (Verdigris/Bottle Green/Oxblood/Prussian...). 'Peacocks Bacchanal in Bottle Green' replaces 'Marine Vignette No.NNNN'
a7c3834e4c0e69889d9740eb1f648445deee780d · 2026-05-31 16:37:49 -0700 · Steve
Files touched
M scripts/refresh_designs_snapshot.py
Diff
commit a7c3834e4c0e69889d9740eb1f648445deee780d
Author: Steve <steve@designerwallcoverings.com>
Date: Sun May 31 16:37:49 2026 -0700
Interior-designer naming: motif-aware pattern names (parse hero animal from Motif: clause) + curated colorway palette (Verdigris/Bottle Green/Oxblood/Prussian...). 'Peacocks Bacchanal in Bottle Green' replaces 'Marine Vignette No.NNNN'
---
scripts/refresh_designs_snapshot.py | 98 +++++++++++++++++++++++++++++++++++--
1 file changed, 93 insertions(+), 5 deletions(-)
diff --git a/scripts/refresh_designs_snapshot.py b/scripts/refresh_designs_snapshot.py
index 576e70e..422ce05 100644
--- a/scripts/refresh_designs_snapshot.py
+++ b/scripts/refresh_designs_snapshot.py
@@ -10,7 +10,7 @@ Generates semantic titles by category palette:
damask → Baroque / Damask / Heirloom + hue-name + No.{id}
mixed → Atelier / Studio / Origin + hue-name + No.{id}
"""
-import json, subprocess, colorsys, os
+import json, subprocess, colorsys, os, re
from pathlib import Path
# Resolve relative to this script so it works in both
@@ -50,6 +50,86 @@ def hue_name(hex_):
if deg < 330: return 'Plum'
return 'Rose'
+# ── Interior-designer colorway names ────────────────────────────────────────
+# Curated heritage paint/textile palette (Farrow & Ball / de Gournay sensibility)
+# keyed by hue band → [dark, mid, light] so lightness picks the right shade name.
+# Steve 2026-05-31: "int des skill color and pattern names" — replace the flat
+# 11-word hue map with named colorways.
+COLORWAYS = {
+ 'neutral': { # s < 0.10, chosen by lightness
+ 'vlight': 'Alabaster', 'light': 'Oyster', 'mid': 'Greige',
+ 'dark': 'Pewter', 'vdark': 'Charcoal',
+ },
+ # hue bands: (max_deg, {dark, mid, light})
+ 'bands': [
+ (15, {'dark': 'Oxblood', 'mid': 'Claret', 'light': 'Blush'}), # red
+ (35, {'dark': 'Terracotta','mid': 'Amber', 'light': 'Apricot'}), # orange
+ (55, {'dark': 'Ochre', 'mid': 'Honey', 'light': 'Chamois'}), # yellow
+ (80, {'dark': 'Loden', 'mid': 'Olive', 'light': 'Chartreuse'}), # yellow-green
+ (155, {'dark': 'Bottle Green','mid': 'Sage', 'light': 'Celadon'}), # green
+ (200, {'dark': 'Verdigris', 'mid': 'Teal', 'light': 'Eau de Nil'}), # teal/marine
+ (250, {'dark': 'Prussian', 'mid': 'Sapphire', 'light': 'Delft'}), # blue
+ (290, {'dark': 'Aubergine', 'mid': 'Amethyst', 'light': 'Wisteria'}), # purple
+ (330, {'dark': 'Damson', 'mid': 'Plum', 'light': 'Mauve'}), # magenta
+ (361, {'dark': 'Garnet', 'mid': 'Rosewood', 'light': 'Rose'}), # pink-red
+ ],
+}
+def colorway_name(hex_):
+ h, l, s = hex_to_hls(hex_)
+ if s < 0.10:
+ n = COLORWAYS['neutral']
+ if l > 0.85: return n['vlight']
+ if l > 0.65: return n['light']
+ if l > 0.42: return n['mid']
+ if l > 0.22: return n['dark']
+ return n['vdark']
+ deg = h * 360
+ for maxd, shades in COLORWAYS['bands']:
+ if deg < maxd:
+ tier = 'light' if l > 0.62 else 'dark' if l < 0.34 else 'mid'
+ return shades[tier]
+ return 'Rose'
+
+# ── Motif-aware pattern names for the animal categories ─────────────────────
+# Parse the actual creature out of the prompt so the name describes the design
+# ("Peacock Carouse in Verdigris") instead of a generic "Marine Vignette".
+ANIMALS = ['peacock','giraffe','elephant','orangutan','bullfrog','treefrog',
+ 'sloth','parrot','macaw','lemur','panda','flamingo','toucan','owl',
+ 'fox','raccoon','koala','otter','badger','hare','rabbit','tiger',
+ 'lion','bear','stag','deer','hedgehog','squirrel','swan','crane',
+ 'heron','pheasant','cockatoo','gecko','chameleon','turtle',
+ 'hummingbird','monkey','frog']
+# display plural override; default is Capitalize + 's'
+ANIMAL_PLURAL = {'fox':'Foxes','hare':'Hares','stag':'Stags','deer':'Deer',
+ 'goose':'Geese','monkey':'Monkeys',
+ 'bullfrog':'Frogs','treefrog':'Frogs'}
+def animal_in(prompt):
+ # The luxe-regen prompt is structured "...Ground: <SKU may name an animal>.
+ # Motif: <hero animal> ...". Search the Motif clause ONLY so a ground SKU like
+ # "Blue Dart Frog" can't out-rank the actual peacock. Fall back to the whole
+ # prompt if there's no Motif: clause. Word-boundary match so 'foxglove'≠fox.
+ p = (prompt or '').lower()
+ m = re.search(r'motif:\s*(.+?)(?:palette:|ground:|$)', p, re.S)
+ hay = m.group(1) if m else p
+ best = None; best_pos = len(hay) + 1
+ for a in ANIMALS:
+ mm = re.search(r'\b' + a + r'(?:s|es)?\b', hay)
+ if mm and mm.start() < best_pos:
+ best, best_pos = a, mm.start()
+ if best:
+ return ANIMAL_PLURAL.get(best, best.capitalize() + 's')
+ return None
+
+# Witty bacchanal nouns for drunk-animals; serene for stoned; grand for murals.
+ANIMAL_NOUNS = {
+ 'drunk-animals': ['Carouse', 'Tipple', 'Soirée', 'Revel', 'Nightcap',
+ 'Bacchanal', 'Spree', 'Toast', 'Saunter', 'Folly'],
+ 'stoned-animals': ['Reverie', 'Daydream', 'Halcyon', 'Vespers', 'Lullaby',
+ 'Drift', 'Idyll', 'Repose', 'Slumber', 'Haze'],
+ 'mural-animals': ['Menagerie', 'Pavillon', 'Tableau', 'Procession',
+ 'Chinoiserie', 'Allée', 'Aviary', 'Court', 'Salon', 'Frieze'],
+}
+
NOUNS = {
'floral': ['Botanical', 'Bouquet', 'Blossom', 'Garden', 'Floret'],
'geometric': ['Lattice', 'Tessellation', 'Geometry', 'Meridian', 'Fan'],
@@ -64,11 +144,19 @@ NOUNS = {
'mural-scenic': ['Scenic', 'Panorama', 'Vista', 'Frieze', 'Tapestry',
'Folly', 'Allée', 'Belvedere', 'Promenade', 'Pavillon']
}
-def title_for(cat, hex_, id_):
+def title_for(cat, hex_, id_, prompt=None):
+ color = colorway_name(hex_)
+ # Animal categories: name from the actual creature → "Peacock Carouse in Verdigris"
+ if cat in ANIMAL_NOUNS:
+ animal = animal_in(prompt)
+ noun = ANIMAL_NOUNS[cat][id_ % len(ANIMAL_NOUNS[cat])]
+ if animal:
+ return f"{animal} {noun} in {color}"
+ return f"{color} {noun} No.{id_}"
+ # Everything else: keep the colorway + category noun + No.{id}
pool = NOUNS.get(cat, NOUNS['mixed'])
- hue = hue_name(hex_)
noun = pool[id_ % len(pool)]
- return f"{hue} {noun} No.{id_}"
+ return f"{color} {noun} No.{id_}"
rows = psql_json(
"SELECT COALESCE(json_agg(t),'[]'::json) FROM ("
@@ -139,7 +227,7 @@ for r in rows:
"category": r['category'],
"dominant_hex": r['dominant_hex'],
"saturation": round(s, 3),
- "title": title_for(r['category'], r['dominant_hex'] or '', r['id']),
+ "title": title_for(r['category'], r['dominant_hex'] or '', r['id'], r.get('prompt')),
"handle": f"wallco-{r['id']:04d}",
"image_url": f"/designs/img/{filename}",
"filename": filename,
← 71b98af generator: user-chosen batch size renders server-side in bac
·
back to Wallco Ai
·
Publish luxe-v2 batch L2 image-reviewed (41576,41844,41868,4 c8fc9a6 →