TroglodyteDerivations commited on
Commit
8ba33bc
·
verified ·
1 Parent(s): 2e81174

Upload 106 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +100 -0
  2. app.py +940 -0
  3. batch_001_20251211_201120.png +3 -0
  4. batch_002_20251211_201120.png +3 -0
  5. batch_003_20251211_201120.png +3 -0
  6. batch_004_20251211_201120.png +3 -0
  7. batch_005_20251211_201120.png +3 -0
  8. batch_006_20251211_201120.png +3 -0
  9. batch_007_20251211_201120.png +3 -0
  10. batch_008_20251211_201120.png +3 -0
  11. batch_009_20251211_201120.png +3 -0
  12. batch_010_20251211_201120.png +3 -0
  13. batch_011_20251211_201120.png +3 -0
  14. batch_012_20251211_201120.png +3 -0
  15. batch_013_20251211_201120.png +3 -0
  16. batch_014_20251211_201120.png +3 -0
  17. batch_015_20251211_201120.png +3 -0
  18. batch_016_20251211_201120.png +3 -0
  19. batch_017_20251211_201120.png +3 -0
  20. batch_018_20251211_201120.png +3 -0
  21. batch_019_20251211_201120.png +3 -0
  22. batch_020_20251211_201120.png +3 -0
  23. batch_021_20251211_201120.png +3 -0
  24. batch_022_20251211_201120.png +3 -0
  25. batch_023_20251211_201120.png +3 -0
  26. batch_024_20251211_201120.png +3 -0
  27. batch_025_20251211_201120.png +3 -0
  28. batch_026_20251211_201120.png +3 -0
  29. batch_027_20251211_201120.png +3 -0
  30. batch_028_20251211_201120.png +3 -0
  31. batch_029_20251211_201120.png +3 -0
  32. batch_030_20251211_201120.png +3 -0
  33. batch_031_20251211_201120.png +3 -0
  34. batch_032_20251211_201120.png +3 -0
  35. batch_033_20251211_201120.png +3 -0
  36. batch_034_20251211_201120.png +3 -0
  37. batch_035_20251211_201120.png +3 -0
  38. batch_036_20251211_201120.png +3 -0
  39. batch_037_20251211_201120.png +3 -0
  40. batch_038_20251211_201120.png +3 -0
  41. batch_039_20251211_201120.png +3 -0
  42. batch_040_20251211_201120.png +3 -0
  43. batch_041_20251211_201120.png +3 -0
  44. batch_042_20251211_201120.png +3 -0
  45. batch_043_20251211_201120.png +3 -0
  46. batch_044_20251211_201120.png +3 -0
  47. batch_045_20251211_201120.png +3 -0
  48. batch_046_20251211_201120.png +3 -0
  49. batch_047_20251211_201120.png +3 -0
  50. batch_048_20251211_201120.png +3 -0
.gitattributes CHANGED
@@ -33,3 +33,103 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ batch_001_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
37
+ batch_002_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
38
+ batch_003_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
39
+ batch_004_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
40
+ batch_005_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
41
+ batch_006_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
42
+ batch_007_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
43
+ batch_008_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
44
+ batch_009_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
45
+ batch_010_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
46
+ batch_011_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
47
+ batch_012_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
48
+ batch_013_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
49
+ batch_014_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
50
+ batch_015_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
51
+ batch_016_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
52
+ batch_017_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
53
+ batch_018_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
54
+ batch_019_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
55
+ batch_020_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
56
+ batch_021_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
57
+ batch_022_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
58
+ batch_023_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
59
+ batch_024_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
60
+ batch_025_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
61
+ batch_026_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
62
+ batch_027_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
63
+ batch_028_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
64
+ batch_029_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
65
+ batch_030_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
66
+ batch_031_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
67
+ batch_032_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
68
+ batch_033_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
69
+ batch_034_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
70
+ batch_035_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
71
+ batch_036_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
72
+ batch_037_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
73
+ batch_038_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
74
+ batch_039_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
75
+ batch_040_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
76
+ batch_041_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
77
+ batch_042_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
78
+ batch_043_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
79
+ batch_044_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
80
+ batch_045_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
81
+ batch_046_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
82
+ batch_047_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
83
+ batch_048_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
84
+ batch_049_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
85
+ batch_050_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
86
+ batch_051_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
87
+ batch_052_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
88
+ batch_053_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
89
+ batch_054_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
90
+ batch_055_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
91
+ batch_056_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
92
+ batch_057_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
93
+ batch_058_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
94
+ batch_059_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
95
+ batch_060_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
96
+ batch_061_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
97
+ batch_062_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
98
+ batch_063_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
99
+ batch_064_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
100
+ batch_065_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
101
+ batch_066_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
102
+ batch_067_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
103
+ batch_068_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
104
+ batch_069_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
105
+ batch_070_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
106
+ batch_071_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
107
+ batch_072_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
108
+ batch_073_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
109
+ batch_074_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
110
+ batch_075_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
111
+ batch_076_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
112
+ batch_077_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
113
+ batch_078_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
114
+ batch_079_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
115
+ batch_080_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
116
+ batch_081_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
117
+ batch_082_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
118
+ batch_083_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
119
+ batch_084_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
120
+ batch_085_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
121
+ batch_086_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
122
+ batch_087_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
123
+ batch_088_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
124
+ batch_089_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
125
+ batch_090_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
126
+ batch_091_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
127
+ batch_092_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
128
+ batch_093_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
129
+ batch_094_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
130
+ batch_095_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
131
+ batch_096_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
132
+ batch_097_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
133
+ batch_098_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
134
+ batch_099_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
135
+ batch_100_20251211_201120.png filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,940 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import os
4
+ from pathlib import Path
5
+ import re
6
+ from datetime import datetime
7
+
8
+ def parse_batch_report(json_path):
9
+ """Parse the batch report JSON file"""
10
+ try:
11
+ with open(json_path, 'r') as f:
12
+ data = json.load(f)
13
+ return data
14
+ except Exception as e:
15
+ return {"error": f"Failed to parse JSON: {str(e)}"}
16
+
17
+ def find_image_files(directory=".", limit=200):
18
+ """Find all image files in directory"""
19
+ image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']
20
+ image_files = []
21
+
22
+ for ext in image_extensions:
23
+ pattern = f"*{ext}"
24
+ image_files.extend(list(Path(directory).glob(pattern)))
25
+ image_files.extend(list(Path(directory).glob(f"*{ext.upper()}")))
26
+
27
+ # Sort by batch number if available
28
+ def sort_key(path):
29
+ path_str = str(path.name)
30
+ match = re.search(r'batch_(\d+)_', path_str)
31
+ if match:
32
+ return int(match.group(1))
33
+ return float('inf')
34
+
35
+ image_files = sorted(image_files, key=sort_key)[:limit]
36
+ return image_files
37
+
38
+ def get_latest_files():
39
+ """Get the latest files for FLUX.2 Hello Kitty Powerball batch"""
40
+ current_dir = Path(".")
41
+
42
+ # Look for batch files
43
+ json_patterns = [
44
+ "batch_report_20251211_201120.json", # The specific file
45
+ "*hello*kitty*powerball*report*.json",
46
+ "batch_report_*.json"
47
+ ]
48
+
49
+ # Find files
50
+ json_files = []
51
+ for pattern in json_patterns:
52
+ json_files.extend(list(current_dir.glob(pattern)))
53
+
54
+ # Remove duplicates and sort by modification time (newest first)
55
+ def get_sorted_unique(files):
56
+ unique_files = list(set(files))
57
+ unique_files.sort(key=lambda x: x.stat().st_mtime if x.exists() else 0, reverse=True)
58
+ return unique_files
59
+
60
+ json_files = get_sorted_unique(json_files)
61
+
62
+ # Use first found or set default
63
+ json_file = str(json_files[0]) if json_files else "batch_report_20251211_201120.json"
64
+
65
+ return json_file
66
+
67
+ def get_image_prompt_mapping(json_data, image_files):
68
+ """Create a mapping of image files to their prompts"""
69
+ prompts = []
70
+
71
+ if isinstance(json_data, dict) and "results" in json_data:
72
+ # Sort results by index to ensure correct order
73
+ sorted_results = sorted(json_data["results"], key=lambda x: x.get("index", 0))
74
+
75
+ # Create dictionary for quick lookup by filename
76
+ file_to_prompt = {}
77
+ for result in sorted_results:
78
+ if "file" in result and "prompt" in result and result["success"]:
79
+ file_to_prompt[result["file"]] = result["prompt"]
80
+
81
+ # Match images to prompts based on filename
82
+ for img_file in image_files:
83
+ img_name = img_file.name
84
+ if img_name in file_to_prompt:
85
+ prompts.append(file_to_prompt[img_name])
86
+ else:
87
+ # Try to extract index from filename
88
+ match = re.search(r'batch_(\d+)_', img_name)
89
+ if match:
90
+ index = int(match.group(1))
91
+ # Find result with matching index
92
+ matching_result = next((r for r in sorted_results if r.get("index") == index and r.get("success")), None)
93
+ if matching_result and "prompt" in matching_result:
94
+ prompts.append(matching_result["prompt"])
95
+ else:
96
+ prompts.append(f"Hello Kitty Powerball Scene #{index}")
97
+ else:
98
+ prompts.append("Hello Kitty Powerball Scene")
99
+ else:
100
+ # Fallback: create generic prompts
101
+ prompts = [f"Hello Kitty Powerball Scene #{i+1}" for i in range(len(image_files))]
102
+
103
+ return prompts
104
+
105
+ def extract_scene_details(prompt):
106
+ """Extract style, numbers, and theme from prompt"""
107
+ style = "Hello Kitty"
108
+ powerball_numbers = ""
109
+ theme = ""
110
+
111
+ # Extract Powerball numbers (white numbers)
112
+ numbers_pattern = r'(\d+)[,\s]*(\d+)[,\s]*(\d+)[,\s]*(\d+)[,\s]*(\d+)'
113
+ match = re.search(numbers_pattern, prompt)
114
+ if match:
115
+ powerball_numbers = f"{match.group(1)}, {match.group(2)}, {match.group(3)}, {match.group(4)}, {match.group(5)}"
116
+
117
+ # Extract Powerball number (red ball)
118
+ powerball_pattern = r'red (?:Powerball )?(?:ornament|ball|cookie|crystal|LED|velvet|comet|strobe|rose|flask|sphere|apple|copper|coral|planet|jewel|berry|spotlight|tomato|orb|surfboard|horseshoe|royal|smoke bomb|paint tube|flash bulb|book|hard hat|fireball|mailbox|cross|gavel|candy|button|pearl|ski|ruby|hourglass|hammer|rover|buoy|switch|diamond|parachute|skate blade|evidence bag|scepter|battery|power core|treasure chest|tornado|law book|compass|flash|apple|thimble|oil can|crystal ball|bookend|jet stream|cherry|paint splatter|metronome|rocket|clue ball|X marks the spot|power source|fairy dust|potion|checkered flag|gingerbread man|watering can|special delivery) (?:shows?|ball) (\d+)'
119
+ match = re.search(powerball_pattern, prompt, re.IGNORECASE)
120
+ if match:
121
+ powerball_numbers += f" + {match.group(1)}"
122
+
123
+ # Extract theme from text in quotes
124
+ theme_pattern = r'\"([^\"]+)\"'
125
+ match = re.search(theme_pattern, prompt)
126
+ if match:
127
+ theme = match.group(1)
128
+
129
+ # Extract Hello Kitty style/occupation
130
+ style_patterns = [
131
+ r'Hello Kitty as a? (rabbi|DJ|scientist|superhero|chef|mermaid|astronaut|pirate|fairy|detective|rockstar|farmer|wizard|surfer|cowboy|queen|ninja|painter|photographer|librarian|construction worker|firefighter|mail carrier|doctor|judge|baker|pilot|diver|skier|knight|ballerina|race car driver|spy|fisherman|beekeeper|archaeologist|teacher|tailor|karate master|gardener|musician|barista|train conductor|florist|clockmaker|carpenter|sailor|electrician|miner|magician|skater|robot|explorer|weather reporter|architect|dentist|mechanic|yoga instructor)',
132
+ r'Cyberpunk Hello Kitty',
133
+ r'Steampunk Hello Kitty',
134
+ r'Kawaii Hello Kitty',
135
+ r'Hello Kitty in a onesie',
136
+ r'Hello Kitty wearing a Santa hat'
137
+ ]
138
+
139
+ for pattern in style_patterns:
140
+ match = re.search(pattern, prompt, re.IGNORECASE)
141
+ if match:
142
+ style = match.group(1).title() if len(match.groups()) > 0 else match.group(0)
143
+ break
144
+
145
+ return style, powerball_numbers, theme
146
+
147
+ def create_main_app():
148
+ """Create the main Gradio application for FLUX.2 Hello Kitty Powerball"""
149
+ # Get latest files
150
+ json_file = get_latest_files()
151
+
152
+ # Parse data
153
+ batch_report = parse_batch_report(json_file) if json_file else {"error": "No JSON file found"}
154
+
155
+ # Find images
156
+ image_files = find_image_files(".", limit=200)
157
+ image_paths = [str(img) for img in image_files]
158
+
159
+ # Extract prompts from JSON and match with images
160
+ prompts = get_image_prompt_mapping(batch_report, image_files)
161
+
162
+ # Parse timestamp for display
163
+ timestamp = "Unknown"
164
+ if isinstance(batch_report, dict) and "timestamp" in batch_report:
165
+ ts = batch_report["timestamp"]
166
+ try:
167
+ dt = datetime.strptime(ts, "%Y%m%d_%H%M%S")
168
+ timestamp = dt.strftime("%Y-%m-%d %H:%M:%S")
169
+ except:
170
+ timestamp = ts
171
+
172
+ # Create Hello Kitty Powerball theme CSS
173
+ custom_css = """
174
+ <style>
175
+ .gradio-container {max-width: 1400px !important}
176
+ .gallery-container { max-height: 600px; overflow-y: auto; }
177
+ .image-large { max-width: 100%; height: auto; max-height: 500px; }
178
+ .prompt-box { max-height: 200px; overflow-y: auto; }
179
+ h1 { color: #FF69B4; margin-bottom: 10px; }
180
+ h2 { color: #4169E1; }
181
+ h3 { color: #FF1493; }
182
+ h4 { color: #9370DB; }
183
+ .stats-box {
184
+ background: #FFF0F5;
185
+ padding: 15px;
186
+ border-radius: 10px;
187
+ margin: 10px 0;
188
+ border: 1px solid #FFB6C1;
189
+ }
190
+ .gallery-item img {
191
+ border-radius: 5px;
192
+ border: 2px solid #FF69B4;
193
+ transition: all 0.2s ease;
194
+ cursor: pointer;
195
+ }
196
+ .gallery-item img:hover {
197
+ border-color: #9370DB;
198
+ transform: scale(1.02);
199
+ box-shadow: 0 4px 12px rgba(255,105,180,0.15);
200
+ }
201
+ .selected-image-container {
202
+ text-align: center;
203
+ padding: 10px;
204
+ background: white;
205
+ border-radius: 10px;
206
+ border: 1px solid #FF69B4;
207
+ }
208
+ .prompt-display {
209
+ background: #FFF8F8;
210
+ padding: 15px;
211
+ border-radius: 8px;
212
+ border-left: 4px solid #4169E1;
213
+ margin: 10px 0;
214
+ }
215
+ .file-info {
216
+ background: #FFF0F5;
217
+ padding: 10px;
218
+ border-radius: 5px;
219
+ margin: 5px 0;
220
+ }
221
+ .hello-kitty-theme {
222
+ background: linear-gradient(135deg, #FF69B4 0%, #FFB6C1 20%, #4169E1 40%, #9370DB 60%, #FF1493 80%, #FF69B4 100%);
223
+ padding: 25px;
224
+ border-radius: 15px;
225
+ color: white;
226
+ margin-bottom: 25px;
227
+ border: 3px solid #FFB6C1;
228
+ box-shadow: 0 4px 20px rgba(255,105,180,0.3);
229
+ }
230
+ .hello-kitty-title {
231
+ font-family: 'Comic Sans MS', 'Chalkboard', cursive;
232
+ font-weight: bold;
233
+ text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
234
+ color: white;
235
+ font-size: 2.5em;
236
+ margin-bottom: 10px;
237
+ }
238
+ .kitty-icon {
239
+ font-size: 28px;
240
+ margin-right: 10px;
241
+ vertical-align: middle;
242
+ }
243
+ .powerball-icon {
244
+ font-size: 28px;
245
+ margin-right: 10px;
246
+ vertical-align: middle;
247
+ }
248
+ .tab-button {
249
+ background: linear-gradient(135deg, #FF69B4 0%, #4169E1 100%) !important;
250
+ color: white !important;
251
+ font-weight: bold;
252
+ border: 1px solid #FFB6C1 !important;
253
+ }
254
+ .batch-info {
255
+ background: rgba(255,255,255,0.2);
256
+ padding: 10px;
257
+ border-radius: 8px;
258
+ margin-top: 15px;
259
+ font-size: 1.1em;
260
+ border: 1px solid rgba(255,255,255,0.3);
261
+ }
262
+ .navigation-buttons {
263
+ margin-top: 20px;
264
+ display: flex;
265
+ gap: 10px;
266
+ justify-content: center;
267
+ }
268
+ .navigation-buttons button {
269
+ padding: 12px 24px;
270
+ font-size: 16px;
271
+ font-weight: bold;
272
+ background: linear-gradient(135deg, #FF69B4 0%, #4169E1 100%);
273
+ color: white;
274
+ border: none;
275
+ border-radius: 5px;
276
+ }
277
+ .navigation-buttons button:hover {
278
+ background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%);
279
+ transform: translateY(-2px);
280
+ }
281
+ .image-counter {
282
+ font-size: 14px;
283
+ color: #666;
284
+ margin-top: 10px;
285
+ font-style: italic;
286
+ }
287
+ .powerball-numbers {
288
+ background: linear-gradient(45deg, #FF69B4, #4169E1);
289
+ color: white;
290
+ padding: 5px 10px;
291
+ border-radius: 5px;
292
+ font-weight: bold;
293
+ display: inline-block;
294
+ margin: 5px;
295
+ }
296
+ .theme-box {
297
+ background: #F0F8FF;
298
+ padding: 10px;
299
+ border-radius: 5px;
300
+ border-left: 3px solid #9370DB;
301
+ font-style: italic;
302
+ margin: 10px 0;
303
+ }
304
+ .style-badge {
305
+ display: inline-block;
306
+ padding: 3px 8px;
307
+ background: #FF69B4;
308
+ color: white;
309
+ border-radius: 4px;
310
+ font-size: 0.9em;
311
+ margin-right: 5px;
312
+ margin-bottom: 5px;
313
+ font-weight: bold;
314
+ }
315
+ .gr-button {
316
+ background: linear-gradient(135deg, #FF69B4 0%, #4169E1 100%);
317
+ color: white;
318
+ border: none;
319
+ border-radius: 5px;
320
+ }
321
+ .gr-button:hover {
322
+ background: linear-gradient(135deg, #4169E1 0%, #FF69B4 100%);
323
+ }
324
+ .scene-card {
325
+ background: white;
326
+ border-radius: 8px;
327
+ padding: 15px;
328
+ margin: 10px 0;
329
+ border: 2px solid #FF69B4;
330
+ box-shadow: 0 2px 8px rgba(255,105,180,0.1);
331
+ }
332
+ .success-rate {
333
+ color: #4169E1;
334
+ font-weight: bold;
335
+ font-size: 1.1em;
336
+ }
337
+ .kitty-color {
338
+ color: #FF69B4;
339
+ font-weight: bold;
340
+ }
341
+ .powerball-color {
342
+ color: #4169E1;
343
+ font-weight: bold;
344
+ }
345
+ .flux-color {
346
+ color: #9370DB;
347
+ font-weight: bold;
348
+ }
349
+ .white-ball {
350
+ display: inline-block;
351
+ width: 15px;
352
+ height: 15px;
353
+ border-radius: 50%;
354
+ margin: 0 2px;
355
+ background: white;
356
+ border: 1px solid #4169E1;
357
+ vertical-align: middle;
358
+ }
359
+ .red-ball {
360
+ display: inline-block;
361
+ width: 20px;
362
+ height: 20px;
363
+ border-radius: 50%;
364
+ margin: 0 3px;
365
+ background: #FF0000;
366
+ color: white;
367
+ text-align: center;
368
+ font-size: 12px;
369
+ line-height: 20px;
370
+ font-weight: bold;
371
+ vertical-align: middle;
372
+ }
373
+ </style>
374
+ """
375
+
376
+ # Create the Gradio app
377
+ with gr.Blocks(title="🐱 FLUX.2 Hello Kitty Powerball Batch Results 🎱") as demo:
378
+
379
+ # Add custom CSS as HTML
380
+ gr.HTML(custom_css)
381
+
382
+ # Get batch statistics
383
+ total_prompts = batch_report.get('total_prompts', 0) if isinstance(batch_report, dict) else 0
384
+ successful = batch_report.get('successful', 0) if isinstance(batch_report, dict) else 0
385
+ failed = batch_report.get('failed', 0) if isinstance(batch_report, dict) else 0
386
+ success_rate = (successful / total_prompts * 100) if total_prompts > 0 else 0
387
+
388
+ # Calculate total generation time
389
+ total_time = 0
390
+ if isinstance(batch_report, dict) and "results" in batch_report:
391
+ for result in batch_report["results"]:
392
+ if result.get("success"):
393
+ total_time += result.get("time", 0)
394
+
395
+ # Theme header
396
+ gr.HTML(f"""
397
+ <div class="hello-kitty-theme">
398
+ <h1 class="hello-kitty-title">🐱 FLUX.2 Hello Kitty Powerball Batch Results 🎱</h1>
399
+ <h3>✨ {successful} Hello Kitty Powerball Scenes Generated with FLUX.2 ✨</h3>
400
+ <p>Hello Kitty in 100 unique scenes combining kawaii charm with Powerball excitement!</p>
401
+ <div class="batch-info">
402
+ <span class="kitty-icon">🐱</span> <strong>Batch Time:</strong> {timestamp} |
403
+ <span class="powerball-icon">🎱</span> <strong>Successful Generations:</strong> {successful} Scenes |
404
+ <span style="margin-left: 20px;">⚡ <strong>Success Rate:</strong> <span class="success-rate">{success_rate:.1f}%</span> ({successful}/{total_prompts}) |
405
+ <span>⏱️ <strong>Total Generation Time:</strong> {total_time/60:.1f} minutes</span>
406
+ </div>
407
+ <div style="margin-top: 10px; font-size: 16px;">
408
+ 🎨 <strong>Creative Elements:</strong> Hello Kitty • Powerball Numbers • 100 Unique Styles • Kawaii Aesthetics • Lottery Themes
409
+ </div>
410
+ <div style="margin-top: 15px;">
411
+ <span class="white-ball"></span><span class="white-ball"></span><span class="white-ball"></span>
412
+ <span class="powerball-numbers">100 WINNING SCENES</span>
413
+ <span class="red-ball">PB</span>
414
+ <span class="white-ball"></span><span class="white-ball"></span><span class="white-ball"></span>
415
+ </div>
416
+ </div>
417
+ """)
418
+
419
+ with gr.Tabs():
420
+ # Tab 1: Image Gallery
421
+ with gr.TabItem("📸 Image Gallery"):
422
+ gr.Markdown(f"### All {successful} Hello Kitty Powerball Scenes - Click to View")
423
+
424
+ # Create image count display
425
+ image_count = gr.Markdown(f"**Total Scenes:** {len(image_paths)} | **Powerball Numbers:** 100 Unique Sets")
426
+
427
+ # Create gallery with large preview
428
+ with gr.Row():
429
+ with gr.Column(scale=2):
430
+ gallery = gr.Gallery(
431
+ value=image_paths,
432
+ label="Click any scene to see details and Powerball numbers",
433
+ columns=5,
434
+ rows=5,
435
+ object_fit="cover",
436
+ height=550
437
+ )
438
+
439
+ with gr.Column(scale=1):
440
+ with gr.Column(elem_classes="selected-image-container"):
441
+ selected_image = gr.Image(
442
+ label="",
443
+ height=350,
444
+ show_label=False
445
+ )
446
+ selected_prompt = gr.Textbox(
447
+ label="Scene Description",
448
+ lines=6,
449
+ interactive=False
450
+ )
451
+ current_counter = gr.Markdown("")
452
+
453
+ # Gallery selection handler
454
+ def update_selected_image(evt: gr.SelectData):
455
+ """Handle gallery selection"""
456
+ if evt.index < len(image_paths):
457
+ image_path = image_paths[evt.index]
458
+ prompt = prompts[evt.index] if evt.index < len(prompts) else "No description available"
459
+ prompt_num = evt.index + 1
460
+ total_images = len(image_paths)
461
+ filename = os.path.basename(image_path)
462
+
463
+ # Extract style, numbers and theme from prompt
464
+ style, numbers, theme = extract_scene_details(prompt)
465
+
466
+ counter_text = f"**Scene {prompt_num}/{total_images}: 🎭 {style} · 🎯 {numbers} · 🎨 {theme[:20]}...** • {filename}"
467
+ return image_path, prompt, counter_text
468
+ return None, "No image available", ""
469
+
470
+ gallery.select(
471
+ fn=update_selected_image,
472
+ outputs=[selected_image, selected_prompt, current_counter]
473
+ )
474
+
475
+ # Initialize with first image
476
+ if image_paths and prompts:
477
+ first_style, first_numbers, first_theme = extract_scene_details(prompts[0])
478
+ demo.load(
479
+ fn=lambda: (
480
+ image_paths[0],
481
+ prompts[0],
482
+ f"**Scene 1/{len(image_paths)}: 🎭 {first_style} · 🎯 {first_numbers} · 🎨 {first_theme}** • {os.path.basename(image_paths[0])}"
483
+ ),
484
+ outputs=[selected_image, selected_prompt, current_counter]
485
+ )
486
+
487
+ # Navigation buttons
488
+ with gr.Row():
489
+ prev_btn = gr.Button("⬅️ Previous Scene")
490
+ next_btn = gr.Button("➡️ Next Scene")
491
+ refresh_btn = gr.Button("🔄 Refresh Gallery")
492
+
493
+ current_index = gr.State(value=0)
494
+
495
+ def navigate(direction, current_idx):
496
+ """Navigate through images"""
497
+ if direction == "next" and current_idx < len(image_paths) - 1:
498
+ new_idx = current_idx + 1
499
+ elif direction == "prev" and current_idx > 0:
500
+ new_idx = current_idx - 1
501
+ else:
502
+ new_idx = current_idx
503
+
504
+ image_path = image_paths[new_idx]
505
+ prompt = prompts[new_idx] if new_idx < len(prompts) else "No description available"
506
+ filename = os.path.basename(image_path)
507
+
508
+ # Extract style, numbers and theme
509
+ style, numbers, theme = extract_scene_details(prompt)
510
+
511
+ counter_text = f"**Scene {new_idx + 1}/{len(image_paths)}: 🎭 {style} · 🎯 {numbers} · 🎨 {theme[:20]}...** • {filename}"
512
+
513
+ return new_idx, image_path, prompt, counter_text
514
+
515
+ prev_btn.click(
516
+ fn=lambda idx: navigate("prev", idx),
517
+ inputs=[current_index],
518
+ outputs=[current_index, selected_image, selected_prompt, current_counter]
519
+ )
520
+
521
+ next_btn.click(
522
+ fn=lambda idx: navigate("next", idx),
523
+ inputs=[current_index],
524
+ outputs=[current_index, selected_image, selected_prompt, current_counter]
525
+ )
526
+
527
+ # Refresh button
528
+ def refresh_gallery():
529
+ json_file_new = get_latest_files()
530
+ batch_report_new = parse_batch_report(json_file_new) if json_file_new else {"error": "No JSON file found"}
531
+ image_files_new = find_image_files(".", limit=200)
532
+ image_paths_new = [str(img) for img in image_files_new]
533
+ prompts_new = get_image_prompt_mapping(batch_report_new, image_files_new)
534
+
535
+ if image_paths_new:
536
+ first_style, first_numbers, first_theme = extract_scene_details(prompts_new[0] if prompts_new else "")
537
+
538
+ return (
539
+ image_paths_new,
540
+ f"**Total Scenes:** {len(image_paths_new)}",
541
+ 0,
542
+ image_paths_new[0],
543
+ prompts_new[0] if prompts_new else "Hello Kitty Powerball Scene",
544
+ f"**Scene 1/{len(image_paths_new)}: 🎭 {first_style} · 🎯 {first_numbers} · 🎨 {first_theme}** • {os.path.basename(image_paths_new[0])}"
545
+ )
546
+ return image_paths_new, f"**Total Scenes:** 0", 0, None, "No scenes found", ""
547
+
548
+ refresh_btn.click(
549
+ fn=refresh_gallery,
550
+ outputs=[gallery, image_count, current_index, selected_image, selected_prompt, current_counter]
551
+ )
552
+
553
+ # Tab 2: Prompts & Powerball Numbers
554
+ with gr.TabItem("📝 Scene Descriptions"):
555
+ gr.Markdown(f"### Complete FLUX.2 Hello Kitty Powerball Descriptions")
556
+
557
+ # Create a dropdown to select scene
558
+ if prompts and len(prompts) > 0:
559
+ # Create display names with style and numbers
560
+ prompt_choices = []
561
+ for i, prompt in enumerate(prompts):
562
+ style, numbers, theme = extract_scene_details(prompt)
563
+ display = f"{i+1:03d}: 🎯 {numbers[:15]} - 🎭 {style[:15]}"
564
+ prompt_choices.append(display)
565
+ default_value = prompt_choices[0]
566
+ else:
567
+ prompt_choices = ["No descriptions available"]
568
+ default_value = "No descriptions available"
569
+
570
+ with gr.Row():
571
+ with gr.Column(scale=1):
572
+ prompt_dropdown = gr.Dropdown(
573
+ choices=prompt_choices,
574
+ label="Select Scene by Powerball Numbers & Style",
575
+ value=default_value,
576
+ interactive=True
577
+ )
578
+ prompt_num = gr.Markdown(f"**Scene 1 of {len(prompts)}**")
579
+
580
+ with gr.Column(scale=2):
581
+ full_prompt_display = gr.Textbox(
582
+ label="Full Scene Description",
583
+ value=prompts[0] if prompts else "No descriptions",
584
+ lines=10,
585
+ interactive=False
586
+ )
587
+
588
+ # Update display when dropdown changes
589
+ def update_prompt_display(selection):
590
+ if selection and selection != "No descriptions available":
591
+ try:
592
+ idx = int(selection.split(":")[0]) - 1
593
+ if 0 <= idx < len(prompts):
594
+ return prompts[idx], f"**Scene {idx + 1} of {len(prompts)}**"
595
+ except:
596
+ pass
597
+ return "No scene selected", f"**Scene ? of {len(prompts)}**"
598
+
599
+ prompt_dropdown.change(
600
+ fn=update_prompt_display,
601
+ inputs=[prompt_dropdown],
602
+ outputs=[full_prompt_display, prompt_num]
603
+ )
604
+
605
+ # Show all prompts in a scrollable textbox
606
+ gr.Markdown(f"### Complete Collection: All {len(prompts)} Hello Kitty Scenes")
607
+
608
+ # Group scenes by style
609
+ style_groups = {}
610
+ for i, prompt in enumerate(prompts):
611
+ style, numbers, theme = extract_scene_details(prompt)
612
+ scene_text = f"{i+1:03d}. 🎭 {style} - 🎯 {numbers} - 🎨 {theme}: {prompt}"
613
+
614
+ if style not in style_groups:
615
+ style_groups[style] = []
616
+ style_groups[style].append(scene_text)
617
+
618
+ # Sort styles by count
619
+ sorted_styles = sorted(style_groups.items(), key=lambda x: len(x[1]), reverse=True)
620
+
621
+ all_prompts_text = "="*80 + "\n"
622
+ for style, scenes in sorted_styles:
623
+ all_prompts_text += f"🎭 {style.upper()} ({len(scenes)} scenes)\n"
624
+ all_prompts_text += "="*80 + "\n"
625
+ all_prompts_text += "\n".join(scenes) + "\n\n"
626
+
627
+ all_prompts_display = gr.Textbox(
628
+ value=all_prompts_text,
629
+ label=f"Complete FLUX.2 Hello Kitty Powerball Collection ({len(prompts)} Descriptions)",
630
+ lines=35,
631
+ interactive=False
632
+ )
633
+
634
+ # Tab 3: Batch Statistics
635
+ with gr.TabItem("📊 Statistics"):
636
+ gr.Markdown("### FLUX.2 Hello Kitty Powerball - Generation Statistics")
637
+
638
+ if isinstance(batch_report, dict) and "error" not in batch_report:
639
+ # Display comprehensive statistics
640
+ gr.Markdown("### 📈 Generation Statistics")
641
+
642
+ # Calculate detailed time statistics
643
+ times = []
644
+ if "results" in batch_report:
645
+ for result in batch_report["results"]:
646
+ if result.get("success") and "time" in result:
647
+ times.append(result["time"])
648
+
649
+ avg_time = sum(times) / len(times) if times else 0
650
+ max_time = max(times) if times else 0
651
+ min_time = min(times) if times else 0
652
+
653
+ # Count styles and themes
654
+ styles_count = {}
655
+ themes_count = {}
656
+
657
+ for prompt in prompts:
658
+ style, numbers, theme = extract_scene_details(prompt)
659
+ styles_count[style] = styles_count.get(style, 0) + 1
660
+ if theme:
661
+ themes_count[theme] = themes_count.get(theme, 0) + 1
662
+
663
+ # Sort by count
664
+ sorted_styles = sorted(styles_count.items(), key=lambda x: x[1], reverse=True)
665
+ sorted_themes = sorted(themes_count.items(), key=lambda x: x[1], reverse=True)
666
+
667
+ stats_html = f"""
668
+ <div class='stats-box'>
669
+ <h4>📊 BATCH SUMMARY</h4>
670
+ <table style='width: 100%; border-collapse: collapse;'>
671
+ <tr><td><strong>Total Prompts:</strong></td><td><span class="kitty-color">{batch_report.get('total_prompts', total_prompts)}</span></td></tr>
672
+ <tr><td><strong>Successful Generations:</strong></td><td><span class="success-rate">{batch_report.get('successful', successful)} Scenes</span></td></tr>
673
+ <tr><td><strong>Failed Generations:</strong></td><td><span class="kitty-color">{batch_report.get('failed', failed)}</span></td></tr>
674
+ <tr><td><strong>Success Rate:</strong></td><td><span class="success-rate">{success_rate:.1f}%</span></td></tr>
675
+ <tr><td><strong>Batch Timestamp:</strong></td><td>{timestamp}</td></tr>
676
+ <tr><td><strong>Prompts Source:</strong></td><td>{batch_report.get('prompts_file', 'hello_kitty_flux2_powerball.txt')}</td></tr>
677
+ <tr><td><strong>Total Generation Time:</strong></td><td>{total_time/60:.1f} minutes</td></tr>
678
+ <tr><td><strong>Average Time per Image:</strong></td><td>{avg_time:.1f} seconds</td></tr>
679
+ <tr><td><strong>Fastest Generation:</strong></td><td>{min_time:.1f} seconds</td></tr>
680
+ <tr><td><strong>Slowest Generation:</strong></td><td>{max_time:.1f} seconds</td></tr>
681
+ <tr><td><strong>Unique Hello Kitty Styles:</strong></td><td>{len(styles_count)} different occupations/outfits</td></tr>
682
+ <tr><td><strong>Unique Powerball Themes:</strong></td><td>{len(themes_count)} different slogans</td></tr>
683
+ </table>
684
+ </div>
685
+ """
686
+
687
+ gr.HTML(stats_html)
688
+
689
+ # Show Hello Kitty style breakdown
690
+ gr.Markdown("### 🎭 Hello Kitty Style Distribution")
691
+
692
+ style_html = "<div class='stats-box'><h4>Top Hello Kitty Styles in Collection</h4><table style='width: 100%; border-collapse: collapse;'>"
693
+ for style, count in sorted_styles[:10]:
694
+ percentage = (count / len(prompts)) * 100
695
+ style_html += f"<tr><td><strong>{style}:</strong></td><td>{count} scenes ({percentage:.1f}%)</td></tr>"
696
+
697
+ style_html += f"<tr><td><strong>Total Unique Styles:</strong></td><td>{len(styles_count)}</td></tr>"
698
+ style_html += "</table></div>"
699
+
700
+ gr.HTML(style_html)
701
+
702
+ # Show theme breakdown
703
+ if themes_count:
704
+ gr.Markdown("### 🎨 Theme Distribution")
705
+
706
+ theme_html = "<div class='stats-box'><h4>Top Powerball Themes</h4><table style='width: 100%; border-collapse: collapse;'>"
707
+ for theme, count in sorted_themes[:10]:
708
+ percentage = (count / len(prompts)) * 100
709
+ theme_html += f"<tr><td><strong>{theme}:</strong></td><td>{count} scenes ({percentage:.1f}%)</td></tr>"
710
+
711
+ theme_html += f"<tr><td><strong>Total Unique Themes:</strong></td><td>{len(themes_count)}</td></tr>"
712
+ theme_html += "</table></div>"
713
+ gr.HTML(theme_html)
714
+
715
+ # Show full JSON
716
+ with gr.Accordion("📁 View Full JSON Data", open=False):
717
+ json_display = gr.Code(
718
+ value=json.dumps(batch_report, indent=2),
719
+ language="json",
720
+ interactive=False,
721
+ lines=25
722
+ )
723
+ else:
724
+ # Create basic stats from files
725
+ stats_html = f"""
726
+ <div class='stats-box'>
727
+ <h4>📊 FLUX.2 Hello Kitty Powerball - File Analysis</h4>
728
+ <p><strong>Total Images Found:</strong> {len(image_paths)}</p>
729
+ <p><strong>Batch Range:</strong> batch_001 to batch_{len(image_paths):03d}</p>
730
+ <p><strong>Total Descriptions:</strong> {len(prompts)} scenes</p>
731
+ <p><strong>Model:</strong> FLUX.2</p>
732
+ <p><strong>Theme:</strong> Hello Kitty Powerball</p>
733
+ <p><strong>Unique Hello Kitty Styles:</strong> {len(set([extract_scene_details(p)[0] for p in prompts]))} different occupations/outfits</p>
734
+ </div>
735
+ """
736
+ gr.HTML(stats_html)
737
+
738
+ # Tab 4: Scene Categories
739
+ with gr.TabItem("🗂️ Categories"):
740
+ gr.Markdown("### Hello Kitty Powerball - Organized by Category")
741
+
742
+ # Categorize scenes by type
743
+ categories = {
744
+ "🎭 Occupations": ["rabbi", "scientist", "chef", "doctor", "teacher", "pilot", "astronaut", "firefighter", "detective", "judge"],
745
+ "🎨 Artistic Styles": ["Cyberpunk", "Steampunk", "Kawaii"],
746
+ "🏆 Activities": ["ice skating", "baking", "gardening", "skating", "surfing", "skiing", "painting", "photography"],
747
+ "🎪 Fantasy Themes": ["fairy", "wizard", "mermaid", "superhero", "pirate", "ninja", "knight", "robot"],
748
+ "🎱 Powerball Focus": ["numbers", "Powerball", "lottery", "winning", "jackpot"]
749
+ }
750
+
751
+ # Initialize all categories
752
+ categorized_scenes = {category: [] for category in categories}
753
+ uncategorized = []
754
+
755
+ for i, prompt in enumerate(prompts):
756
+ style, numbers, theme = extract_scene_details(prompt)
757
+ categorized = False
758
+
759
+ prompt_lower = prompt.lower()
760
+
761
+ # Categorize by occupation
762
+ if any(word in prompt_lower for word in ["rabbi", "scientist", "chef", "doctor", "teacher", "pilot", "astronaut", "firefighter", "detective", "judge", "baker", "librarian", "construction", "mail carrier", "farmer", "fisherman", "beekeeper", "archaeologist", "tailor", "train conductor", "florist", "clockmaker", "carpenter", "sailor", "electrician", "miner", "magician", "mechanic", "architect", "dentist"]):
763
+ categorized_scenes["🎭 Occupations"].append(f"{i+1:03d}. 🎭 {style} - 🎯 {numbers}")
764
+ categorized = True
765
+
766
+ # Categorize by artistic style
767
+ elif any(word in prompt_lower for word in ["cyberpunk", "steampunk", "kawaii"]):
768
+ categorized_scenes["🎨 Artistic Styles"].append(f"{i+1:03d}. 🎭 {style} - 🎯 {numbers}")
769
+ categorized = True
770
+
771
+ # Categorize by activities
772
+ elif any(word in prompt_lower for word in ["ice skating", "baking", "gardening", "skating", "surfing", "skiing", "painting", "photography", "dancing", "singing", "music", "sports"]):
773
+ categorized_scenes["🏆 Activities"].append(f"{i+1:03d}. 🎭 {style} - 🎯 {numbers}")
774
+ categorized = True
775
+
776
+ # Categorize by fantasy themes
777
+ elif any(word in prompt_lower for word in ["fairy", "wizard", "mermaid", "superhero", "pirate", "ninja", "knight", "robot", "queen", "princess", "fairy tale"]):
778
+ categorized_scenes["🎪 Fantasy Themes"].append(f"{i+1:03d}. 🎭 {style} - 🎯 {numbers}")
779
+ categorized = True
780
+
781
+ # Categorize by Powerball focus
782
+ elif any(word in prompt_lower for word in ["powerball", "lottery", "winning", "jackpot", "numbers", "fortune"]):
783
+ categorized_scenes["🎱 Powerball Focus"].append(f"{i+1:03d}. 🎭 {style} - 🎯 {numbers}")
784
+ categorized = True
785
+
786
+ if not categorized:
787
+ uncategorized.append(f"{i+1:03d}. 🎭 {style} - 🎯 {numbers}")
788
+
789
+ # Create category display
790
+ category_text = ""
791
+ for category, scenes in categorized_scenes.items():
792
+ if scenes:
793
+ category_text += f"\n{'='*60}\n"
794
+ category_text += f"{category} ({len(scenes)} scenes)\n"
795
+ category_text += f"{'='*60}\n"
796
+ category_text += "\n".join(scenes) + "\n"
797
+
798
+ if uncategorized:
799
+ category_text += f"\n{'='*60}\n"
800
+ category_text += f"🎭 Other Scenes ({len(uncategorized)} scenes)\n"
801
+ category_text += f"{'='*60}\n"
802
+ category_text += "\n".join(uncategorized)
803
+
804
+ gr.Markdown("### 📊 Scenes by Category")
805
+
806
+ # Category statistics
807
+ stats_text = ""
808
+ for category, scenes in categorized_scenes.items():
809
+ if scenes:
810
+ percentage = (len(scenes) / len(prompts)) * 100
811
+ stats_text += f"**{category}:** {len(scenes)} scenes ({percentage:.1f}%)\n"
812
+
813
+ if uncategorized:
814
+ percentage = (len(uncategorized) / len(prompts)) * 100
815
+ stats_text += f"\n**Other Categories:** {len(uncategorized)} scenes ({percentage:.1f}%)"
816
+
817
+ gr.Markdown(stats_text)
818
+
819
+ # Display categorized list
820
+ category_display = gr.Textbox(
821
+ value=category_text,
822
+ label="Complete Hello Kitty Powerball Collection Categorized",
823
+ lines=35,
824
+ interactive=False
825
+ )
826
+
827
+ # Tab 5: Info & Instructions
828
+ with gr.TabItem("⚙️ App Info"):
829
+ gr.Markdown("### Application Information & Instructions")
830
+
831
+ # File information
832
+ files_info = f"""
833
+ <div class='stats-box'>
834
+ <h4>📂 FILES LOADED:</h4>
835
+ <div class='file-info'>
836
+ <strong>📊 Batch Report:</strong> {os.path.basename(json_file) if json_file else 'Not found'}<br>
837
+ <strong>📝 Prompts Source:</strong> {batch_report.get('prompts_file', 'hello_kitty_flux2_powerball.txt') if isinstance(batch_report, dict) else 'Unknown'}<br>
838
+ <strong>🎨 Images Found:</strong> {len(image_paths)} scenes<br>
839
+ <strong>⏰ Batch Time:</strong> {timestamp}<br>
840
+ <strong>📈 Success Rate:</strong> <span class="success-rate">{success_rate:.1f}%</span>
841
+ </div>
842
+ </div>
843
+ """
844
+
845
+ gr.HTML(files_info)
846
+
847
+ # Statistics
848
+ gr.Markdown("### 📈 COMPLETE COLLECTION STATISTICS")
849
+
850
+ # Count unique items
851
+ unique_styles = len(set([extract_scene_details(p)[0] for p in prompts]))
852
+ unique_numbers = len(set([extract_scene_details(p)[1] for p in prompts]))
853
+ unique_themes = len(set([extract_scene_details(p)[2] for p in prompts if extract_scene_details(p)[2]]))
854
+
855
+ # Calculate average time
856
+ avg_time = 0
857
+ if isinstance(batch_report, dict) and "results" in batch_report and successful > 0:
858
+ total_time_sum = sum([r.get('time', 0) for r in batch_report.get('results', []) if r.get('success')])
859
+ avg_time = total_time_sum / successful
860
+
861
+ stats_text = f"""
862
+ <div class='stats-box'>
863
+ <h4>📊 GENERATION PERFORMANCE</h4>
864
+ <p><strong>Model:</strong> FLUX.2</p>
865
+ <p><strong>Total Prompts:</strong> {total_prompts} descriptions</p>
866
+ <p><strong>Successful Generations:</strong> {successful} scenes</p>
867
+ <p><strong>Failed Generations:</strong> {failed}</p>
868
+ <p><strong>Success Rate:</strong> <span class="success-rate">{success_rate:.1f}%</span></p>
869
+ <p><strong>Average Generation Time:</strong> {avg_time:.1f} seconds per image</p>
870
+ <p><strong>Theme:</strong> Hello Kitty Powerball</p>
871
+ <p><strong>Hello Kitty Styles:</strong> {unique_styles} different occupations/outfits</p>
872
+ <p><strong>Powerball Combinations:</strong> {unique_numbers} unique number sets</p>
873
+ <p><strong>Powerball Themes:</strong> {unique_themes} different slogans</p>
874
+ </div>
875
+ """
876
+ gr.HTML(stats_text)
877
+
878
+ # Instructions
879
+ gr.Markdown("""
880
+ ### 🎯 HOW TO USE THIS APP:
881
+
882
+ **1. 📸 Image Gallery Tab:**
883
+ - Browse all Hello Kitty Powerball scenes in a grid
884
+ - Click any scene to view it larger with its full description
885
+ - Use Previous/Next buttons to navigate sequentially
886
+ - Each image shows Hello Kitty style, Powerball numbers, and theme
887
+
888
+ **2. 📝 Scene Descriptions Tab:**
889
+ - View all scene descriptions with Powerball numbers
890
+ - Use dropdown to jump to specific scenes by their numbers
891
+ - Descriptions are grouped by Hello Kitty style for easy navigation
892
+ - See the complete collection
893
+
894
+ **3. 📊 Statistics Tab:**
895
+ - See detailed generation statistics
896
+ - View Hello Kitty style and theme distributions
897
+ - Check generation times and performance
898
+ - View complete JSON data
899
+
900
+ **4. 🗂️ Categories Tab:**
901
+ - View scenes organized by Hello Kitty occupations, activities, and themes
902
+ - Find scenes by artistic style
903
+ - Browse fantasy themes and creative interpretations
904
+
905
+ **🐱 Theme:** Hello Kitty in 100 unique scenes combining kawaii charm with Powerball excitement.
906
+
907
+ **🎱 Powerball Integration:** Each scene features unique Powerball numbers on ornaments with matching red Powerball.
908
+
909
+ **🎨 Style Variety:** Hello Kitty as scientist, astronaut, chef, fairy, wizard, and many more!
910
+
911
+ **🌟 Creative Concepts:** From Hello Kitty baking cookies to Hello Kitty as a space explorer - all with Powerball themes.
912
+ """)
913
+
914
+ # Quick stats
915
+ scenes_per_hour = len(image_paths) / (total_time / 3600) if total_time > 0 else 0
916
+ gr.Markdown(f"""
917
+ ### 📊 QUICK STATS
918
+ - **Total Processing Time:** {total_time/3600:.2f} hours
919
+ - **Scenes per Hour:** {scenes_per_hour:.1f}
920
+ - **File Size (approx):** {len(image_paths) * 2:.0f} MB of images
921
+ - **Unique Hello Kitty Styles:** {unique_styles}
922
+ - **Powerball Combinations:** {unique_numbers}
923
+ - **Powerball Themes:** {unique_themes} different slogans
924
+ - **Resolution:** All images in high quality
925
+ """)
926
+
927
+ return demo
928
+
929
+ if __name__ == "__main__":
930
+ # Launch the app
931
+ demo = create_main_app()
932
+
933
+ # Launch settings
934
+ demo.launch(
935
+ server_name="0.0.0.0",
936
+ server_port=7860,
937
+ share=False,
938
+ debug=False,
939
+ show_error=True
940
+ )
batch_001_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 2296e46db47d3e8e5a9616b825ea68577b65d1db03a70e611473f82b09df1711
  • Pointer size: 132 Bytes
  • Size of remote file: 1.42 MB
batch_002_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 50919e6cb85077e3ad350ecd26c69fe23f91945ea7e58e2d7cf657e27262c670
  • Pointer size: 132 Bytes
  • Size of remote file: 1.5 MB
batch_003_20251211_201120.png ADDED

Git LFS Details

  • SHA256: d51aa3b9c735ecbb4b705059f06e69f34d2827c38562fa64a78a21d3a0b19fa8
  • Pointer size: 132 Bytes
  • Size of remote file: 1.42 MB
batch_004_20251211_201120.png ADDED

Git LFS Details

  • SHA256: e277e67181953c1c1f7db08ba2c87865e6bfbdb036023c32b96fccff6c4a5019
  • Pointer size: 132 Bytes
  • Size of remote file: 1.76 MB
batch_005_20251211_201120.png ADDED

Git LFS Details

  • SHA256: cc2ec3e262a765c18ffed5dc3b24993cdf5e238df9d50a6b1141bdf972bc7cef
  • Pointer size: 132 Bytes
  • Size of remote file: 1.82 MB
batch_006_20251211_201120.png ADDED

Git LFS Details

  • SHA256: b187e2c11766b2bf41ae6058d2aa80b277fd3461ef8fa85960fc66618486b124
  • Pointer size: 132 Bytes
  • Size of remote file: 1.44 MB
batch_007_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 1cbad16c9e54586e301d360686104d6b316c4a38817ddbea9095b456963fcf68
  • Pointer size: 132 Bytes
  • Size of remote file: 1.65 MB
batch_008_20251211_201120.png ADDED

Git LFS Details

  • SHA256: c4ebf29c72f61c5d7332f70ec1f448663a274c9866f6019ecfd4f16cada7e04f
  • Pointer size: 132 Bytes
  • Size of remote file: 1.54 MB
batch_009_20251211_201120.png ADDED

Git LFS Details

  • SHA256: faa5f512527cb8d1d387fe94da0cbb00b2c7516da3f657a3ef3da26dc9b1367c
  • Pointer size: 132 Bytes
  • Size of remote file: 1.97 MB
batch_010_20251211_201120.png ADDED

Git LFS Details

  • SHA256: a360a55fbd9507a802f25145f1ab2fc9bd307a94d340c25c23c6480c73073900
  • Pointer size: 132 Bytes
  • Size of remote file: 1.44 MB
batch_011_20251211_201120.png ADDED

Git LFS Details

  • SHA256: d02283be3be1ad4b6711f0fac20b8bf1cfd95c4731fef0f33c9718ce72a26e69
  • Pointer size: 132 Bytes
  • Size of remote file: 2.04 MB
batch_012_20251211_201120.png ADDED

Git LFS Details

  • SHA256: e7f2cde41d56c5750df7a619564198c72dfe87decbdca3af95df8c1cf5e97376
  • Pointer size: 132 Bytes
  • Size of remote file: 1.58 MB
batch_013_20251211_201120.png ADDED

Git LFS Details

  • SHA256: a75ae016c3f6b8a3b36e7b020a5d8b36a20e2490e9bd293dd61346eed45851d9
  • Pointer size: 132 Bytes
  • Size of remote file: 1.8 MB
batch_014_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 2d4718bb4e68b585c694a013d85575f483052fb569ddd7856e710843840cdbf9
  • Pointer size: 132 Bytes
  • Size of remote file: 1.94 MB
batch_015_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 86a1b1971550439956b923e6ab716d4f5e44ea2a0b057c694a0be1ee02c69a94
  • Pointer size: 132 Bytes
  • Size of remote file: 1.79 MB
batch_016_20251211_201120.png ADDED

Git LFS Details

  • SHA256: cebecd0f868a0f0bb33c6103cd2d59555cc943495594d35f3f56539e47836695
  • Pointer size: 132 Bytes
  • Size of remote file: 1.86 MB
batch_017_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 592026675fb022346efa12ca64f96feb871ac446ea8c6e043458e825074232b4
  • Pointer size: 132 Bytes
  • Size of remote file: 1.47 MB
batch_018_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 9d43016021c36dedc63340535ef8be30582eb398df821b1f844be768a5ccec84
  • Pointer size: 132 Bytes
  • Size of remote file: 1.69 MB
batch_019_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 330872979ad0eb9283756a712dd52bf3396fccee9beae7ef351873dba99baf37
  • Pointer size: 132 Bytes
  • Size of remote file: 1.49 MB
batch_020_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 6f571ea46f3aceb87bd8fcd90115064380a66ecea53c2749f4c9eebe792d9eb2
  • Pointer size: 132 Bytes
  • Size of remote file: 1.71 MB
batch_021_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 5e0a3304b5bb02a62fb28e94eb78da375a5a18cfbc0aec60c8d1e7547d3267e3
  • Pointer size: 132 Bytes
  • Size of remote file: 1.63 MB
batch_022_20251211_201120.png ADDED

Git LFS Details

  • SHA256: e23d5d8b1f0a3ff7024e519af898b09c3995aeffe3708fa2d8fe1f2903e7dd44
  • Pointer size: 132 Bytes
  • Size of remote file: 1.25 MB
batch_023_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 9362e53771176e1a1a0a4f0d5f9f59935d45ce17b20f37b67cf0e5eace2fac0c
  • Pointer size: 132 Bytes
  • Size of remote file: 1.77 MB
batch_024_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 84972ffcfc3d7db0d31d79bb84794849df9f2c6bce6fe8cdf5481c31fefc940d
  • Pointer size: 132 Bytes
  • Size of remote file: 1.9 MB
batch_025_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 0699dbad196b89b635433f739f9f7f0f21e3545907c95aa4ad411f0e48db2713
  • Pointer size: 132 Bytes
  • Size of remote file: 1.64 MB
batch_026_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 921a1a31d420ba156562e61503def19cea4b4944642b76ef81eea7933d304d25
  • Pointer size: 132 Bytes
  • Size of remote file: 1.87 MB
batch_027_20251211_201120.png ADDED

Git LFS Details

  • SHA256: cc2fa99d64b1d8d92724f52a17e0e5fdf42495f565e047ca929d29232500319b
  • Pointer size: 132 Bytes
  • Size of remote file: 1.46 MB
batch_028_20251211_201120.png ADDED

Git LFS Details

  • SHA256: b7a3c5428cefec4d44293c094898159c7a3d31d1e3c4ec386feeeb9fbb3864dd
  • Pointer size: 132 Bytes
  • Size of remote file: 1.71 MB
batch_029_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 6cf1a17d3d547f0ae0da528c4bc8af75bd71ee9304c5411ee0062523397254d4
  • Pointer size: 132 Bytes
  • Size of remote file: 1.46 MB
batch_030_20251211_201120.png ADDED

Git LFS Details

  • SHA256: edbd23467f00dbd2837a728808a5b9547eb526b2a85b33d391fa62072ec04077
  • Pointer size: 132 Bytes
  • Size of remote file: 1.49 MB
batch_031_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 34c4652f67002b62fcb35d2abf7afc0c775a82c2dafd073abb052386a8a5c739
  • Pointer size: 132 Bytes
  • Size of remote file: 1.35 MB
batch_032_20251211_201120.png ADDED

Git LFS Details

  • SHA256: aa7acb7a79b9aa5db145d33c7ca4bf06ac7c5472056594ce263bda6e33e887b0
  • Pointer size: 132 Bytes
  • Size of remote file: 1.51 MB
batch_033_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 91f149a3b2a7916afbc8345df39b53fd6cc5517b9fe821b43f148fdc8b21e372
  • Pointer size: 132 Bytes
  • Size of remote file: 1.4 MB
batch_034_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 6ce645523850feb4d356360e347507d2f5633e17febc6b193b7597bc165f24cb
  • Pointer size: 132 Bytes
  • Size of remote file: 1.48 MB
batch_035_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 09b9ff7f0d66b95a1e10a9cd3949e21ee5a87829ca5fd5ecf421bdeeac0297a1
  • Pointer size: 132 Bytes
  • Size of remote file: 1.73 MB
batch_036_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 8a1120950494e1e6078348d2c697a30ab487a75b13598184232e11094a387d21
  • Pointer size: 132 Bytes
  • Size of remote file: 1.72 MB
batch_037_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 075466474bd2ed9d2c03dac324e4c7d182416407b4af9cfab935ae2439e22e9f
  • Pointer size: 132 Bytes
  • Size of remote file: 1.46 MB
batch_038_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 08f47ba2b83a8ac68a41b0b6fc6ee80f892ae5c8b27449b6ebc45dc188479f89
  • Pointer size: 132 Bytes
  • Size of remote file: 1.63 MB
batch_039_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 8f3b2e56d17dc26a1bf9db4db8c0f52b9e9c1e917ed4c35eb8793703506b2b69
  • Pointer size: 132 Bytes
  • Size of remote file: 1.36 MB
batch_040_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 0647fffc0d8843ce24c8b4994c72623a9a7889162377342ae817a10075731236
  • Pointer size: 132 Bytes
  • Size of remote file: 1.62 MB
batch_041_20251211_201120.png ADDED

Git LFS Details

  • SHA256: d4388d49fd556cb7093622b563c2981bccca953b8113a0f884ee699582baf2f5
  • Pointer size: 132 Bytes
  • Size of remote file: 1.66 MB
batch_042_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 764624ff670795cc8341f184016e564f28d6afbf07a074075ffd35fcc1ebe8a4
  • Pointer size: 132 Bytes
  • Size of remote file: 1.72 MB
batch_043_20251211_201120.png ADDED

Git LFS Details

  • SHA256: f4fc13472e8c6538229d646474cf4ed61eb78c429febbd8f1684624a0833d07b
  • Pointer size: 132 Bytes
  • Size of remote file: 1.56 MB
batch_044_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 03d3a33f6758af0642cf612bddf9c8431b1aa7a104f49263daebfd28fef3523f
  • Pointer size: 132 Bytes
  • Size of remote file: 1.89 MB
batch_045_20251211_201120.png ADDED

Git LFS Details

  • SHA256: a8591fa04ebea8abd5fc87cec87d60433e58d6607d642d7a022274354b928221
  • Pointer size: 132 Bytes
  • Size of remote file: 1.46 MB
batch_046_20251211_201120.png ADDED

Git LFS Details

  • SHA256: d312f771a7a189e1edc36b369d28a1bb99b16f05047bf38bd1aa56782db8bcd1
  • Pointer size: 132 Bytes
  • Size of remote file: 1.67 MB
batch_047_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 47b9222aae0ddacd80c8db332567816855f0602dff26873bee8cdfd49f5dc65a
  • Pointer size: 132 Bytes
  • Size of remote file: 1.91 MB
batch_048_20251211_201120.png ADDED

Git LFS Details

  • SHA256: 20c27bbdcd371fc0f209a7e4b84622f7263ebc3d07b6ec39d3929088e761fb3b
  • Pointer size: 132 Bytes
  • Size of remote file: 1.7 MB