Files
kjvstudy.org/scripts/show_commentary_coverage.py
kennethreitz 801c8b93f0 Add script to show verse commentary coverage
Create utility script to track progress on enhanced verse commentary.
Displays statistics about which verses have enhanced JSON commentary
and provides various reporting options.

Features:
- Summary view showing books and verse counts
- Book-specific detail view
- Complete verse listing
- Detailed statistics including field completeness

Usage examples:
  python scripts/show_commentary_coverage.py              # Summary
  python scripts/show_commentary_coverage.py --book Genesis
  python scripts/show_commentary_coverage.py --list       # All verses
  python scripts/show_commentary_coverage.py --stats      # Detailed stats

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-28 13:05:21 -05:00

288 lines
9.6 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Show which verses have enhanced commentary and which don't.
This script analyzes the verse_commentary.json file and displays statistics
about commentary coverage across the Bible. It helps track progress on adding
enhanced verse-by-verse commentary.
Usage:
python scripts/show_commentary_coverage.py # Show summary
python scripts/show_commentary_coverage.py --book Genesis # Show specific book
python scripts/show_commentary_coverage.py --list # List all commentated verses
python scripts/show_commentary_coverage.py --missing # Show verses without commentary
python scripts/show_commentary_coverage.py --stats # Detailed statistics
"""
import json
import sys
from pathlib import Path
from collections import defaultdict
from typing import Dict, List, Tuple
import argparse
# Path to data directory
DATA_DIR = Path(__file__).parent.parent / "kjvstudy_org" / "data"
VERSE_COMMENTARY_PATH = DATA_DIR / "verse_commentary.json"
def load_commentary() -> Dict[str, dict]:
"""Load verse commentary from JSON file."""
if not VERSE_COMMENTARY_PATH.exists():
print(f"Error: {VERSE_COMMENTARY_PATH} not found")
sys.exit(1)
with open(VERSE_COMMENTARY_PATH, 'r', encoding='utf-8') as f:
return json.load(f)
def parse_verse_ref(verse_ref: str) -> Tuple[str, int, int]:
"""
Parse verse reference like 'Genesis 1:1' into (book, chapter, verse).
Args:
verse_ref: Verse reference string like "Genesis 1:1" or "1 John 3:16"
Returns:
Tuple of (book_name, chapter_num, verse_num)
"""
parts = verse_ref.rsplit(' ', 1)
if len(parts) != 2:
return ("Unknown", 0, 0)
book = parts[0]
chapter_verse = parts[1]
if ':' not in chapter_verse:
return (book, 0, 0)
chapter_str, verse_str = chapter_verse.split(':', 1)
try:
chapter = int(chapter_str)
verse = int(verse_str)
except ValueError:
return (book, 0, 0)
return (book, chapter, verse)
def organize_by_book(commentary: Dict[str, dict]) -> Dict[str, Dict[int, List[int]]]:
"""
Organize commentary by book and chapter.
Returns:
Dict of {book: {chapter: [verse1, verse2, ...]}}
"""
organized = defaultdict(lambda: defaultdict(list))
for verse_ref in commentary.keys():
book, chapter, verse = parse_verse_ref(verse_ref)
if chapter > 0 and verse > 0:
organized[book][chapter].append(verse)
# Sort verses within each chapter
for book in organized:
for chapter in organized[book]:
organized[book][chapter].sort()
return dict(organized)
def show_summary(commentary: Dict[str, dict]):
"""Show high-level summary of commentary coverage."""
organized = organize_by_book(commentary)
print("=" * 70)
print("VERSE COMMENTARY COVERAGE SUMMARY")
print("=" * 70)
print()
total_verses = len(commentary)
total_books = len(organized)
print(f"📖 Total verses with enhanced commentary: {total_verses}")
print(f"📚 Books with commentary: {total_books}")
print()
print("Coverage by Book:")
print("-" * 70)
for book in sorted(organized.keys()):
chapters = organized[book]
total_verses_in_book = sum(len(verses) for verses in chapters.values())
chapter_list = sorted(chapters.keys())
chapter_range = f"{min(chapter_list)}-{max(chapter_list)}" if len(chapter_list) > 1 else str(chapter_list[0])
print(f" {book:30} {total_verses_in_book:4} verses (chapters: {chapter_range})")
print()
def show_book_detail(commentary: Dict[str, dict], book_name: str):
"""Show detailed commentary coverage for a specific book."""
organized = organize_by_book(commentary)
if book_name not in organized:
print(f"❌ No commentary found for book: {book_name}")
print(f"\nAvailable books:")
for book in sorted(organized.keys()):
print(f" - {book}")
return
print("=" * 70)
print(f"COMMENTARY COVERAGE: {book_name}")
print("=" * 70)
print()
chapters = organized[book_name]
total_verses = sum(len(verses) for verses in chapters.values())
print(f"Total verses: {total_verses}")
print(f"Chapters with commentary: {len(chapters)}")
print()
for chapter in sorted(chapters.keys()):
verses = chapters[chapter]
verse_list = ", ".join(str(v) for v in verses)
print(f" Chapter {chapter:3} ({len(verses):2} verses): {verse_list}")
print()
def list_all_verses(commentary: Dict[str, dict]):
"""List all verses with commentary."""
organized = organize_by_book(commentary)
print("=" * 70)
print("ALL VERSES WITH ENHANCED COMMENTARY")
print("=" * 70)
print()
for book in sorted(organized.keys()):
print(f"\n{book}")
print("-" * 70)
chapters = organized[book]
for chapter in sorted(chapters.keys()):
verses = chapters[chapter]
verse_list = ", ".join(str(v) for v in verses)
print(f" {chapter}:{verse_list}")
print()
def show_statistics(commentary: Dict[str, dict]):
"""Show detailed statistics about commentary coverage."""
organized = organize_by_book(commentary)
print("=" * 70)
print("DETAILED COMMENTARY STATISTICS")
print("=" * 70)
print()
# Total verses
total_verses = len(commentary)
total_books = len(organized)
total_chapters = sum(len(chapters) for chapters in organized.values())
print(f"📊 Total Statistics:")
print(f" • Enhanced verses: {total_verses}")
print(f" • Books covered: {total_books}")
print(f" • Chapters covered: {total_chapters}")
print()
# Book-level stats
print("📚 Coverage by Testament:")
# Common book groupings
ot_books = ["Genesis", "Exodus", "Leviticus", "Numbers", "Deuteronomy",
"Joshua", "Judges", "Ruth", "1 Samuel", "2 Samuel", "1 Kings", "2 Kings",
"1 Chronicles", "2 Chronicles", "Ezra", "Nehemiah", "Esther",
"Job", "Psalms", "Proverbs", "Ecclesiastes", "Song of Solomon",
"Isaiah", "Jeremiah", "Lamentations", "Ezekiel", "Daniel",
"Hosea", "Joel", "Amos", "Obadiah", "Jonah", "Micah", "Nahum",
"Habakkuk", "Zephaniah", "Haggai", "Zechariah", "Malachi"]
nt_books = ["Matthew", "Mark", "Luke", "John", "Acts", "Romans",
"1 Corinthians", "2 Corinthians", "Galatians", "Ephesians", "Philippians",
"Colossians", "1 Thessalonians", "2 Thessalonians", "1 Timothy", "2 Timothy",
"Titus", "Philemon", "Hebrews", "James", "1 Peter", "2 Peter",
"1 John", "2 John", "3 John", "Jude", "Revelation"]
ot_verses = sum(sum(len(verses) for verses in organized[book].values())
for book in ot_books if book in organized)
nt_verses = sum(sum(len(verses) for verses in organized[book].values())
for book in nt_books if book in organized)
ot_books_with_commentary = sum(1 for book in ot_books if book in organized)
nt_books_with_commentary = sum(1 for book in nt_books if book in organized)
print(f" • Old Testament: {ot_verses} verses across {ot_books_with_commentary} books")
print(f" • New Testament: {nt_verses} verses across {nt_books_with_commentary} books")
print()
# Top books by coverage
print("🏆 Top 10 Books by Commentary Coverage:")
book_verse_counts = []
for book in organized:
count = sum(len(verses) for verses in organized[book].values())
book_verse_counts.append((book, count))
book_verse_counts.sort(key=lambda x: x[1], reverse=True)
for i, (book, count) in enumerate(book_verse_counts[:10], 1):
print(f" {i:2}. {book:30} {count:4} verses")
print()
# Commentary field completeness
print("✅ Commentary Field Completeness:")
has_analysis = sum(1 for v in commentary.values() if v.get('analysis'))
has_historical = sum(1 for v in commentary.values() if v.get('historical_context'))
has_questions = sum(1 for v in commentary.values() if v.get('questions'))
has_application = sum(1 for v in commentary.values() if v.get('application'))
print(f" • Analysis: {has_analysis}/{total_verses} ({100*has_analysis/total_verses:.1f}%)")
print(f" • Historical Context: {has_historical}/{total_verses} ({100*has_historical/total_verses:.1f}%)")
print(f" • Questions: {has_questions}/{total_verses} ({100*has_questions/total_verses:.1f}%)")
print(f" • Application: {has_application}/{total_verses} ({100*has_application/total_verses:.1f}%)")
print()
def main():
"""Main entry point."""
parser = argparse.ArgumentParser(
description="Show verse commentary coverage",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python scripts/show_commentary_coverage.py
python scripts/show_commentary_coverage.py --book Genesis
python scripts/show_commentary_coverage.py --list
python scripts/show_commentary_coverage.py --stats
"""
)
parser.add_argument('--book', type=str, help='Show detail for a specific book')
parser.add_argument('--list', action='store_true', help='List all commentated verses')
parser.add_argument('--stats', action='store_true', help='Show detailed statistics')
args = parser.parse_args()
# Load commentary data
commentary = load_commentary()
if args.book:
show_book_detail(commentary, args.book)
elif args.list:
list_all_verses(commentary)
elif args.stats:
show_statistics(commentary)
else:
show_summary(commentary)
if __name__ == "__main__":
main()