""" EU-Utility - Mining Helper Plugin Track mining finds, claims, and locations. """ import json from datetime import datetime from pathlib import Path from collections import defaultdict from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTableWidget, QTableWidgetItem, QComboBox, QTextEdit ) from PyQt6.QtCore import Qt from plugins.base_plugin import BasePlugin class MiningHelperPlugin(BasePlugin): """Track mining activities and claims.""" name = "Mining Helper" version = "1.0.0" author = "ImpulsiveFPS" description = "Track mining finds, claims, and hotspot locations" hotkey = "ctrl+shift+n" # N for miNiNg # Resource types RESOURCES = [ "Alicenies Liquid", "Ares Powder", "Blausariam", "Caldorite", "Cobalt", "Copper", "Dianthus", "Erdorium", "Frigulite", "Ganganite", "Himi", "Ignisium", "Iron", "Kaz Ingot", "Lysterium", "Maganite", "Niksarium", "Oil", "Platinum", "Redulite", "Rubio", "Sopur", "Titan", "Typonolic Steam", "Uranium", "Veldspar", "Xantium", "Zinc", ] def initialize(self): """Setup mining helper.""" self.data_file = Path("data/mining_helper.json") self.data_file.parent.mkdir(parents=True, exist_ok=True) self.claims = [] self.current_run = { 'start_time': None, 'drops': 0, 'finds': [], 'total_tt': 0.0, } self._load_data() def _load_data(self): """Load historical data.""" if self.data_file.exists(): try: with open(self.data_file, 'r') as f: data = json.load(f) self.claims = data.get('claims', []) except: self.claims = [] def _save_data(self): """Save data.""" with open(self.data_file, 'w') as f: json.dump({'claims': self.claims}, f, indent=2) def get_ui(self): """Create plugin UI.""" widget = QWidget() widget.setStyleSheet("background: transparent;") layout = QVBoxLayout(widget) layout.setSpacing(15) layout.setContentsMargins(0, 0, 0, 0) # Title title = QLabel("⛏️ Mining Helper") title.setStyleSheet("color: white; font-size: 16px; font-weight: bold;") layout.addWidget(title) # Stats stats = QHBoxLayout() self.drops_label = QLabel("Drops: 0") self.drops_label.setStyleSheet("color: #9c27b0; font-size: 14px; font-weight: bold;") stats.addWidget(self.drops_label) self.finds_label = QLabel("Finds: 0") self.finds_label.setStyleSheet("color: #4caf50; font-size: 14px; font-weight: bold;") stats.addWidget(self.finds_label) self.hit_rate_label = QLabel("Hit Rate: 0%") self.hit_rate_label.setStyleSheet("color: #ffc107; font-size: 14px; font-weight: bold;") stats.addWidget(self.hit_rate_label) layout.addLayout(stats) # Quick add claim add_frame = QWidget() add_frame.setStyleSheet(""" QWidget { background-color: rgba(0, 0, 0, 50); border-radius: 8px; border: 1px solid rgba(255, 255, 255, 20); } """) add_layout = QHBoxLayout(add_frame) add_layout.setContentsMargins(10, 10, 10, 10) self.resource_combo = QComboBox() self.resource_combo.addItems(self.RESOURCES) self.resource_combo.setStyleSheet(""" QComboBox { background-color: rgba(255, 255, 255, 15); color: white; border: none; padding: 5px; border-radius: 4px; } """) add_layout.addWidget(self.resource_combo) self.size_combo = QComboBox() self.size_combo.addItems(["Tiny", "Small", "Medium", "Large", "Huge", "Massive"]) self.size_combo.setStyleSheet(self.resource_combo.styleSheet()) add_layout.addWidget(self.size_combo) add_btn = QPushButton("+ Add Claim") add_btn.setStyleSheet(""" QPushButton { background-color: #9c27b0; color: white; padding: 8px 15px; border: none; border-radius: 6px; font-weight: bold; } QPushButton:hover { background-color: #ab47bc; } """) add_btn.clicked.connect(self._add_claim) add_layout.addWidget(add_btn) layout.addWidget(add_frame) # Claims table self.claims_table = QTableWidget() self.claims_table.setColumnCount(4) self.claims_table.setHorizontalHeaderLabels(["Resource", "Size", "TT", "Time"]) self.claims_table.setStyleSheet(""" QTableWidget { background-color: rgba(30, 30, 30, 100); color: white; border: none; border-radius: 6px; } QHeaderView::section { background-color: rgba(156, 39, 176, 100); color: white; padding: 6px; } """) self.claims_table.horizontalHeader().setStretchLastSection(True) layout.addWidget(self.claims_table) layout.addStretch() return widget def _add_claim(self): """Add a claim manually.""" resource = self.resource_combo.currentText() size = self.size_combo.currentText() claim = { 'resource': resource, 'size': size, 'tt_value': self._estimate_tt(size), 'time': datetime.now().isoformat(), 'location': None, # Could get from game } self.claims.append(claim) self._save_data() self._update_table() self._update_stats() def _estimate_tt(self, size): """Estimate TT value based on claim size.""" estimates = { 'Tiny': 0.05, 'Small': 0.25, 'Medium': 1.00, 'Large': 5.00, 'Huge': 25.00, 'Massive': 100.00, } return estimates.get(size, 0.05) def _update_table(self): """Update claims table.""" recent = self.claims[-20:] # Show last 20 self.claims_table.setRowCount(len(recent)) for i, claim in enumerate(recent): self.claims_table.setItem(i, 0, QTableWidgetItem(claim['resource'])) self.claims_table.setItem(i, 1, QTableWidgetItem(claim['size'])) self.claims_table.setItem(i, 2, QTableWidgetItem(f"{claim['tt_value']:.2f}")) time_str = claim['time'][11:16] if claim['time'] else '-' self.claims_table.setItem(i, 3, QTableWidgetItem(time_str)) def _update_stats(self): """Update statistics.""" drops = len(self.claims) + 10 # Estimate finds = len(self.claims) hit_rate = (finds / drops * 100) if drops > 0 else 0 self.drops_label.setText(f"Drops: ~{drops}") self.finds_label.setText(f"Finds: {finds}") self.hit_rate_label.setText(f"Hit Rate: {hit_rate:.1f}%") def parse_chat_message(self, message): """Parse mining claims from chat.""" # Look for claim patterns # Example: "You found a Tiny Lysterium claim" for resource in self.RESOURCES: if resource in message and "claim" in message.lower(): # Extract size sizes = ["Tiny", "Small", "Medium", "Large", "Huge", "Massive"] size = "Unknown" for s in sizes: if s in message: size = s break claim = { 'resource': resource, 'size': size, 'tt_value': self._estimate_tt(size), 'time': datetime.now().isoformat(), 'location': None, } self.claims.append(claim) self._save_data() self._update_table() self._update_stats() break