# -*- coding: utf-8 -*-
"""Asigna nivel (basico/intermedio/avanzado) y clave (estrella) a cada tarjeta in-place en cards-*.json."""
import json, glob, unicodedata, re

def norm(s):
    s = unicodedata.normalize("NFD", s.lower())
    return "".join(c for c in s if unicodedata.category(c) != "Mn")

SUB_DEFAULT = {
    ("java", "Sintaxis y tipos"): "basico",
    ("java", "POO"): "basico",
    ("java", "String y texto"): "basico",
    ("java", "Colecciones"): "intermedio",
    ("java", "Genéricos"): "intermedio",
    ("java", "Excepciones"): "intermedio",
    ("java", "Streams y lambdas"): "intermedio",
    ("java", "Concurrencia"): "avanzado",
    ("java", "JVM y rendimiento"): "avanzado",
    ("java", "Java moderno"): "intermedio",
    ("java", "I/O y serialización"): "intermedio",
    ("java", "Fechas y hora"): "basico",
    ("java", "Snippets: ¿qué imprime?"): "intermedio",
    ("java", "JDBC y localización"): "intermedio",
    ("spring", "Núcleo IoC"): "intermedio",
    ("spring", "Configuración"): "basico",
    ("spring", "Boot y starters"): "basico",
    ("spring", "Web MVC y REST"): "intermedio",
    ("spring", "Spring Data JPA"): "intermedio",
    ("spring", "Transacciones"): "avanzado",
    ("spring", "AOP"): "avanzado",
    ("spring", "Seguridad"): "avanzado",
    ("spring", "Testing"): "intermedio",
    ("spring", "Producción y observabilidad"): "avanzado",
    ("spring", "Async, caché y scheduling"): "avanzado",
    ("spring", "Spring Cloud y resiliencia"): "avanzado",
    ("spring", "Troubleshooting clásico"): "intermedio",
    ("spring", "WebFlux y reactivo"): "avanzado",
    ("spring", "Ecosistema y build"): "basico",
    ("spring", "Trampas de entrevista"): "intermedio",
    ("gcp", "Fundamentos y organización"): "basico",
    ("gcp", "IAM y seguridad"): "avanzado",
    ("gcp", "Redes"): "avanzado",
    ("gcp", "Compute y contenedores"): "intermedio",
    ("gcp", "Serverless"): "basico",
    ("gcp", "Almacenamiento"): "basico",
    ("gcp", "Bases de datos"): "intermedio",
    ("gcp", "Mensajería y eventos"): "intermedio",
    ("gcp", "Analítica de datos"): "avanzado",
    ("gcp", "DevOps y CI/CD"): "intermedio",
    ("gcp", "Observabilidad y SRE"): "intermedio",
    ("gcp", "gcloud y herramientas"): "basico",
    ("gcp", "Patrones de arquitectura"): "avanzado",
    ("gcp", "Escenarios de entrevista"): "avanzado",
    ("micro", "Fundamentos y decisiones"): "intermedio",
    ("micro", "Comunicación"): "intermedio",
    ("micro", "Datos y consistencia"): "avanzado",
    ("micro", "Resiliencia"): "avanzado",
    ("micro", "Observabilidad"): "intermedio",
    ("micro", "APIs y edge"): "intermedio",
    ("micro", "Seguridad"): "avanzado",
    ("micro", "Plataforma y despliegue"): "intermedio",
    ("micro", "Testing y calidad"): "intermedio",
    ("micro", "Operación y organización"): "intermedio",
}

AVANZADO_Q = [
    "type erasure", "pecs", "wildcard capture", "happens-before", "double-checked",
    "pinning de virtual", "structured concurrency", "virtual threads (java 21",
    "g1 gc", "zgc", "escape analysis", "flame graphs", "jmh",
    "flight recorder", "string deduplication", "caches de cpu", "memory leak en java",
    "referencias fuertes", "classloading: delegacion", "covarianza de arrays",
    "record patterns", "pattern matching para switch", "jpms", "proxy dinamico",
    "cuanta memoria ocupa un string", "excepciones suprimidas", "lanzar excepciones es caro",
    "teeing", "parallelstream", "longadder", "forkjoinpool", "work-stealing",
    "threadlocal", "outofmemoryerror", "resize de hashmap", "vistas (views)",
    "transactiontemplate", "7 propagaciones", "readonly=true", "dual-write",
    "transactionaleventlistener", "post-commit", "transacciones largas",
    "anomalias de aislamiento", "multi-tenancy ligero", "token exchange",
    "constraintvalidator", "grupos de validacion", "graalvm native", "layered jars",
    "virtual threads en spring boot", "circuitbreaker config", "spring cloud config server",
    "private pools", "gitops", "cache stampede", "schedulers en cluster",
    "backpressure", "r2dbc", "deferredresult", "streaming de respuestas", "hateoas",
    "content negotiation", "etags y cache http", "async requests mvc",
    "beanpostprocessor", "factorybean", "dependencias circulares", "interfaces aware",
    "sin anotaciones ni escaneo", "@lookup", "lite mode", "open-in-view",
    "exactamente una vez tras crear un pedido", "problema de dual-write",
    "terraform state", "landing zone", "disaster recovery",
    "vpc service controls", "workload identity federation", "iam conditions",
    "binary authorization", "cloud kms", "interconnect vs cloud vpn", "packet mirroring",
    "private google access", "mtls entre servicios", "dataplane v2", "network policy en gke",
    "ingress vs gateway api", "statefulset", "node auto-provisioning",
    "spanner", "bigtable", "database migration service",
    "vector databases", "cross-region disaster recovery", "ack deadline", "ordering keys",
    "exactly-once", "pub/sub lite", "bigquery ml", "vertex ai",
    "dataflow", "lakehouse", "composer (airflow", "log analytics",
    "managed service for prometheus", "slos en cloud monitoring", "multi-ventana",
    "flow logs", "troubleshooting de conectividad", "activa-activa", "cqrs aplicado",
    "claim check", "zero downtime deploy", "rate limiting global", "gdpr/pii en gcp",
    "chat en tiempo real", "buscador sobre millones", "facturas nunca se pierden",
    "notificaciones para 10m", "lento solo para usuarios", "donde entra cada servicio",
    "multi-region de un microservicio", "poddistributionbudget", "hpa con metricas custom",
    "canary automated", "service mesh y cuando", "migraciones de schema compatibles",
    "agregados ddd", "context mapping", "hexagonal/ports", "event sourcing",
    "outbox pattern", "inbox pattern", "2pc/xa", "cap aplicado", "crdt",
    "locks distribuidos", "crypto-shredding", "upcasting y gdpr", "materialized views",
    "read model local", "saga coreografiada", "saga orquestada", "compensaciones de saga",
    "anomalias de consistencia", "sharding de datos", "change data capture",
    "tail sampling", "cardinalidad", "burn-rate", "request hedging", "load shedding",
    "graceful degradation", "chaos engineering", "serve-stale", "thundering herd",
    "scatter-gather", "process manager", "splitter / aggregator", "dead letter processing",
    "ttl del dedup", "threat modeling", "on-behalf-of", "centralizada vs por servicio",
    "fitness functions", "contract testing consumer-driven", "testing en produccion",
    "webhooks salientes", "saga log", "justificar inversion en confiabilidad",
    "security command center", "cloud armor", "identity-aware proxy",
    "memoria: los 6 knobs",
]
INTERMEDIO_Q = [
    "mono y flux", "webflux vs mvc",
    "como funciona el garbage collector", "stack vs heap", "integer cache",
    "effectively final", "bigdecimal", "orden de inicializacion", "dynamic dispatch",
    "field hiding", "metodo fabrica estatico", "clone() y por que", "string pool",
    "concatenar string en un loop", "regex en java", "fail-fast", "vistas (views)",
    "remove(int index)", "enumset", "complejidades", "colecciones y null",
    "synchronized: metodo vs bloque", "ciclo de vida de un hilo", "race condition",
    "volatile vs synchronized", "que es executorservice", "que anade completablefuture",
    "reentrantlock", "atomicinteger", "countdownlatch", "blockingqueue",
    "scheduledexecutorservice", "contencion (contention)", "@async en spring",
    "jwt flow completo", "hs256 vs rs256", "401 vs 403", "csrf", "session vs stateless",
    "passwordencoder", "authentication vs authorization", "oauth2 resource server",
    "oauth2 client", "validar jwt a mano", "authorization code + pkce",
    "oidc: que anade", "jwt en la practica", "rate limiting por identidad",
    "zero trust en una frase", "pii entre microservicios", "secrets en un ecosistema",
    "testcontainers", "mockitobean", "jacoco", "transacciones y tests",
    "micrometer", "health indicator", "logging con traceid", "config de logging",
    "graceful shutdown y readiness", "@async: setup", "@scheduled: cron", "@cacheable",
    "caffeine", "cache con redis", "cuando cachear y cuando no", "eventos de aplicacion",
    "eventlistener vs", "resilience4j: los 4 modulos", "spring cloud gateway",
    "retry bien hecho", "openfeign", "open-in-view",
    "estados de una entidad jpa", "lazyinitializationexception",
    "join fetch", "optimistic locking", "pessimistic locking",
    "flyway/liquibase", "dirty checking", "flush y el orden", "batching: como hacer",
    "ddl-auto", "cloud sql: ha", "alloydb", "matriz de decision de bases",
    "memorystore para redis: ha", "cache-aside", "knobs", "flags y mantenimiento",
    "secrets y datos sensibles en bds", "push vs pull", "schemas y filtrado",
    "cloud tasks vs pub/sub", "event-driven en gcp", "idempotencia de consumidores",
    "poison messages", "cloud scheduler + workflows", "modelo de costos",
    "partitioning y clustering", "cargar datos a bigquery", "looker studio",
    "streaming pipeline canonico", "cloud build: pipeline basico", "triggers de cloud build",
    "secrets en cloud build", "cd a cloud run", "estrategia de branching",
    "terraform en gcp", "feature flags en pipeline", "cloud logging: consultas",
    "cloud monitoring: uptime", "error reporting", "alertas que no despiertan",
    "golden signals", "comandos gcloud", "gsutil vs gcloud", "logs y debugging",
    "iam desde cli", "costos por cli", "asset inventory", "cloud code",
    "api management", "webhooks entrantes", "jobs nocturnos", "app web moderna",
    "backend for a mobile", "multi-tenant saas", "exponer cloud run con dominio",
    "reducir el 40%", "migrar una app on-prem", "otro equipo debe consumir",
    "compute engine o cloud run", "audit", "slas reales",
    "cuantos proyectos", "cuotas y limites", "labels vs tags",
    "organization policies vs iam", "resource hierarchy anti", "well architecture",
    "cloud apis: quotas", "marketplace", "regiones: como elegir",
    "defensa en profundidad", "rotacion de secretos", "custom roles",
    "sensitive data protection", "audit logs: que registra", "claves de service account",
    "que no es un microservicio", "senales de que no deberias", "monolito modular",
    "ley de conway", "event storming", "strangler fig", "c4 model", "adr:",
    "service ownership", "metricas dora", "cuantos microservicios",
    "api-first", "domain services vs application", "anticorruption layer",
    "golden path", "cuando extraer un servicio", "product over project",
    "rest vs grpc", "request-reply sobre mensajeria", "schema evolution",
    "consumer groups", "cloudevents", "event granularity",
    "versionado de eventos", "long polling", "deadlines y presupuesto",
    "integracion directa a la bd", "api composition", "consistencia en ui",
    "weak vs strong consistency", "soft delete vs hard delete",
    "data ownership ambiguity", "sagas y validacion", "timeout defaults",
    "circuit breaker + cache", "graceful shutdown en microservicios",
    "budget de error en operaciones", "3 pilares de la observabilidad",
    "distributed tracing", "instrumentacion con opentelemetry",
    "dashboards por servicio", "alertas multi-ventana",
    "dependencias externas", "postmortem blameless", "logging en microservicios",
    "slos por microservicio", "api gateway y que responsabilidades",
    "bff (backend for frontend)", "graphql entre microservicios",
    "contratos en el edge", "idempotency-key", "gateway anti-patrones",
    "versionado de apis sin romper", "authorization code + pkce",
    "service template", "requests y limits", "feature flags: liberar",
    "blue/green vs canary", "liveness vs readiness", "12 factores",
    "configuracion centralizada", "ambientes efimeros", "sidecar, ambassador",
    "stateless de verdad", "progressive delivery",
    "piramide de testing aplicada", "webmvctest", "datajpatest",
    "springboottest con puerto", "como probar codigo async", "fixture de datos",
    "assertj", "piramide invertida", "e2e en microservicios", "contenedores: bds reales",
    "runbook", "on-call sostenible", "incident management", "finops por microservicio",
    "deprecar y matar", "catalog de servicios", "capacity planning", "game days",
    "documentacion viva", "estimacion de carga", "cortar un servicio de otro",
    "costo real de los microservicios", "microservicio puede llamar a otro",
    "rompe y", "p99 exploto", "reporte que cruza", "dos equipos editan",
    "migrar 200 endpoints", "datos de 3 eventos", "la cola crece sin parar",
    "gateway es un spof", "catalogo se cae", "cliente abuse", "usuarios reportan",
    "regulatorio exige", "suite de integracion tarda", "no podemos probar",
    "deploy requiere 15 pasos", "config en 5 servicios", "presupuesto de observabilidad",
    "convence al cto", "startups rapido", "conway",
    "como funciona y que trampas", "niveles de aislamiento de transacciones",
    "circuit breaker (resilience4j", "como funciona la autoconfiguracion",
    "service accounts", "vpc, subredes y firewall", "load balancing y cloud cdn",
    "para que sirve secret manager", "conecto cloud run", "autenticacion de usuarios finales",
    "application default credentials", "idempotencia: por que es clave",
    "consistencia eventual", "database per service", "patrones de resiliencia",
]
BASICO_Q = [
    "jdk, jre y jvm", "cuantos tipos de datos primitivos", "primitivos vs wrappers",
    "que es var (java 10", "overflow aritmetico", "casting entre tipos",
    "4 pilares de la poo", "list vs set vs map", "arraylist vs linkedlist",
    "jerarquia completa de throwable", "maven lifecycle", "scope de dependencias",
    "lombok", "que es spring boot y que aporta", "que son ioc y la inyeccion",
    "@component vs @service", "@bean vs @component", "inyectar por constructor",
    "@controller vs @restcontroller", "@pathvariable vs @requestparam",
    "excepciones globalmente", "application.properties, yaml",
    "spring boot actuator", "que es un starter", "servidor embebido",
    "@springbootapplication exactamente", "ddl-auto", "maven vs gradle",
    "compute engine vs app engine vs cloud run vs gke", "cuando elegirias cloud run",
    "cloud storage: clases", "como funciona iam en gcp", "proyecto' en gcp",
    "jerarquia de recursos en gcp", "machine types", "cloud functions vs cloud run",
    "app engine en 2024", "elegir ambiente de ejecucion", "sitio estatico",
    "comandos gcloud del dia a dia", "gsutil vs gcloud", "console: atajos",
    "para que sirve memorystore", "monolito o microservicios", "que no es un microservicio",
    "adr:", "runbook: el documento", "api gateway y que responsabilidades",
    "division entera vs decimal", "char vs string",
    "alcance (scope) de una variable", "metodo main", "operador ternario",
    "for vs while", "arrays en java", "literales", "variable local, de instancia",
    "long vs int vs double", "que es instanceof", "que hace static",
    "modificadores de acceso", "constructores: reglas", "this y super",
    "interfaz vs clase abstracta", "que es una interfaz funcional",
    "upcasting y downcasting", "sobrecarga y resolucion", "clase de utilidades",
    "por que string es inmutable", "metodos esenciales de string",
    "string.format y text blocks", "trim() vs strip()", "comparar strings correctamente",
    "string.join", "como iterar los caracteres", "conversion string",
    "que hace try-with-resources", "final / finally / finalize",
    "checked vs unchecked", "throw vs throws",
    "jerarquia del collection framework", "hashset: como decide",
    "treeset: que garantizan", "linkedhashmap", "arraydeque vs stack",
    "priorityqueue", "como eliminar elementos de una lista",
    "comparable vs comparator aplicado", "list.of() vs arrays.aslist()",
    "colecciones no modificables", "metodos de map modernos",
    "iterator: contrato", "entryset vs keyset", "por que map no extiende",
    "para que existen los genericos", "metodos genericos", "raw types",
    "list<int>", "genericos, static y arrays", "herencia con genericos",
    "sintaxis de lambda", "method references", "4 interfaces funcionales",
    "que es un stream y en que se diferencia", "intermedias vs terminales",
    "map vs flatmap", "reduce: las 3 formas", "collectors que hay que dominar",
    "groupingby: los niveles", "streams de primitivas", "short-circuit",
    "optional en streams", "sorted(), distinct()", "cuando no usar streams",
    "lambda vs clase anonima", "comparator moderno",
    "java.time: las clases", "inmutables y thread-safe", "duration vs period",
    "datetimeformatter", "zonas horarias: la regla", "operaciones frecuentes con localdate",
    "localdate vs localdatetime", "migrar codigo legado con date",
    "comparar y medir intervalos", "java.io vs java.nio", "files y path",
    "encoding: por que", "lectura de archivos grandes", "transient y serialversionuid",
    "scanner vs bufferedreader", "temp files",
    "que hace la jvm al ejecutar", "estructura de memoria de la jvm",
    "que es un record (java", "switch de expresion", "nuevos metodos de coleccion",
    "httpclient (java 11", "anotaciones: @retention", "reflection: usos",
    "jshell", "que cambio con las versiones lts", "unnamed variables",
    "que son las interfaces @enable", "component scan", "bean con nombre",
    "@profile", "placeholders, defaults", "@propertysource", "propiedades comunes",
    "clase main: springapplication", "anotaciones de mapeo", "responseentity",
    "jackson: anotaciones", "por que nunca devolver entidades", "validacion: @valid",
    "interceptor vs filter", "handlerinterceptor", "cors: las 3 formas",
    "paginacion y ordenacion", "upload de archivos", "manejo de errores rest moderno",
    "exceptionhandler jerarquia", "clientes http modernos", "restclient: ejemplo",
    "dtos: mapeo manual", "arquitectura en capas vs hexagonal",
    "donde va la logica de negocio", "multipart + dto", "como manejar ids en uris",
    "query derivation", "@query: jpql", "proyecciones", "save() vs saveandflush",
    "relaciones jpa", "cascade: tipos", "@embeddable", "attributeconverter",
    "auditoria automatica", "repositorios multiples", "que es @transactional",
]

CLAVE_Q = [
    "jdk, jre y jvm", "garbage collector", "stack vs heap", "string es inmutable",
    "== vs equals", "hashmap internamente", "arraylist vs linkedlist", "list vs set vs map",
    "interfaz vs clase abstracta", "checked vs unchecked", "try-with-resources",
    "final / finally / finalize", "que son los streams de java 8", "para que sirve optional",
    "volatile vs synchronized", "que es executorservice", "que anade completablefuture",
    "que es un record (java", "overloading vs overriding", "que hace static",
    "contrato correcto de equals", "contrato de hashcode", "comparable vs comparator aplicado",
    "jerarquia completa de throwable",
    "que es spring boot y que aporta", "como funciona la autoconfiguracion",
    "que son ioc y la inyeccion", "@component vs @service", "inyectar por constructor",
    "scopes de beans en spring", "ciclo de vida de un bean", "@controller vs @restcontroller",
    "flujo de una peticion en spring mvc", "@pathvariable vs @requestparam",
    "que es jpa", "estados de una entidad jpa", "@transactional: como funciona",
    "lazyinitializationexception", "excepciones globalmente", "application.properties, yaml",
    "spring boot actuator", "circuit breaker (resilience4j)", "join fetch",
    "@configurationproperties vs @value", "securityfilterchain", "jwt flow completo",
    "@webmvctest", "contenedores: bds reales", "@cacheable",
    "compute engine vs app engine vs cloud run", "cuando elegirias cloud run",
    "cloud storage: clases", "pub/sub: modelo y garantias", "base de datos gcp elijo",
    "como funciona iam en gcp", "service accounts: que son", "vpc, subredes y firewall",
    "load balancing y cloud cdn", "cloud build", "para que sirve secret manager",
    "application default credentials", "jerarquia de recursos", "optimizacion de costos",
    "cloud functions vs cloud run", "conecto cloud run",
    "matriz de decision de bases", "cloud operations: logging", "cloud run: revisiones",
    "monolito o microservicios", "bounded context", "comunicacion sincrona vs asincrona",
    "rest vs grpc", "api gateway y que responsabilidades", "service discovery",
    "patrones de resiliencia: timeout", "patron saga", "que es cqrs", "que es event sourcing",
    "database per service", "consistencia eventual", "idempotencia: por que es clave",
    "3 pilares de la observabilidad", "distributed tracing: como funciona",
    "liveness vs readiness", "blue/green vs canary", "12 factores",
    "versionado de apis sin romper", "outbox pattern", "integracion directa a la bd",
    "strangler fig",
]

CLAVE_EXTRA = [
    "concurrenthashmap: que lo hace", "metodos de map modernos", "blockingqueue",
    "wait/notify", "como dimensionar un pool", "estructura de memoria de la jvm",
    "outofmemoryerror: los tipos", "integer a=127", "remove(1)", "0.1+0.2",
    "que hace @springbootapplication", "jackson: anotaciones", "nunca devolver entidades",
    "validacion: @valid", "globalexceptionhandler", "query derivation", "@query: jpql",
    "save() vs saveandflush", "relaciones jpa", "cascade: tipos", "7 propagaciones",
    "passwordencoder", "jwt en la practica", "csrf", "mockmvc: el recetario",
    "graceful shutdown y readiness", "ddl-auto", "flyway/liquibase", "open-in-view",
    "spring cloud gateway", "retry bien hecho", "hikaripool",
    "cloud nat", "vpc global vs subredes", "health checks del lb", "signed urls",
    "lifecycle rules", "cloud sql: ha", "conectarte a cloud sql", "cache-aside",
    "elegir ambiente de ejecucion", "workload identity en gke", "partitioning y clustering",
    "push vs pull", "cloud tasks vs pub/sub", "recommender y right-sizing",
    "autopilot vs standard", "concurrencia y cpu allocation", "cold starts",
    "dual write", "read model local", "api composition", "idempotency-key",
    "bff (backend for frontend)", "contract testing consumer-driven",
    "feature flags: liberar", "stateless de verdad", "requests y limits",
    "timeout defaults", "deadlines y presupuesto", "golden signals",
]

stats = {}
clave_total = 0
n_cards = 0
TODOS = CLAVE_Q + CLAVE_EXTRA
for f in sorted(glob.glob("cards-*-*.json")):
    d = json.load(open(f, encoding="utf-8"))
    m = re.search(r"cards-([a-z]+)-", f)
    cat = m.group(1)
    for t in d["tarjetas"]:
        if t.get("nivel"):
            clave_total += 1 if t["clave"] else 0
            n_cards += 1
            stats[t["nivel"]] = stats.get(t["nivel"], 0) + 1
            continue
        qn = norm(t["q"])
        nivel = None
        for pat in AVANZADO_Q:
            if pat and norm(pat) in qn:
                nivel = "avanzado"; break
        if not nivel:
            for pat in INTERMEDIO_Q:
                if pat and norm(pat) in qn:
                    nivel = "intermedio"; break
        if not nivel:
            for pat in BASICO_Q:
                if pat and norm(pat) in qn:
                    nivel = "basico"; break
        if not nivel:
            nivel = SUB_DEFAULT.get((cat, t.get("sub", "")), "intermedio")
        t["nivel"] = nivel
        t["clave"] = any(norm(p) in qn for p in TODOS if p)
        clave_total += 1 if t["clave"] else 0
        stats[nivel] = stats.get(nivel, 0) + 1
        n_cards += 1
    json.dump(d, open(f, "w", encoding="utf-8"), ensure_ascii=False, indent=1)
print("nuevas:", n_cards, stats, "| clave nuevas:", clave_total)

# ---------- tarjetas viejas (cards.json) ----------
sub_old = {}
for theme in ["java", "spring", "gcp", "micro"]:
    d0 = json.load(open("cards-%s-1.json" % theme, encoding="utf-8"))
    sub_old[theme] = d0.get("sub_old", {})
PREF = {"java": "J", "spring": "S", "gcp": "G", "micro": "M"}
d = json.load(open("cards.json", encoding="utf-8"))
cnt = {}
old_stats = {}
old_clave = 0
for t in d["tarjetas"]:
    cat = t["cat"]
    cnt[cat] = cnt.get(cat, 0) + 1
    old_id = "%s%02d" % (PREF[cat], cnt[cat])
    sub = sub_old[cat].get(old_id, "")
    t["sub"] = sub
    qn = norm(t["q"])
    nivel = None
    for lista, val in ((AVANZADO_Q, "avanzado"), (INTERMEDIO_Q, "intermedio"), (BASICO_Q, "basico")):
        for pat in lista:
            if pat and norm(pat) in qn:
                nivel = val
                break
        if nivel:
            break
    if not nivel:
        nivel = SUB_DEFAULT.get((cat, sub), "intermedio")
    t["nivel"] = nivel
    t["clave"] = any(norm(p) in qn for p in TODOS if p)
    old_clave += 1 if t["clave"] else 0
    old_stats[nivel] = old_stats.get(nivel, 0) + 1
json.dump(d, open("cards.json", "w", encoding="utf-8"), ensure_ascii=False, indent=1)
print("viejas:", old_stats, "| clave viejas:", old_clave)
print("TOTAL clave:", clave_total + old_clave)
