aboutsummaryrefslogtreecommitdiff
path: root/interactive_optimizer.py
blob: 24b63ede7ab9a7814b058c5fcf968ef72f663212 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
import json
import sys
from typing import Dict, List, Tuple, Optional
from artifact_optimizer import ArtifactOptimizer

class InteractiveArtifactOptimizer:
    def __init__(self):
        self.optimizer = ArtifactOptimizer()
        self.available_characters = []
        
    def load_data(self):
        """Load artifact and character data"""
        try:
            self.optimizer.load_data('data.json', 'characters.json')
            self.available_characters = list(self.optimizer.character_data.keys())
            print("✅ Data loaded successfully!")
            print(f"📦 Total artifacts: {len(self.optimizer.artifacts)}")
            print(f"👥 Available characters: {len(self.available_characters)}")
            return True
        except FileNotFoundError as e:
            print(f"❌ Error loading data: {e}")
            print("Make sure 'data.json' and 'characters.json' are in the current directory.")
            return False
        except Exception as e:
            print(f"❌ Unexpected error: {e}")
            return False
    
    def display_character_info(self, character: str):
        """Display detailed character information"""
        char_data = self.optimizer.character_data.get(character, {})
        
        print(f"\n{'='*50}")
        print(f"CHARACTER INFO: {character}")
        print(f"{'='*50}")
        
        # ER Requirements
        er_req = char_data.get('er_requirement', {})
        print("🔋 Energy Recharge Requirements:")
        if isinstance(er_req, dict) and 'min' in er_req:
            print(f"   {er_req['min']}-{er_req.get('max', er_req['min'])}%")
        elif isinstance(er_req, dict):
            for scenario, req in er_req.items():
                print(f"   {scenario}: {req['min']}-{req['max']}%")
        else:
            print("   No specific requirement")
        
        # Ideal Main Stats
        ideal_stats = char_data.get('ideal_main_stats', {})
        if ideal_stats:
            print("\n🎯 Ideal Main Stats:")
            for slot, stats in ideal_stats.items():
                print(f"   {slot.capitalize()}: {', '.join(stats)}")
        
        # Substat Priority
        substats = char_data.get('substat_priority', [])
        if substats:
            print(f"\n📊 Substat Priority: {' > '.join(substats)}")
        
        # Notes
        notes = char_data.get('notes', [])
        if notes:
            print(f"\n📝 Notes:")
            for note in notes:
                print(f"   • {note}")
    
    def select_characters(self) -> List[str]:
        """Interactive character selection"""
        print(f"\n{'='*60}")
        print("CHARACTER SELECTION")
        print(f"{'='*60}")
        
        print("Available characters:")
        for i, char in enumerate(self.available_characters, 1):
            print(f"  {i}. {char}")
        
        selected_chars = []
        
        while True:
            print(f"\n📋 Current priority order: {' -> '.join(selected_chars) if selected_chars else '(none)'}")
            print(f"🎯 Remaining characters: {len(self.available_characters) - len(selected_chars)}")
            
            print("\nOptions:")
            print("  • Enter character number to add to priority list")
            print("  • Type character name directly")
            print("  • 'info [character]' to view character details")
            print("  • 'remove [position]' to remove from priority list")
            print("  • 'done' to finish selection")
            print("  • 'quit' to exit")
            
            choice = input("\n➤ Your choice: ").strip()
            
            if choice.lower() == 'quit':
                sys.exit(0)
            elif choice.lower() == 'done':
                if selected_chars:
                    break
                else:
                    print("❌ Please select at least one character!")
                    continue
            
            elif choice.startswith('info '):
                char_name = choice[5:].strip()
                if char_name in self.available_characters:
                    self.display_character_info(char_name)
                else:
                    print(f"❌ Character '{char_name}' not found!")
            
            elif choice.startswith('remove '):
                try:
                    pos = int(choice[7:].strip()) - 1
                    if 0 <= pos < len(selected_chars):
                        removed = selected_chars.pop(pos)
                        print(f"✅ Removed {removed} from position {pos + 1}")
                    else:
                        print("❌ Invalid position!")
                except ValueError:
                    print("❌ Invalid position number!")
            
            elif choice.isdigit():
                try:
                    char_index = int(choice) - 1
                    if 0 <= char_index < len(self.available_characters):
                        char = self.available_characters[char_index]
                        if char not in selected_chars:
                            selected_chars.append(char)
                            print(f"✅ Added {char} to priority position {len(selected_chars)}")
                        else:
                            print(f"⚠️ {char} is already in the priority list!")
                    else:
                        print("❌ Invalid character number!")
                except ValueError:
                    print("❌ Invalid input!")
            
            elif choice in self.available_characters:
                if choice not in selected_chars:
                    selected_chars.append(choice)
                    print(f"✅ Added {choice} to priority position {len(selected_chars)}")
                else:
                    print(f"⚠️ {choice} is already in the priority list!")
            
            else:
                print("❌ Invalid choice! Try again.")
        
        return selected_chars
    
    def get_optimization_settings(self) -> Dict:
        """Get optimization settings from user"""
        print(f"\n{'='*60}")
        print("OPTIMIZATION SETTINGS")
        print(f"{'='*60}")
        
        settings = {}
        
        # Ask about 4-star fallback
        while True:
            use_4star = input("Allow 4-star artifacts as fallback? (y/n) [default: y]: ").strip().lower()
            if use_4star in ['', 'y', 'yes']:
                settings['allow_4star_fallback'] = True
                break
            elif use_4star in ['n', 'no']:
                settings['allow_4star_fallback'] = False
                break
            else:
                print("❌ Please enter 'y' or 'n'")
        
        # Ask about ER flexibility
        while True:
            try:
                er_flexibility = input("ER requirement flexibility (%) [default: 20]: ").strip()
                if er_flexibility == '':
                    settings['er_flexibility'] = 20
                    break
                else:
                    settings['er_flexibility'] = float(er_flexibility)
                    break
            except ValueError:
                print("❌ Please enter a valid number")
        
        return settings
    
    def run_optimization(self, character_priority: List[str], settings: Dict):
        """Run the optimization process"""
        print(f"\n{'='*60}")
        print("RUNNING OPTIMIZATION")
        print(f"{'='*60}")
        
        print(f"🎯 Character priority: {' -> '.join(character_priority)}")
        print(f"⚙️ Settings: {settings}")
        print("\nOptimizing...")
        
        # Run optimization
        results = self.optimizer.optimize_builds(character_priority)
        
        # Display results
        formatted_output = self.optimizer.format_results(results)
        print(formatted_output)
        
        # Save results
        filename = 'interactive_optimization_results.txt'
        with open(filename, 'w') as f:
            f.write("INTERACTIVE ARTIFACT OPTIMIZATION RESULTS\n")
            f.write("="*60 + "\n")
            f.write(f"Character Priority: {' -> '.join(character_priority)}\n")
            f.write(f"Settings: {settings}\n")
            f.write("="*60 + "\n\n")
            f.write(formatted_output)
        
        print(f"\n💾 Results saved to '{filename}'")
        
        return results
    
    def show_summary_stats(self, results: Dict):
        """Show summary statistics"""
        print(f"\n{'='*60}")
        print("SUMMARY STATISTICS")
        print(f"{'='*60}")
        
        successful_builds = [data for data in results.values() if data['build'] is not None]
        
        if successful_builds:
            scores = [data['average_score'] for data in successful_builds]
            
            print(f"📊 Build Quality Distribution:")
            print(f"   Best build: {max(scores):.1f}/100")
            print(f"   Worst build: {min(scores):.1f}/100")
            print(f"   Average: {sum(scores)/len(scores):.1f}/100")
            
            # Quality tiers
            tiers = {
                'God-like (88+)': len([s for s in scores if s >= 88]),
                'Insane (77+)': len([s for s in scores if 77 <= s < 88]),
                'Amazing (66+)': len([s for s in scores if 66 <= s < 77]),
                'Great (55+)': len([s for s in scores if 55 <= s < 66]),
                'Good (44+)': len([s for s in scores if 44 <= s < 55]),
                'Below 44': len([s for s in scores if s < 44])
            }
            
            print(f"\n🏆 Quality Tiers:")
            for tier, count in tiers.items():
                if count > 0:
                    print(f"   {tier}: {count} build(s)")
        
        # ER compliance
        er_compliant = sum(1 for data in results.values() 
                          if data['build'] and data['er_info']['meets_requirement'])
        
        print(f"\n⚡ Energy Recharge Compliance:")
        print(f"   Builds meeting ER requirements: {er_compliant}/{len(results)}")
    
    def main_menu(self):
        """Main interactive menu"""
        print("="*60)
        print("🎮 INTERACTIVE GENSHIN ARTIFACT OPTIMIZER")
        print("="*60)
        print("Based on the artifact scoring system by Sevy")
        print("Automates the optimization process for multiple characters")
        
        if not self.load_data():
            return
        
        while True:
            print(f"\n{'='*40}")
            print("MAIN MENU")
            print(f"{'='*40}")
            print("1. Start Optimization")
            print("2. View Character Info")
            print("3. View Available Characters")
            print("4. Exit")
            
            choice = input("\n➤ Select option (1-4): ").strip()
            
            if choice == '1':
                # Start optimization process
                character_priority = self.select_characters()
                if character_priority:
                    settings = self.get_optimization_settings()
                    results = self.run_optimization(character_priority, settings)
                    self.show_summary_stats(results)
                    
                    # Ask if user wants to try again
                    while True:
                        again = input("\n🔄 Run another optimization? (y/n): ").strip().lower()
                        if again in ['y', 'yes']:
                            break
                        elif again in ['n', 'no']:
                            continue
                        else:
                            print("❌ Please enter 'y' or 'n'")
                    
                    if again in ['n', 'no']:
                        break
            
            elif choice == '2':
                # View character info
                print("\nAvailable characters:")
                for i, char in enumerate(self.available_characters, 1):
                    print(f"  {i}. {char}")
                
                char_choice = input("\nEnter character name or number: ").strip()
                
                if char_choice.isdigit():
                    try:
                        char_index = int(char_choice) - 1
                        if 0 <= char_index < len(self.available_characters):
                            self.display_character_info(self.available_characters[char_index])
                        else:
                            print("❌ Invalid character number!")
                    except ValueError:
                        print("❌ Invalid input!")
                elif char_choice in self.available_characters:
                    self.display_character_info(char_choice)
                else:
                    print(f"❌ Character '{char_choice}' not found!")
            
            elif choice == '3':
                # View available characters
                print(f"\n📋 Available Characters ({len(self.available_characters)}):")
                for char in sorted(self.available_characters):
                    print(f"  • {char}")
            
            elif choice == '4':
                print("\n👋 Thanks for using the Artifact Optimizer!")
                break
            
            else:
                print("❌ Invalid choice! Please select 1-4.")

def main():
    """Main entry point"""
    optimizer = InteractiveArtifactOptimizer()
    try:
        optimizer.main_menu()
    except KeyboardInterrupt:
        print("\n\n👋 Optimization interrupted. Goodbye!")
    except Exception as e:
        print(f"\n❌ An error occurred: {e}")
        print("Please check your data files and try again.")

if __name__ == "__main__":
    main()