""" EU-Utility - Auction Tracker Plugin Track auction prices and market trends. """ import json from datetime import datetime, timedelta from pathlib import Path from collections import defaultdict from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTableWidget, QTableWidgetItem, QLineEdit, QComboBox, QFrame ) from PyQt6.QtCore import Qt from plugins.base_plugin import BasePlugin from core.icon_manager import get_icon_manager from PyQt6.QtGui import QIcon class AuctionTrackerPlugin(BasePlugin): """Track auction prices and analyze market trends.""" name = "Auction Tracker" version = "1.0.0" author = "ImpulsiveFPS" description = "Track prices, markups, and market trends" hotkey = "ctrl+shift+a" def initialize(self): """Setup auction tracker.""" self.data_file = Path("data/auction_tracker.json") self.data_file.parent.mkdir(parents=True, exist_ok=True) self.price_history = defaultdict(list) self.watchlist = [] self._load_data() def _load_data(self): """Load auction data.""" if self.data_file.exists(): try: with open(self.data_file, 'r') as f: data = json.load(f) self.price_history = defaultdict(list, data.get('prices', {})) self.watchlist = data.get('watchlist', []) except: pass def _save_data(self): """Save auction data.""" with open(self.data_file, 'w') as f: json.dump({ 'prices': dict(self.price_history), 'watchlist': self.watchlist }, f, indent=2) def get_ui(self): """Create auction tracker UI.""" widget = QWidget() widget.setStyleSheet("background: transparent;") layout = QVBoxLayout(widget) layout.setSpacing(15) layout.setContentsMargins(0, 0, 0, 0) # Get icon manager icon_mgr = get_icon_manager() # Title with icon title_layout = QHBoxLayout() title_icon = QLabel() icon_pixmap = icon_mgr.get_pixmap('trending-up', size=20) title_icon.setPixmap(icon_pixmap) title_icon.setFixedSize(20, 20) title_layout.addWidget(title_icon) title = QLabel("Auction Tracker") title.setStyleSheet("color: white; font-size: 16px; font-weight: bold;") title_layout.addWidget(title) title_layout.addStretch() layout.addLayout(title_layout) # Search search_layout = QHBoxLayout() self.search_input = QLineEdit() self.search_input.setPlaceholderText("Search item...") self.search_input.setStyleSheet(""" QLineEdit { background-color: rgba(30, 35, 45, 200); color: white; border: 1px solid rgba(100, 110, 130, 80); border-radius: 4px; padding: 8px; } """) search_layout.addWidget(self.search_input) search_btn = QPushButton() search_pixmap = icon_mgr.get_pixmap('search', size=16) search_btn.setIcon(QIcon(search_pixmap)) search_btn.setIconSize(Qt.QSize(16, 16)) search_btn.setFixedSize(32, 32) search_btn.setStyleSheet(""" QPushButton { background-color: #ff8c42; border: none; border-radius: 4px; } QPushButton:hover { background-color: #ffa060; } """) search_btn.clicked.connect(self._search_item) search_layout.addWidget(search_btn) layout.addLayout(search_layout) # Price table self.price_table = QTableWidget() self.price_table.setColumnCount(6) self.price_table.setHorizontalHeaderLabels(["Item", "Bid", "Buyout", "Markup", "Trend", "Time"]) self.price_table.setStyleSheet(""" QTableWidget { background-color: rgba(30, 35, 45, 200); color: white; border: 1px solid rgba(100, 110, 130, 80); border-radius: 6px; } QHeaderView::section { background-color: rgba(35, 40, 55, 200); color: rgba(255,255,255,180); padding: 8px; font-weight: bold; font-size: 11px; } """) self.price_table.horizontalHeader().setStretchLastSection(True) layout.addWidget(self.price_table) # Quick scan scan_btn = QPushButton("Scan Auction Window") scan_btn.setStyleSheet(""" QPushButton { background-color: #ffc107; color: black; padding: 12px; border: none; border-radius: 4px; font-weight: bold; } QPushButton:hover { background-color: #ffd54f; } """) scan_btn.clicked.connect(self._scan_auction) layout.addWidget(scan_btn) # Sample data self._add_sample_data() layout.addStretch() return widget def _add_sample_data(self): """Add sample auction data.""" sample_items = [ {"name": "Nanocube", "bid": 304.00, "buyout": 304.00, "markup": 101.33}, {"name": "Aakas Plating", "bid": 154.00, "buyout": 159.00, "markup": 102.67}, {"name": "Wenrex Ingot", "bid": 111.00, "buyout": 118.00, "markup": 108.82}, ] self.price_table.setRowCount(len(sample_items)) for i, item in enumerate(sample_items): self.price_table.setItem(i, 0, QTableWidgetItem(item['name'])) self.price_table.setItem(i, 1, QTableWidgetItem(f"{item['bid']:.2f}")) self.price_table.setItem(i, 2, QTableWidgetItem(f"{item['buyout']:.2f}")) markup_item = QTableWidgetItem(f"{item['markup']:.2f}%") if item['markup'] > 105: markup_item.setForeground(Qt.GlobalColor.red) elif item['markup'] < 102: markup_item.setForeground(Qt.GlobalColor.green) self.price_table.setItem(i, 3, markup_item) self.price_table.setItem(i, 4, QTableWidgetItem("→")) self.price_table.setItem(i, 5, QTableWidgetItem("2m ago")) def _search_item(self): """Search for item price history.""" query = self.search_input.text().lower() # TODO: Implement search def _scan_auction(self): """Scan auction window with OCR.""" # TODO: Implement OCR scanning pass def record_price(self, item_name, bid, buyout, tt_value=None): """Record a price observation.""" entry = { 'time': datetime.now().isoformat(), 'bid': bid, 'buyout': buyout, 'tt': tt_value, 'markup': (buyout / tt_value * 100) if tt_value else None } self.price_history[item_name].append(entry) # Keep last 100 entries per item if len(self.price_history[item_name]) > 100: self.price_history[item_name] = self.price_history[item_name][-100:] self._save_data() def get_price_trend(self, item_name, days=7): """Get price trend for an item.""" history = self.price_history.get(item_name, []) if not history: return None cutoff = (datetime.now() - timedelta(days=days)).isoformat() recent = [h for h in history if h['time'] > cutoff] if len(recent) < 2: return None prices = [h['buyout'] for h in recent] return { 'current': prices[-1], 'average': sum(prices) / len(prices), 'min': min(prices), 'max': max(prices), 'trend': 'up' if prices[-1] > prices[0] else 'down' if prices[-1] < prices[0] else 'stable' } def get_deals(self, max_markup=102.0): """Find items below market price.""" deals = [] for item_name, history in self.price_history.items(): if not history: continue latest = history[-1] markup = latest.get('markup') if markup and markup <= max_markup: deals.append({ 'item': item_name, 'price': latest['buyout'], 'markup': markup }) return sorted(deals, key=lambda x: x['markup'])