aboutsummaryrefslogtreecommitdiff
path: root/interactive_optimizer.py
diff options
context:
space:
mode:
Diffstat (limited to 'interactive_optimizer.py')
-rw-r--r--interactive_optimizer.py340
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