# -*- coding: utf-8 -*-
r"""Passa por TODAS as capturas e junta so o que sai consistente.

    python tools/varrer_tudo.py

Usa o motor do extrair_tudo (o que mede a variacao do personagem depois de cada accao) mas
junta as capturas todas e mostra apenas o que se repete: um efeito so entra se aparecer em
pelo menos MIN_FRACCAO das vezes que a accao aconteceu, e com pelo menos MIN_AMOSTRAS casos.

O FILTRO E O PONTO. Numa captura em que o jogador esta sempre a lutar, tudo parece causar
tudo: a janela de 1,5 s a seguir a apanhar um item apanha o golpe do mob, o tique de
regeneracao e a EXP do abate anterior. O que distingue efeito de coincidencia e a
CONSISTENCIA -- uma pocao de mana da MP em quase 100 por cento das vezes, o ruido nao.
"""
import collections
import glob
import os
import sys

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import extrair_tudo as E                                             # noqa: E402

MIN_FRACCAO = 0.40
MIN_AMOSTRAS = 8


def juntar(chave_de, accoes_de):
    """chave -> lista de dicionarios de efeito, sobre todas as capturas."""
    saida = collections.defaultdict(list)
    caps = sorted(glob.glob(r"C:\Users\Administrator\Desktop\CapturaKaros\*.log")) + \
           sorted(glob.glob(r"C:\RoshHook\traffic*.log"))
    for cam in caps:
        try:
            d = E.ler(cam)
        except Exception as e:                                       # noqa: BLE001
            print("   (%s falhou: %s)" % (os.path.basename(cam), str(e)[:60]))
            continue
        if not d["estado"]:
            continue
        for chave, t in accoes_de(d):
            ef = E.efeito(d["estado"], t)
            saida[chave].append(ef)
    return saida


def mostrar(titulo, dados, nome_de=lambda k: ""):
    print()
    print(titulo)
    print("-" * 78)
    linhas = []
    for chave, efs in dados.items():
        n = len(efs)
        if n < MIN_AMOSTRAS:
            continue
        por = collections.defaultdict(list)
        for e in efs:
            for k, v in e.items():
                por[k].append(v)
        # MOSTRA A PERCENTAGEM SEMPRE. E ela que distingue efeito de coincidencia: uma
        # pocao de mana da MP em quase 100 por cento das vezes, o golpe do mob que calhou
        # na mesma janela aparece em 30 e nao volta a aparecer noutra captura.
        fortes = sorted(((k, E.p50(v), len(v)) for k, v in por.items()
                         if len(v) >= n * MIN_FRACCAO), key=lambda x: -x[2])[:4]
        if fortes:
            linhas.append((n, chave, fortes))
    if not linhas:
        print("   nada com consistencia suficiente")
        return
    for n, chave, fortes in sorted(linhas, key=lambda x: -x[0])[:25]:
        print("   %-22s n=%-5d %-30s %s"
              % (chave, n, nome_de(chave)[:30],
                 ", ".join("%s %+g em %d%%" % (k, v, 100 * q // n) for k, v, q in fortes)))


def main() -> int:
    E.D.carregar() if E.D else None
    cat = E.D.indice("Item", "item_id") if E.D else {}
    skills = {r["skill_id"]: r.get("descricao") for r in E.D.tabela("Skill")} if E.D else {}

    print("SKILLS -- o que cada uma provocou em quem a lancou")
    d = juntar(None, lambda d: [(s, t) for t, quem, s in d["skill"] if quem == d["eu"]])
    mostrar("", d, lambda k: str(skills.get(k, "")))

    print()
    print("ITENS -- o que cada um provocou")
    d = juntar(None, lambda d: [("%s %d" % (k, i), t) for t, k, i in d["item"]])
    mostrar("", d, lambda k: str((cat.get(int(k.split()[-1])) or {}).get("nome", "")))
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
