mirror of
https://github.com/kennethreitz/kjvstudy.org.git
synced 2026-06-05 23:00:16 +00:00
0132efbfbc
Created comprehensive statistics script for analyzing the red letter edition data (words of Jesus Christ). Features: - Total verse counts (full vs partial) - Breakdown by book with percentages - Testament distribution (Gospels vs Acts/Revelation) - Longest continuous discourses (e.g., Sermon on the Mount) - Notable discourse references Usage: uv run python scripts/red_letter_stats.py 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
202 lines
6.0 KiB
Python
Executable File
202 lines
6.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Red Letter Edition Statistics
|
|
|
|
This script analyzes and displays statistics about the red letter verses
|
|
(words of Jesus Christ) in the KJV Study Bible.
|
|
|
|
Usage:
|
|
python scripts/red_letter_stats.py
|
|
uv run python scripts/red_letter_stats.py
|
|
"""
|
|
|
|
import json
|
|
from pathlib import Path
|
|
from collections import Counter, defaultdict
|
|
|
|
|
|
def load_red_letter_data():
|
|
"""Load the red letter verses JSON file."""
|
|
data_path = Path(__file__).parent.parent / "kjvstudy_org" / "data" / "red_letter_verses.json"
|
|
|
|
with open(data_path, 'r', encoding='utf-8') as f:
|
|
return json.load(f)
|
|
|
|
|
|
def parse_verse_reference(ref):
|
|
"""Parse a verse reference like 'Matthew 3:15' into components."""
|
|
parts = ref.rsplit(' ', 1)
|
|
book = parts[0]
|
|
chapter_verse = parts[1].split(':')
|
|
chapter = int(chapter_verse[0])
|
|
verse = int(chapter_verse[1])
|
|
return book, chapter, verse
|
|
|
|
|
|
def analyze_red_letter_data(data):
|
|
"""Analyze the red letter verses and return statistics."""
|
|
verses = data['verses']
|
|
|
|
# Basic counts
|
|
total_verses = len(verses)
|
|
full_verses = sum(1 for v in verses.values() if v == 'full')
|
|
partial_verses = total_verses - full_verses
|
|
|
|
# Count by book
|
|
books = Counter()
|
|
full_by_book = Counter()
|
|
partial_by_book = Counter()
|
|
|
|
# Track consecutive verses (discourses)
|
|
discourses = []
|
|
current_discourse = []
|
|
last_book = None
|
|
last_chapter = None
|
|
last_verse = None
|
|
|
|
for ref, text in sorted(verses.items()):
|
|
book, chapter, verse = parse_verse_reference(ref)
|
|
|
|
books[book] += 1
|
|
|
|
if text == 'full':
|
|
full_by_book[book] += 1
|
|
else:
|
|
partial_by_book[book] += 1
|
|
|
|
# Track discourses (consecutive verses)
|
|
if (book == last_book and
|
|
chapter == last_chapter and
|
|
verse == last_verse + 1):
|
|
current_discourse.append((book, chapter, verse))
|
|
else:
|
|
if len(current_discourse) > 1:
|
|
discourses.append(current_discourse)
|
|
current_discourse = [(book, chapter, verse)]
|
|
|
|
last_book = book
|
|
last_chapter = chapter
|
|
last_verse = verse
|
|
|
|
# Don't forget the last discourse
|
|
if len(current_discourse) > 1:
|
|
discourses.append(current_discourse)
|
|
|
|
# Sort discourses by length
|
|
discourses.sort(key=len, reverse=True)
|
|
|
|
return {
|
|
'total_verses': total_verses,
|
|
'full_verses': full_verses,
|
|
'partial_verses': partial_verses,
|
|
'books': books,
|
|
'full_by_book': full_by_book,
|
|
'partial_by_book': partial_by_book,
|
|
'discourses': discourses,
|
|
}
|
|
|
|
|
|
def format_discourse(discourse):
|
|
"""Format a discourse for display."""
|
|
book, start_chapter, start_verse = discourse[0]
|
|
_, end_chapter, end_verse = discourse[-1]
|
|
|
|
if start_chapter == end_chapter:
|
|
return f"{book} {start_chapter}:{start_verse}-{end_verse}"
|
|
else:
|
|
return f"{book} {start_chapter}:{start_verse} - {end_chapter}:{end_verse}"
|
|
|
|
|
|
def print_stats(stats):
|
|
"""Print statistics in a formatted way."""
|
|
print("=" * 70)
|
|
print("RED LETTER EDITION STATISTICS")
|
|
print("Words of Jesus Christ in the KJV Bible")
|
|
print("=" * 70)
|
|
print()
|
|
|
|
# Overall stats
|
|
print("📊 OVERALL STATISTICS")
|
|
print("-" * 70)
|
|
print(f"Total verses with Christ's words: {stats['total_verses']:,}")
|
|
print(f" • Full verses (entire verse): {stats['full_verses']:,} ({stats['full_verses']/stats['total_verses']*100:.1f}%)")
|
|
print(f" • Partial verses (quoted only): {stats['partial_verses']:,} ({stats['partial_verses']/stats['total_verses']*100:.1f}%)")
|
|
print()
|
|
|
|
# By book
|
|
print("📖 VERSES BY BOOK")
|
|
print("-" * 70)
|
|
print(f"{'Book':<15} {'Total':>8} {'Full':>8} {'Partial':>8} {'% Full':>8}")
|
|
print("-" * 70)
|
|
|
|
for book in sorted(stats['books'].keys()):
|
|
total = stats['books'][book]
|
|
full = stats['full_by_book'][book]
|
|
partial = stats['partial_by_book'][book]
|
|
pct_full = (full / total * 100) if total > 0 else 0
|
|
|
|
print(f"{book:<15} {total:>8,} {full:>8,} {partial:>8,} {pct_full:>7.1f}%")
|
|
|
|
print("-" * 70)
|
|
print(f"{'TOTAL':<15} {stats['total_verses']:>8,} {stats['full_verses']:>8,} {stats['partial_verses']:>8,}")
|
|
print()
|
|
|
|
# Testament breakdown
|
|
gospels = ['Matthew', 'Mark', 'Luke', 'John']
|
|
gospel_count = sum(stats['books'][book] for book in gospels if book in stats['books'])
|
|
other_count = stats['total_verses'] - gospel_count
|
|
|
|
print("📚 BY TESTAMENT")
|
|
print("-" * 70)
|
|
print(f"Gospels (Matthew, Mark, Luke, John): {gospel_count:,} verses ({gospel_count/stats['total_verses']*100:.1f}%)")
|
|
print(f"Acts & Revelation: {other_count:,} verses ({other_count/stats['total_verses']*100:.1f}%)")
|
|
print()
|
|
|
|
# Longest discourses
|
|
print("💬 LONGEST CONTINUOUS DISCOURSES")
|
|
print("-" * 70)
|
|
print("(Consecutive verses where Jesus speaks)")
|
|
print()
|
|
|
|
for i, discourse in enumerate(stats['discourses'][:15], 1):
|
|
length = len(discourse)
|
|
formatted = format_discourse(discourse)
|
|
print(f"{i:2}. {formatted:<40} ({length:3} verses)")
|
|
|
|
print()
|
|
|
|
# Notable discourses
|
|
print("⭐ NOTABLE DISCOURSES")
|
|
print("-" * 70)
|
|
|
|
notable = {
|
|
"Sermon on the Mount": ("Matthew", 5, 1, 7, 27),
|
|
"Olivet Discourse": ("Matthew", 24, 4, 25, 46),
|
|
"Upper Room Discourse": ("John", 14, 1, 16, 33),
|
|
"High Priestly Prayer": ("John", 17, 1, 17, 26),
|
|
"Good Shepherd": ("John", 10, 1, 10, 18),
|
|
"Bread of Life": ("John", 6, 26, 6, 65),
|
|
}
|
|
|
|
for name, (book, sc, sv, ec, ev) in notable.items():
|
|
if sc == ec:
|
|
reference = f"{book} {sc}:{sv}-{ev}"
|
|
else:
|
|
reference = f"{book} {sc}:{sv} - {ec}:{ev}"
|
|
|
|
print(f" {name:<25} {reference}")
|
|
|
|
print()
|
|
print("=" * 70)
|
|
|
|
|
|
def main():
|
|
"""Main function to run the statistics."""
|
|
data = load_red_letter_data()
|
|
stats = analyze_red_letter_data(data)
|
|
print_stats(stats)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|