11__author__ = "Lukas Mahler"
22__version__ = "0.0.0"
3- __date__ = "08.10 .2025"
3+ __date__ = "02.11 .2025"
44__email__ = "m@hler.eu"
55__status__ = "Development"
66
77
88import json
9- import os
109import re
10+ from dataclasses import dataclass
11+ from pathlib import Path
1112from typing import Optional
1213
13- current_dir = os .path .dirname (os .path .abspath (__file__ ))
14- json_path = os .path .join (current_dir , "pattern.json" )
15- with open (json_path , "r" ) as file :
16- SPECIAL_PATTERN = json .load (file )
14+
15+ DIR = Path (__file__ ).resolve ().parent
16+ PATTERN_MAP = json .loads ((DIR / "pattern.json" ).read_text (encoding = "utf-8" ))
17+ ICON_MAP = json .loads ((DIR / "icons.json" ).read_text (encoding = "utf-8" ))
18+
19+
20+ @dataclass (frozen = True )
21+ class PatternInfo :
22+ """
23+ Normalized lookup result for a pattern query.
24+
25+ Exposes the normalized identifiers (`weapon`, `skin`, `pattern`),
26+ rarity status, ordering metadata (when applicable), and a representative icon for the matched group.
27+ """
28+
29+ weapon : Optional [str ] = None
30+ skin : Optional [str ] = None
31+ pattern : Optional [int ] = None
32+ is_rare : bool = False
33+ group : Optional [str ] = None
34+ ordered : bool = False
35+ order : Optional [tuple [int , int ]] = None
36+ icon : Optional [str ] = None
1737
1838
1939def _normalize_input (market_hash : str , pattern : int ) -> Optional [tuple [str , str , int ]]:
@@ -47,34 +67,41 @@ def _normalize_input(market_hash: str, pattern: int) -> Optional[tuple[str, str,
4767 return weapon , skin , pattern
4868
4969
50- def _check_special (normalized_data : tuple [str , str , int ]) -> Optional [tuple [str , int ]]:
70+ def _match_group (normalized_data : tuple [str , str , int ]) -> Optional [tuple [str , bool , Optional [ int ], Optional [ int ] ]]:
5171 """
52- Check if the normalized data matches a special pattern.
72+ Match the normalized data against the known rare pattern groups .
5373
5474 :param normalized_data: The normalized weapon, skin, and pattern tuple.
5575 :type normalized_data: tuple[str, str, int]
5676
57- :return: A tuple with the pattern name and index, -1 if unordered, or None if no match is found .
58- :rtype: Optional[tuple[str, int]]
77+ :return: Tuple with pattern group name, ordered flag, optional rank, and total if ordered; None if no match.
78+ :rtype: Optional[tuple[str, bool, Optional[ int], Optional[int] ]]
5979 """
6080
6181 weapon , skin , pattern = normalized_data
6282
6383 # Check if skin and weapon exist in the pattern data
64- if skin not in SPECIAL_PATTERN or weapon not in SPECIAL_PATTERN [skin ]:
84+ if skin not in PATTERN_MAP or weapon not in PATTERN_MAP [skin ]:
6585 return None
6686
67- groups = SPECIAL_PATTERN [skin ][weapon ]
87+ groups = PATTERN_MAP [skin ][weapon ]
6888
6989 for group in groups :
70- if pattern in group .get ('pattern' , []):
71- index = group ['pattern' ].index (pattern ) + 1 if group .get ('ordered' ) else - 1
72- return group ['name' ], index
90+ patterns = list (group .get ('pattern' , []))
91+ if pattern in patterns :
92+ ordered = bool (group .get ('ordered' , False ))
93+ if ordered :
94+ rank = patterns .index (pattern ) + 1
95+ total = len (patterns )
96+ else :
97+ rank = None
98+ total = None
99+ return group .get ('name' ), ordered , rank , total
73100
74101 return None
75102
76103
77- def check_rare (market_hash : str , pattern : int ) -> tuple [ bool , Optional [ tuple [ str , int ]]] :
104+ def check_rare (market_hash : str , pattern : int ) -> PatternInfo :
78105 """
79106 Determine if the given item is rare based on market hash and pattern.
80107
@@ -83,28 +110,47 @@ def check_rare(market_hash: str, pattern: int) -> tuple[bool, Optional[tuple[str
83110 :param pattern: The pattern to check for rarity.
84111 :type pattern: int
85112
86- :return: A tuple indicating if the item is rare and the special pattern details if any .
87- :rtype: tuple[bool, Optional[tuple[str, int]]]
113+ :return: Structured `PatternInfo` with normalized data, rarity details, ordering metadata, and icon .
114+ :rtype: PatternInfo
88115 """
89116
90117 normalized = _normalize_input (market_hash , pattern )
91118 if not normalized :
92- return False , None
93-
94- special = _check_special (normalized )
95-
96- return (True , special ) if special else (False , None )
119+ return PatternInfo ()
120+
121+ weapon , skin , normalized_pattern = normalized
122+ special = _match_group (normalized )
123+
124+ if not special :
125+ return PatternInfo (
126+ weapon = weapon ,
127+ skin = skin ,
128+ pattern = normalized_pattern ,
129+ )
130+
131+ group_name , ordered , rank , total = special
132+ order_info = (rank , total ) if ordered and rank is not None and total is not None else None
133+ return PatternInfo (
134+ weapon = weapon ,
135+ skin = skin ,
136+ pattern = normalized_pattern ,
137+ is_rare = True ,
138+ group = group_name ,
139+ ordered = ordered ,
140+ order = order_info ,
141+ icon = ICON_MAP .get (group_name ),
142+ )
97143
98144
99145def get_pattern_dict () -> dict :
100146 """
101- Retrieve the dictionary containing special patterns .
147+ Retrieve the full pattern map containing all configured rarity groups .
102148
103- :return: The special pattern dictionary .
149+ :return: Mapping of skin -> weapon -> list of group definitions .
104150 :rtype: dict
105151 """
106152
107- return SPECIAL_PATTERN
153+ return PATTERN_MAP
108154
109155
110156if __name__ == '__main__' :
0 commit comments