Merge branch 'main' into 'Sentiments-Radar-Chart'
# Conflicts: # src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/html/HtmlSpeech.java # src/main/java/org/texttechnologylab/project/gruppe_05_1/domain/nlp/Sentiment.java # src/main/resources/templates/nlp.ftl
This commit is contained in:
commit
54ff4b1c7f
8 changed files with 133 additions and 73 deletions
|
@ -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);
|
||||
|
|
|
@ -3,10 +3,7 @@ package org.texttechnologylab.project.gruppe_05_1.domain.html;
|
|||
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.nlp.*;
|
||||
import org.texttechnologylab.project.gruppe_05_1.domain.speech.SpeechMetaData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -69,6 +66,7 @@ public class HtmlSpeech {
|
|||
List<Document> dependenciesDocs = nlpDoc.get("dependencies", MongoDBHandler.DOC_LIST_CLASS);
|
||||
|
||||
List<Document> namedEntitiesDocs = nlpDoc.get("namedEntities", MongoDBHandler.DOC_LIST_CLASS);
|
||||
nlp.setNamedEntities(NamedEntity.readNamedEntitiesFromMongo(namedEntitiesDocs));
|
||||
|
||||
List<Document> sentimentDocs = nlpDoc.get("sentiments", MongoDBHandler.DOC_LIST_CLASS);
|
||||
nlp.setSentiments(List.of(Sentiment.readFirstSentimentFromMongo(sentimentDocs)));
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
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;
|
||||
|
||||
public class NamedEntity {
|
||||
String type; // PER, LOC etc.
|
||||
// int begin; // TODO: momentan nicht in MongoDB
|
||||
// int end; // TODO: momentan nicht in MongoDB
|
||||
String text;
|
||||
|
||||
public NamedEntity() {
|
||||
|
@ -52,4 +54,15 @@ public class NamedEntity {
|
|||
.add("text='" + text + "'")
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static List<NamedEntity> readNamedEntitiesFromMongo(List<Document> nadocs) {
|
||||
List<NamedEntity> nes = new ArrayList<>();
|
||||
for (Document doc : nadocs) {
|
||||
nes.add(new NamedEntity(
|
||||
doc.getString("type"),
|
||||
doc.getString("text")
|
||||
));
|
||||
}
|
||||
return nes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -184,12 +184,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<Token>()); // Ensure it's never null
|
||||
}
|
||||
|
||||
|
|
|
@ -72,44 +72,59 @@ public class SpeechController {
|
|||
Map<String, Object> 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
|
||||
String picture = MongoPprUtils.getParlamentarierPictureByID(parlamentarierId);
|
||||
attributes.put("picture", picture);
|
||||
|
||||
// NLP: Topic
|
||||
if ((speech.getNlp() != null) && (speech.getNlp().getTopics() != null)) {
|
||||
Map<String, Double> 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<String, Double> 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<Token> tokens = speech.getNlp().getTokens();
|
||||
|
||||
Map<String, Integer> posCounts = Token.countPOS(tokens);
|
||||
|
||||
List<Token> 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<Token>()); // 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<Token> tokens = speech.getNlp().getTokens();
|
||||
|
||||
Map<String, Integer> posCounts = Token.countPOS(tokens);
|
||||
|
||||
List<Token> posList = posCounts.entrySet().stream()
|
||||
.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);
|
||||
|
||||
speech.getNlp().setPosList((List) posList);
|
||||
|
||||
} else {
|
||||
System.out.println("DEBUG: POS List is EMPTY");
|
||||
speech.getNlp().setPosList((List) new ArrayList<Token>()); // 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
@ -227,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;
|
||||
|
|
|
@ -4,7 +4,13 @@
|
|||
<link rel="stylesheet" href="/index.css">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Rede von ${s.speakerName} <#if s.fraction??> (${s.fraction}) </#if></title>
|
||||
<title>
|
||||
<#if s??>
|
||||
Rede von ${s.speakerName} <#if s.fraction??> (${s.fraction}) </#if>
|
||||
<#else>
|
||||
Fehler
|
||||
</#if>
|
||||
</title>
|
||||
<style type="text/css">
|
||||
th, td {
|
||||
padding: 12px;
|
||||
|
@ -15,44 +21,52 @@
|
|||
</head>
|
||||
<#include "header.ftl">
|
||||
<body>
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<h1>
|
||||
Rede von ${s.speakerName}
|
||||
<#if s.fraction??> (${s.fraction}) </#if>
|
||||
<#if s.dateTimeString??> vom ${s.dateTimeString} </#if>
|
||||
</h1>
|
||||
<#if s??>
|
||||
<script src="https://d3js.org/d3.v7.min.js"></script>
|
||||
<h1>
|
||||
Rede von ${s.speakerName}
|
||||
<#if s.fraction??> (${s.fraction}) </#if>
|
||||
<#if s.dateTimeString??> vom ${s.dateTimeString} </#if>
|
||||
</h1>
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<h2>
|
||||
Rede ${s.speechKey}
|
||||
<#if s.agendaTitle??> / Agendapunkt: ${s.agendaTitle} </#if>
|
||||
</h2>
|
||||
<h2>
|
||||
Rede ${s.speechKey}
|
||||
<#if s.agendaTitle??> / Agendapunkt: ${s.agendaTitle} </#if>
|
||||
</h2>
|
||||
|
||||
<br>
|
||||
<main>
|
||||
<#if picture??>
|
||||
<img style="max-width: 400px; height: auto;" src="data:image/jpeg;base64,${picture}" alt="Foto von ${s.speakerName}" />
|
||||
<br>
|
||||
<main>
|
||||
<#if picture??>
|
||||
<div class="centered-content">
|
||||
<img style="max-width: 400px; height: auto; margin-bottom: 20px" src="data:image/jpeg;base64,${picture}" alt="Foto von ${s.speakerName}" />
|
||||
</div>
|
||||
<#else>
|
||||
<h2>(kein Foto verfügbar)</h2>
|
||||
</#if>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<#list s.content as c>
|
||||
<#include "speechContent.ftl">
|
||||
</#list>
|
||||
|
||||
<br><br>
|
||||
<#if s.nlp??>
|
||||
<h2>NLP Information</h2>
|
||||
<#assign nlp = "${s.nlp}">
|
||||
<#include "nlp.ftl">
|
||||
<#else>
|
||||
<h2>Keine NLP Information verfügbar für diese Rede</h2>
|
||||
</#if>
|
||||
<br> <br>
|
||||
|
||||
</main>
|
||||
<#else>
|
||||
<h2>(kein Foto verfügbar)</h2>
|
||||
<h2> ${error} </h2>
|
||||
</#if>
|
||||
<br> <br>
|
||||
|
||||
<#list s.content as c>
|
||||
<#include "speechContent.ftl">
|
||||
</#list>
|
||||
|
||||
<br><br>
|
||||
<#if s.nlp??>
|
||||
<h2>NLP Information</h2>
|
||||
<#assign nlp = "${s.nlp}">
|
||||
<#include "nlp.ftl">
|
||||
<#else>
|
||||
<h2>Keine NLP Information verfügbar für diese Rede</h2>
|
||||
</#if>
|
||||
<br> <br>
|
||||
|
||||
</main>
|
||||
</body>
|
||||
<#include "footer.ftl">
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue