From 7c24f570de1fbfc18883a1d6cac1d4c7f3eba01f Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Thu, 20 Mar 2025 15:16:23 +0100 Subject: [PATCH 1/7] centered image in speech view --- src/main/resources/static/index.css | 7 +++++++ src/main/resources/templates/speech.ftl | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/resources/static/index.css b/src/main/resources/static/index.css index 7b4108d..3c319f2 100644 --- a/src/main/resources/static/index.css +++ b/src/main/resources/static/index.css @@ -82,7 +82,14 @@ body { main { width: 80%; + flex: 1 +} + +.centered-content { + display: flex; justify-content: center; + align-items: center; + padding: 0 auto; } /* Heading Styling */ diff --git a/src/main/resources/templates/speech.ftl b/src/main/resources/templates/speech.ftl index 0fd7304..8c282d8 100644 --- a/src/main/resources/templates/speech.ftl +++ b/src/main/resources/templates/speech.ftl @@ -32,11 +32,14 @@
<#if picture??> - Foto von ${s.speakerName} +
+ Foto von ${s.speakerName} +
<#else>

(kein Foto verfügbar)

-

+
+
<#list s.content as c> <#include "speechContent.ftl"> From 9306a1f715522f992f09fb5daa0acb6c051a7035 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Thu, 20 Mar 2025 15:21:02 +0100 Subject: [PATCH 2/7] Migrated logs to my implementation --- .../texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java index e01e647..32f842e 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/nlp/NlpUtils.java @@ -360,8 +360,8 @@ public class NlpUtils { bulkOperations.add(new UpdateOneModel<>(updateFilter, update)); } if (!bulkOperations.isEmpty()) { - System.out.println("Processing of " + bulkOperations.size() + " documents finished"); - System.out.println("uploading..."); + Logger.debug("Processing of " + bulkOperations.size() + " documents finished"); + Logger.debug("uploading..."); mongoDBHandler.bulkWriteNlpData(bulkOperations); Logger.debug("Bulk write completed for " + bulkOperations.size() + " documents."); mongoDBHandler.close(); From a4e76dbc770028f79882e0af0f58867dbde47e66 Mon Sep 17 00:00:00 2001 From: Jonas Werner Date: Thu, 20 Mar 2025 15:22:32 +0100 Subject: [PATCH 3/7] Migrated logs to my implementation --- .../project/gruppe_05_1/rest/FrontEndController.java | 4 ++-- .../project/gruppe_05_1/rest/SpeechController.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 69bda9f..e859fc0 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 @@ -178,12 +178,12 @@ public class FrontEndController { .map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), "")) // Lemma remains empty .collect(Collectors.toList()); - System.out.println("DEBUG: Sending POS List to NLP - " + posList); + Logger.debug("Sending POS List to NLP - " + posList); speech.getNlp().setPosList((List) posList); } else { - System.out.println("DEBUG: POS List is EMPTY"); + Logger.debug("POS List is EMPTY"); speech.getNlp().setPosList((List) new ArrayList()); // Ensure it's never null } 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 9a6e689..94a326f 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 @@ -98,12 +98,12 @@ public class SpeechController { .map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), "")) // Lemma remains empty .collect(Collectors.toList()); - System.out.println("DEBUG: Sending POS List to NLP - " + posList); + Logger.debug("Sending POS List to NLP - " + posList); speech.getNlp().setPosList((List) posList); } else { - System.out.println("DEBUG: POS List is EMPTY"); + Logger.debug("POS List is EMPTY"); speech.getNlp().setPosList((List) new ArrayList()); // Ensure it's never null } From b7953147167230e591be7cf6a0151b46439242e9 Mon Sep 17 00:00:00 2001 From: vysitor Date: Thu, 20 Mar 2025 15:24:44 +0100 Subject: [PATCH 4/7] added stylesheet sentiment colors --- src/main/resources/static/index.css | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/resources/static/index.css b/src/main/resources/static/index.css index 3c319f2..94d0436 100644 --- a/src/main/resources/static/index.css +++ b/src/main/resources/static/index.css @@ -234,6 +234,18 @@ tbody tr:hover { text-align: center; } +.sentiment-positive { + color: green; +} + +.sentiment-negative { + color: red; +} + +.sentiment-neutral { + color: grey; +} + .back-link { position: fixed; bottom: 50px; From e65abe88bcd0da42c821ab369a94e7981d8592fb Mon Sep 17 00:00:00 2001 From: vysitor Date: Thu, 20 Mar 2025 15:30:43 +0100 Subject: [PATCH 5/7] Work on Sentiment, Bug with empty topic list fixed --- .../gruppe_05_1/domain/html/HtmlSpeech.java | 2 + .../gruppe_05_1/domain/nlp/Sentiment.java | 25 +++++++ .../gruppe_05_1/rest/SpeechController.java | 70 +++++++++++-------- src/main/resources/templates/nlp.ftl | 4 +- 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/html/HtmlSpeech.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/html/HtmlSpeech.java index c002048..dfc795d 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/html/HtmlSpeech.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/html/HtmlSpeech.java @@ -4,6 +4,7 @@ import org.bson.Document; 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.nlp.NlpInfo; +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; @@ -70,6 +71,7 @@ public class HtmlSpeech { List namedEntitiesDocs = nlpDoc.get("namedEntities", MongoDBHandler.DOC_LIST_CLASS); List sentimentsDocs = nlpDoc.get("sentiments", MongoDBHandler.DOC_LIST_CLASS); + nlp.setSentiments(Sentiment.readSentimentsFromMongo(sentimentsDocs)); List topicsDocs = nlpDoc.get("topics", MongoDBHandler.DOC_LIST_CLASS); nlp.setTopics(Topic.readTopicsFromMongo(topicsDocs)); diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/nlp/Sentiment.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/nlp/Sentiment.java index a2f04e3..ce29182 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/nlp/Sentiment.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/nlp/Sentiment.java @@ -1,5 +1,9 @@ package org.texttechnologylab.project.gruppe_05_1.domain.nlp; +import org.bson.Document; + +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.StringJoiner; @@ -94,4 +98,25 @@ public class Sentiment { .add("positive=" + positive) .toString(); } + + /** + * + * @param sentimentDocs Die Sentiment-Dokumente (Speech --> analysisResults --> sentiment) aus der MongoDB lesen. + * Das erste Dokument ist für die gesamte Rede, Sentiments 1..n entsprechen Sentences 0..n-1 + * @return + */ + public static List readSentimentsFromMongo(List sentimentDocs) { + List sentiments = new ArrayList<>(); + for (Document doc : sentimentDocs) { + sentiments.add(new Sentiment( + doc.getInteger("begin"), + doc.getInteger("end"), + doc.getDouble("score"), + doc.getDouble("pos"), + doc.getDouble("neu"), + doc.getDouble("neg") + )); + } + return sentiments; + } } 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 94a326f..16d9856 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 @@ -78,38 +78,48 @@ public class SpeechController { String picture = MongoPprUtils.getParlamentarierPictureByID(parlamentarierId); attributes.put("picture", picture); - // NLP: Topic - if ((speech.getNlp() != null) && (speech.getNlp().getTopics() != null)) { - Map topics = Topic.condenseTopicInformation(speech.getNlp().getTopics()); // Daten "verdichten"... - // ... und ersetzen - speech.getNlp().setTopics( - topics.entrySet().stream() - .map(me -> new Topic(me.getKey(), me.getValue(), null)) - .collect(Collectors.toList())); + // NLP + if (speech.getNlp() != null) { + + // NLP: Topic + if ((speech.getNlp().getTopics() != null) && (speech.getNlp().getTopics().size() > 0)) { + Map topics = Topic.condenseTopicInformation(speech.getNlp().getTopics()); // Daten "verdichten"... + // ... und ersetzen + speech.getNlp().setTopics( + topics.entrySet().stream() + .map(me -> new Topic(me.getKey(), me.getValue(), null)) + .collect(Collectors.toList())); + } else { + speech.getNlp().setTopics(null); + } + + // NLP: POS + if (speech.getNlp().getTokens() != null) { + List tokens = speech.getNlp().getTokens(); + + Map posCounts = Token.countPOS(tokens); + + List posList = posCounts.entrySet().stream() + .map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), "")) // Lemma remains empty + .collect(Collectors.toList()); + + Logger.debug("Sending POS List to NLP - " + posList); + + speech.getNlp().setPosList((List) posList); + + } else { + Logger.debug("POS List is EMPTY"); + speech.getNlp().setPosList((List) new ArrayList()); // Ensure it's never 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 + if (speech.getNlp().getSentiments() != null) { + + } } - // NLP: POS - if (speech.getNlp() != null && speech.getNlp().getTokens() != null) { - List tokens = speech.getNlp().getTokens(); - - Map posCounts = Token.countPOS(tokens); - - List posList = posCounts.entrySet().stream() - .map(entry -> new Token(entry.getKey(), String.valueOf(entry.getValue()), "")) // Lemma remains empty - .collect(Collectors.toList()); - - Logger.debug("Sending POS List to NLP - " + posList); - - speech.getNlp().setPosList((List) posList); - - } else { - Logger.debug("POS List is EMPTY"); - speech.getNlp().setPosList((List) new ArrayList()); // Ensure it's never 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 - - ctx.render("speech.ftl", attributes); } diff --git a/src/main/resources/templates/nlp.ftl b/src/main/resources/templates/nlp.ftl index 4dfeb43..e37399b 100644 --- a/src/main/resources/templates/nlp.ftl +++ b/src/main/resources/templates/nlp.ftl @@ -17,7 +17,9 @@ <#if s.nlp.sentiments??>

SentimentsInformation (als Radar Chart)

- <#assign overallSentiment = s.nlp.overallSentiment> + <#if s.nlp.overallSentiment??> + <#assign overallSentiment = s.nlp.overallSentiment> + <#assign sentiments = s.nlp.sentiments> <#include "sentimentsRadarChart.ftl"> <#else> From a21c19ab7567e2fb473dcd6576002cf6b466c39d Mon Sep 17 00:00:00 2001 From: vysitor Date: Thu, 20 Mar 2025 17:31:39 +0100 Subject: [PATCH 6/7] Error handling for non existing speeches --- .../gruppe_05_1/database/MongoPprUtils.java | 1 + .../gruppe_05_1/rest/SpeechController.java | 5 ++ src/main/resources/templates/speech.ftl | 83 +++++++++++-------- 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java index 6cdb273..ae937b4 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/database/MongoPprUtils.java @@ -623,6 +623,7 @@ public class MongoPprUtils { System.out.println("SpeechDoc "+ speechDoc); // TODO: remove when no longer needed if (speechDoc == null) { Logger.error("Rede " + key + " nicht gefunden"); + return null; } return new HtmlSpeech(speechDoc); 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 16d9856..032561d 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 @@ -72,6 +72,11 @@ public class SpeechController { Map attributes = new HashMap<>(); HtmlSpeech speech = MongoPprUtils.getSpeechByKey(redeId); + if (speech == null) { + attributes.put("error", "Rede " + redeId + " nicht vorhanden"); + ctx.render("speech.ftl", attributes); + return; + } attributes.put("s", speech); // Foto des Abgeordnetes diff --git a/src/main/resources/templates/speech.ftl b/src/main/resources/templates/speech.ftl index 8c282d8..fb17b71 100644 --- a/src/main/resources/templates/speech.ftl +++ b/src/main/resources/templates/speech.ftl @@ -4,7 +4,13 @@ - Rede von ${s.speakerName} <#if s.fraction??> (${s.fraction}) </#if> + + <#if s??> + Rede von ${s.speakerName} <#if s.fraction??> (${s.fraction}) </#if> + <#else> + Fehler + </#if> +