From 3fe8463a03f6d0e30044d1c534ab08dbc405900b Mon Sep 17 00:00:00 2001 From: Lars Date: Sun, 28 Dec 2025 11:44:04 +0100 Subject: [PATCH] bug fix --- app/frontend/ui_graph_service.py | 56 ++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/app/frontend/ui_graph_service.py b/app/frontend/ui_graph_service.py index 1aeeaba..1d38a77 100644 --- a/app/frontend/ui_graph_service.py +++ b/app/frontend/ui_graph_service.py @@ -202,6 +202,8 @@ class GraphExplorerService: # Case C: Edge zeigt auf unseren Titel (Wikilinks) # WICHTIG: target_id ist der vollständige Wikilink-Text ohne [[]], z.B. "Meine Prinzipien 2025#P3 – Disziplin" # Das kann sein: "Titel" oder "Titel#Abschnitt" oder "Titel#Abschnitt (Details)" + # PROBLEM: Wikilinks können andere Titel verwenden als der gespeicherte Note-Titel! + # Beispiel: Note-Titel = "Persönliches Leitbild (2025–2029)", aber Wikilink = "Mein Persönliches Leitbild 2025" note_titles_to_search = [] if note_title: note_titles_to_search.append(note_title) @@ -209,8 +211,29 @@ class GraphExplorerService: # Fallback: Lade Titel der Notes, wenn note_title nicht übergeben wurde for nid in note_ids: note = self._fetch_note_cached(nid) - if note and note.get("title"): - note_titles_to_search.append(note.get("title")) + if note: + if note.get("title"): + note_titles_to_search.append(note.get("title")) + # WICHTIG: Auch Aliases hinzufügen (falls vorhanden) + aliases = note.get("aliases", []) + if isinstance(aliases, str): + aliases = [aliases] + for alias in aliases: + if alias and alias not in note_titles_to_search: + note_titles_to_search.append(alias) + + # ZUSÄTZLICH: Lade auch Aliases für alle Notes, wenn note_title übergeben wurde + # (um auch Varianten wie "Mein Persönliches Leitbild 2025" zu finden) + if note_title: + for nid in note_ids: + note = self._fetch_note_cached(nid) + if note: + aliases = note.get("aliases", []) + if isinstance(aliases, str): + aliases = [aliases] + for alias in aliases: + if alias and alias not in note_titles_to_search: + note_titles_to_search.append(alias) # Für jeden Titel: Suche nach exaktem Match # WICHTIG: target_id kann "Titel" oder "Titel#Abschnitt" oder "Titel#Abschnitt (Details)" sein @@ -284,6 +307,35 @@ class GraphExplorerService: existing_edge_ids.add(edge.id) matched_count += 1 break # Nur einmal hinzufügen, auch wenn mehrere Titel passen + + # ZUSÄTZLICH: Fuzzy-Matching für ähnliche Titel + # PROBLEM: Wikilinks können andere Titel verwenden als der gespeicherte Note-Titel + # Beispiel: Note-Titel = "Persönliches Leitbild (2025–2029)", aber Wikilink = "Mein Persönliches Leitbild 2025" + # Strategie: Prüfe, ob target_id mit dem Kern-Titel beginnt (ohne Jahreszahl/Varianten) + if not any(tgt_id == t or tgt_id.startswith(t + "#") for t in note_titles_to_search): + # Extrahiere Kern-Titel (ohne Jahreszahl, ohne Klammern) + for title in note_titles_to_search: + # Entferne Jahreszahlen und Klammern für Vergleich + core_title = re.sub(r'\s*\([^)]*\)', '', title) # Entferne (2025–2029) + core_title = re.sub(r'\s+\d{4}', '', core_title) # Entferne Jahreszahlen + core_title = core_title.strip() + + # Entferne auch "Mein/Meine" Präfixe für Vergleich + core_title_clean = re.sub(r'^(Mein|Meine)\s+', '', core_title, flags=re.IGNORECASE).strip() + + # Prüfe, ob target_id mit Kern-Titel beginnt + tgt_core = re.sub(r'\s*\([^)]*\)', '', tgt_id.split("#")[0]) # Entferne Klammern aus target_id + tgt_core = re.sub(r'\s+\d{4}', '', tgt_core).strip() + tgt_core_clean = re.sub(r'^(Mein|Meine)\s+', '', tgt_core, flags=re.IGNORECASE).strip() + + # Vergleich: Wenn Kern-Titel ähnlich ist, akzeptiere + if (core_title_clean and tgt_core_clean and + (tgt_core_clean.startswith(core_title_clean) or core_title_clean.startswith(tgt_core_clean)) and + len(core_title_clean) > 5): # Mindestlänge, um False Positives zu vermeiden + results.append(edge) + existing_edge_ids.add(edge.id) + matched_count += 1 + break return results