File size: 9,644 Bytes
e8510d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
import json
import os
import logging
import sqlite3
import re
from typing import Dict, List, Any
from gematria import calculate_gematria, strip_diacritics
from deep_translator import GoogleTranslator

logger = logging.getLogger(__name__)

def process_bible_files(start: int, end: int) -> Dict[int, Dict[str, Any]]:
    """
    Processes Bible JSON files and returns a dictionary mapping book IDs to their data.

    Args:
        start: The starting book ID (inclusive).
        end: The ending book ID (inclusive).

    Returns:
        A dictionary where keys are book IDs and values are dictionaries
        containing 'title' and 'text' fields.
    """
    base_path = "texts/bible"
    results = {}

    for i in range(start, end + 1):
        file_name = f"{base_path}/{i}.json"
        try:
            with open(file_name, 'r', encoding='utf-8') as file:
                data = json.load(file)
                if data:
                    # Extract title and verses
                    title = data.get("title", "No title")
                    text = data.get("text", [])

                    # Store book ID as key and book data as value
                    results[i] = {"title": title, "text": text}

        except FileNotFoundError:
            logger.warning(f"File {file_name} not found.")
        except json.JSONDecodeError as e:
            logger.warning(f"File {file_name} could not be read as JSON: {e}")
        except Exception as e:
            logger.warning(f"Error processing {file_name}: {e}")

    return results

def process_json_files(start, end, step, rounds="1", length=0, tlang="en", strip_spaces=True, strip_in_braces=True,
                       strip_diacritics_value=True, translate=False):
    """
    Processes Bible JSON files and performs ELS (Equidistant Letter Sequence) search.

    Parameters:
    - start (int): Start number of the Bible book.
    - end (int): End number of the Bible book.
    - step (int): Step size for character selection.
    - rounds (str): Comma-separated list of round numbers (can include negative values).
    - length (int): Maximum length of the result text.
    - tlang (str): Target language for translation.
    - strip_spaces (bool): Whether to remove spaces from the text.
    - strip_in_braces (bool): Whether to remove text within braces.
    - strip_diacritics_value (bool): Whether to remove diacritics from the text.
    - translate (bool): Whether to translate the result text.

    Returns:
    - list: A list of dictionaries containing processed data or error messages.
    """
    logger.debug(f"Processing Bible files {start}-{end} with step {step}, rounds {rounds}")
    results = []
    
    try:
        bible_data = process_bible_files(start, end)
        
        if not bible_data:
            return [{"error": f"No Bible data found for books {start}-{end}"}]
        
        rounds_list = [int(r.strip()) for r in rounds.split(",")]
        
        for book_id, book_info in bible_data.items():
            book_title = book_info.get("title", "Unknown")
            chapters = book_info.get("text", [])
            
            if not chapters:
                results.append({"error": f"No text found for book {book_title} (ID: {book_id})"})
                continue
            
            # Flatten the text
            flattened_text = ""
            for chapter_idx, chapter in enumerate(chapters, 1):
                for verse_idx, verse in enumerate(chapter, 1):
                    if verse:
                        flattened_text += verse + " "
            
            # Clean the text based on parameters
            processed_text = flattened_text.lower()
            
            if strip_in_braces:
                # Remove content within brackets or parentheses
                processed_text = re.sub(r'\[.*?\]|\(.*?\)', '', processed_text)
            
            if strip_spaces:
                # Remove spaces and other whitespace
                processed_text = re.sub(r'\s+', '', processed_text)
            
            if strip_diacritics_value:
                # Remove diacritics from letters
                processed_text = strip_diacritics(processed_text)
            
            # To match daily_psalm, process round 1 first, then other rounds
            sorted_rounds = sorted(rounds_list, key=lambda r: 0 if r == 1 else abs(r))
            
            # Perform ELS search for each round
            for round_num in sorted_rounds:
                if round_num == 0:
                    continue
                
                direction = 1 if round_num > 0 else -1
                abs_round = abs(round_num)
                
                # Calculate step size
                actual_step = step * abs_round
                
                # Apply ELS algorithm
                els_result = None
                
                # Determine start index based on direction
                start_idx = 0 if direction > 0 else len(processed_text) - 1
                
                # Loop through possible starting positions
                for i in range(abs_round):
                    # Skip if starting position is out of bounds
                    if start_idx + i >= len(processed_text) or start_idx - i < 0:
                        continue
                    
                    # Get starting position for this round
                    pos = start_idx + i if direction > 0 else start_idx - i
                    
                    # Extract letters at intervals
                    result_text = ""
                    while 0 <= pos < len(processed_text) and (length == 0 or len(result_text) < length):
                        result_text += processed_text[pos]
                        pos += actual_step * direction
                    
                    # Only record non-empty results
                    if result_text:
                        # Prepare result object
                        result = {
                            "result_text": result_text,
                            "step": actual_step * direction,
                            "start_pos": i,
                            "book_id": book_id,
                            "book_title": book_title,
                            "round": round_num,
                            "gematria": calculate_gematria(result_text)
                        }
                        
                        # Translate result if requested
                        if translate and result_text and tlang != "en":
                            try:
                                translator = GoogleTranslator(source='en', target=tlang)
                                result["translated_text"] = translator.translate(result_text)
                            except Exception as e:
                                logger.warning(f"Translation error: {e}")
                                result["translated_text"] = result_text
                        
                        # Add result to results list
                        results.append(result)
                        
                        # For efficiency, once we find a valid result for this round, break the loop
                        # This ensures we get one result per round but don't waste time on additional calculations
                        break
    
    except Exception as e:
        logger.error(f"Error processing Bible files: {e}", exc_info=True)
        results.append({"error": f"Error processing Bible files: {str(e)}"})
    
    return results

def create_bible_display_iframe(book_title, book_id, chapter=None, verse=None):
    """
    Creates an iframe HTML string for BibleGateway.

    Args:
        book_title (str): The title of the book.
        book_id (int): The ID of the book.
        chapter (int, optional): The chapter number.
        verse (int, optional): The verse number.

    Returns:
        str: An iframe HTML string for displaying the specified Bible passage.
    """
    from urllib.parse import quote_plus
    
    # Format the passage reference
    if chapter and verse:
        reference = f"{book_title}+{chapter}:{verse}"
    elif chapter:
        reference = f"{book_title}+{chapter}"
    else:
        reference = book_title
    
    encoded_reference = quote_plus(reference)
    url = f"https://www.biblegateway.com/passage/?search={encoded_reference}&version=CJB"
    iframe = f'<iframe src="{url}" width="800" height="600"></iframe>'
    
    return iframe

def find_bible_verse_by_gematria(gematria_sum, db_file="bible.db"):
    """
    Finds a Bible verse with a matching gematria sum.

    Args:
        gematria_sum (int): The gematria sum to match.
        db_file (str): Path to the database file.

    Returns:
        dict or None: Dictionary with verse details or None if no match found.
    """
    try:
        with sqlite3.connect(db_file) as conn:
            cursor = conn.cursor()
            cursor.execute('''
                SELECT book, chapter, verse, words
                FROM verses
                WHERE gematria_sum = ?
                ORDER BY LENGTH(words) ASC
                LIMIT 1
            ''', (gematria_sum,))
            result = cursor.fetchone()
            
            if result:
                book, chapter, verse, words = result
                return {
                    "book": book,
                    "chapter": chapter,
                    "verse": verse,
                    "words": words
                }
            
            return None
            
    except sqlite3.Error as e:
        logger.error(f"Database error: {e}")
        return None