From 11059d08f0a60bfba5b6d068ac25b47d858834b6 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sun, 23 Mar 2025 14:57:54 +0100 Subject: [PATCH 1/7] moved duplicate code to method --- .../project/gruppe_05_1/export/TeXUtil.java | 10 ++++ .../rest/SpeechesLatexExportController.java | 49 ++----------------- 2 files changed, 15 insertions(+), 44 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 2f01145..ab70cd2 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -229,6 +229,16 @@ public class TeXUtil { }); } + public static void tryDeleteTeXTempDirContents() { + try { + deleteTeXTempDirContents(); + } catch (IOException e) { + Logger.error("Failed to delete temporary folder."); + Logger.error(e.getMessage()); + Logger.debug(Arrays.toString(e.getStackTrace())); + } + } + public static boolean isTeXSdkInstalled() { try { Process process = Runtime.getRuntime().exec("pdflatex --version"); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesLatexExportController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesLatexExportController.java index f3b6205..abf729e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesLatexExportController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechesLatexExportController.java @@ -48,14 +48,7 @@ public class SpeechesLatexExportController { // Send the PDF as a response ctx.result(stream); - try { - // delete the temporary folder - deleteTeXTempDirContents(); - } catch (IOException e) { - Logger.error("Failed to delete temporary folder."); - Logger.error(e.getMessage()); - Logger.debug(Arrays.toString(e.getStackTrace())); - } + tryDeleteTeXTempDirContents(); } @OpenApi( @@ -91,15 +84,7 @@ public class SpeechesLatexExportController { // Send the PDF as a response ctx.result(stream); - try { - // delete the temporary folder - deleteTeXTempDirContents(); - Logger.debug("Temporary folder deleted."); - } catch (IOException e) { - Logger.error("Failed to delete temporary folder."); - Logger.error(e.getMessage()); - Logger.debug(Arrays.toString(e.getStackTrace())); - } + tryDeleteTeXTempDirContents(); } @OpenApi( @@ -135,15 +120,7 @@ public class SpeechesLatexExportController { // Send the PDF as a response ctx.result(stream); - try { - // delete the temporary folder - deleteTeXTempDirContents(); - Logger.debug("Temporary folder deleted."); - } catch (IOException e) { - Logger.error("Failed to delete temporary folder."); - Logger.error(e.getMessage()); - Logger.debug(Arrays.toString(e.getStackTrace())); - } + tryDeleteTeXTempDirContents(); } @OpenApi( @@ -179,15 +156,7 @@ public class SpeechesLatexExportController { // Send the PDF as a response ctx.result(stream); - try { - // delete the temporary folder - deleteTeXTempDirContents(); - Logger.debug("Temporary folder deleted."); - } catch (IOException e) { - Logger.error("Failed to delete temporary folder."); - Logger.error(e.getMessage()); - Logger.debug(Arrays.toString(e.getStackTrace())); - } + tryDeleteTeXTempDirContents(); } @OpenApi( @@ -230,14 +199,6 @@ public class SpeechesLatexExportController { // Send the PDF as response ctx.result(stream); - try { - // Clean up temporary files - deleteTeXTempDirContents(); - Logger.debug("Temporary folder deleted."); - } catch (IOException e) { - Logger.error("Failed to delete temporary folder."); - Logger.error(e.getMessage()); - Logger.debug(Arrays.toString(e.getStackTrace())); - } + tryDeleteTeXTempDirContents(); } } From 53bade28e9acfc51804b4eadd4e1b1a7ad79bfc2 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sun, 23 Mar 2025 15:22:52 +0100 Subject: [PATCH 2/7] fixed Hashtag causing tex gen issues --- .../texttechnologylab/project/gruppe_05_1/export/TeXUtil.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index ab70cd2..178b5db 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -163,6 +163,7 @@ public class TeXUtil { // Format tex string to UTF-8 tex = new String(tex.getBytes("UTF-8")); + tex = tex.replaceAll("#", "\\\\#"); // Replace all # with \# tex = tex.replaceAll("[^\\x00-\\x7F]", ""); // Replace all non-ASCII characters // Local datetime stamp From 547479c3e45a69247b248441d8f62f935de07d3f Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sun, 23 Mar 2025 17:00:13 +0100 Subject: [PATCH 3/7] fixed nlp data not being exported with xml --- .../texttechnologylab/project/gruppe_05_1/export/XMLUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java index c9baea5..76f30d6 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java @@ -124,6 +124,9 @@ public class XMLUtil { Speaker_MongoDB_Impl speaker = getSpeakerById(String.valueOf(speech.getSpeakerId())); + HtmlSpeech htmlSpeech = getHtmlSpeechByKey(String.valueOf(speech.getSpeechId())); + addNlpData(doc, htmlSpeech); + speechElement.appendChild(speaker.toXML(doc)); speechElement.appendChild(speech.toXML(doc)); } From 74c6666efa675dc9acc916008d257083293e75e5 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sun, 23 Mar 2025 17:00:44 +0100 Subject: [PATCH 4/7] fixed formatting for latex graphs on export --- .../project/gruppe_05_1/export/TeXUtil.java | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java index 178b5db..7180e6b 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/TeXUtil.java @@ -53,16 +53,6 @@ public class TeXUtil { tex.append(speech.toTeX()); Map topics = Topic.condenseTopicInformation(getHtmlSpeechByKey(speechId).getNlp().getTopics()); - // loop through topics and Logger.pink them - for (Map.Entry entry : topics.entrySet()) { - Logger.pink(entry + " " + entry.getValue()); - } - - /*Map pos = getPOSInformationCardinalitiesForSpeechById(speechId); - // loop through topics and Logger.pink them - for (Map.Entry entry : pos.entrySet()) { - Logger.pink(entry + " " + entry.getValue()); - }*/ return tex.toString().replace("$$SPEAKERINFO$$", speaker.toTeX()) .replace("$$NLPMETADATA$$", @@ -79,7 +69,20 @@ public class TeXUtil { tex.append(speech.toTeX()); - return tex.toString().replace("$$SPEAKERINFO$$", speaker.toTeX()); + Map topics = null; + + Logger.pink(String.valueOf(speech.getSpeechKey())); + + try { + topics = Topic.condenseTopicInformation(getHtmlSpeechByKey(speech.getSpeechKey()).getNlp().getTopics()); + } catch (Exception e) { + topics = Map.of(); + } + + return tex.toString().replace("$$SPEAKERINFO$$", speaker.toTeX()).replace("$$NLPMETADATA$$", + generateChartView(generateBubbleChartLatex(topics), + generateBarChartLatex(getPOSInformationCardinalitiesForSpeechById(speech.getSpeechKey())), + generateRadarChartLatex(getHtmlSpeechByKey(speech.getSpeechKey()).getNlp().getSentiments()), "")); } public static String getExportedSpeechBase64StringBySpeechId(String speechId) throws IOException, InterruptedException { @@ -310,8 +313,8 @@ public class TeXUtil { StringBuilder xCords = new StringBuilder(); xCords.append("{"); for (Map.Entry entry : barData.entrySet()) { - xCords.append(entry.getKey()).append(", "); - graphData.append("\t(").append(entry.getKey()).append(", ").append(entry.getValue()).append(")\n"); + xCords.append(entry.getKey().replace(",", "\\,")).append(", "); + graphData.append("\t(").append(entry.getKey().replace(",", "\\,")).append(", ").append(entry.getValue()).append(")\n"); } xCords.append("}"); String xCordsString = xCords.toString().replace("$", "\\$"); From 5472b4a75fa8a82db781022dc45729400eb7bd4e Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sun, 23 Mar 2025 17:11:34 +0100 Subject: [PATCH 5/7] added speech and speaker-speech export buttons --- src/main/resources/static/index.css | 6 ++++++ .../resources/templates/parlamentarierDetails.ftl | 12 ++++++++++++ src/main/resources/templates/speech.ftl | 14 ++++++++++++++ 3 files changed, 32 insertions(+) diff --git a/src/main/resources/static/index.css b/src/main/resources/static/index.css index c77d335..73f5f71 100644 --- a/src/main/resources/static/index.css +++ b/src/main/resources/static/index.css @@ -296,3 +296,9 @@ select { margin-bottom: 20px; border-radius: 10px; } + +.export-button { + flex: 1; + flex-direction: row; + justify-content: center; +} diff --git a/src/main/resources/templates/parlamentarierDetails.ftl b/src/main/resources/templates/parlamentarierDetails.ftl index 9bd8a6a..d256399 100644 --- a/src/main/resources/templates/parlamentarierDetails.ftl +++ b/src/main/resources/templates/parlamentarierDetails.ftl @@ -32,6 +32,18 @@ +
+

Reden Export von allen Reden von ${p.vorname} ${p.nachname}

+
+ +
+ + +
<#else> Keine Reden vorhanden diff --git a/src/main/resources/templates/speech.ftl b/src/main/resources/templates/speech.ftl index 24a20e1..d4a6f31 100644 --- a/src/main/resources/templates/speech.ftl +++ b/src/main/resources/templates/speech.ftl @@ -48,6 +48,20 @@

+

Reden Export von dieser Rede

+
+ +
+ + +
+ +
+
<#list s.content as c> <#if sentimentIcons??> From 796b36a55e401381b8e7f53ba1bd928416955475 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Sun, 23 Mar 2025 17:13:43 +0100 Subject: [PATCH 6/7] fixed speech key for XML exports --- .../texttechnologylab/project/gruppe_05_1/export/XMLUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java index 76f30d6..64e766d 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/export/XMLUtil.java @@ -124,7 +124,7 @@ public class XMLUtil { Speaker_MongoDB_Impl speaker = getSpeakerById(String.valueOf(speech.getSpeakerId())); - HtmlSpeech htmlSpeech = getHtmlSpeechByKey(String.valueOf(speech.getSpeechId())); + HtmlSpeech htmlSpeech = getHtmlSpeechByKey(speech.getSpeechKey()); addNlpData(doc, htmlSpeech); speechElement.appendChild(speaker.toXML(doc)); From 756603e8bf7e8879efd4327dd970ea786d5e133a Mon Sep 17 00:00:00 2001 From: vysitor Date: Sun, 23 Mar 2025 17:17:47 +0100 Subject: [PATCH 7/7] Added READMe --- README.md | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 127 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 05365b3..22f9b2c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,137 @@ # Multimodal Parliament Explorer (Gruppe_05_1) +## Umgebung - wichtiger Hinweis! +Damit der Zugriff auf die Docker-Treiber funktioniert, muss man in IntelliJ folgendes tun: -## Classdiagram puml generator +Edit Run Environment --> Modify Option --> Add VM options + +Dann im neu erscheinenden "VM options"-Feld folgendes schreiben: + +--add-opens java.base/java.util=ALL-UNNAMED + +## Aufruf + +Der Nutzer führt die **Main.java** Datei aus. +Folgende Command Line Argumente werden akzeptiert: + +- onlyRunWeb: Fährt die WebServies hoch und wartet auf Requests. Die Einstiegsseite kann im Browser geöffnet werden: http://localhost:5876 (Port 5876 ist in der Resourcendatei javalin.properties definiert). In der Regel würde man Main nur mit diesem Parameter aufrufen. +- uploadMemberPhotos: Um Parlamentarierfotos vom Resource-Verzeichnis in die Datenbank hochzuladen. +- forceUploadMembers: Lädt die Daten der Parlamentariern erneut in die Datenbank. +- forceUploadSpeeches: Lädt die Reden erneut in die Datenbank, führt die NLP-Analyse auf der Reden und speichert die Analyseergebnisse in die Datenbank. +- rebuildMetadata: Berechnet die Metadaten neu. In der Metadata-Collection stehen Daten, welche oft benötigt werden, aber nicht jedes Mal erneut berechnet werden sollen. Momentan sind es die Liste der Parteien und die Liste der möglichen NLP-Topics. +- debugLogging: Diese Flag bestimmt, ob Debug-Ausgaben des Loggers angezeigt werden sollen. + +## Dokumentation + +- Use Case Diagramm +- Package/Klassen-Diagramm +- Die Plannung +- Das Gantt Diagramm +stehen im "doku"-Verzeichnis. + +Die Plannung beinhaltet: +- Die Liste der Aufgaben, nach Bereichen gruppiert. Die Bereiche sind: Plannung, Domain-Entitäten, XML, Datenbank, Rest Services, Front End, NLP-Verarbeitug, Export, Dokumentation +- Wer macht was +- Geschätzter Aufwand (niedrig / mittel / hoch) + + +### Classdiagram puml generator +Das Classdiagram wird durch den puml generator generiert: ```shell python puml_generator.py ``` -## Upload member Images + +## Datenbank + +Die wichtigsten Collections sind *"speech"* und *"speaker"*. In "pictures" stehen die Bilder der Abgeordneten. In "metadata" stehen die bereits erwähnten Metadaten. +Die Collections "agendaItems" und "sessions" werden zwar initial befüllt und kurzzeitig verwendet, um die Zeitstempel der Reden sowie die Agendapunkte zu konstruieren, werden aber danach nicht weiter verwendet. + +## Erzeugung der NLP-Daten +TODO HENRY + + + +## Komponenten und Package Struktur +- database: die Klasse *MongoDBHandler* kümmert sich um die Herstellung der Datenbankverbindung und um generelle CRUD-Operationen. Die Klasse *MongoPprUtils* kümmert sich um das Lesen der Objekte und Datenstrukturen, die für diese Übung notwendig sind. + +- domain: hier werden die Entitäten definiert. Subpackage "database" behandelt die Objekte, die aus der Datenbank kommen. Subpackage "html" behandelt die Objekte, die nicht in der Datenbank sind und lediglich angezeigt werden. + +- rest: alles, was mit den WebServices zu tun hat - die 4 Controller (für Parlamentarier, Fotos, Videos und Reden), eine Configklasse und der Handler. Im Handler wird die Javalin-Konfiguration definiert sowie die Routes für die 8 Endpoints. + +- export: alles, was mit dem Export (LaTex/PDF, XML) zu tun hat, findet hier Platz. + +- xml: für das Einlesen der Parlamentarier- und Rede-Daten. + +- util: eine kleine Sammlung von Utility-Klassen. + +- nlp: Utils für die NLP-Verarbeitung + +- exceptions: für die Exceptions + + +## Struktur des resources-Ordner + +- config: config files für javalin und für XML (im letzteren steht die URL zum Herunterladen der Parlamentarier) + +- plenarprotokolle: enthält die DTD-Datei zum Parsen der Abgeordnetendaten + +- speeches: enthält die Datei TypeSystem.xml + +- static: enthält das Stylesheet und das Favicon + +- templates: enthält die FreeMarker-Templates + +- tex: enthält die nötigen Resourcen für Latex, etwa die preamble.tex + + +## Ablauf / Workflow + +Wir gehen hier vom Workflow des Endnutzers aus. + +Wie man die Daten hochlädt, wurde bereit oben kurz erklärt. + +1. Die Klasse Main wird ausgefüht und zwar mit dem "onlyRunWeb" Parameter. +2. Javalin fährt die Webservices hoch und wartet auf Requests. +3. Der User lädt die Einstiegsseite im Browser, etwas http://localhost:5876 . Die Startseite wird angezeigt. Das Hauptmenü enthält im Burgermenü Links zu "Parlamentarier", "Reden", "Exportieren" sowie "Home" und "Über". + +### Parlamentarier-Seite + +Eine Liste der Parlamentarier wird angezeigt. Man kann die Liste filtern. Man kann auf die jeweiligen Parlamentarier klicken und gelangt dann auf die Seite eines Parlamentariers. + +Die Seite eines Parlamentariers beinhaltet Name, Foto, persöhnliche Daten, Mitgliedschaften und einen Link zu den Reden des Parlamentariers. + +### Reden-Seite + +Es werden alle Reden der jetzigen Legislaturperiode angezeigt. +Man kann die Liste filtern (MOMENTAN NOCH ZU IMPLEMENTIEREN). Man kann auf die jeweilige Rede klicken und gelangt dann auf die Rede-Seite. + +### Redeseite + +Folgende Informationen werden angezeigt: +- Informationen zum Redner (Name, Partei, Foto). +- Informationen zur Rede (Datum, Uhrzeit, Agendapunkt). +- Redetext. Vorstellung und Kommentare werden farblich gekennzeichnet. +- NLP Informationen. + +Der NLP-Abschnitt beinhaltet folgende Informationen: +- Topics Information (als Bubble Chart): dabei entspricht die Größe der Bubbles der Häufigkeit/Prävalenz der Topics. Durch einen Mouse-Hover verändert sich die Schriftgröße, damit man auch die Texte der kleinen Bubbles sehen kann. +- POS Information (als Bar Chart) - TODO +- Sentiments Information (als Radar Chart) - TODO +- Named Entities (als Sunburst Chart): der innere Kreis steht für den Typ (LOC, PER, ORG, MISC). Der äußere Kreis steht für die jeweiligen Named Entities. Die Größe der Bögen entsprechen den Häufigkeiten der Entitäten bzw. der Typen. + + +Ein "Zurück"-Button ist auf den Seiten implementiert. Er führt erwartungsgemäß zur vorherigen Seite. + + + + +## Verschiedenes + +### Nachladen neuer Reden (Thread) - TODO + + +### Upload member Images Crawl member images (not required as already in repository) ```shell cd src/main/resources