""" EU-Utility - Global Tracker Plugin Track globals, HOFs, with notifications. """ import json from datetime import datetime, timedelta from pathlib import Path from collections import deque from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTableWidget, QTableWidgetItem, QCheckBox, QFrame ) from PyQt6.QtCore import Qt from plugins.base_plugin import BasePlugin from core.icon_manager import get_icon_manager from PyQt6.QtGui import QPixmap class GlobalTrackerPlugin(BasePlugin): """Track globals and HOFs with stats.""" name = "Global Tracker" version = "1.0.0" author = "ImpulsiveFPS" description = "Track globals, HOFs, and ATHs" hotkey = "ctrl+shift+g" def initialize(self): """Setup global tracker.""" self.data_file = Path("data/globals.json") self.data_file.parent.mkdir(parents=True, exist_ok=True) self.globals = deque(maxlen=1000) self.my_globals = [] self.notifications_enabled = True self._load_data() def _load_data(self): """Load global data.""" if self.data_file.exists(): try: with open(self.data_file, 'r') as f: data = json.load(f) self.globals.extend(data.get('globals', [])) self.my_globals = data.get('my_globals', []) except: pass def _save_data(self): """Save global data.""" with open(self.data_file, 'w') as f: json.dump({ 'globals': list(self.globals), 'my_globals': self.my_globals }, f, indent=2) def get_ui(self): """Create global 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('dollar-sign', size=20) title_icon.setPixmap(icon_pixmap) title_icon.setFixedSize(20, 20) title_layout.addWidget(title_icon) title = QLabel("Global Tracker") title.setStyleSheet("color: white; font-size: 16px; font-weight: bold;") title_layout.addWidget(title) title_layout.addStretch() layout.addLayout(title_layout) # Stats stats_frame = QFrame() stats_frame.setStyleSheet(""" QFrame { background-color: rgba(30, 35, 45, 200); border: 1px solid rgba(100, 110, 130, 80); border-radius: 6px; } """) stats_layout = QHBoxLayout(stats_frame) total = len(self.globals) hofs = sum(1 for g in self.globals if g.get('value', 0) >= 1000) self.total_label = QLabel(f"Globals: {total}") self.total_label.setStyleSheet("color: #4caf50; font-weight: bold;") stats_layout.addWidget(self.total_label) self.hof_label = QLabel(f"HOFs: {hofs}") self.hof_label.setStyleSheet("color: #ffc107; font-weight: bold;") stats_layout.addWidget(self.hof_label) self.my_label = QLabel(f"My Globals: {len(self.my_globals)}") self.my_label.setStyleSheet("color: #ff8c42; font-weight: bold;") stats_layout.addWidget(self.my_label) stats_layout.addStretch() layout.addWidget(stats_frame) # Filters filters = QHBoxLayout() self.show_mine_cb = QCheckBox("Show only my globals") self.show_mine_cb.setStyleSheet("color: white;") filters.addWidget(self.show_mine_cb) self.show_hof_cb = QCheckBox("HOFs only") self.show_hof_cb.setStyleSheet("color: white;") filters.addWidget(self.show_hof_cb) filters.addStretch() layout.addLayout(filters) # Globals table self.globals_table = QTableWidget() self.globals_table.setColumnCount(5) self.globals_table.setHorizontalHeaderLabels(["Time", "Player", "Mob/Item", "Value", "Type"]) self.globals_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.globals_table.horizontalHeader().setStretchLastSection(True) layout.addWidget(self.globals_table) self._refresh_globals() # Test buttons test_layout = QHBoxLayout() test_global = QPushButton("Test Global") test_global.setStyleSheet(""" QPushButton { background-color: #4caf50; color: white; padding: 8px; border: none; border-radius: 4px; } """) test_global.clicked.connect(self._test_global) test_layout.addWidget(test_global) test_hof = QPushButton("Test HOF") test_hof.setStyleSheet(""" QPushButton { background-color: #ffc107; color: black; padding: 8px; border: none; border-radius: 4px; } """) test_hof.clicked.connect(self._test_hof) test_layout.addWidget(test_hof) test_layout.addStretch() layout.addLayout(test_layout) layout.addStretch() return widget def _refresh_globals(self): """Refresh globals table.""" recent = list(self.globals)[-50:] # Last 50 self.globals_table.setRowCount(len(recent)) for i, g in enumerate(reversed(recent)): self.globals_table.setItem(i, 0, QTableWidgetItem(g.get('time', '-')[-8:])) self.globals_table.setItem(i, 1, QTableWidgetItem(g.get('player', 'Unknown'))) self.globals_table.setItem(i, 2, QTableWidgetItem(g.get('target', 'Unknown'))) value_item = QTableWidgetItem(f"{g.get('value', 0):.2f} PED") value = g.get('value', 0) if value >= 10000: value_item.setForeground(Qt.GlobalColor.magenta) elif value >= 1000: value_item.setForeground(Qt.GlobalColor.yellow) elif value >= 50: value_item.setForeground(Qt.GlobalColor.green) self.globals_table.setItem(i, 3, value_item) g_type = "ATH" if value >= 10000 else "HOF" if value >= 1000 else "Global" self.globals_table.setItem(i, 4, QTableWidgetItem(g_type)) def _test_global(self): """Add test global.""" self.add_global("TestPlayer", "Argo Scout", 45.23, is_mine=True) self._refresh_globals() def _test_hof(self): """Add test HOF.""" self.add_global("TestPlayer", "Oratan Miner", 1250.00, is_mine=True) self._refresh_globals() def add_global(self, player, target, value, is_mine=False): """Add a global.""" entry = { 'time': datetime.now().isoformat(), 'player': player, 'target': target, 'value': value, 'is_mine': is_mine } self.globals.append(entry) if is_mine: self.my_globals.append(entry) self._save_data() self._refresh_globals() def parse_chat_message(self, message): """Parse global from chat.""" # Look for global patterns import re # Example: "Player killed Argo Scout worth 45.23 PED!" pattern = r'(\w+)\s+(?:killed|mined|crafted)\s+(.+?)\s+worth\s+([\d.]+)\s+PED' match = re.search(pattern, message, re.IGNORECASE) if match: player = match.group(1) target = match.group(2) value = float(match.group(3)) is_mine = player == "You" or player == "Your avatar" self.add_global(player, target, value, is_mine)