diff options
| author | Fuwn <[email protected]> | 2025-05-28 07:12:43 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2025-05-28 07:12:43 -0700 |
| commit | 035008f3ee1bf5ee84a0cd290d37f222a1cd5e61 (patch) | |
| tree | 950ffad958908892a40ed9cb69c0db6a23e59a3a /interactive_optimizer.py | |
| download | genshin-artifact-playground-035008f3ee1bf5ee84a0cd290d37f222a1cd5e61.tar.xz genshin-artifact-playground-035008f3ee1bf5ee84a0cd290d37f222a1cd5e61.zip | |
Diffstat (limited to 'interactive_optimizer.py')
| -rw-r--r-- | interactive_optimizer.py | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/interactive_optimizer.py b/interactive_optimizer.py new file mode 100644 index 0000000..24b63ed --- /dev/null +++ b/interactive_optimizer.py @@ -0,0 +1,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()
\ No newline at end of file |