EU-Utility-Plugins-Repo/plugins/auction_tracker/plugin.py

262 lines
8.7 KiB
Python

"""
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'])