Compare commits
1 Commits
v2.65.2.25
...
v2.65.2.26
| Author | SHA1 | Date | |
|---|---|---|---|
| e119eeb14a |
@@ -20,15 +20,19 @@
|
|||||||
|
|
||||||
# noinspection PyPackageRequirements
|
# noinspection PyPackageRequirements
|
||||||
import wx
|
import wx
|
||||||
from collections import Counter
|
import re
|
||||||
|
|
||||||
from eos.const import FittingSlot
|
|
||||||
from service.fit import Fit as svcFit
|
from service.fit import Fit as svcFit
|
||||||
from service.port.eft import exportEft, importEft, _importPrepare
|
from service.port.eft import exportEft
|
||||||
from service.const import PortEftOptions
|
from service.const import PortEftOptions
|
||||||
|
|
||||||
_t = wx.GetTranslation
|
_t = wx.GetTranslation
|
||||||
|
|
||||||
|
# Regex for parsing items: itemName x? quantity?, ,? chargeName?
|
||||||
|
ITEM_REGEX = re.compile(
|
||||||
|
r"^(?P<itemName>[-\'\w\s]+?)x?\s*(?P<quantity>\d+)?\s*(?:,\s*(?P<chargeName>[-\'\w\s]+))?$"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class FitDiffFrame(wx.Frame):
|
class FitDiffFrame(wx.Frame):
|
||||||
"""A frame to display differences between two fits."""
|
"""A frame to display differences between two fits."""
|
||||||
@@ -169,158 +173,44 @@ class FitDiffFrame(wx.Frame):
|
|||||||
self.diffText.SetValue('\n'.join(diffLines))
|
self.diffText.SetValue('\n'.join(diffLines))
|
||||||
|
|
||||||
def parsePastedFit(self, text):
|
def parsePastedFit(self, text):
|
||||||
"""Parse pasted EFT text into a fit object."""
|
"""Parse pasted EFT text into a map of item name to count."""
|
||||||
try:
|
items = {}
|
||||||
lines = _importPrepare(text.splitlines())
|
for line in text.splitlines():
|
||||||
if not lines:
|
line = line.strip()
|
||||||
return None
|
if not line or line.startswith("["):
|
||||||
return importEft(lines)
|
continue
|
||||||
except Exception:
|
match = ITEM_REGEX.match(line)
|
||||||
return None
|
if match:
|
||||||
|
item_name = match.group("itemName").strip()
|
||||||
|
quantity = match.group("quantity")
|
||||||
|
count = int(quantity) if quantity else 1
|
||||||
|
if item_name not in items:
|
||||||
|
items[item_name] = 0
|
||||||
|
items[item_name] += count
|
||||||
|
return items
|
||||||
|
|
||||||
def calculateDiff(self, fit1, fit2):
|
def calculateDiff(self, fit1_items, fit2_items):
|
||||||
"""Calculate items needed to transform fit1 into fit2.
|
"""Calculate items needed to transform fit1 into fit2.
|
||||||
|
|
||||||
Returns a list of strings in the format: "<item> <quantity>"
|
Returns a list of strings showing additions and extra items.
|
||||||
Only shows items that need to be added (no negative values).
|
|
||||||
"""
|
"""
|
||||||
diffLines = []
|
diffLines = []
|
||||||
|
|
||||||
# Get module counts by type for each fit (grouped by slot type)
|
all_items = set(fit1_items.keys()) | set(fit2_items.keys())
|
||||||
fit1_modules = self.getModuleCounts(fit1)
|
additions = []
|
||||||
fit2_modules = self.getModuleCounts(fit2)
|
extras = []
|
||||||
|
|
||||||
# Slot order
|
for item in sorted(all_items):
|
||||||
slotOrder = [
|
count1 = fit1_items.get(item, 0)
|
||||||
FittingSlot.HIGH,
|
count2 = fit2_items.get(item, 0)
|
||||||
FittingSlot.MED,
|
|
||||||
FittingSlot.LOW,
|
|
||||||
FittingSlot.RIG,
|
|
||||||
FittingSlot.SUBSYSTEM,
|
|
||||||
FittingSlot.SERVICE,
|
|
||||||
]
|
|
||||||
|
|
||||||
# Diff modules by slot - only show items needed to add
|
|
||||||
for slot in slotOrder:
|
|
||||||
fit1_slot_modules = fit1_modules.get(slot, Counter())
|
|
||||||
fit2_slot_modules = fit2_modules.get(slot, Counter())
|
|
||||||
|
|
||||||
all_module_types = set(fit1_slot_modules.keys()) | set(fit2_slot_modules.keys())
|
|
||||||
slot_diff_lines = []
|
|
||||||
for module_type in sorted(all_module_types):
|
|
||||||
count1 = fit1_slot_modules.get(module_type, 0)
|
|
||||||
count2 = fit2_slot_modules.get(module_type, 0)
|
|
||||||
if count2 > count1:
|
|
||||||
slot_diff_lines.append(f"{module_type} x{count2 - count1}")
|
|
||||||
|
|
||||||
if slot_diff_lines:
|
|
||||||
if diffLines:
|
|
||||||
diffLines.append("")
|
|
||||||
diffLines.extend(slot_diff_lines)
|
|
||||||
|
|
||||||
# Get drone counts
|
|
||||||
fit1_drones = self.getDroneCounts(fit1)
|
|
||||||
fit2_drones = self.getDroneCounts(fit2)
|
|
||||||
|
|
||||||
all_drone_types = set(fit1_drones.keys()) | set(fit2_drones.keys())
|
|
||||||
for drone_type in sorted(all_drone_types):
|
|
||||||
count1 = fit1_drones.get(drone_type, 0)
|
|
||||||
count2 = fit2_drones.get(drone_type, 0)
|
|
||||||
if count2 > count1:
|
if count2 > count1:
|
||||||
diffLines.append(f"{drone_type} x{count2 - count1}")
|
additions.append(f"{item} x{count2 - count1}")
|
||||||
|
elif count1 > count2:
|
||||||
|
extras.append(f"{item} x-{count1 - count2}")
|
||||||
|
|
||||||
# Get fighter counts
|
diffLines.extend(additions)
|
||||||
fit1_fighters = self.getFighterCounts(fit1)
|
if additions and extras:
|
||||||
fit2_fighters = self.getFighterCounts(fit2)
|
diffLines.extend(["", ""])
|
||||||
|
diffLines.extend(extras)
|
||||||
all_fighter_types = set(fit1_fighters.keys()) | set(fit2_fighters.keys())
|
|
||||||
for fighter_type in sorted(all_fighter_types):
|
|
||||||
count1 = fit1_fighters.get(fighter_type, 0)
|
|
||||||
count2 = fit2_fighters.get(fighter_type, 0)
|
|
||||||
if count2 > count1:
|
|
||||||
diffLines.append(f"{fighter_type} x{count2 - count1}")
|
|
||||||
|
|
||||||
# Get cargo counts
|
|
||||||
fit1_cargo = self.getCargoCounts(fit1)
|
|
||||||
fit2_cargo = self.getCargoCounts(fit2)
|
|
||||||
|
|
||||||
all_cargo_types = set(fit1_cargo.keys()) | set(fit2_cargo.keys())
|
|
||||||
for cargo_type in sorted(all_cargo_types):
|
|
||||||
count1 = fit1_cargo.get(cargo_type, 0)
|
|
||||||
count2 = fit2_cargo.get(cargo_type, 0)
|
|
||||||
if count2 > count1:
|
|
||||||
diffLines.append(f"{cargo_type} x{count2 - count1}")
|
|
||||||
|
|
||||||
# Get implants
|
|
||||||
fit1_implants = self.getImplantNames(fit1)
|
|
||||||
fit2_implants = self.getImplantNames(fit2)
|
|
||||||
|
|
||||||
for implant in sorted(fit2_implants - fit1_implants):
|
|
||||||
diffLines.append(f"{implant} x1")
|
|
||||||
|
|
||||||
# Get boosters
|
|
||||||
fit1_boosters = self.getBoosterNames(fit1)
|
|
||||||
fit2_boosters = self.getBoosterNames(fit2)
|
|
||||||
|
|
||||||
for booster in sorted(fit2_boosters - fit1_boosters):
|
|
||||||
diffLines.append(f"{booster} x1")
|
|
||||||
|
|
||||||
return diffLines
|
return diffLines
|
||||||
|
|
||||||
def getModuleCounts(self, fit):
|
|
||||||
"""Get a counter of module types for a fit, grouped by slot type.
|
|
||||||
|
|
||||||
Returns a dict mapping FittingSlot -> Counter of module names.
|
|
||||||
Position doesn't matter, just counts by module name.
|
|
||||||
"""
|
|
||||||
counts_by_slot = {}
|
|
||||||
for module in fit.modules:
|
|
||||||
if module.isEmpty:
|
|
||||||
continue
|
|
||||||
slot = module.slot
|
|
||||||
if slot not in counts_by_slot:
|
|
||||||
counts_by_slot[slot] = Counter()
|
|
||||||
# Use item type name for comparison
|
|
||||||
name = module.item.typeName if module.item else ""
|
|
||||||
counts_by_slot[slot][name] += 1
|
|
||||||
return counts_by_slot
|
|
||||||
|
|
||||||
def getDroneCounts(self, fit):
|
|
||||||
"""Get a counter of drone types for a fit."""
|
|
||||||
counts = Counter()
|
|
||||||
for drone in fit.drones:
|
|
||||||
if drone.item:
|
|
||||||
counts[drone.item.typeName] += drone.amount
|
|
||||||
return counts
|
|
||||||
|
|
||||||
def getFighterCounts(self, fit):
|
|
||||||
"""Get a counter of fighter types for a fit."""
|
|
||||||
counts = Counter()
|
|
||||||
for fighter in fit.fighters:
|
|
||||||
if fighter.item:
|
|
||||||
counts[fighter.item.typeName] += fighter.amount
|
|
||||||
return counts
|
|
||||||
|
|
||||||
def getCargoCounts(self, fit):
|
|
||||||
"""Get a counter of cargo items for a fit."""
|
|
||||||
counts = Counter()
|
|
||||||
for cargo in fit.cargo:
|
|
||||||
if cargo.item:
|
|
||||||
counts[cargo.item.typeName] += cargo.amount
|
|
||||||
return counts
|
|
||||||
|
|
||||||
def getImplantNames(self, fit):
|
|
||||||
"""Get a set of implant names for a fit."""
|
|
||||||
names = set()
|
|
||||||
for implant in fit.implants:
|
|
||||||
if implant.item:
|
|
||||||
names.add(implant.item.typeName)
|
|
||||||
return names
|
|
||||||
|
|
||||||
def getBoosterNames(self, fit):
|
|
||||||
"""Get a set of booster names for a fit."""
|
|
||||||
names = set()
|
|
||||||
for booster in fit.boosters:
|
|
||||||
if booster.item:
|
|
||||||
names.add(booster.item.typeName)
|
|
||||||
return names
|
|
||||||
|
|||||||
Reference in New Issue
Block a user