From d21c7aafa128194524cc19b076e1411169cab680 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 1 Apr 2026 14:45:37 +0300 Subject: fix(z5): encapsulate artistic styles pool --- internal/image/openai.go | 17 ++++++----------- internal/image/styles.go | 32 +++++++++++++++++++++++++++++-- internal/image/styles_test.go | 44 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 73 insertions(+), 20 deletions(-) (limited to 'internal/image') diff --git a/internal/image/openai.go b/internal/image/openai.go index 1df6eb7..79fbe38 100644 --- a/internal/image/openai.go +++ b/internal/image/openai.go @@ -6,7 +6,6 @@ import ( "encoding/hex" "fmt" "io" - "math/rand" "net/http" "strings" "time" @@ -244,16 +243,12 @@ func (c *OpenAIClient) createEducationalPrompt(ctx context.Context, bulgarianWor scene = "" } - // Copy the shared styles before shuffling so the package-level list stays stable. - styles := append([]string(nil), ArtisticStyles...) - - // Shuffle the styles to avoid bias - rand.Shuffle(len(styles), func(i, j int) { - styles[i], styles[j] = styles[j], styles[i] - }) - - // Select a random style from the shuffled list - selectedStyle := styles[0] + // Select a random style from the shared pool. Fall back to a generic style if + // the pool has been emptied by tests or future callers. + selectedStyle := chooseArtisticStyle() + if selectedStyle == defaultArtisticStyle { + fmt.Printf(" No artistic styles available, using generic prompt\n") + } fmt.Printf(" Using image style: %s\n", selectedStyle) // Define prompt components in order of importance diff --git a/internal/image/styles.go b/internal/image/styles.go index a88bb69..d4a32a9 100644 --- a/internal/image/styles.go +++ b/internal/image/styles.go @@ -1,7 +1,11 @@ package image -// ArtisticStyles contains the shared pool of artistic styles used for image prompts. -var ArtisticStyles = []string{ +import "math/rand" + +const defaultArtisticStyle = "simple illustration" + +// artisticStyles contains the shared pool of artistic styles used for image prompts. +var artisticStyles = []string{ "Photorealism", "Hyperrealism", "Surrealism", "Impressionism", "Minimalism", "Pop Art", "Art Nouveau", "Digital Art", "Watercolor", "Oil Painting", "Pencil Sketch", "Ink Drawing", @@ -72,3 +76,27 @@ var ArtisticStyles = []string{ "Archigram", "Metabolism", "Structuralism", "Postmodernism", "Minimalist Photography", "Conceptual Photography", "Staged Photography", "Candid Photography", } + +func pickArtisticStyle() string { + if len(artisticStyles) == 0 { + return "" + } + + styles := append([]string(nil), artisticStyles...) + + // Shuffle the styles to avoid bias without mutating the shared pool. + rand.Shuffle(len(styles), func(i, j int) { + styles[i], styles[j] = styles[j], styles[i] + }) + + return styles[0] +} + +func chooseArtisticStyle() string { + style := pickArtisticStyle() + if style == "" { + return defaultArtisticStyle + } + + return style +} diff --git a/internal/image/styles_test.go b/internal/image/styles_test.go index 8eeb7c1..1848342 100644 --- a/internal/image/styles_test.go +++ b/internal/image/styles_test.go @@ -1,18 +1,48 @@ package image -import "testing" +import ( + "reflect" + "testing" +) func TestArtisticStyles(t *testing.T) { - if len(ArtisticStyles) == 0 { - t.Fatal("ArtisticStyles should not be empty") + if len(artisticStyles) == 0 { + t.Fatal("artisticStyles should not be empty") } - if !hasStyle(ArtisticStyles, "Photorealism") { - t.Fatal(`ArtisticStyles should include "Photorealism"`) + if !hasStyle(artisticStyles, "Photorealism") { + t.Fatal(`artisticStyles should include "Photorealism"`) } - if !hasStyle(ArtisticStyles, "Candid Photography") { - t.Fatal(`ArtisticStyles should include "Candid Photography"`) + if !hasStyle(artisticStyles, "Candid Photography") { + t.Fatal(`artisticStyles should include "Candid Photography"`) + } +} + +func TestChooseArtisticStyle_EmptyPool(t *testing.T) { + original := artisticStyles + artisticStyles = nil + t.Cleanup(func() { + artisticStyles = original + }) + + if got := chooseArtisticStyle(); got != defaultArtisticStyle { + t.Fatalf("chooseArtisticStyle() = %q, want %q", got, defaultArtisticStyle) + } +} + +func TestPickArtisticStyle_DoesNotMutateSharedPool(t *testing.T) { + original := append([]string(nil), artisticStyles...) + t.Cleanup(func() { + artisticStyles = original + }) + + artisticStyles = []string{"Photorealism", "Surrealism", "Impressionism"} + + _ = pickArtisticStyle() + + if !reflect.DeepEqual(artisticStyles, []string{"Photorealism", "Surrealism", "Impressionism"}) { + t.Fatalf("pickArtisticStyle() mutated shared pool: got %v", artisticStyles) } } -- cgit v1.2.3