| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- extends Control
- # Referencias a los nodos de la UI
- onready var company_option_button = $VBoxContainer/HBoxContainer_Selectors/CompanyOptionButton
- onready var synergy_option_button = $VBoxContainer/HBoxContainer_Selectors/SynergyOptionButton
- onready var search_button = $VBoxContainer/HBoxContainer_Selectors/SearchButton
- onready var item_list_results = $VBoxContainer/ItemList_Results
- onready var rich_text_label_details = $VBoxContainer/RichTextLabel_Details
- onready var download_button = $VBoxContainer/DownloadButton
- onready var file_dialog = $FileDialog
- # --- NODOS PARA EXPORTACIÓN MASIVA ---
- onready var export_all_button = $VBoxContainer/HBoxContainer_Bulk/ExportAllButton
- onready var progress_label = $VBoxContainer/HBoxContainer_Bulk/ProgressLabel
- onready var directory_dialog = $DirectoryDialog
- const SYNERGY_TYPES = [
- "Strategic Alliance",
- "Customer-Supplier",
- "Tech Integration",
- "Competitor Analysis"
- ]
- var _current_matches = []
- var _selected_match_data = null
- func _ready():
- # Conexiones de señales
- search_button.connect("pressed", self, "_on_search_button_pressed")
- item_list_results.connect("item_selected", self, "_on_result_item_selected")
- download_button.connect("pressed", self, "_on_download_button_pressed")
- file_dialog.connect("file_selected", self, "_on_file_dialog_file_selected")
- # --- NUEVAS CONEXIONES ---
- export_all_button.connect("pressed", self, "_on_export_all_button_pressed")
- directory_dialog.connect("dir_selected", self, "_on_directory_selected")
- populate_company_dropdown()
- populate_synergy_dropdown()
-
- item_list_results.clear()
- rich_text_label_details.bbcode_enabled = true
- rich_text_label_details.text = "Select a company and a synergy type, then press 'Search'."
-
- download_button.disabled = true
- progress_label.text = ""
- file_dialog.filters = PoolStringArray(["*.json ; JSON Files"])
- directory_dialog.mode = FileDialog.MODE_OPEN_DIR # Forzar modo de selección de directorio
- func populate_company_dropdown():
- var company_names = CompanyDB.get_all_company_names()
- for name in company_names:
- company_option_button.add_item(name)
- func populate_synergy_dropdown():
- for synergy_type in SYNERGY_TYPES:
- synergy_option_button.add_item(synergy_type)
- # --- LÓGICA DE LA INTERFAZ (BÚSQUEDA INDIVIDUAL) ---
- func _on_search_button_pressed():
- search_button.disabled = true
- download_button.disabled = true
- _selected_match_data = null
- item_list_results.clear()
- _current_matches.clear()
- rich_text_label_details.text = "Searching..."
-
- yield(get_tree(), "idle_frame")
-
- var selected_company_name = company_option_button.get_item_text(company_option_button.selected)
- var selected_synergy_type = synergy_option_button.get_item_text(synergy_option_button.selected)
-
- _find_and_display_matches(selected_company_name, selected_synergy_type)
-
- search_button.disabled = false
- func _on_result_item_selected(index):
- if index >= _current_matches.size():
- return
- _selected_match_data = _current_matches[index]
- var company_details = _selected_match_data["company"]
- var reason = _selected_match_data["reason"]
-
- rich_text_label_details.bbcode_text = ""
- rich_text_label_details.append_bbcode("[b]Name:[/b] " + company_details.get("company_name", "N/A") + "\n")
- rich_text_label_details.append_bbcode("[b]Website:[/b] " + company_details.get("website", "N/A") + "\n\n")
- var description = company_details.get("description", {}).get("brief", "No hay descripción breve.")
- rich_text_label_details.append_bbcode("[b]Description:[/b] " + description + "\n\n")
- rich_text_label_details.append_bbcode("[b]Synergy Analysis (" + _selected_match_data["synergy_type"] + "):[/b]\n")
- rich_text_label_details.append_bbcode(reason)
- func _on_download_button_pressed():
- if _current_matches.empty():
- return
- var source_company_name = company_option_button.get_item_text(company_option_button.selected).replace(" ", "_")
- var synergy_type = _current_matches[0]["synergy_type"].replace(" ", "_")
-
- file_dialog.current_file = "%s_%s_Matches.json" % [source_company_name, synergy_type]
- file_dialog.popup_centered()
- func _on_file_dialog_file_selected(path):
- if _current_matches.empty():
- return
- var matches_to_save = []
- for match_data in _current_matches:
- var single_match_dict = {
- "matched_company": match_data["company"].get("company_name"),
- "synergy_type": match_data["synergy_type"],
- "justification": match_data["reason"].replace("[b]", "").replace("[/b]", "").replace("[i]", "").replace("[/i]", "").replace("[ul]", "").replace("[/ul]", "").replace("[li]", "- ")
- }
- matches_to_save.append(single_match_dict)
-
- var json_string = JSON.print(matches_to_save, "\t")
-
- var file = File.new()
- if file.open(path, File.WRITE) == OK:
- file.store_string(json_string)
- file.close()
- else:
- print("Error saving JSON file.")
- # --- LÓGICA DE EXPORTACIÓN MASIVA ---
- func _on_export_all_button_pressed():
- directory_dialog.popup_centered()
- func _on_directory_selected(path):
- search_button.disabled = true
- export_all_button.disabled = true
- download_button.disabled = true
-
- var all_companies = CompanyDB.company_data
- var total_companies = all_companies.size()
- var matches_found = 0
-
- for i in range(total_companies):
- var source_company = all_companies[i]
- var source_company_name = source_company.get("company_name", "Unknown")
-
- progress_label.text = "Processing %d/%d: %s..." % [i + 1, total_companies, source_company_name]
- yield(get_tree(), "idle_frame")
-
- var company_matches = []
- for target_company in all_companies:
- if source_company_name == target_company.get("company_name", "Unknown2"):
- continue
-
- for synergy_type in SYNERGY_TYPES:
- var reason = _get_synergy_reason(source_company, target_company, synergy_type)
-
- if reason:
- matches_found += 1
- company_matches.append({
- "matched_company": target_company.get("company_name"),
- "synergy_type": synergy_type,
- "justification": reason.replace("[b]", "").replace("[/b]", "").replace("[i]", "").replace("[/i]", "").replace("[ul]", "").replace("[/ul]", "").replace("[li]", "- ")
- })
-
- # --- LÓGICA DE GUARDADO MODIFICADA ---
- var json_string_to_save = ""
- # Si se encontraron matches, se guarda la lista de matches.
- if not company_matches.empty():
- json_string_to_save = JSON.print(company_matches, "\t")
- # Si NO se encontraron, se guarda un mensaje de estado.
- else:
- var no_match_data = {
- "status": "No synergies found",
- "message": "No potential synergies were identified for %s based on the current criteria." % source_company_name
- }
- json_string_to_save = JSON.print(no_match_data, "\t")
-
- # Guardar el archivo en cualquier caso.
- var filename = "%s_Synergies.json" % source_company_name.replace(" ", "_")
- var file_path = path.plus_file(filename)
-
- var file = File.new()
- if file.open(file_path, File.WRITE) == OK:
- file.store_string(json_string_to_save)
- file.close()
- progress_label.text = "Export complete! Found %d potential synergies across %d companies." % [matches_found, total_companies]
- search_button.disabled = false
- export_all_button.disabled = false
- # --- LÓGICA DE BÚSQUEDA Y ANÁLISIS ---
- func _find_and_display_matches(company_name, synergy_type):
- var source_company = CompanyDB.get_company_by_name(company_name)
- if not source_company:
- rich_text_label_details.text = "Error: Could not find data for the base company."
- return
- _current_matches.clear()
- var all_companies = CompanyDB.company_data
- for target_company in all_companies:
- if target_company.get("company_name") == source_company.get("company_name"):
- continue
- var reason = _get_synergy_reason(source_company, target_company, synergy_type)
- if reason:
- _current_matches.append({
- "company": target_company,
- "reason": reason,
- "synergy_type": synergy_type
- })
- if not _current_matches.empty():
- for match_data in _current_matches:
- item_list_results.add_item(match_data["company"].get("company_name"))
- rich_text_label_details.text = "Found %d matches. Select one to see the analysis." % _current_matches.size()
- download_button.disabled = false
- else:
- rich_text_label_details.text = "No matches found for the selected criteria."
- download_button.disabled = true
- func _get_synergy_reason(comp_a, comp_b, synergy_type):
- match synergy_type:
- "Competitor Analysis":
- return _get_competitor_reason(comp_a, comp_b)
- "Strategic Alliance":
- return _get_strategic_alliance_reason(comp_a, comp_b)
- "Customer-Supplier":
- return _get_customer_supplier_reason(comp_a, comp_b)
- "Tech Integration":
- return _get_tech_integration_reason(comp_a, comp_b)
- return null
- func _get_competitor_reason(comp_a, comp_b):
- var sectors_a = comp_a.get("target_markets", {}).get("sectors", [])
- var sectors_b = comp_b.get("target_markets", {}).get("sectors", [])
- var services_a = comp_a.get("offerings", {}).get("services", [])
- var services_b = comp_b.get("offerings", {}).get("services", [])
- var shared_sectors = _get_array_intersection(sectors_a, sectors_b)
- if shared_sectors.empty(): return null
- var shared_services = _get_array_intersection(services_a, services_b)
- if shared_services.empty(): return null
-
- var reason = "A competitive overlap exists between [b]%s[/b] and [b]%s[/b].\n\n" % [comp_a.get("company_name"), comp_b.get("company_name")]
- reason += "Key points of analysis:\n"
- reason += "[ul][li]Both companies operate in the following shared sectors: [b]%s[/b].[/li]\n" % PoolStringArray(shared_sectors).join(", ")
- reason += "[li]They offer similar services to the market, including: [b]%s[/b].[/li][/ul]\n" % PoolStringArray(shared_services).join(", ")
- reason += "This alignment in market focus and service offerings suggests they are direct or indirect competitors."
- return reason
- func _get_strategic_alliance_reason(comp_a, comp_b):
- var sectors_a = comp_a.get("target_markets", {}).get("sectors", [])
- var sectors_b = comp_b.get("target_markets", {}).get("sectors", [])
- var keywords_a = comp_a.get("capability_map", {}).get("core_technical_keywords", [])
- var keywords_b = comp_b.get("capability_map", {}).get("core_technical_keywords", [])
- var shared_sectors = _get_array_intersection(sectors_a, sectors_b)
- if shared_sectors.empty(): return null
- var shared_keywords = _get_array_intersection(keywords_a, keywords_b)
- if shared_keywords.size() > 3: return null
- var reason = "A potential strategic alliance exists between [b]%s[/b] and [b]%s[/b].\n\n" % [comp_a.get("company_name"), comp_b.get("company_name")]
- reason += "Justification:\n"
- reason += "[ul][li]Both companies are active in the [b]%s[/b] sector(s).[/li]\n" % PoolStringArray(shared_sectors).join(", ")
- reason += "[li][b]%s[/b]'s expertise in [i]%s[/i] could be complemented by [b]%s[/b]'s capabilities in [i]%s[/i].[/li][/ul]\n" % [comp_a.get("company_name"), PoolStringArray(keywords_a).join(", "), comp_b.get("company_name"), PoolStringArray(keywords_b).join(", ")]
- reason += "A partnership could lead to a more comprehensive and integrated solution for their shared market."
- return reason
- func _get_customer_supplier_reason(comp_a, comp_b):
- var reason_a_is_customer = _check_customer_supplier_direction(comp_a, comp_b)
- if reason_a_is_customer: return reason_a_is_customer
-
- var reason_b_is_customer = _check_customer_supplier_direction(comp_b, comp_a)
- if reason_b_is_customer: return reason_b_is_customer
-
- return null
- func _check_customer_supplier_direction(customer, supplier):
- var customer_domains = customer.get("capability_map", {}).get("application_domains", [])
- var supplier_services = supplier.get("offerings", {}).get("services", [])
-
- var match_keywords = _get_array_intersection(customer_domains, supplier_services)
- if match_keywords.empty(): return null
- var reason = "A potential customer-supplier relationship exists between [b]%s[/b] (Customer) and [b]%s[/b] (Supplier).\n\n" % [customer.get("company_name"), supplier.get("company_name")]
- reason += "Justification:\n"
- reason += "[ul][li][b]%s[/b]'s focus on the [b]%s[/b] domain(s) aligns directly with the services offered by [b]%s[/b], such as [b]%s[/b].[/li][/ul]\n" % [customer.get("company_name"), PoolStringArray(customer_domains).join(", "), supplier.get("company_name"), PoolStringArray(supplier_services).join(", ")]
- reason += "[b]%s[/b] could enhance its offerings by integrating [b]%s[/b]'s specialized solutions." % [customer.get("company_name"), supplier.get("company_name")]
- return reason
- func _get_tech_integration_reason(comp_a, comp_b):
- var hardware_a = comp_a.get("technology_stack", {}).get("hardware", [])
- var software_a = comp_a.get("technology_stack", {}).get("software", [])
- var hardware_b = comp_b.get("technology_stack", {}).get("hardware", [])
- var software_b = comp_b.get("technology_stack", {}).get("software", [])
- var integration_path = null
- if not _get_array_intersection(hardware_a, software_b).empty() or not _get_array_intersection(software_a, hardware_b).empty():
- integration_path = "Hardware/Software"
-
- if not integration_path: return null
- var reason = "A technological integration opportunity exists between [b]%s[/b] and [b]%s[/b].\n\n" % [comp_a.get("company_name"), comp_b.get("company_name")]
- reason += "Justification:\n"
- reason += "[ul][li]There is a clear [b]%s[/b] integration path.[/li]\n" % integration_path
- reason += "[li][b]%s[/b]'s hardware expertise ([i]%s[/i]) and software capabilities ([i]%s[/i]) are complementary to [b]%s[/b]'s stack ([i]%s[/i] hardware, [i]%s[/i] software).[/li][/ul]\n" % [comp_a.get("company_name"), PoolStringArray(hardware_a).join(", "), PoolStringArray(software_a).join(", "), comp_b.get("company_name"), PoolStringArray(hardware_b).join(", "), PoolStringArray(software_b).join(", ")]
- reason += "Combining their technologies could result in a powerful, turnkey solution."
- return reason
- func _get_array_intersection(arr1, arr2):
- var intersection = []
- for item in arr1:
- if item in arr2:
- intersection.append(item)
- return intersection
|