aboutsummaryrefslogtreecommitdiff
path: root/sbdata/tasks/find_kat_recipes.py
blob: fb32c43a7e2576c87eddeb2e14028af88c96295b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import json

import mwparserfromhell.nodes

from sbdata.repo import find_item_by_name, item_list, Item, save_modified_file
from sbdata.task import register_task, Arguments
from sbdata.wiki import get_wiki_sources_by_title

# Format:
# <stat>_<postfix>(optional rest of postfix) -> before upgrade rarity index
rarity_postfixes = {
    'c': 0,
    'u': 1,
    'r': 2,
    'e': 3,
    'l': 4
}


@register_task("Find Kat Recipes")
def find_kat_recipes(args: Arguments):
    itemids = set()
    for item in item_list.values():
        if "Lvl" in item.displayname and ';' in item.internalname:
            itemids.add(item.internalname.split(';')[0])
    print(f"Analyzing: {itemids}")
    for itemid in itemids:
        analyze_pet(itemid)


def analyze_pet(itemid: str):
    x = next(iter(get_wiki_sources_by_title('_'.join(x.capitalize() for x in itemid.split('_')) + '_Pet', wiki_host='hypixel-skyblock.fandom.com').values()))
    for t in x.filter_templates():
        if t.name.strip() == 'Kat Cost table':
            t: mwparserfromhell.nodes.Template
            for rarity_postfix, rarity_before_idx in rarity_postfixes.items():
                costp = find_param(t, 'cost', rarity_postfix)
                matsp = find_param(t, 'mats', rarity_postfix)
                timep = find_param(t, 'time', rarity_postfix)
                if None in [costp, timep]:
                    print(f"Missing data for {rarity_postfix} in {itemid}")
                    continue
                cost = parse_coins(costp.value.strip_code())
                time = parse_time(timep.value.strip_code())
                mats = parse_mats(matsp.value.strip_code()) if matsp else []
                # print(f"Upgrading from {rarity_before_idx} to {rarity_before_idx + 1} using {mats} and {cost} coins in {time} seconds")
                from sbdata.repo import get_item_file
                itemfile = get_item_file(itemid + ';' + str(rarity_before_idx + 1))
                itemjson = json.loads(itemfile.read_text())
                itemjson['recipes'] = [dict(
                    type='katgrade',
                    coins=cost,
                    time=time,
                    input=f'{itemid};{rarity_before_idx}',
                    output=f'{itemid};{rarity_before_idx + 1}',
                    items=[f'{x[0].internalname}:{str(x[1])}' for x in mats]
                )] + [r for r in itemjson.get('recipes', []) if r.get('type') != 'katgrade']
                save_modified_file(itemfile, itemjson)
            break


postfix_numbers = dict(
    k=1000,
    m=1000000,
)


def parse_coins(a: str):
    a = a.lower().replace('coins', '').replace('coin', '').replace(',', '').strip()
    try:
        return int(a)
    except ValueError:
        pass
    for pn, pi in postfix_numbers.items():
        if a.endswith(pn):
            return int(a[:-len(pn)]) * pi
    raise ""


def parse_mats(a: str) -> [(Item, int)]:
    r = []
    for b in a.split('*'):
        b = b.strip()
        if not b or b.lower() == 'none' or b.lower() == 'n/a':
            continue
        x = b.split(",")
        if len(x) != 2:
            raise ""
        i = find_item_by_name(x[0])
        if not i:
            raise ""
        r += [(i, int(x[1]))]
    return r


times = {
    'second': 1,
    'seconds': 1,
    'minute': 60,
    'minutes': 60,
    'hour': 60 * 60,
    'hours': 60 * 60,
    'day': 60 * 60 * 24,
    'days': 60 * 60 * 24,
}


def parse_time(a: str) -> int:
    # returns seconds
    n = -1
    t = 0
    for p in a.split():
        p = p.strip().lower()
        if not p:
            continue
        if p.isdigit():
            if n > 0:
                raise "Double number"
            n = int(p)
            continue
        if p not in times:
            raise "Unknown time"
        t = n * times[p]
        n = -1
    if t == 0:
        raise ""
    return t


def find_param(t: mwparserfromhell.nodes.Template, name: str, rp: str) -> mwparserfromhell.nodes.template.Parameter:
    s = name + '_' + rp
    for p in t.params:
        if p.name.strip().startswith(s):
            return p