#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Детектор: aa='Various Artists' у папки, где БОЛЬШИНСТВО файлов имеет одного artist. Класс дефекта (сессия 8, 2026-09-27): Папка-АЛЬБОМ помечена 'Various Artists', хотя исполнитель один. Причины ложного срабатывания критерия «разные artist = сборник»: 1. разнобой написания одного исполнителя ('Иванушки' / 'Иванушки Int.' / 'Иванушки International'); 2. несколько чужих файлов в корне папки артиста (7 чужих треков среди 52 треков 'Агата Кристи'). Правило Alex: «Папка с 1 уникальным артистом → АЛЬБОМ, albumartist = artist». Запуск: python3 find_va_misuse.py [путь_к_APPLY-PLAN.csv] Выход: список папок-кандидатов с частотой доминирующего артиста. ⚠️ Кандидат ≠ дефект. Каждый случай подтверждать у Alex (правило сессии 7: «не отвечать за Alex»). Спорный случай: '!Рэп/НТЛ' — формально попадает под правило сборника из сессии 5 (треки в корне при наличии подпапок-альбомов). Контроль после правок: гонять детектор, пока он не вернёт пусто или только подтверждённые Alex спорные случаи (класс выявляется итеративно). """ import csv import collections import sys P = sys.argv[1] if len(sys.argv) > 1 else '/Users/admin/Downloads/music-tags/APPLY-PLAN.csv' rows = list(csv.DictReader(open(P, encoding='utf-8-sig', newline=''))) def s(v): return (v or '').strip() by = collections.defaultdict(list) for r in rows: by[r['folder']].append(r) suspects = [] for folder, rs in sorted(by.items()): aa = {s(r['new_albumartist']) for r in rs} if aa != {'Various Artists'}: continue art = collections.Counter(s(r['new_artist']) for r in rs if s(r['new_artist'])) if not art: continue top, n = art.most_common(1)[0] total = len(rs) # доминирует один артист: >50% файлов if n / total > 0.5 and n >= 2: suspects.append((n, total, top, folder)) print(f"ПАПОК-КАНДИДАТОВ: {len(suspects)} (файлов: {sum(s[1] for s in suspects)})") print() for n, total, top, folder in sorted(suspects, key=lambda x: -x[1]): print(f" {n:3d}/{total:<3d} artist={top!r}") print(f" {folder}")