Skip to content

Commit 77aa2c0

Browse files
authored
Merge pull request #9 from Helyux/dev
v0.6.0
2 parents 166fc84 + 36fd16c commit 77aa2c0

File tree

9 files changed

+662
-474
lines changed

9 files changed

+662
-474
lines changed

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,15 @@ To check if your skin has a rare pattern:
3131
from cs2pattern import check_rare
3232

3333
# Provide full item name and pattern number
34-
is_rare, details = check_rare("★ Karambit | Case Hardened (Factory New)", 269)
35-
if is_rare:
36-
rare_name, rank = details
37-
print(f"Rare pattern: {rare_name} (rank {rank})")
38-
39-
#=> Rare pattern: gem_blue (rank 5)
34+
result = check_rare("★ Karambit | Case Hardened (Factory New)", 269)
35+
if result.is_rare:
36+
if result.ordered and result.order:
37+
rank, total = result.order
38+
print(f"Rare pattern: {result.group} (rank {rank}/{total})")
39+
else:
40+
print(f"Rare pattern: {result.group}")
41+
42+
#=> Rare pattern: gem_blue (rank 5/14)
4043
```
4144

4245
### Modular helpers

cs2pattern/__init__.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
__author__ = "Lukas Mahler"
2-
__version__ = "0.5.0"
3-
__date__ = "15.10.2025"
2+
__version__ = "0.6.0"
3+
__date__ = "02.11.2025"
44
__email__ = "m@hler.eu"
55
__status__ = "Development"
66

7-
from cs2pattern.check import check_rare, get_pattern_dict
7+
from cs2pattern.check import PatternInfo, check_rare, get_pattern_dict
88
from cs2pattern.modular import *
99

1010
__all__ = [
11+
'PatternInfo',
1112
'check_rare',
1213
'get_pattern_dict',
1314
'abyss',
1415
'berries',
1516
'blaze',
16-
'fade',
17-
'fire_and_ice',
17+
'fade',
18+
'fire_and_ice',
1819
'gem_black',
1920
'gem_blue',
2021
'gem_diamond',

cs2pattern/check.py

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
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

88
import json
9-
import os
109
import re
10+
from dataclasses import dataclass
11+
from pathlib import Path
1112
from 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

1939
def _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

99145
def 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

110156
if __name__ == '__main__':

cs2pattern/icons.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"white_scope": "🎯",
3+
"gem_blue": "🟦",
4+
"gem_red": "🟥",
5+
"blaze": "🔥",
6+
"fire_and_ice": "❄️",
7+
"fade": "🌈",
8+
"gem_diamond": "💎",
9+
"gem_gold": "🟨",
10+
"gem_green": "🟩",
11+
"gem_pink": "♀️",
12+
"gem_purple": "🟪",
13+
"gem_white": "⬜️",
14+
"gem_black": "⬛️",
15+
"blue_hive": "🔵",
16+
"orange_hive": "🟠",
17+
"star": "",
18+
"golden_cat": "🐈",
19+
"stoner_cat": "🌿",
20+
"phoenix": "🐦‍🔥",
21+
"pussy": "🐾"
22+
}

0 commit comments

Comments
 (0)