import sys, json, collections
sys.path.insert(0,'/tmp/claude-1000')
from load import load, eff
STAGE='/tmp/claude-1000/stage/'
R = load()
EXTEND_339_ROLL_RANGE = False   # True = regenerate text as if XI-XV also roll (after the C++ list is extended)

bk = {}
for l in open('/tmp/claude-1000/bk.tsv').read().split('\n')[1:]:
    if l.strip():
        a,b = l.split('\t'); bk[int(a)] = int(b)
assert len(bk) == 342, len(bk)

RES = {1:'magic',2:'fire',3:'cold',4:'poison',5:'disease',6:'chromatic',7:'prismatic',8:'physical',9:'corruption'}
def amount(base, mx, formula):
    assert formula == 100
    ub = abs(base)
    up = not (mx < base and mx != 0)
    r = ub
    if mx != 0:
        if up:
            if r > mx: r = mx
        else:
            if r < mx: r = mx
    if base < 0 and r > 0: r = -r
    return abs(r)
def fmt(n): return f"{n:,}"
def pct(x):
    r = round(x*100*2)/2
    return f"{r:g}"
def mod(total):
    if total > 0 and total <= 2500: return 0.25
    if total > 2500 and total < 7000: return 0.167*((total-1000.0)/1000.0)
    return total/7000.0
def raw_chance(total, base):
    return (6.0/100.0)*(base/10.0)*mod(total)

def info(d):
    f = None; lim = {}
    for i in range(1,13):
        e = eff(d,i)
        if e[0] in (339,383): f = (e[0], e)
        elif e[0] != 254: lim[e[0]] = e[1]
    return f, lim

def proc_action(d, fam, lim, p):
    pe = [(k, eff(p,k), p['formula%d'%k]) for k in range(1,13) if eff(p,k)[0] != 254]
    kinds = {e[1][0]:e for e in pe}
    dur = int(p['buffduration']); tt = int(p['targettype']); good = p['goodEffect'] == '1'
    name = p['name']
    det_trigger = lim[138] == 0
    if 0 in kinds:
        k, e, fo = kinds[0]
        A = amount(e[1], e[3], int(fo))
        if not good:
            T = RES[int(p['resisttype'])]
            if dur:
                s = f"hit the target with a damage-over-time effect for {fmt(A)} {T} damage over 6 sec ({name})"
            else:
                s = f"strike the target for {fmt(A)} {T} damage ({name})"
            if 21 in kinds:
                st = kinds[21][1]
                s += f" and stun it for {st[1]/1000:g} sec (monsters up to level {st[3]})"
            return s
        # heal
        if tt == 41: who = "that target's group"
        elif tt == 46: who = "your target's target"
        elif fam == 339: who = "the target"
        elif det_trigger: who = "you"
        else: who = "the target"
        return f"heal {who} for {fmt(A)} ({name})"
    if 15 in kinds:
        A = amount(kinds[15][1][1], kinds[15][1][3], int(kinds[15][2]))
        return f"restore {fmt(A)} mana to you ({name})"
    if 92 in kinds:
        e = kinds[92][1]
        A = amount(e[1], e[3], int(kinds[92][2]))
        return f"lower your hate on the target by {fmt(A)} ({name})"
    if 152 in kinds:
        e = kinds[152][1]
        return f"summon a temporary pet for {e[3]} sec ({name})"
    raise Exception('unhandled proc '+name)

def describe(d):
    (fam, fe), lim = info(d)
    p = R[fe[2]]
    det = lim[138] == 0
    has137 = 137 in lim
    noun = ("damage spells" if has137 else "detrimental spells") if det else ("healing spells" if has137 else "beneficial spells")
    lv = lim.get(142, 0)
    parts = ["any level" if lv <= 1 else f"level {lv} or higher", f"at least {lim[348]} mana"]
    if 311 in lim and lim[311] == 0: parts.append("not combat abilities")
    if 143 in lim: parts.append(f"cast time of at least {lim[143]/1000:g} sec")
    action = proc_action(d, fam, lim, p)
    sid = int(d['id'])
    if fam == 339:
        roll = (24356 <= sid <= 24365) or (24434 <= sid <= 24443) or EXTEND_339_ROLL_RANGE
        if roll:
            lead = (f"Your {noun} cast from spell gems ({', '.join(parts)}) have a chance per cast to also {action}. "
                    "Chance is at least 30 pct, rising with cast time plus recovery (45 pct at 5.5 sec, 100 pct at 11.7 sec).")
        else:
            lead = (f"Every time you cast one of your {noun} from spell gems ({', '.join(parts)}), you also {action}. "
                    "It triggers on every qualifying cast.")
        tail = (" Damage-over-time spells roll once on cast." if roll else " Damage-over-time spells trigger it once on cast.") if det else ""
        return lead + tail
    base = fe[1]
    c1, c2, c3 = raw_chance(2500, base), raw_chance(5500, base), raw_chance(11667, base)
    ch = (f"Chance per roll rises with cast time plus recovery: {pct(c1)} pct (2.5 sec or less), {pct(c2)} pct (5.5 sec), "
          f"{pct(min(c3,1.0))} pct (11.7 sec or more); item proc rate adds more.")
    if det:
        when = " Rolls on cast; damage-over-time spells roll each tick (and on landing if they also hit directly)."
    else:
        when = " Rolls on cast; heal-over-time spells roll each tick."
    return f"Your {noun} ({', '.join(parts)}) can {action}. {ch}{when}"

if __name__ == '__main__':
    sym = sorted([d for d in R.values() if d['name'].startswith('Sympathetic') and info(d)[0]], key=lambda d:int(d['id']))
    print(len(sym))
    for sid in (24362, 24395, 24434, 21551, 38606, 24421, 20249, 33411, 13397, 24456+1, 33352):
        d = R[sid]; print(sid, d['name'], '|', describe(d), '\n')
