neuralworm commited on
Commit
ccf23f2
·
1 Parent(s): 606dcc8

results structure

Browse files
Files changed (1) hide show
  1. app.py +313 -311
app.py CHANGED
@@ -28,6 +28,7 @@ from typing import List, Tuple
28
  import calendar
29
  import translation_utils
30
  import hashlib
 
31
 
32
  translation_utils.create_translation_table()
33
 
@@ -743,91 +744,22 @@ with gr.Blocks() as app:
743
  outputs=[search_term_els, gematria_sum_search_els]
744
  )
745
 
746
- # Hauptfunktion für den vierten Tab
747
- def perform_date_range_els_search(start_date, end_date, names_input, search_type, search_term, gematria_sum_search, search_mode, include_torah, include_bible, include_quran, include_hindu, include_tripitaka, translate_results, sub_oscillation_search, sub_oscillation_level):
748
- names = [n.strip() for n in names_input.split("\n") if n.strip()]
749
- date_gematrias = perform_gematria_calculation_for_date_range(start_date, end_date)
750
- search_term = strip_diacritics(search_term)
751
- # Zwischenergebnisse mit Datum, Namen und Gematria-Summe speichern
752
- intermediate_results = []
753
- for date_str, date_data in date_gematrias.items():
754
- for name in names:
755
- name_gematria = calculate_gematria_sum(name, "")
756
- combined_gematria_sum = date_data["date_gematria"] + name_gematria
757
- intermediate_results.append(
758
- {"date": date_str, "name": name, "gematria_sum": combined_gematria_sum}
759
- )
760
-
761
- # Ergebnisse nach Datum sortieren
762
- intermediate_results.sort(key=lambda x: x["date"])
763
-
764
- all_results = []
765
- for intermediate_result in intermediate_results:
766
- date_str = intermediate_result["date"]
767
- name = intermediate_result["name"]
768
- initial_gematria_sum = intermediate_result["gematria_sum"]
769
-
770
- # Basis-Suche durchführen
771
- base_results = perform_els_search_for_gematria_sum(
772
- initial_gematria_sum, include_torah, include_bible, include_quran, include_hindu, include_tripitaka
773
- )
774
-
775
- # Nur ausgewählte Bücher für die Sub-Oszillationen-Suche berücksichtigen
776
- selected_books_results = {}
777
- if include_torah:
778
- selected_books_results["Torah"] = base_results.get("Torah", [])
779
- if include_bible:
780
- selected_books_results["Bible"] = base_results.get("Bible", [])
781
- if include_quran:
782
- selected_books_results["Quran"] = base_results.get("Quran", [])
783
- if include_hindu:
784
- selected_books_results["Rig Veda"] = base_results.get("Rig Veda", [])
785
- if include_tripitaka:
786
- selected_books_results["Tripitaka"] = base_results.get("Tripitaka", [])
787
-
788
- # Speichere die base_results in einer Liste
789
- base_results_list = []
790
- for book_name, book_results in selected_books_results.items():
791
- for result in book_results:
792
- base_results_list.append({'book': book_name, 'result': result})
793
-
794
- # Sub-Oszillationen-Suche, falls aktiviert und Level > 0
795
- if sub_oscillation_search and sub_oscillation_level > 0:
796
- base_results_list = perform_sub_oscillation_search(
797
- base_results_list, initial_gematria_sum, sub_oscillation_level,
798
- include_torah, include_bible, include_quran, include_hindu, include_tripitaka
799
- )
800
-
801
- # Umwandlung der erweiterten base_results_list in base_results
802
- base_results = {}
803
- for result_entry in base_results_list:
804
- book_name = result_entry['book']
805
- if book_name not in base_results:
806
- base_results[book_name] = []
807
- base_results[book_name].append(result_entry['result'])
808
-
809
- # Filterung und Hinzufügen der Ergebnisse zu all_results
810
- filtered_results = filter_and_format_results(
811
- base_results, search_type, search_term, gematria_sum_search,
812
- search_mode, date_str, name, initial_gematria_sum, sub_oscillation_level, base_results_list
813
- )
814
- all_results.extend(filtered_results)
815
-
816
- # Übersetzung der Ergebnisse, falls angefordert
817
- if translate_results:
818
- for result_entry in all_results:
819
- try:
820
- text_to_translate = result_entry["result"]["result_text"]
821
- source_lang = result_entry["result"].get("source_language", "auto")
822
- translated_text = translation_utils.get_translation(text_to_translate, "en", source_lang)[0]
823
- result_entry["result"]["translated_text"] = translated_text
824
- except KeyError as e:
825
- logger.error(f"KeyError translating result_text: {e}")
826
-
827
- return all_results
828
-
829
- # Hilfsfunktion zum Durchführen der ELS-Suche für eine gegebene Gematria-Summe
830
- def perform_els_search_for_gematria_sum(gematria_sum, include_torah, include_bible, include_quran, include_hindu, include_tripitaka):
831
  return perform_els_search(
832
  step=gematria_sum,
833
  rounds_combination="1,-1",
@@ -842,261 +774,331 @@ with gr.Blocks() as app:
842
  include_tripitaka=include_tripitaka
843
  )
844
 
845
- # Hilfsfunktion zum Filtern und Formatieren der Ergebnisse
846
- def filter_and_format_results(results, search_type, search_term, gematria_sum_search, search_mode, date_str, name, initial_gematria_sum, sub_oscillation_level, base_results_list):
847
- search_term=strip_diacritics(search_term)
848
- filtered_results = []
849
- for book_name, book_results in results.items():
850
- if book_results:
851
- for result in book_results:
852
- try:
853
- result_text = result['result_text']
854
- result_sum = result['result_sum']
855
-
856
- # Finde die verwendete Sub-Oszillation heraus
857
- sub_oscillation_sums = []
858
- current_gematria_sum = initial_gematria_sum
859
-
860
- if sub_oscillation_level > 0:
861
- for i in range(1, sub_oscillation_level + 1):
862
- for base_result_entry_tuple in base_results_list:
863
- base_result_entry = dict(base_result_entry_tuple)
864
- if result.get('result_sum') == base_result_entry['result'].get('result_sum') and result.get('result_text') == base_result_entry['result'].get('result_text'):
865
- sub_gematria_sum = base_result_entry.get('sub_gematria_sum')
866
- if sub_gematria_sum:
867
- sub_oscillation_sums.append(sub_gematria_sum)
868
- current_gematria_sum += sub_gematria_sum
869
- break # Innere Schleife beenden, da das passende Ergebnis gefunden wurde
870
- else:
871
- continue # Äußere Schleife fortsetzen, wenn kein passendes Ergebnis gefunden wurde
872
- break
873
-
874
- # Sub-Oszillation Summen an den Namen anhängen
875
- sub_oscillation_text = ""
876
- if sub_oscillation_sums:
877
- sub_oscillation_text = " + " + " + ".join(map(str, sub_oscillation_sums))
878
-
879
- # Filtern der Ergebnisse
880
- if search_type == "Text in result_text":
881
- if search_mode == "Exact Search" and search_term == result_text:
882
- filtered_results.append(
883
- {
884
- "date": date_str,
885
- "name": f"{name}{sub_oscillation_text}",
886
- "gematria_sum": current_gematria_sum,
887
- "book": book_name,
888
- "result": result
889
- }
890
- )
891
- elif search_mode == "Contains Word" and search_term in result_text:
892
- filtered_results.append(
893
- {
894
- "date": date_str,
895
- "name": f"{name}{sub_oscillation_text}",
896
- "gematria_sum": current_gematria_sum,
897
- "book": book_name,
898
- "result": result
899
- }
900
- )
901
- elif search_type == "Gematria Sum in results":
902
- if result_sum == gematria_sum_search:
903
- filtered_results.append(
904
- {
905
- "date": date_str,
906
- "name": f"{name}{sub_oscillation_text}",
907
- "gematria_sum": current_gematria_sum,
908
- "book": book_name,
909
- "result": result
910
- }
911
- )
912
- except KeyError as e:
913
- logger.error(f"KeyError - Key '{e.args[0]}' not found in result. Skipping this result.")
914
- continue
915
- return filtered_results
916
-
917
- def perform_date_range_els_search(start_date, end_date, names_input, search_type, search_term, gematria_sum_search, search_mode, include_torah, include_bible, include_quran, include_hindu, include_tripitaka, translate_results, sub_oscillation_search, sub_oscillation_level):
918
- names = [n.strip() for n in names_input.split("\n") if n.strip()]
919
- date_gematrias = perform_gematria_calculation_for_date_range(start_date, end_date)
920
 
921
- # Zwischenergebnisse mit Datum, Namen und Gematria-Summe speichern
922
- intermediate_results = []
923
- for date_str, date_data in date_gematrias.items():
924
- for name in names:
925
- name_gematria = calculate_gematria_sum(name, "")
926
- combined_gematria_sum = date_data["date_gematria"] + name_gematria
927
- intermediate_results.append(
928
- {"date": date_str, "name": name, "gematria_sum": combined_gematria_sum}
929
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
930
 
931
- # Ergebnisse nach Datum sortieren
932
- intermediate_results.sort(key=lambda x: x["date"])
933
 
934
- all_results = []
935
- for intermediate_result in intermediate_results:
936
- date_str = intermediate_result["date"]
937
- name = intermediate_result["name"]
938
- initial_gematria_sum = intermediate_result["gematria_sum"]
 
 
 
 
 
 
 
 
939
 
940
- # Basis-Suche durchführen
941
- base_results = perform_els_search_for_gematria_sum(
942
- initial_gematria_sum, include_torah, include_bible, include_quran, include_hindu, include_tripitaka
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
943
  )
944
 
945
- # Nur ausgewählte Bücher für die Sub-Oszillationen-Suche berücksichtigen
946
- selected_books_results = {}
947
- if include_torah:
948
- selected_books_results["Torah"] = base_results.get("Torah", [])
949
- if include_bible:
950
- selected_books_results["Bible"] = base_results.get("Bible", [])
951
- if include_quran:
952
- selected_books_results["Quran"] = base_results.get("Quran", [])
953
- if include_hindu:
954
- selected_books_results["Rig Veda"] = base_results.get("Rig Veda", [])
955
- if include_tripitaka:
956
- selected_books_results["Tripitaka"] = base_results.get("Tripitaka", [])
957
-
958
- # Speichere die base_results in einer Liste von Tupeln
959
- base_results_list = []
960
- for book_name, book_results in selected_books_results.items():
961
- for result in book_results:
962
- base_results_list.append(tuple(sorted({'book': book_name, 'result': result}.items())))
963
-
964
- # Sub-Oszillationen-Suche, falls aktiviert und Level > 0
965
- if sub_oscillation_search and sub_oscillation_level > 0:
966
- base_results_list = perform_sub_oscillation_search(
967
- base_results_list, initial_gematria_sum, sub_oscillation_level,
968
- include_torah, include_bible, include_quran, include_hindu, include_tripitaka
969
- )
 
 
 
 
 
 
970
 
971
- # Umwandlung der erweiterten base_results_list in base_results
972
- base_results = {}
973
- for result_entry_tuple in base_results_list:
974
- result_entry = dict(result_entry_tuple) # Konvertiere zurück zu Dictionary
975
- book_name = result_entry['book']
976
- if book_name not in base_results:
977
- base_results[book_name] = []
978
- base_results[book_name].append(result_entry['result'])
979
-
980
- # Filterung und Hinzufügen der Ergebnisse zu all_results
981
- filtered_results = filter_and_format_results(
982
- base_results, search_type, search_term, gematria_sum_search,
983
- search_mode, date_str, name, initial_gematria_sum, sub_oscillation_level, base_results_list
 
 
 
 
 
 
 
984
  )
985
- all_results.extend(filtered_results)
986
 
987
- # Übersetzung der Ergebnisse, falls angefordert
988
- if translate_results:
989
- for result_entry in all_results:
990
- try:
991
- text_to_translate = result_entry["result"]["result_text"]
992
- source_lang = result_entry["result"].get("source_language", "auto")
993
- translated_text = translation_utils.get_translation(text_to_translate, "en", source_lang)[0]
994
- result_entry["result"]["translated_text"] = translated_text
995
- except KeyError as e:
996
- logger.error(f"KeyError translating result_text: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
997
 
998
- return all_results
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
999
 
1000
  def remove_duplicates(dict_list):
1001
  """
1002
- Entfernt Duplikate aus dict_list, basierend auf einer ID (repr).
1003
- dict_list: Liste aus Dictionaries (oder Tupeln),
1004
- in denen wir Duplikate filtern wollen.
1005
  """
1006
  seen = set()
1007
  unique_list = []
1008
  for item in dict_list:
1009
- # Hier legen wir fest, was item sein kann:
1010
- # - typischerweise ein dict: {'book':..., 'result':...}
1011
- # - oder ein tuple, das wir ggf. in dict umwandeln
1012
-
1013
- # Mache item zu einem Dictionary, falls es ein tuple ist
1014
- if isinstance(item, tuple):
1015
- item = dict(item)
1016
- # => Jetzt haben wir item als Dictionary
1017
-
1018
- # Erstelle eine ID; repr(item) enthält Keys und Values
1019
- # Wenn du es feingranular willst, kannst du stattdessen
1020
- # nur bestimmte Felder rausziehen, z.B. (book, result_sum, result_text)
1021
  item_id = repr(item)
1022
-
1023
  if item_id not in seen:
1024
  seen.add(item_id)
1025
  unique_list.append(item)
1026
-
1027
  return unique_list
1028
 
1029
 
1030
- def perform_sub_oscillation_search(base_results_list, initial_gematria_sum, level,
1031
- include_torah, include_bible, include_quran,
1032
- include_hindu, include_tripitaka):
1033
- """
1034
- Führt 'level' Sub-Oszillationsrunden durch und
1035
- hängt neu entstehende Ergebnisse an base_results_list an.
1036
- Verwendet remove_duplicates, um Dopplungen zu vermeiden.
1037
- """
1038
- if level == 0:
1039
- return base_results_list
1040
-
1041
- # Mache base_results_list komplett zu Dicts
1042
- # (falls es Tupel gibt, wandeln wir die hier in Dicts):
1043
- dict_list = []
1044
- for entry in base_results_list:
1045
- if isinstance(entry, tuple):
1046
- dict_list.append(dict(entry))
1047
- elif isinstance(entry, dict):
1048
- dict_list.append(entry)
1049
- else:
1050
- dict_list.append({"unknown": entry})
1051
-
1052
- new_results = []
1053
- # Erzeuge in diesem Durchgang neue Einträge
1054
- for base_entry in dict_list:
1055
- sub_gematria_sum = base_entry['result']['result_sum']
1056
- combined_sub_gematria_sum = initial_gematria_sum + sub_gematria_sum
1057
-
1058
- sub_results = perform_els_search_for_gematria_sum(
1059
- combined_sub_gematria_sum,
1060
- include_torah, include_bible, include_quran, include_hindu, include_tripitaka
1061
- )
1062
-
1063
- # Für jedes gefundene sub_result => new_entry
1064
- for book_name, book_list in sub_results.items():
1065
- for res in book_list:
1066
- new_entry = {
1067
- 'book': book_name,
1068
- 'result': res,
1069
- # speichere optional sub_gematria_sum
1070
- 'sub_gematria_sum': sub_gematria_sum
1071
- }
1072
- new_results.append(new_entry)
1073
-
1074
- # Kombiniere Originaldaten + neue Daten
1075
- combined = dict_list + new_results
1076
-
1077
- # Entferne Duplikate
1078
- combined_no_dupes = remove_duplicates(combined)
1079
-
1080
- # Rekursion: ein Level tiefer
1081
- return perform_sub_oscillation_search(
1082
- combined_no_dupes,
1083
- initial_gematria_sum,
1084
- level - 1,
1085
- include_torah,
1086
- include_bible,
1087
- include_quran,
1088
- include_hindu,
1089
- include_tripitaka
1090
- )
1091
-
1092
  perform_search_btn_els.click(
1093
  perform_date_range_els_search,
1094
- inputs=[start_date_els, end_date_els, names_input_els, search_type_els, search_term_els, gematria_sum_search_els, search_mode_els, include_torah_chk_els, include_bible_chk_els, include_quran_chk_els, include_hindu_chk_els, include_tripitaka_chk_els, translate_results_chk_els, sub_oscillation_search_chk_els, sub_oscillation_level_els],
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1095
  outputs=[filtered_results_output_els]
1096
  )
1097
 
1098
-
1099
-
1100
  # --- Event Handlers ---
1101
 
1102
  search_type.change(
 
28
  import calendar
29
  import translation_utils
30
  import hashlib
31
+ import copy
32
 
33
  translation_utils.create_translation_table()
34
 
 
744
  outputs=[search_term_els, gematria_sum_search_els]
745
  )
746
 
747
+ def perform_els_search_for_gematria_sum(
748
+ gematria_sum,
749
+ include_torah,
750
+ include_bible,
751
+ include_quran,
752
+ include_hindu,
753
+ include_tripitaka
754
+ ):
755
+ """
756
+ Calls your actual ELS search function, returning a dict like:
757
+ {
758
+ "Torah": [ { "result_sum": ..., "result_text": ..., "source_language": ...}, ...],
759
+ "Bible": [...],
760
+ ...
761
+ }
762
+ """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
763
  return perform_els_search(
764
  step=gematria_sum,
765
  rounds_combination="1,-1",
 
774
  include_tripitaka=include_tripitaka
775
  )
776
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
777
 
778
+ def perform_sub_oscillation_search(
779
+ base_results_list,
780
+ initial_gematria_sum,
781
+ level,
782
+ include_torah,
783
+ include_bible,
784
+ include_quran,
785
+ include_hindu,
786
+ include_tripitaka
787
+ ):
788
+ """
789
+ Recursively populates 'subresults' for each base entry, up to the specified level.
790
+ base_results_list: A list of dicts, each shaped like:
791
+ {
792
+ "book": "Torah",
793
+ "result": {
794
+ "result_sum": ...,
795
+ "result_text": ...
796
+ },
797
+ "subresults": []
798
+ }
799
+ initial_gematria_sum: The base sum from day+name (or from prior recursion).
800
+ level: how many sub-levels we still want to descend.
801
+ include_XXX: booleans for controlling which texts to include.
802
+ """
803
 
804
+ if level <= 0:
805
+ return base_results_list
806
 
807
+ for base_entry in base_results_list:
808
+ parent_sum = base_entry["result"]["result_sum"]
809
+ combined_sum = initial_gematria_sum + parent_sum
810
+
811
+ # Next-level search
812
+ sub_search_results = perform_els_search_for_gematria_sum(
813
+ gematria_sum=combined_sum,
814
+ include_torah=include_torah,
815
+ include_bible=include_bible,
816
+ include_quran=include_quran,
817
+ include_hindu=include_hindu,
818
+ include_tripitaka=include_tripitaka
819
+ )
820
 
821
+ # Build child entries
822
+ child_entries = []
823
+ for book_name, res_list in sub_search_results.items():
824
+ for one_res in res_list:
825
+ child_entries.append({
826
+ "book": book_name,
827
+ "result": one_res,
828
+ "subresults": []
829
+ })
830
+
831
+ # Attach to subresults
832
+ base_entry["subresults"].extend(child_entries)
833
+
834
+ # Recurse deeper
835
+ perform_sub_oscillation_search(
836
+ base_entry["subresults"],
837
+ initial_gematria_sum,
838
+ level - 1,
839
+ include_torah,
840
+ include_bible,
841
+ include_quran,
842
+ include_hindu,
843
+ include_tripitaka
844
  )
845
 
846
+ return base_results_list
847
+
848
+
849
+ def matches_criteria(item, search_type, search_term, gematria_sum_search, search_mode):
850
+ """
851
+ Checks if a single item (a dict with 'result_text', 'result_sum', etc.)
852
+ matches the user’s chosen filter criteria.
853
+
854
+ item shape example:
855
+ {
856
+ "book": "Torah",
857
+ "result": {
858
+ "result_text": "foo bar",
859
+ "result_sum": 1234,
860
+ ...
861
+ },
862
+ "subresults": [ ... ]
863
+ }
864
+ """
865
+ result_text = item["result"].get("result_text", "")
866
+ result_sum = item["result"].get("result_sum", None)
867
+
868
+ if search_type == "Text in result_text":
869
+ if search_mode == "Exact Search":
870
+ return (result_text == search_term)
871
+ else: # "Contains Word"
872
+ return (search_term in result_text)
873
+ else:
874
+ # search_type == "Gematria Sum in results"
875
+ return (result_sum == gematria_sum_search)
876
+
877
 
878
+ def prune_tree_by_search_criteria(results_list, search_type, search_term, gematria_sum_search, search_mode):
879
+ """
880
+ Recursively filters a list of items so that:
881
+ - An item is included if it directly matches the search criteria,
882
+ OR if any of its child subresults match (in which case we keep
883
+ the item *and* the matching children).
884
+ - This preserves parent chain for matching subresults.
885
+
886
+ returns a new, pruned list of items with the same nested structure,
887
+ but only containing the branches that match or lead to a match.
888
+ """
889
+ pruned_list = []
890
+ for item in results_list:
891
+ # Recurse into subresults first
892
+ pruned_sub = prune_tree_by_search_criteria(
893
+ item["subresults"],
894
+ search_type,
895
+ search_term,
896
+ gematria_sum_search,
897
+ search_mode
898
  )
899
+ does_item_match = matches_criteria(item, search_type, search_term, gematria_sum_search, search_mode)
900
 
901
+ # If the item itself matches OR any child matches
902
+ if does_item_match or len(pruned_sub) > 0:
903
+ # Make a copy of the item so we don't destroy the original
904
+ new_item = copy.deepcopy(item)
905
+ # Overwrite subresults with the pruned version
906
+ new_item["subresults"] = pruned_sub
907
+ pruned_list.append(new_item)
908
+
909
+ return pruned_list
910
+
911
+
912
+
913
+ def translate_subresults_recursive(subresults_list):
914
+ """
915
+ Recursively translates the 'result_text' of each item in subresults_list.
916
+ We only visit items that remain in the filtered results.
917
+ """
918
+ for sub_item in subresults_list:
919
+ text = sub_item["result"].get("result_text", "")
920
+ source_lang = sub_item["result"].get("source_language", "auto")
921
+ if text:
922
+ translated_text = translation_utils.get_translation(text, "en", source_lang)[0]
923
+ sub_item["result"]["translated_text"] = translated_text
924
+
925
+ # Recurse into deeper subresults
926
+ if sub_item["subresults"]:
927
+ translate_subresults_recursive(sub_item["subresults"])
928
+
929
+ def perform_date_range_els_search(
930
+ start_date,
931
+ end_date,
932
+ names_input,
933
+ search_type,
934
+ search_term,
935
+ gematria_sum_search,
936
+ search_mode,
937
+ include_torah,
938
+ include_bible,
939
+ include_quran,
940
+ include_hindu,
941
+ include_tripitaka,
942
+ translate_results,
943
+ sub_oscillation_search,
944
+ sub_oscillation_level
945
+ ):
946
+ """
947
+ - Builds a fully nested sub-oscillation structure if requested.
948
+ - Then prunes it so only matching items remain (plus parents).
949
+ - Finally, optionally translates the pruned items if requested.
950
+ - Returns the filtered (and optionally translated) structure.
951
+ """
952
+ # 1) Compute gematria sums for all dates in the chosen range
953
+ names = [n.strip() for n in names_input.split("\n") if n.strip()]
954
+ date_gematrias = perform_gematria_calculation_for_date_range(start_date, end_date)
955
 
956
+ all_filtered_results = []
957
+
958
+ # 2) Loop over each date
959
+ for date_str, date_data in date_gematrias.items():
960
+ for name in names:
961
+ # base sum: day gematria + name gematria
962
+ name_gem = calculate_gematria_sum(name, "")
963
+ initial_gem = date_data["date_gematria"] + name_gem
964
+ date_words = date_data["date_words"]
965
+ search_path_basic = f"{name} {date_words}"
966
+
967
+ # 3) Do the base ELS search (this is the top-level results)
968
+ base_results = perform_els_search_for_gematria_sum(
969
+ gematria_sum=initial_gem,
970
+ include_torah=include_torah,
971
+ include_bible=include_bible,
972
+ include_quran=include_quran,
973
+ include_hindu=include_hindu,
974
+ include_tripitaka=include_tripitaka
975
+ )
976
+
977
+ # 4) Convert "base_results" into a uniform nested format
978
+ # shaped like { "0": {"book":..., "results": [ {...}, ... ]}, ... }
979
+ formatted_base_results = {}
980
+ idx_counter = 0
981
+ for book_name, book_res_list in base_results.items():
982
+ if book_res_list:
983
+ formatted_base_results[str(idx_counter)] = {
984
+ "book": book_name,
985
+ "results": []
986
+ }
987
+ for res in book_res_list:
988
+ formatted_base_results[str(idx_counter)]["results"].append({
989
+ "book": book_name,
990
+ "result": res,
991
+ "subresults": []
992
+ })
993
+ idx_counter += 1
994
+
995
+ # 5) Flatten out for sub-osc recursion
996
+ base_results_list = []
997
+ for val in formatted_base_results.values():
998
+ base_results_list.extend(val["results"])
999
+
1000
+ # 6) If sub-oscillation is requested, build deeper levels
1001
+ if sub_oscillation_search and sub_oscillation_level > 0 and base_results_list:
1002
+ perform_sub_oscillation_search(
1003
+ base_results_list,
1004
+ initial_gem,
1005
+ sub_oscillation_level,
1006
+ include_torah,
1007
+ include_bible,
1008
+ include_quran,
1009
+ include_hindu,
1010
+ include_tripitaka
1011
+ )
1012
+
1013
+ # 7) Now we prune (filter) the results according to the user’s search criteria
1014
+ # For each "book" block, we filter the "results" array
1015
+ pruned_base_results = {}
1016
+ for key, block in formatted_base_results.items():
1017
+ original_list = block["results"] # each is {book, result, subresults}
1018
+ filtered_list = prune_tree_by_search_criteria(
1019
+ original_list,
1020
+ search_type,
1021
+ search_term,
1022
+ gematria_sum_search,
1023
+ search_mode
1024
+ )
1025
+ # Keep only if we got something back
1026
+ if filtered_list:
1027
+ pruned_base_results[key] = {
1028
+ "book": block["book"],
1029
+ "results": filtered_list
1030
+ }
1031
+
1032
+ # If there’s nothing left after filtering, skip adding
1033
+ if not pruned_base_results:
1034
+ continue
1035
+
1036
+ # 8) Build the final item for this date+name, with pruned results
1037
+ final_item = {
1038
+ "date": date_str,
1039
+ "name": name,
1040
+ "search_path_basic": search_path_basic,
1041
+ "basic_gematria": initial_gem,
1042
+ "basic_results": pruned_base_results
1043
+ }
1044
+
1045
+ # 9) If translation is requested, only translate the pruned results
1046
+ if translate_results:
1047
+ # Recursively translate only the items in pruned_base_results
1048
+ for block_key, block_val in final_item["basic_results"].items():
1049
+ for entry in block_val["results"]:
1050
+ txt = entry["result"].get("result_text", "")
1051
+ src_lang = entry["result"].get("source_language", "auto")
1052
+ if txt:
1053
+ trans = translation_utils.get_translation(txt, "en", src_lang)[0]
1054
+ entry["result"]["translated_text"] = trans
1055
+ # And go deeper into subresults
1056
+ if entry["subresults"]:
1057
+ translate_subresults_recursive(entry["subresults"])
1058
+
1059
+ # 10) Add this final, fully filtered (and possibly translated) item
1060
+ all_filtered_results.append(final_item)
1061
+
1062
+ # Return the fully processed set of results
1063
+ return all_filtered_results
1064
 
1065
  def remove_duplicates(dict_list):
1066
  """
1067
+ If you need to remove duplicates at any stage, you can call this,
1068
+ but it's optional if your data doesn't require deduping.
 
1069
  """
1070
  seen = set()
1071
  unique_list = []
1072
  for item in dict_list:
 
 
 
 
 
 
 
 
 
 
 
 
1073
  item_id = repr(item)
 
1074
  if item_id not in seen:
1075
  seen.add(item_id)
1076
  unique_list.append(item)
 
1077
  return unique_list
1078
 
1079
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1080
  perform_search_btn_els.click(
1081
  perform_date_range_els_search,
1082
+ inputs=[
1083
+ start_date_els,
1084
+ end_date_els,
1085
+ names_input_els,
1086
+ search_type_els,
1087
+ search_term_els,
1088
+ gematria_sum_search_els,
1089
+ search_mode_els,
1090
+ include_torah_chk_els,
1091
+ include_bible_chk_els,
1092
+ include_quran_chk_els,
1093
+ include_hindu_chk_els,
1094
+ include_tripitaka_chk_els,
1095
+ translate_results_chk_els,
1096
+ sub_oscillation_search_chk_els,
1097
+ sub_oscillation_level_els
1098
+ ],
1099
  outputs=[filtered_results_output_els]
1100
  )
1101
 
 
 
1102
  # --- Event Handlers ---
1103
 
1104
  search_type.change(