From 995d811a9369668941908b378f2047b4ab299a41 Mon Sep 17 00:00:00 2001 From: Artorias Date: Sun, 23 Mar 2025 18:55:54 +0100 Subject: [PATCH] Updated documentation --- README.md | 14 +++++++---- .../project/gruppe_05_1/nlp/XmiExtractor.java | 24 +++++++++++++++++-- .../gruppe_05_1/rest/FrontEndController.java | 19 ++++----------- .../gruppe_05_1/rest/SpeechController.java | 8 +++---- src/main/resources/templates/charts.ftl | 1 - 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 22f9b2c..76aed29 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,12 @@ Folgende Command Line Argumente werden akzeptiert: - Use Case Diagramm - Package/Klassen-Diagramm -- Die Plannung +- Die Planung - 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 +Die Planung beinhaltet: +- Die Liste der Aufgaben, nach Bereichen gruppiert. Die Bereiche sind: Planung, Domain-Entitäten, XML, Datenbank, Rest Services, Front End, NLP-Verarbeitug, Export, Dokumentation - Wer macht was - Geschätzter Aufwand (niedrig / mittel / hoch) @@ -116,13 +116,17 @@ Folgende Informationen werden angezeigt: 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 +- POS Information (als Bar Chart): Auf der X-Achse werden alle verschiedenen POS-Elemente die in der Rede erfasst wurden abgebildet, auf der Y-Achse die genaue Anzahl dieser Elemente. +- Sentiments Information (als Radar Chart): Dieses Chart besitzt 3 Achsen, eine für den wert des positiven sentiments, eine für das negative sentiment, und die letzte für das neutrale sentiment. Die mitte des Charts steht für den Wert 0, und jede Ecke steht für den Wert 1 des zugehörigen sentiments. Es wird jeder analysierte Satz inklusive die gesamte Rede abgebildet. Ein Polygon steht hierbei für einen bestimmten analysierten Abschnitt der rede. - 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. +### Charts-Seite + +Gleiche Struktur wie die Charts für die einzelnen reden, hier nur auf alle in der Datenbank vorhandenen Reden angewendet. Die sammlung der Daten passiert hier dynamisch ab Abruf der Seite. + diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java index 89fee0d..4c920a9 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/XmiExtractor.java @@ -6,7 +6,6 @@ import com.mongodb.client.model.WriteModel; import org.apache.uima.fit.util.JCasUtil; import org.bson.Document; import java.io.*; -import java.nio.charset.StandardCharsets; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; @@ -24,7 +23,10 @@ import org.texttechnologylab.project.gruppe_05_1.util.Logger; import static org.texttechnologylab.project.gruppe_05_1.Main.JCAS_SPEECHES_TYPESYSTEM_DIR; - +/** + * Extrahiert NLP‑Analyseergebnisse aus komprimierten XMI‑Dateien und lädt sie batchweise in MongoDB hoch. + * Liest .xmi.gz Dateien aus einem ZIP‑Archiv, erstellt für jede Rede ein "analysisResults" Dokument und führt Bulk‑Writes durch. + */ public class XmiExtractor { private final List> bulkOperations = Collections.synchronizedList(new ArrayList<>()); @@ -36,6 +38,11 @@ public class XmiExtractor { mongoDBHandler = new MongoDBHandler(); } + /** + * Liest alle .xmi.gz Dateien aus dem ZIP‑Archiv "speeches/20.zip", extrahiert deren NLP‑Daten + * und lädt sie in Form von BATCH_SIZE Dokumenten in MongoDB hoch. + * @throws IOException falls die ZIP‑Datei nicht gefunden oder ein Lese-/Schreibfehler auftritt + */ public void extractAndUploadXmiData() throws IOException { InputStream resourceStream = getClass().getClassLoader().getResourceAsStream("speeches/20.zip"); if (resourceStream == null) { @@ -85,6 +92,11 @@ public class XmiExtractor { mongoDBHandler.close(); } + /** + * Liest ein komprimiertes XMI ein und erstellt Bulk‑Update‑Operationen für MongoDB. + * @param inputStream komprimierter XMI‑InputStream + * @param filename Name der Datei im ZIP‑Archiv (für speechKey) + */ private void processXmiGzStream(InputStream inputStream, String filename) { JCas jCas = null; try (GZIPInputStream gis = new GZIPInputStream(inputStream)) { @@ -181,11 +193,19 @@ public class XmiExtractor { } } + /** + * Extrahiert aus dem Dateinamen (z.B. "20/ABC123.xmi.gz") den speechKey. + * @param filename Name der Datei innerhalb des ZIP‑Archivs + * @return speechKey oder null, wenn das Format nicht erkannt wird + */ private static String extractSpeechKeyFromFilename(String filename) { String baseName = filename.replace(".xmi.gz", ""); return baseName.replace("20/", ""); } + /** + * Führt alle gesammelten BulkWrite-Operationen in MongoDB aus und leert den Batch. + */ private synchronized void flushBatch() { if (!bulkOperations.isEmpty()) { mongoDBHandler.bulkWriteNlpData(bulkOperations); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/FrontEndController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/FrontEndController.java index 5df9760..c24a7ac 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/FrontEndController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/FrontEndController.java @@ -1,32 +1,20 @@ package org.texttechnologylab.project.gruppe_05_1.rest; import com.mongodb.client.MongoCollection; -import gnu.trove.impl.sync.TSynchronizedShortObjectMap; import io.javalin.http.Context; import io.javalin.openapi.*; -import org.apache.commons.collections.bag.SynchronizedSortedBag; -import org.texttechnologylab.project.gruppe_05_1.database.MongoDBHandler; import org.texttechnologylab.project.gruppe_05_1.database.MongoPprUtils; -import org.texttechnologylab.project.gruppe_05_1.domain.html.HtmlSpeech; import org.texttechnologylab.project.gruppe_05_1.domain.html.Parlamentarier; -import org.texttechnologylab.project.gruppe_05_1.domain.html.ParlamentarierDetails; -import org.texttechnologylab.project.gruppe_05_1.domain.nlp.NamedEntity; import org.texttechnologylab.project.gruppe_05_1.domain.nlp.Sentiment; import org.texttechnologylab.project.gruppe_05_1.domain.nlp.Token; import org.texttechnologylab.project.gruppe_05_1.domain.nlp.Topic; -import org.texttechnologylab.project.gruppe_05_1.domain.speech.SpeechMetaData; -import org.texttechnologylab.project.gruppe_05_1.util.Logger; import org.texttechnologylab.project.gruppe_05_1.util.PPRUtils; -import org.texttechnologylab.project.gruppe_05_1.xml.speeches.Interfaces.Speech; -import com.mongodb.client.AggregateIterable; import com.mongodb.client.model.Aggregates; import com.mongodb.client.model.Accumulators; -import com.mongodb.client.model.Facet; import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; import org.bson.Document; import org.bson.conversions.Bson; -import java.util.*; import java.util.ArrayList; import java.util.HashMap; @@ -35,8 +23,6 @@ import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; -import static javax.management.Query.eq; -import static org.texttechnologylab.project.gruppe_05_1.util.PPRUtils.listFractionsFromMembers; public class FrontEndController { @OpenApi( @@ -81,6 +67,11 @@ public class FrontEndController { ctx.render("parlamentarier.ftl", attributes); } + /** + * Aggregiert für alle Reden die NLP‑Ergebnisse (Topics, POS, Named Entities, erste Sentiment‑Objekte) + * und liefert die zusammengefassten Daten an die Charts‑Ansicht. + * @param ctx Javalin Context zum Rendern der Seite mit den aggregierten Chart‑Daten + */ public static void getCharts(Context ctx) { MongoCollection col = MongoPprUtils.getSpeechCollection(); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java index c91a08e..9035a5f 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/SpeechController.java @@ -105,7 +105,7 @@ public class SpeechController { Map posCounts = Token.countPOS(tokens); List posList = posCounts.entrySet().stream() - .map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), "")) // Lemma remains empty + .map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), "")) .collect(Collectors.toList()); Logger.debug("Sending POS List to NLP - " + posList); @@ -114,7 +114,7 @@ public class SpeechController { } else { Logger.debug("POS List is EMPTY"); - speech.getNlp().setPosList((List) new ArrayList()); // Ensure it's never null + speech.getNlp().setPosList((List) new ArrayList()); } // NLP: Named Entities @@ -151,10 +151,8 @@ public class SpeechController { attributes.put("na_info", null); } - // TODO: Token wird momentan etwas komisch abgespeichert, da im Attribut text die POS art steht, und in pos die Anzahl dieser POS arten. Umstrukturieren damit keine Verwirrung herrscht - // NLP: Sentiments - // Der erste Sentiment gilt der gesamten Rede. Die weitere Sentiments entsprechen die Sätze. + // Der erste Sentiment gilt der gesamten Rede. Die weitere Sentiments entsprechen die Sätze. overallSentiments speichert alle Analyseobjekte und sentiments nur die der einzelnen Sätze List sentiments = speech.getNlp().getSentiments(); if ((sentiments != null) && ! sentiments.isEmpty()) { List overallSentiments = new ArrayList<>(sentiments); diff --git a/src/main/resources/templates/charts.ftl b/src/main/resources/templates/charts.ftl index efdefc7..bc45694 100644 --- a/src/main/resources/templates/charts.ftl +++ b/src/main/resources/templates/charts.ftl @@ -30,7 +30,6 @@
<#if aggregatedSentiment?? && (aggregatedSentiment?size gt 0)>

Sentiments Information (als Radar Chart)

- <#-- Wrap the aggregated sentiment map in a list so that the chart partial can iterate --> <#assign sentiments = [aggregatedSentiment]> <#include "sentimentsRadarChart.ftl"> <#else>