248 lines
8.3 KiB
Python
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)
|