import logging logger = logging.getLogger(__name__) logging.basicConfig(level=logging.INFO) import gradio as gr import torah from utils import number_to_ordinal_word, custom_normalize, date_to_words, translate_date_to_words from gematria import calculate_gematria, strip_diacritics import pandas as pd from deep_translator import GoogleTranslator from gradio_calendar import Calendar from datetime import datetime import math import json import re def create_language_dropdown(label, default_value='en', show_label=True): """Creates a Gradio dropdown menu for language selection.""" languages = GoogleTranslator(source='en', target='en').get_supported_languages(as_dict=True) return gr.Dropdown( choices=list(languages.keys()), label=label, value=default_value, show_label=show_label ) def calculate_gematria_sum(text, date_words): """Calculates the Gematria sum for a text and date words.""" combined_input = f"{text} {date_words}" logger.info(f"Combined input for Gematria: {combined_input}") sum_value = calculate_gematria(strip_diacritics(combined_input)) logger.info(f"Gematria sum: {sum_value}") return sum_value def perform_els_search(start, end, step, rounds, length, tlang, strip_spaces, strip_in_braces, strip_diacritics_chk, average_combine): """Performs the Equidistant Letter Sequences (ELS) search.""" logger.info("Starting ELS search...") if step == 0 or rounds == 0: logger.info("cant search with step 0 or rounds 0") return None results = torah.process_json_files(start, end, step, rounds, length, tlang, strip_spaces, strip_in_braces, strip_diacritics, average_combine) df = pd.DataFrame(results) df.index = range(1, len(df) + 1) df.reset_index(inplace=True) df.rename(columns={'index': 'Result Number'}, inplace=True) logger.info(f"ELS search results: {df}") return df def generate_json_dump(start, end, step, rounds, length, tlang, strip_spaces, strip_in_braces, strip_diacritics_chk, search_phrase, results_df): """Generates the JSON dump with both configuration and results.""" config = { "Start Book": start, "End Book": end, "Step": step, "Rounds": rounds, "Length": length, "Target Language": tlang, "Strip Spaces": strip_spaces, "Strip Text in Braces": strip_in_braces, "Strip Diacritics": strip_diacritics_chk, "Search Phrase": search_phrase } result = { "Configuration": config, "Results": json.loads(results_df.to_json(orient='records', force_ascii=False)) } logger.info(f"Generated JSON dump: {result}") return json.dumps(result, indent=4, ensure_ascii=False) def download_json_file(config_json, step, rounds, strip_spaces, strip_in_braces, strip_diacritics_chk): """Downloads the JSON config file with a descriptive name.""" filename_suffix = "" if strip_spaces: filename_suffix += "-stSp" if strip_in_braces: filename_suffix += "-stBr" if strip_diacritics_chk: filename_suffix += "-stDc" file_path = f"step-{step}-rounds-{rounds}{filename_suffix}.json" # Include rounds in filename with open(file_path, "w", encoding='utf-8') as file: file.write(config_json) logger.info(f"Downloaded JSON file to: {file_path}") return file_path # --- Load Forbidden Names --- def load_forbidden_names(filename="c.txt"): """Loads forbidden names from the specified file.""" try: with open(filename, "r", encoding='utf-8') as f: forbidden_names = [line.strip() for line in f] return forbidden_names except FileNotFoundError: print(f"Error: Forbidden names file '{filename}' not found.") return [] # --- Name Similarity Check --- def check_name_similarity(name, forbidden_names, threshold=80): """Checks if a name is similar to any forbidden name.""" from fuzzywuzzy import fuzz for forbidden_name in forbidden_names: similarity_ratio = fuzz.ratio(name.lower(), forbidden_name.lower()) if similarity_ratio >= threshold: logging.info(f"Forbidden word {forbidden_name} detected in: {name}") return True return False # --- UI Components --- with gr.Blocks() as app: with gr.Row(): selected_date = Calendar(type="datetime", label="1. Date to investigate", info="Pick a date from the calendar") date_language_input = create_language_dropdown("2. Mother-tongue / Dream-language of the person/topic (Date Word Language (supported: all based on: latin, greek, arabic, hebrew))", default_value='english') date_to_word_btn = gr.Button("3. Convert Date to Words") date_words_output = gr.Textbox(label="4. Date in Words Translated") with gr.Row(): gematria_text = gr.Textbox(label="5. Name and/or Topic", value="Hans Albert Einstein") gematria_btn = gr.Button("6. Calculate Journal Sum") gematria_result = gr.Number(label="Journal Sum") with gr.Row(): start = gr.Number(label="Start Book", value=1) end = gr.Number(label="End Book", value=39) step = gr.Number(label="Jump Width (Steps) for ELS") rounds = gr.Number(label="Rounds through Books", value=1) float_step = gr.Number(visible=False, value=1) # For half/double step calculations half_step_btn = gr.Button("Steps / 2") double_step_btn = gr.Button("Steps * 2") with gr.Column(): round_x = gr.Number(label="Round (x)", value=1) round_y = gr.Number(label="Round (y)", value=-1) average_combine_chk = gr.Checkbox(label="Average-Combine Combined Rounds (hacky)", value=False) mirror_book_numbers = gr.Checkbox(label="Mirror book numbers for negative rounds (axis=book 20)", value=False) rounds_combination = gr.Textbox(label="Combined Rounds", value="1,-1") with gr.Row(): length = gr.Number(label="Result Length (0=inf)", value=0) tlang = create_language_dropdown("Target Language for Translation", default_value='english') strip_spaces = gr.Checkbox(label="Strip Spaces from Books", value=True) strip_in_braces = gr.Checkbox(label="Strip Text in Braces from Books", value=True) strip_diacritics_chk = gr.Checkbox(label="Strip Diacritics from Books", value=True) acknowledgment_chk = gr.Checkbox( label="The User hereby accepts that the User will not harm or stalk anyone with this information, or bet on any of this information, in any regards.", # Add your full disclaimer here value=True ) translate_btn = gr.Button("8. Search with ELS") markdown_output = gr.Dataframe() json_output = gr.Textbox(label="JSON Configuration Output") json_download_btn = gr.Button("Prepare .json for Download") json_file = gr.File(label="Download Config JSON", file_count="single") # --- Load Forbidden Names --- forbidden_names = load_forbidden_names() # --- Event Handlers --- def update_rounds_combination(round_x, round_y): """Updates the rounds_combination textbox based on round_x and round_y.""" return f"{int(round_x)},{int(round_y)}" def calculate_journal_sum(text, date_words): """Calculates the journal sum and updates the step value.""" if check_name_similarity(text, forbidden_names): return 0, 0, 0 # Raise an error if the name is forbidden if check_name_similarity(date_words, forbidden_names): return 0, 0, 0 # Raise an error if the name is forbidden sum_value = calculate_gematria_sum(text, date_words) return sum_value, sum_value, sum_value # Returning the same value three times def update_step_half(float_step): """Updates the step value to half.""" new_step = math.ceil(float_step / 2) return new_step, float_step / 2 def update_step_double(float_step): """Updates the step value to double.""" new_step = math.ceil(float_step * 2) return new_step, float_step * 2 # Update rounds_combination when round_x or round_y changes round_x.change(update_rounds_combination, inputs=[round_x, round_y], outputs=rounds_combination) round_y.change(update_rounds_combination, inputs=[round_x, round_y], outputs=rounds_combination) def handle_json_download(config_json, step, rounds, strip_spaces, strip_in_braces, strip_diacritics_chk): """Handles the download of the JSON config file.""" return download_json_file(config_json, step, rounds, strip_spaces, strip_in_braces, strip_diacritics_chk) def perform_search_and_create_json(start, end, step, rounds, length, tlang, strip_spaces, strip_in_braces, strip_diacritics_chk, gematria_text, date_words_output, average_combine): """Performs the ELS search, creates the JSON config, and displays the results.""" df = perform_els_search(start, end, step, rounds, length, tlang, strip_spaces, strip_in_braces, strip_diacritics_chk, average_combine) search_phrase = f"{date_words_output} {gematria_text}" # Include search phrase in JSON config_json = generate_json_dump(start, end, step, rounds, length, tlang, strip_spaces, strip_in_braces, strip_diacritics_chk, search_phrase, df) return config_json, df date_to_word_btn.click( translate_date_to_words, inputs=[selected_date, date_language_input], outputs=[date_words_output] ) gematria_btn.click( calculate_journal_sum, inputs=[gematria_text, date_words_output], outputs=[gematria_result, step, float_step] # Assign the returned values to the correct outputs ) half_step_btn.click( update_step_half, inputs=[float_step], outputs=[step, float_step] ) double_step_btn.click( update_step_double, inputs=[float_step], outputs=[step, float_step] ) translate_btn.click( perform_search_and_create_json, inputs=[start, end, step, rounds_combination, length, tlang, strip_spaces, strip_in_braces, strip_diacritics_chk, gematria_text, date_words_output, average_combine_chk], outputs=[json_output, markdown_output] ) json_download_btn.click( handle_json_download, inputs=[json_output, step, rounds, strip_spaces, strip_in_braces, strip_diacritics_chk], # Pass rounds to download function outputs=[json_file] ) if __name__ == "__main__": app.launch(share=False)