Skip to content

Commit 33c8b97

Browse files
authored
Merge pull request #77 from LPiner/item_modifier_cleanup
refactor: Itemmodifiers are now python objects
2 parents 6bb397c + 719ca96 commit 33c8b97

File tree

12 files changed

+109
-108
lines changed

12 files changed

+109
-108
lines changed

.isort.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[settings]
2-
known_third_party = PIL,colorama,keyboard,requests
2+
known_third_party = PIL,attr,colorama,keyboard,requests

enums/__init__.py

Whitespace-only changes.

enums/item_modifier_type.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from enum import Enum
2+
3+
4+
class ItemModifierType(Enum):
5+
PSEUDO = "pseudo"
6+
EXPLICIT = "explicit"
7+
IMPLICIT = "implicit"
8+
FRACTURED = "fractured"
9+
ENCHANT = "enchant"
10+
CRAFTED = "crafted"
11+
VEILED = "veiled"
12+
MONSTER = "monster"
13+
DELVE = "delve"

factories/__init__.py

Whitespace-only changes.

factories/item_modifier.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from typing import Dict
2+
3+
from enums.item_modifier_type import ItemModifierType
4+
from models.item_modifier import ItemModifier
5+
6+
7+
def build_from_json(blob: Dict) -> ItemModifier:
8+
return ItemModifier(id=blob["id"], text=blob["text"], type=ItemModifierType(blob["type"].lower()))

models/__init__.py

Whitespace-only changes.

models/item_modifier.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from attr import attrib, attrs
2+
3+
from enums.item_modifier_type import ItemModifierType
4+
5+
6+
@attrs(auto_attribs=True)
7+
class ItemModifier:
8+
type: ItemModifierType
9+
id: str
10+
text: str

parse.py

Lines changed: 63 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,36 @@
11
import re
22
import time
33
import traceback
4-
from tkinter import TclError
5-
from tkinter import Tk
6-
from typing import Dict
7-
from typing import List
4+
from itertools import chain
5+
from tkinter import TclError, Tk
6+
from typing import Any, Collection, Dict, Iterable, List, Optional, Tuple
87

98
import requests
10-
from colorama import Fore
11-
from colorama import deinit
12-
from colorama import init
9+
from colorama import Fore, deinit, init
1310

1411
# Local imports
15-
from utils.config import LEAGUE
16-
from utils.config import PROJECT_URL
17-
from utils.config import USE_GUI
18-
from utils.config import USE_HOTKEYS
19-
from utils.currency import CATALYSTS
20-
from utils.currency import CURRENCY
21-
from utils.currency import DIV_CARDS
22-
from utils.currency import ESSENCES
23-
from utils.currency import FOSSILS
24-
from utils.currency import FRAGMENTS_AND_SETS
25-
from utils.currency import INCUBATORS
26-
from utils.currency import OILS
27-
from utils.currency import RESONATORS
28-
from utils.currency import SCARABS
29-
from utils.currency import VIALS
12+
from enums.item_modifier_type import ItemModifierType
13+
from models.item_modifier import ItemModifier
14+
from utils.config import LEAGUE, PROJECT_URL, USE_GUI, USE_HOTKEYS
15+
from utils.currency import (
16+
CATALYSTS,
17+
CURRENCY,
18+
DIV_CARDS,
19+
ESSENCES,
20+
FOSSILS,
21+
FRAGMENTS_AND_SETS,
22+
INCUBATORS,
23+
OILS,
24+
RESONATORS,
25+
SCARABS,
26+
VIALS,
27+
)
3028
from utils.exceptions import InvalidAPIResponseException
31-
from utils.trade import get_leagues
29+
from utils.trade import get_item_modifiers, get_leagues
3230

3331
DEBUG = False
3432

35-
36-
# All available stats on items.
37-
ITEM_MODIFIERS = requests.get(url="https://www.pathofexile.com/api/trade/data/stats").json()
33+
ITEM_MODIFIERS: Optional[Tuple[ItemModifier, ...]] = None
3834

3935

4036
def parse_item_info(text: str) -> Dict:
@@ -422,7 +418,11 @@ def query_trade(
422418
j["query"]["stats"][0]["type"] = "and"
423419
j["query"]["stats"][0]["filters"] = []
424420
for stat in stats:
425-
(proper_affix, value) = find_affix_match(stat)
421+
try:
422+
(proper_affix, value) = find_affix_match(stat)
423+
except NotImplementedError:
424+
# Can't find mod, move on
425+
continue
426426
affix_types = ["implicit", "crafted", "explicit", "enchantments"]
427427
if any(atype in proper_affix for atype in affix_types): # If proper_affix is an actual mod...
428428
j["query"]["stats"][0]["filters"].append({"id": proper_affix, "value": {"min": value, "max": 999}})
@@ -457,7 +457,7 @@ def query_trade(
457457
print(
458458
"[-] Removing the"
459459
+ Fore.CYAN
460-
+ f" {stat_translate(i)} "
460+
+ f" {stat_translate(i['id']).text} "
461461
+ Fore.WHITE
462462
+ "mod from the list due to"
463463
+ Fore.RED
@@ -485,7 +485,7 @@ def query_trade(
485485
print(
486486
"[-] Removing the"
487487
+ Fore.CYAN
488-
+ f" {stat_translate(i)} "
488+
+ f" {stat_translate(i['id']).text} "
489489
+ Fore.WHITE
490490
+ "mod from the list due to"
491491
+ Fore.RED
@@ -684,7 +684,7 @@ def result_prices_are_none(j: Dict) -> bool:
684684
return all(x["listing"]["price"] == None for x in j)
685685

686686

687-
def query_exchange(qcur, league):
687+
def query_exchange(qcur):
688688
"""
689689
Build JSON for fetch request of wanted currency exchange.
690690
"""
@@ -728,7 +728,7 @@ def query_exchange(qcur, league):
728728
return results
729729

730730

731-
def affix_equals(text, affix):
731+
def affix_equals(text, affix) -> Optional[int]:
732732
"""
733733
Clean up the affix to match the given text so we can find the correct id to search with.
734734
@@ -758,94 +758,52 @@ def affix_equals(text, affix):
758758
print(
759759
"[+] Found mod " + Fore.GREEN + f"{text[0:]}: {value}"
760760
) # TODO: support "# to # damage to attacks" type mods and other similar
761-
return (True, value)
761+
return value
762762

763-
return (False, 0)
763+
return None
764764

765765

766-
def find_affix_match(affix):
766+
def find_affix_match(affix: str) -> Tuple[str, int]:
767767
"""
768768
Search for the proper id to return the correct results.
769769
770770
returns tuple (id of the affix requested, value)
771771
"""
772-
pseudos = ITEM_MODIFIERS["result"][0]["entries"]
773-
explicits = ITEM_MODIFIERS["result"][1]["entries"]
774-
implicits = ITEM_MODIFIERS["result"][2]["entries"]
775-
crafted = ITEM_MODIFIERS["result"][5]["entries"]
776-
enchantments = ITEM_MODIFIERS["result"][4]["entries"]
777-
proper_affix = ("", 0)
772+
773+
def get_mods_by_type(type: ItemModifierType) -> Iterable[ItemModifier]:
774+
return (x for x in ITEM_MODIFIERS if x.type == type)
778775

779776
if DEBUG:
780777
print("AFFIX:", affix)
781778

782-
if "(pseudo)" in affix:
783-
for pseudo in pseudos:
784-
(match, value) = affix_equals(pseudo["text"], affix)
785-
if match:
786-
proper_affix = (pseudo["id"], value)
787-
788-
elif "(implicit)" in affix:
789-
for implicit in implicits:
790-
(match, value) = affix_equals(implicit["text"], affix)
791-
if match:
792-
proper_affix = (implicit["id"], value)
793-
794-
elif "(crafted)" in affix:
795-
for craft in crafted:
796-
(match, value) = affix_equals(craft["text"], affix)
797-
if match:
798-
proper_affix = (craft["id"], value)
799-
779+
if re.search(r"\((pseudo|implicit|crafted)\)", affix):
780+
# Do these need to be searched in a specific order?
781+
search_order = [ItemModifierType.PSEUDO, ItemModifierType.IMPLICIT, ItemModifierType.CRAFTED]
782+
search_mods = chain(*(get_mods_by_type(x) for x in search_order))
783+
for mod in search_mods:
784+
value = affix_equals(mod.text, affix)
785+
if value is not None:
786+
return (mod.id, value)
800787
else:
801-
Found = False
802-
for explicit in explicits:
803-
(match, value) = affix_equals(explicit["text"], affix)
804-
if match:
805-
proper_affix = (explicit["id"], value)
806-
Found = True
788+
for explicit in (x for x in ITEM_MODIFIERS if x.type is ItemModifierType.EXPLICIT):
789+
value = affix_equals(explicit.text, affix)
790+
if value is not None:
791+
return (explicit.id, value)
807792

808-
if not Found:
809-
# Maybe it's an enchantment
810-
for enchant in enchantments:
811-
(match, value) = affix_equals(enchant["text"], affix)
812-
if match:
813-
proper_affix = (enchant["id"], value)
793+
# Maybe it's an enchantment
794+
for enchant in (x for x in ITEM_MODIFIERS if x.type is ItemModifierType.ENCHANT):
795+
value = affix_equals(enchant.text, affix)
796+
if value is not None:
797+
return (enchant.id, value)
814798

815-
return proper_affix
799+
raise NotImplementedError("Unable to find matching affix.")
816800

817801

818-
def stat_translate(jaffix):
802+
def stat_translate(jaffix: str) -> ItemModifier:
819803
"""
820804
Translate id to the equivalent stat.
821805
"""
822-
affix = jaffix["id"]
823-
824-
pseudos = ITEM_MODIFIERS["result"][0]["entries"]
825-
explicits = ITEM_MODIFIERS["result"][1]["entries"]
826-
implicits = ITEM_MODIFIERS["result"][2]["entries"]
827-
crafted = ITEM_MODIFIERS["result"][5]["entries"]
828-
enchantments = ITEM_MODIFIERS["result"][4]["entries"]
829-
830-
# TODO add enchantments ability to be lookedup.
831-
832-
if "pseudo" in affix:
833-
return find_stat_by_id(affix, pseudos)
834-
elif "implicit" in affix:
835-
return find_stat_by_id(affix, implicits)
836-
elif "crafted" in affix:
837-
return find_stat_by_id(affix, crafted)
838-
else:
839-
return find_stat_by_id(affix, explicits)
840-
841-
842-
def find_stat_by_id(affix, stat_list):
843-
"""
844-
Helper function to find stats by their id.
845-
"""
846-
for stat in stat_list:
847-
if stat["id"] == affix:
848-
return stat["text"]
806+
return next(x for x in ITEM_MODIFIERS if x.id == jaffix)
849807

850808

851809
def watch_clipboard():
@@ -1067,14 +1025,17 @@ def watch_clipboard():
10671025
root.withdraw()
10681026
DEBUG = False
10691027

1028+
ITEM_MODIFIERS = get_item_modifiers()
1029+
print(f"Loaded {len(ITEM_MODIFIERS)} item mods.")
10701030
valid_leagues = get_leagues()
1031+
1032+
print(f"If you wish to change the selected league you may do so in settings.cfg.")
1033+
print(f"Valid league values are {Fore.MAGENTA}{', '.join(valid_leagues)}.")
1034+
10711035
if LEAGUE not in valid_leagues:
10721036
print(f"Unable to locate {LEAGUE}, please check settings.cfg.")
1073-
10741037
else:
10751038
print(f"All values will be from the {Fore.MAGENTA}{LEAGUE} league")
1076-
print(f"If you wish to change the selected league you may do so in settings.cfg.")
1077-
print(f"Valid league values are {Fore.MAGENTA}{', '.join(valid_leagues)}.")
10781039

10791040
if USE_HOTKEYS:
10801041
import utils.hotkeys as hotkeys

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ exclude = '''
4040
'''
4141

4242
[tool.isort]
43-
force_single_line = true
43+
force_single_line = false
4444
multi_line_output = 3
4545
include_trailing_comma = true
4646
force_grid_wrap = 0

settings.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
useHotKeys = yes
33
league = Metamorph
44
useGUI = yes
5+
56
projectURL = https://github.com/Ethck/Path-of-Accounting/

0 commit comments

Comments
 (0)