summaryrefslogtreecommitdiff
path: root/internal/image
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-01 14:45:37 +0300
committerPaul Buetow <paul@buetow.org>2026-04-01 14:45:37 +0300
commitd21c7aafa128194524cc19b076e1411169cab680 (patch)
tree5ec44af6ae0e3ecda36ea88c061de9ae2d700f70 /internal/image
parenta63552412e1bca0c742dcc4deafa86d14393d3e0 (diff)
fix(z5): encapsulate artistic styles pool
Diffstat (limited to 'internal/image')
-rw-r--r--internal/image/openai.go17
-rw-r--r--internal/image/styles.go32
-rw-r--r--internal/image/styles_test.go44
3 files changed, 73 insertions, 20 deletions
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)
}
}