neuralworm
commited on
Commit
·
769668f
1
Parent(s):
40eb436
initial commit
Browse files- .gitignore +1 -0
- __pycache__/gematria.cpython-310.pyc +0 -0
- app.py +156 -0
- gematria.py +100 -0
- requirements.txt +5 -0
.gitignore
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
__pycache__
|
__pycache__/gematria.cpython-310.pyc
ADDED
Binary file (4.7 kB). View file
|
|
app.py
ADDED
@@ -0,0 +1,156 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import logging
|
2 |
+
logger = logging.getLogger(__name__)
|
3 |
+
logging.basicConfig(level=logging.DEBUG) # Set to DEBUG for detailed output
|
4 |
+
|
5 |
+
import gradio as gr
|
6 |
+
from gradio_calendar import Calendar
|
7 |
+
from gematria import calculate_gematria, strip_diacritics
|
8 |
+
from datetime import datetime, timedelta
|
9 |
+
import json
|
10 |
+
import inflect
|
11 |
+
|
12 |
+
# --- Helper Functions ---
|
13 |
+
def calculate_gematria_sum(text):
|
14 |
+
if text:
|
15 |
+
text_gematria = calculate_gematria(strip_diacritics(text))
|
16 |
+
return text_gematria
|
17 |
+
else:
|
18 |
+
return None
|
19 |
+
|
20 |
+
# Custom function to convert number to ordinal words
|
21 |
+
def number_to_ordinal_word(number):
|
22 |
+
ordinal_dict = {
|
23 |
+
1: "first", 2: "second", 3: "third", 4: "fourth", 5: "fifth",
|
24 |
+
6: "sixth", 7: "seventh", 8: "eighth", 9: "ninth", 10: "tenth",
|
25 |
+
11: "eleventh", 12: "twelfth", 13: "thirteenth", 14: "fourteenth",
|
26 |
+
15: "fifteenth", 16: "sixteenth", 17: "seventeenth", 18: "eighteenth",
|
27 |
+
19: "nineteenth", 20: "twentieth", 21: "twentyfirst", 22: "twentysecond",
|
28 |
+
23: "twentythird", 24: "twentyfourth", 25: "twentyfifth",
|
29 |
+
26: "twentysixth", 27: "twentyseventh", 28: "twentyeighth",
|
30 |
+
29: "twentyninth", 30: "thirtieth", 31: "thirtyfirst"
|
31 |
+
}
|
32 |
+
return ordinal_dict.get(number, "")
|
33 |
+
|
34 |
+
def date_to_words(date_string):
|
35 |
+
"""Converts a date in YYYY-MM-DD format to English words."""
|
36 |
+
inf_engine = inflect.engine()
|
37 |
+
date_obj = datetime.strptime(date_string, "%Y-%m-%d")
|
38 |
+
|
39 |
+
year = date_obj.year
|
40 |
+
if 1100 <= year <= 1999:
|
41 |
+
year_words = f"{inf_engine.number_to_words(year // 100, andword='') } hundred"
|
42 |
+
if year % 100 != 0:
|
43 |
+
year_words += f" {inf_engine.number_to_words(year % 100, andword='')}"
|
44 |
+
else:
|
45 |
+
year_words = inf_engine.number_to_words(year, andword='')
|
46 |
+
year_formatted = year_words.replace(',', '')
|
47 |
+
|
48 |
+
month = date_obj.strftime("%B")
|
49 |
+
day = date_obj.day
|
50 |
+
day_ordinal = number_to_ordinal_word(day)
|
51 |
+
|
52 |
+
output_text = f"{day_ordinal} {month} {year_formatted}"
|
53 |
+
return output_text
|
54 |
+
|
55 |
+
def perform_gematria_calculation_for_date_range(start_date, end_date):
|
56 |
+
logger.debug(f"Calculating date gematria for range: {start_date} - {end_date}")
|
57 |
+
results = {}
|
58 |
+
delta = timedelta(days=1)
|
59 |
+
current_date = start_date
|
60 |
+
|
61 |
+
while current_date <= end_date:
|
62 |
+
date_string = current_date.strftime("%Y-%m-%d")
|
63 |
+
date_words = date_to_words(date_string)
|
64 |
+
date_gematria = calculate_gematria_sum(date_words)
|
65 |
+
|
66 |
+
results[date_string] = {
|
67 |
+
"date_words": date_words,
|
68 |
+
"date_gematria": date_gematria,
|
69 |
+
}
|
70 |
+
current_date += delta
|
71 |
+
logger.debug(f"Finished calculating date gematria.")
|
72 |
+
return results
|
73 |
+
|
74 |
+
|
75 |
+
def find_matching_dates(date_gematrias, names, search_journal_sum):
|
76 |
+
logger.debug(f"Searching for matches with journal sum: {search_journal_sum}")
|
77 |
+
matching_dates = {}
|
78 |
+
|
79 |
+
for name in names:
|
80 |
+
name_gematria = calculate_gematria_sum(name)
|
81 |
+
target_date_gematria = search_journal_sum - name_gematria if name_gematria is not None else None
|
82 |
+
logger.debug(f"Name: {name}, Gematria: {name_gematria}, Target Date Gematria: {target_date_gematria}")
|
83 |
+
|
84 |
+
if target_date_gematria is not None:
|
85 |
+
for date_str, date_data in date_gematrias.items():
|
86 |
+
if date_data["date_gematria"] == target_date_gematria:
|
87 |
+
if name not in matching_dates:
|
88 |
+
matching_dates[name] = []
|
89 |
+
matching_dates[name].append(date_str)
|
90 |
+
logger.debug(f"Matches for {name}: {matching_dates.get(name, [])}")
|
91 |
+
return matching_dates
|
92 |
+
|
93 |
+
|
94 |
+
def find_shared_gematria_dates(date_gematrias, names):
|
95 |
+
"""Finds dates where names share the same journal sum."""
|
96 |
+
logger.debug("Calculating shared gematria dates...")
|
97 |
+
shared_dates = {}
|
98 |
+
name_gematrias = {}
|
99 |
+
|
100 |
+
for name in names:
|
101 |
+
name_gematrias[name] = calculate_gematria_sum(name)
|
102 |
+
|
103 |
+
for date_str, date_data in date_gematrias.items():
|
104 |
+
date_gematria = date_data["date_gematria"]
|
105 |
+
for name1 in names:
|
106 |
+
for name2 in names:
|
107 |
+
if name1 != name2:
|
108 |
+
journal_sum1 = date_gematria + name_gematrias[name1]
|
109 |
+
journal_sum2 = date_gematria + name_gematrias[name2]
|
110 |
+
|
111 |
+
if journal_sum1 == journal_sum2:
|
112 |
+
key = tuple(sorted((name1, name2))) # Create a consistent key regardless of name order
|
113 |
+
if key not in shared_dates:
|
114 |
+
shared_dates[key] = []
|
115 |
+
shared_dates[key].append(date_str)
|
116 |
+
|
117 |
+
logger.debug(f"Shared Gematria Dates: {shared_dates}") # Log the shared dates
|
118 |
+
return shared_dates
|
119 |
+
|
120 |
+
def calculate_and_find(start_date, end_date, names_input, search_journal_sum):
|
121 |
+
names = [n.strip() for n in names_input.split("\n") if n.strip()]
|
122 |
+
date_gematrias = perform_gematria_calculation_for_date_range(start_date, end_date)
|
123 |
+
matching_dates = find_matching_dates(date_gematrias, names, int(search_journal_sum))
|
124 |
+
shared_gematria_dates = find_shared_gematria_dates(date_gematrias, names)
|
125 |
+
|
126 |
+
return (
|
127 |
+
json.dumps(matching_dates, indent=4, ensure_ascii=False),
|
128 |
+
json.dumps(date_gematrias, indent=4, ensure_ascii=False), # Keep this for debugging if needed
|
129 |
+
json.dumps(shared_gematria_dates, indent=4, ensure_ascii=False)
|
130 |
+
)
|
131 |
+
|
132 |
+
|
133 |
+
# --- Main Gradio App ---
|
134 |
+
with gr.Blocks() as app:
|
135 |
+
with gr.Row():
|
136 |
+
start_date = Calendar(type="datetime", label="Start Date")
|
137 |
+
end_date = Calendar(type="datetime", label="End Date")
|
138 |
+
with gr.Row():
|
139 |
+
names_input = gr.Textbox(label="Names (one per line)", lines=5) # Multiline input
|
140 |
+
search_sum = gr.Number(label="Search Journal Sum", precision=0)
|
141 |
+
|
142 |
+
calculate_btn = gr.Button("Calculate")
|
143 |
+
with gr.Row():
|
144 |
+
matching_dates_output = gr.JSON(label="Matching Dates")
|
145 |
+
shared_dates_output = gr.JSON(label="Shared Gematria Dates") # New output component
|
146 |
+
json_output = gr.JSON(label="Complete Results (for debugging)")
|
147 |
+
|
148 |
+
|
149 |
+
calculate_btn.click(
|
150 |
+
calculate_and_find,
|
151 |
+
inputs=[start_date, end_date, names_input, search_sum],
|
152 |
+
outputs=[matching_dates_output, json_output, shared_dates_output] # Added shared_dates_output
|
153 |
+
)
|
154 |
+
|
155 |
+
if __name__ == "__main__":
|
156 |
+
app.launch(share=False)
|
gematria.py
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import unicodedata
|
2 |
+
import logging
|
3 |
+
|
4 |
+
logger = logging.getLogger(__name__)
|
5 |
+
|
6 |
+
def strip_diacritics(text):
|
7 |
+
"""
|
8 |
+
Entfernt Diakritika von Unicode-Zeichen, um den Basisbuchstaben zu erhalten, und gibt Warnungen
|
9 |
+
für tatsächlich unbekannte Zeichen aus.
|
10 |
+
"""
|
11 |
+
stripped_text = ''
|
12 |
+
for char in unicodedata.normalize('NFD', text):
|
13 |
+
if unicodedata.category(char) not in ['Mn', 'Cf']:
|
14 |
+
stripped_text += char
|
15 |
+
else:
|
16 |
+
logger.debug(f"Info: Diakritisches Zeichen '{char}' wird ignoriert.")
|
17 |
+
return stripped_text
|
18 |
+
|
19 |
+
def letter_to_value(letter):
|
20 |
+
"""
|
21 |
+
Konvertiert einen einzelnen Buchstaben in seinen Gematria-Wert, ignoriert Leerzeichen
|
22 |
+
und Nicht-Buchstaben-Zeichen.
|
23 |
+
"""
|
24 |
+
# Dein vorhandenes Wörterbuch bleibt unverändert
|
25 |
+
values = {
|
26 |
+
# Lateinische Buchstaben
|
27 |
+
'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 600,
|
28 |
+
'k': 10, 'l': 20, 'm': 30, 'n': 40, 'o': 50, 'p': 60, 'q': 70, 'r': 80, 's': 90,
|
29 |
+
't': 100, 'u': 200, 'v': 700, 'w': 900, 'x': 300, 'y': 400, 'z': 500,
|
30 |
+
|
31 |
+
'A': 1, 'B': 2, 'C': 3, 'D': 4, 'E': 5, 'F': 6, 'G': 7, 'H': 8, 'I': 9, 'J': 600,
|
32 |
+
'K': 10, 'L': 20, 'M': 30, 'N': 40, 'O': 50, 'P': 60, 'Q': 70, 'R': 80, 'S': 90,
|
33 |
+
'T': 100, 'U': 200, 'V': 700, 'W': 900, 'X': 300, 'Y': 400, 'Z': 500,
|
34 |
+
|
35 |
+
# Basisbuchstaben und einige bereits genannte Varianten
|
36 |
+
'ا': 1, 'أ': 1, 'إ': 1, 'آ': 1, 'ب': 2, 'ج': 3, 'د': 4, 'ه': 5, 'و': 6, 'ز': 7, 'ح': 8, 'ط': 9,
|
37 |
+
'ي': 10, 'ى': 10, 'ك': 20, 'ک': 20, 'ل': 30, 'م': 40, 'ن': 50, 'س': 60, 'ع': 70, 'ف': 80,
|
38 |
+
'ص': 90, 'ق': 100, 'ر': 200, 'ش': 300, 'ت': 400, 'ث': 500, 'خ': 600, 'ذ': 700, 'ض': 800, 'ظ': 900, 'غ': 1000,
|
39 |
+
'ٱ': 1, # Alif Wasla
|
40 |
+
'ـ': 0, # Tatweel
|
41 |
+
|
42 |
+
# Zusätzliche Varianten und Sonderzeichen
|
43 |
+
'ة': 400, # Taa Marbuta
|
44 |
+
'ؤ': 6, # Waw mit Hamza darüber
|
45 |
+
'ئ': 10, # Ya mit Hamza darüber
|
46 |
+
'ء': 1, # Hamza
|
47 |
+
'ى': 10, # Alif Maqsurah
|
48 |
+
'ٹ': 400, # Taa' marbuta goal
|
49 |
+
'پ': 2, # Pe (Persisch/Urdu)
|
50 |
+
'چ': 3, # Che (Persisch/Urdu)
|
51 |
+
'ژ': 7, # Zhe (Persisch/Urdu)
|
52 |
+
'گ': 20, # Gaf (Persisch/Urdu)
|
53 |
+
'ڭ': 20, # Ngaf (Kazakh, Uyghur, Uzbek, and in some Arabic dialects)
|
54 |
+
'ں': 50, # Noon Ghunna (Persisch/Urdu)
|
55 |
+
'ۀ': 5, # Heh with Yeh above (Persisch/Urdu)
|
56 |
+
'ے': 10, # Barree Yeh (Persisch/Urdu)
|
57 |
+
'؋': 0, # Afghani Sign (wird als Währungssymbol verwendet, nicht für Gematria relevant, aber hier zur Vollständigkeit aufgeführt)
|
58 |
+
|
59 |
+
# Anmerkung: Das Währungssymbol und ähnliche Zeichen sind in einem Gematria-Kontext normalerweise nicht relevant,
|
60 |
+
# werden aber der Vollständigkeit halber aufgeführt. Es gibt noch viele weitere spezifische Zeichen in erweiterten
|
61 |
+
# arabischen Schriftsystemen (z.B. für andere Sprachen wie Persisch, Urdu, Pashto usw.), die hier nicht vollständig
|
62 |
+
# abgedeckt sind.
|
63 |
+
|
64 |
+
# Grund- und Schlussformen hebräischer Buchstaben
|
65 |
+
|
66 |
+
'א': 1, 'ב': 2, 'ג': 3, 'ד': 4, 'ה': 5, 'ו': 6, 'ז': 7, 'ח': 8, 'ט': 9, 'י': 10,
|
67 |
+
'כ': 20, 'ך': 500, 'ל': 30, 'מ': 40, 'ם': 600, 'נ': 50, 'ן': 700, 'ס': 60, 'ע': 70, 'פ': 80, 'ף': 800,
|
68 |
+
'צ': 90, 'ץ': 900, 'ק': 100, 'ר': 200, 'ש': 300, 'ת': 400,
|
69 |
+
|
70 |
+
# Griechische Buchstaben
|
71 |
+
'α': 1, 'β': 2, 'γ': 3, 'δ': 4, 'ε': 5, 'ϝ': 6, 'ζ': 7, 'η': 8, 'θ': 9, 'ι': 10,
|
72 |
+
'κ': 20, 'λ': 30, 'μ': 40, 'ν': 50, 'ξ': 60, 'ο': 70, 'π': 80, 'ϟ': 90, 'ρ': 100,
|
73 |
+
'σ': 200, 'τ': 300, 'υ': 400, 'φ': 500, 'χ': 600, 'ψ': 700, 'ω': 800, 'ϡ': 900,
|
74 |
+
|
75 |
+
# Griechische Großbuchstaben
|
76 |
+
'Α': 1, 'Β': 2, 'Γ': 3, 'Δ': 4, 'Ε': 5, 'Ϝ': 6, 'Ζ': 7, 'Η': 8, 'Θ': 9, 'Ι': 10,
|
77 |
+
'Κ': 20, 'Λ': 30, 'Μ': 40, 'Ν': 50, 'Ξ': 60, 'Ο': 70, 'Π': 80, 'Ϟ': 90, 'Ρ': 100,
|
78 |
+
'Σ': 200, 'Τ': 300, 'Υ': 400, 'Φ': 500, 'Χ': 600, 'Ψ': 700, 'Ω': 800, 'Ϡ': 900,
|
79 |
+
'σ': 200, # Sigma
|
80 |
+
'ς': 200, # Final Sigma
|
81 |
+
'ϲ': 200, # Lunate Sigma (Greek)
|
82 |
+
'Ϲ': 200, # Uppercase Lunate Sigma (Greek)
|
83 |
+
}
|
84 |
+
|
85 |
+
# Stelle sicher, dass Diakritika entfernt werden, bevor auf das Wörterbuch zugegriffen wird
|
86 |
+
letter_no_diacritics = strip_diacritics(letter)
|
87 |
+
|
88 |
+
if letter_no_diacritics in values:
|
89 |
+
return values[letter_no_diacritics.lower()]
|
90 |
+
elif letter.strip() == "": # Ignoriere Leerzeichen und leere Zeilen
|
91 |
+
return 0
|
92 |
+
else:
|
93 |
+
# Gib eine spezifische Warnung aus, wenn das Zeichen unbekannt ist
|
94 |
+
logger.debug(f"Warnung: Unbekanntes Zeichen '{letter}' ignoriert.")
|
95 |
+
return 0
|
96 |
+
|
97 |
+
|
98 |
+
def calculate_gematria(text):
|
99 |
+
"""Calculate the Gematria value of a given Hebrew text, ignoring spaces and non-Hebrew characters."""
|
100 |
+
return sum(letter_to_value(letter) for letter in text if letter.strip() != "")
|
requirements.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#fastapi==0.112.3
|
2 |
+
#gradio==4.31.0
|
3 |
+
deep_translator==1.11.4
|
4 |
+
gradio_calendar==0.0.4
|
5 |
+
inflect==7.2.1
|