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

248 lines
8.3 KiB
Python

"""
EU-Utility - Profession Scanner Plugin
Scan and track profession progress with OCR.
"""
import re
import json
from datetime import datetime
from pathlib import Path
from decimal import Decimal
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QPushButton, QTableWidget, QTableWidgetItem, QProgressBar,
QFrame, QGroupBox, QComboBox
)
from PyQt6.QtCore import Qt, QThread, pyqtSignal
from plugins.base_plugin import BasePlugin
class ProfessionOCRThread(QThread):
"""OCR scan for professions window."""
scan_complete = pyqtSignal(dict)
scan_error = pyqtSignal(str)
progress_update = pyqtSignal(str)
def run(self):
"""Perform OCR scan."""
try:
self.progress_update.emit("Capturing screen...")
import pyautogui
screenshot = pyautogui.screenshot()
self.progress_update.emit("Running OCR...")
# OCR
try:
import easyocr
reader = easyocr.Reader(['en'], verbose=False)
results = reader.readtext(screenshot)
text = '\n'.join([r[1] for r in results])
except:
import pytesseract
from PIL import Image
text = pytesseract.image_to_string(screenshot)
# Parse professions
professions = self._parse_professions(text)
self.scan_complete.emit(professions)
except Exception as e:
self.scan_error.emit(str(e))
def _parse_professions(self, text):
"""Parse profession data from OCR text."""
professions = {}
# Pattern: ProfessionName Rank %Progress
# Example: "Laser Pistoleer (Hit) Elite, 72 68.3%"
lines = text.split('\n')
for line in lines:
# Match profession with rank and percentage
match = re.search(r'(\w+(?:\s+\w+)*)\s+\(?(\w+)?\)?\s+(Elite|Champion|Astonishing|Remarkable|Outstanding|Marvelous|Prodigious|Amazing|Incredible|Awesome),?\s+(\d+)[,\s]+(\d+\.?\d*)%?', line)
if match:
prof_name = match.group(1).strip()
spec = match.group(2) or ""
rank_name = match.group(3)
rank_num = match.group(4)
progress = float(match.group(5))
full_name = f"{prof_name} ({spec})" if spec else prof_name
professions[full_name] = {
'rank_name': rank_name,
'rank_num': int(rank_num),
'progress': progress,
'scanned_at': datetime.now().isoformat()
}
return professions
class ProfessionScannerPlugin(BasePlugin):
"""Scan and track profession progress."""
name = "Profession Scanner"
version = "1.0.0"
author = "ImpulsiveFPS"
description = "Track profession ranks and progress"
hotkey = "ctrl+shift+p"
def initialize(self):
"""Setup profession scanner."""
self.data_file = Path("data/professions.json")
self.data_file.parent.mkdir(parents=True, exist_ok=True)
self.professions = {}
self._load_data()
def _load_data(self):
"""Load saved data."""
if self.data_file.exists():
try:
with open(self.data_file, 'r') as f:
data = json.load(f)
self.professions = data.get('professions', {})
except:
pass
def _save_data(self):
"""Save data."""
with open(self.data_file, 'w') as f:
json.dump({'professions': self.professions}, f, indent=2)
def get_ui(self):
"""Create profession scanner UI."""
widget = QWidget()
layout = QVBoxLayout(widget)
layout.setSpacing(15)
layout.setContentsMargins(0, 0, 0, 0)
# Header
header = QLabel("Profession Tracker")
header.setStyleSheet("font-size: 18px; font-weight: bold; color: white;")
layout.addWidget(header)
# Summary
summary = QHBoxLayout()
self.total_label = QLabel(f"Professions: {len(self.professions)}")
self.total_label.setStyleSheet("color: #4ecdc4; font-weight: bold;")
summary.addWidget(self.total_label)
summary.addStretch()
layout.addLayout(summary)
# Scan button
scan_btn = QPushButton("Scan Professions Window")
scan_btn.setStyleSheet("""
QPushButton {
background-color: #ff8c42;
color: white;
padding: 12px;
border: none;
border-radius: 4px;
font-weight: bold;
}
""")
scan_btn.clicked.connect(self._scan_professions)
layout.addWidget(scan_btn)
# Progress
self.progress_label = QLabel("Ready to scan")
self.progress_label.setStyleSheet("color: rgba(255,255,255,150);")
layout.addWidget(self.progress_label)
# Professions table
self.prof_table = QTableWidget()
self.prof_table.setColumnCount(4)
self.prof_table.setHorizontalHeaderLabels(["Profession", "Rank", "Level", "Progress"])
self.prof_table.horizontalHeader().setStretchLastSection(True)
# Style table
self.prof_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;
}
""")
layout.addWidget(self.prof_table)
# Refresh table
self._refresh_table()
return widget
def _scan_professions(self):
"""Start OCR scan."""
self.scanner = ProfessionOCRThread()
self.scanner.scan_complete.connect(self._on_scan_complete)
self.scanner.scan_error.connect(self._on_scan_error)
self.scanner.progress_update.connect(self._on_progress)
self.scanner.start()
def _on_progress(self, message):
"""Update progress."""
self.progress_label.setText(message)
def _on_scan_complete(self, professions):
"""Handle scan completion."""
self.professions.update(professions)
self._save_data()
self._refresh_table()
self.progress_label.setText(f"Found {len(professions)} professions")
self.total_label.setText(f"Professions: {len(self.professions)}")
def _on_scan_error(self, error):
"""Handle error."""
self.progress_label.setText(f"Error: {error}")
def _refresh_table(self):
"""Refresh professions table."""
self.prof_table.setRowCount(len(self.professions))
for i, (name, data) in enumerate(sorted(self.professions.items())):
self.prof_table.setItem(i, 0, QTableWidgetItem(name))
self.prof_table.setItem(i, 1, QTableWidgetItem(data.get('rank_name', '-')))
self.prof_table.setItem(i, 2, QTableWidgetItem(str(data.get('rank_num', 0))))
# Progress with bar
progress = data.get('progress', 0)
progress_widget = QWidget()
progress_layout = QHBoxLayout(progress_widget)
progress_layout.setContentsMargins(5, 2, 5, 2)
bar = QProgressBar()
bar.setValue(int(progress))
bar.setTextVisible(True)
bar.setFormat(f"{progress:.1f}%")
bar.setStyleSheet("""
QProgressBar {
background-color: rgba(60, 70, 90, 150);
border: none;
border-radius: 3px;
text-align: center;
color: white;
}
QProgressBar::chunk {
background-color: #ff8c42;
border-radius: 3px;
}
""")
progress_layout.addWidget(bar)
self.prof_table.setCellWidget(i, 3, progress_widget)