#!/usr/bin/env python3 """Compare old-server vs current (live) drops for high-level farmed NPCs. Additive weight model: P(item) = weight / sum(weights). weight 0 = guaranteed. """ import re, sys sys.path.insert(0, '.') from collections import defaultdict from compare_drops import load_enums n2i, i2n, it2i, iti2n = load_enums() def parse(path): drops = defaultdict(list) for line in open(path): m = re.match(r"\((\d+),\s*'(-?\d+)',\s*(-?\d+),\s*(\d+),\s*(\d+)\),?\s*$", line.strip()) if m: drops[int(m.group(1))].append((int(m.group(3)), int(m.group(2)), int(m.group(4)))) return drops def prices(): p = {} names = {} txt = open('pk_itemdef.sql').read() for m in re.finditer(r"\((\d+),\s*-?\d+,\s*-?\d+,\s*'((?:[^'\\]|\\.)*)',.*?,\s*(\d+)\),?\s*\n", txt): iid = int(m.group(1)); name = m.group(2); price = int(m.group(3)) p[iid] = price; names[iid] = name return p, names PRICE, INAME = prices() def iname(iid): return INAME.get(iid) or iti2n.get(iid, f'#{iid}') old = parse('pk_npcdrops_old_server.sql') live = parse('pk_npcdrops_live.sql') TARGETS = { 196:'DRAGON(green)', 201:'RED_DRAGON', 202:'BLUE_DRAGON', 291:'BLACK_DRAGON', 477:'KING_BLACK_DRAGON', 22:'LESSER_DEMON', 181:'LESSER_DEMON_MAZE', 184:'GREATER_DEMON', 290:'BLACK_DEMON', 344:'FIRE_GIANT', 294:'HELLHOUND', 135:'ICE_GIANT', 104:'MOSS_GIANT', 315:'CHRONOZON', 298:'OTHERWORLDLY_BEING', } def rate_map(rows): tot = sum(w for _,_,w in rows if w>0) out = {} for iid,amt,w in rows: if w==0: out[(iid,amt)] = ('GUARANTEED', 0, w) else: out[(iid,amt)] = (f'1/{round(tot/w)}', tot/w, w) return out, tot def fmt_price(iid, amt): pv = PRICE.get(iid,0)*max(amt,1) return f'{pv:,}' for nid, label in TARGETS.items(): o = old.get(nid, []) l = live.get(nid, []) if not o and not l: continue omap, otot = rate_map(o) lmap, ltot = rate_map(l) print('='*100) print(f'NPC {nid} {label} old_total_w={otot:,} ({len(o)} rows) live_total_w={ltot:,} ({len(l)} rows)') print('-'*100) keys = sorted(set(omap)|set(lmap), key=lambda k:(-(PRICE.get(k[0],0)*max(k[1],1)))) print(f'{"item":34} {"amt":>5} {"OLD rate":>12} {"LIVE rate":>12} {"unitprice":>10} {"status"}') for (iid,amt) in keys: if iid in (-1,20,) : # skip nothing + bones(20) noise? keep -1 shown sep pass orate = omap.get((iid,amt)) lrate = lmap.get((iid,amt)) status='' if orate and not lrate: status='OLD-ONLY (candidate)' elif lrate and not orate: status='LIVE-ONLY' os_ = orate[0] if orate else '-' ls_ = lrate[0] if lrate else '-' nm = iname(iid) if iid==-1: nm='(nothing)' print(f'{nm[:34]:34} {amt:>5} {os_:>12} {ls_:>12} {fmt_price(iid,amt):>10} {status}') print()