#!/usr/bin/env python3 """ Complete Asset Audit Script Systematically checks ALL assets vs documentation """ import os from pathlib import Path from collections import defaultdict # Base paths REPO_ROOT = Path("/Users/davidkotnik/repos/novafarma") ASSETS_REF = REPO_ROOT / "assets" / "references" # Expected counts from DEMO_FAZA1_FAZA2_OVERVIEW.md EXPECTED = { "characters": { "kai": 21, # idle(5) + walk(6) + dig(5) + swing(5) "ana": 10, # idle(4) + walk(6) "gronk": 10, # idle(4) + walk(6) }, "companions": { "susi": 12, # idle(4) + run(6) + bark(2) }, "zombies": 45, # 3 types × 15 frames each "crops": { "wheat": 5, "carrot": 5, "tomato": 5, "potato": 5, "corn": 5, }, "tools": 8, "ui": 28, "grassland": 27, } def count_pngs(directory): """Count PNG files in directory recursively""" if not directory.exists(): return 0 return len(list(directory.rglob("*.png"))) def audit_characters(): """Audit main characters""" print("\n## 1. MAIN CHARACTERS") print("=" * 60) char_path = ASSETS_REF / "main_characters" results = {} for char in ["kai", "ana", "gronk"]: char_dir = char_path / char actual = count_pngs(char_dir) expected = EXPECTED["characters"][char] status = "✅" if actual >= expected else "❌" gap = actual - expected results[char] = { "expected": expected, "actual": actual, "status": status, "gap": gap } print(f"\n{char.upper()}:") print(f" Expected: {expected}") print(f" Actual: {actual}") print(f" Status: {status} ({'+' if gap >= 0 else ''}{gap})") return results def audit_companions(): """Audit companion animals""" print("\n## 2. COMPANIONS") print("=" * 60) comp_path = ASSETS_REF / "companions" results = {} for comp in ["susi"]: comp_dir = comp_path / comp actual = count_pngs(comp_dir) expected = EXPECTED["companions"][comp] status = "✅" if actual >= expected else "❌" gap = actual - expected results[comp] = { "expected": expected, "actual": actual, "status": status, "gap": gap } print(f"\n{comp.upper()}:") print(f" Expected: {expected}") print(f" Actual: {actual}") print(f" Status: {status} ({'+' if gap >= 0 else ''}{gap})") return results def audit_crops(): """Audit crop growth stages""" print("\n## 3. CROPS") print("=" * 60) crops_path = ASSETS_REF / "crops" results = {} for crop in ["wheat", "carrot", "tomato", "potato", "corn"]: crop_dir = crops_path / crop / "growth_stages" actual = count_pngs(crop_dir) expected = EXPECTED["crops"][crop] status = "✅" if actual >= expected else "❌" gap = actual - expected results[crop] = { "expected": expected, "actual": actual, "status": status, "gap": gap } print(f"\n{crop.upper()}:") print(f" Expected: {expected}") print(f" Actual: {actual}") print(f" Status: {status} ({'+' if gap >= 0 else ''}{gap})") return results def audit_audio(): """Audit audio files""" print("\n## 4. AUDIO") print("=" * 60) audio_path = ASSETS_REF.parent / "audio" # Count voice files voices = audio_path / "voices" voice_count = len(list(voices.rglob("*.mp3"))) if voices.exists() else 0 # Count sound effects sfx = audio_path / "sfx" sfx_count = len(list(sfx.rglob("*.wav"))) if sfx.exists() else 0 # Count music music_path = REPO_ROOT / "music" music_count = len(list(music_path.rglob("*.mp3"))) if music_path.exists() else 0 music_count += len(list(music_path.rglob("*.wav"))) if music_path.exists() else 0 music_count += len(list(music_path.rglob("*.ogg"))) if music_path.exists() else 0 print(f"\nVOICES (MP3): {voice_count}") print(f"SOUND EFFECTS (WAV): {sfx_count}") print(f"MUSIC: {music_count} {'❌ MISSING!' if music_count == 0 else '✅'}") return { "voices": voice_count, "sfx": sfx_count, "music": music_count } def generate_report(): """Generate complete audit report""" print("\n" + "="*60) print("🔍 COMPLETE ASSET AUDIT - JAN 8, 2026") print("="*60) # Run all audits chars = audit_characters() comps = audit_companions() crops = audit_crops() audio = audit_audio() # Summary print("\n" + "="*60) print("📊 SUMMARY") print("="*60) total_expected = sum(EXPECTED["characters"].values()) total_expected += sum(EXPECTED["companions"].values()) total_expected += sum(EXPECTED["crops"].values()) total_expected += EXPECTED["zombies"] total_expected += EXPECTED["tools"] total_expected += EXPECTED["ui"] total_actual = count_pngs(ASSETS_REF) print(f"\nTOTAL PNG FILES: {total_actual}") print(f"AUDIO FILES: {audio['voices'] + audio['sfx'] + audio['music']}") print(f" - Voices: {audio['voices']}") print(f" - SFX: {audio['sfx']}") print(f" - Music: {audio['music']} {'❌' if audio['music'] == 0 else '✅'}") # Missing items print("\n" + "="*60) print("❌ MISSING / NEEDS ATTENTION") print("="*60) missing = [] for char, data in chars.items(): if data['gap'] < 0: missing.append(f" - {char.upper()}: {abs(data['gap'])} sprites short") for crop, data in crops.items(): if data['gap'] < 0: missing.append(f" - {crop.upper()}: {abs(data['gap'])} sprites short") if audio['music'] == 0: missing.append(f" - MUSIC: Need 3+ background tracks") if missing: for item in missing: print(item) else: print(" ✅ ALL ASSETS COMPLETE!") print("\n" + "="*60) if __name__ == "__main__": generate_report()