diff --git a/app/scheduler/junk_performers.py b/app/scheduler/junk_performers.py index 9d1a281..de77d03 100644 --- a/app/scheduler/junk_performers.py +++ b/app/scheduler/junk_performers.py @@ -25,8 +25,33 @@ właścicielem i partnerami ze sceny, kategoria z całym katalogiem. Zmierzone: Próg 50 leży ponad dwukrotnie powyżej najwyższej prawdziwej osoby. Dodatkowo chronimy nazwy w formacie „Imię Nazwisko", bo sygnał studia (odrzucony) wciągał marki osobiste. +**Drugie kryterium: tag przytłacza performera.** Promiskuityczność zawodzi dla śmieci, +które mają ref kanoniczny — bo TPDB i StashDB SAME zawierają wpisy „Hardcore", „Blonde", +„Masturbation", „Amateur". Co gorsza, `obcy` mierzy tam popularność, nie śmieciowość: +przy wartości 50-59 stoją Adriana Chechik (4201 scen), Lauren Phillips i Jane Wilde. + +Rozstrzyga stosunek `scen z tagiem / scen performera`. Nazwisko-tag siedzi głównie na +scenach swojej właścicielki, więc stosunek jest ułamkiem; kategoria wisi na całym +katalogu, więc idzie w setki: + + Hardcore 1720,6 Masturbation 1570,4 Blonde 770,0 Anal Creampie 31,4 + najwyższy wśród 921 PEWNYCH osób (ref kanoniczny + ≥500 scen): **0,35** + +**Próg 2 wynika z zasady, nie z próbki.** Nazwisko użyte jako własny tag daje stosunek +≈1 Z DEFINICJI, bo tag siedzi dokładnie na scenach swojej właścicielki — potwierdzone na +twórcach z własną marką: Hotwifevictoria 1,02, Rossmexicana 0,99, Sexwithmilfstella 0,87. +Wielkie gwiazdy mają jeszcze mniej (tuby tagują tylko część ich scen). Stosunek ≥2 +oznacza więc, że słowo jest doklejane do scen, które do tej osoby nie należą. + +Wymóg ≥50 scen odcina szum przy małych liczbach (przy 11 scenach „Denzel" wychodził na +161, ale to za mało danych, żeby przesądzać). Przy progu 2 na 78 trafień dwa są +dyskusyjne („Teddy", „Grey" mogą być nazwiskami) — ale i one mają tag rozlany na 3× +więcej scen, niż mają przypisań, więc ich atrybucje i tak są w większości słowne. + Job, nie bramka w `resolve_performer`: kasowanie cyklem nie dotyka gorącej ścieżki -ingestu, a śmieci i tak odrastają wolno. Ta sama logika co przy [[phash_blacklist]]. +ingestu, a śmieci i tak odrastają wolno. Dotyczy to zwłaszcza tego drugiego kryterium, +bo tamte rekordy odtwarza sam ingest TPDB/StashDB. Ta sama logika co przy +[[phash_blacklist]]. """ from __future__ import annotations @@ -40,6 +65,11 @@ log = logging.getLogger(__name__) #: Ponad 2× powyżej najwyższej zmierzonej prawdziwej osoby (Julia Reaves, 20). DEFAULT_MIN_FOREIGN_PERFORMERS = 50 +#: 2× powyżej naturalnej wartości dla nazwiska użytego jako własny tag (≈1). +DEFAULT_MIN_TAG_RATIO = 2 +#: Poniżej tego stosunek jest szumem — za mało scen, żeby cokolwiek przesądzać. +DEFAULT_MIN_SCENES_FOR_RATIO = 50 + _SELECT_SQL = """ WITH junk AS ( SELECT pf.id, pf.canonical_name, pf.slug @@ -63,8 +93,33 @@ WHERE ( """ -def find_junk_performers(session: Session, *, min_foreign: int = DEFAULT_MIN_FOREIGN_PERFORMERS): - return [r[0] for r in session.execute(text(_SELECT_SQL), {"min_foreign": min_foreign})] +_RATIO_SQL = """ +SELECT pf.id +FROM performers pf +WHERE EXISTS (SELECT 1 FROM tags t WHERE t.slug = pf.slug) + AND (SELECT count(*) FROM scene_performers sp WHERE sp.performer_id = pf.id) >= :min_scenes + AND (SELECT count(*) FROM scene_tags st JOIN tags t ON t.id = st.tag_id WHERE t.slug = pf.slug)::numeric + / NULLIF((SELECT count(*) FROM scene_performers sp WHERE sp.performer_id = pf.id), 0) >= :min_ratio +""" + + +def find_junk_performers( + session: Session, + *, + min_foreign: int = DEFAULT_MIN_FOREIGN_PERFORMERS, + min_ratio: int = DEFAULT_MIN_TAG_RATIO, + min_scenes: int = DEFAULT_MIN_SCENES_FOR_RATIO, +): + """Suma dwóch niezależnych kryteriów — pierwsze łapie śmieci bez refa kanonicznego, + drugie te, które ref mają (bo TPDB/StashDB też zawierają „Hardcore" czy „Blonde").""" + ids = {r[0] for r in session.execute(text(_SELECT_SQL), {"min_foreign": min_foreign})} + ids |= { + r[0] + for r in session.execute( + text(_RATIO_SQL), {"min_ratio": min_ratio, "min_scenes": min_scenes} + ) + } + return list(ids) def run_junk_performer_cleanup(