Fixed all Chart issues, all 4 now displayed. FrontendController largerly absorbed into Speech-/ Parlamentariercontroller
This commit is contained in:
parent
8a10ef9364
commit
3a2dce4853
7 changed files with 50 additions and 174 deletions
|
@ -69,7 +69,7 @@ public class HtmlSpeech {
|
|||
nlp.setNamedEntities(NamedEntity.readNamedEntitiesFromMongo(namedEntitiesDocs));
|
||||
|
||||
List<Document> sentimentDocs = nlpDoc.get("sentiments", MongoDBHandler.DOC_LIST_CLASS);
|
||||
nlp.setSentiments(List.of(Sentiment.readFirstSentimentFromMongo(sentimentDocs)));
|
||||
nlp.setSentiments(Sentiment.readSentimentsFromMongo((sentimentDocs)));
|
||||
|
||||
List<Document> topicsDocs = nlpDoc.get("topics", MongoDBHandler.DOC_LIST_CLASS);
|
||||
nlp.setTopics(Topic.readTopicsFromMongo(topicsDocs));
|
||||
|
|
|
@ -99,14 +99,24 @@ public class Sentiment {
|
|||
.toString();
|
||||
}
|
||||
|
||||
public static Sentiment readFirstSentimentFromMongo(List<Document> sentimentDocs) {
|
||||
Document doc = sentimentDocs.get(0);
|
||||
return new Sentiment(doc.getInteger("begin"),
|
||||
doc.getInteger("end"),
|
||||
doc.getDouble("score"),
|
||||
doc.getDouble("pos"),
|
||||
doc.getDouble("neu"),
|
||||
doc.getDouble("neg")
|
||||
);
|
||||
/**
|
||||
*
|
||||
* @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<Sentiment> readSentimentsFromMongo(List<Document> sentimentDocs) {
|
||||
List<Sentiment> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@ public class FrontEndController {
|
|||
ctx.render("home.ftl");
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: getAllParlamentarier gibt es hier UND im ParlamentarierController (etwas unterschiedliche Implementierungen)
|
||||
--> konsolidieren!
|
||||
*/
|
||||
@OpenApi(
|
||||
summary = "Get alle Parlamentarier. Man kann nach Vor-, Nachname oder Partei filtern.",
|
||||
description = "Listet alle Parlamentarier bzw. diejenige, welche den Filter entsprechen",
|
||||
|
@ -63,157 +67,16 @@ public class FrontEndController {
|
|||
ctx.render("parlamentarier.ftl", attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeigt die Details eines Parlamentariers an:
|
||||
* - persönliche Daten (Geburtsdatum, -ort, Vita, Religion etc.).
|
||||
* - Mitgliederschaften, falls vorhanden
|
||||
* - Fotos, falls vorhanden
|
||||
* @param ctx JavaLin-Context
|
||||
/*
|
||||
TODO: Achtung: getParlamentarierDetails gibt es ab jetzt LEDIGLICH im ParlamentarierController!
|
||||
*/
|
||||
|
||||
@OpenApi(
|
||||
summary = "Zeigt die Details eines Parlamentariers an",
|
||||
description = "Zeigt persönliche Daten, Mitgliederschaften, Fotos",
|
||||
operationId = "getParlamentarierDetails",
|
||||
path = "/portfolio/{id}",
|
||||
methods = HttpMethod.GET,
|
||||
tags = {"Parlamentarier"},
|
||||
pathParams = {
|
||||
@OpenApiParam(name = "id", description = "id des Parlamentariers", required = true),
|
||||
},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = ParlamentarierDetails.class)})
|
||||
})
|
||||
public static void getParlamentarierDetails(Context ctx) {
|
||||
String id = ctx.pathParam("id");
|
||||
Logger.info("getParlamentarierDetails, ID = " + id);
|
||||
|
||||
ParlamentarierDetails pd = MongoPprUtils.getParlamentarierDetailsByID(id);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("p", pd);
|
||||
Long speechCount = MongoPprUtils.countSpeechesOfSpeaker(pd.getId());
|
||||
attributes.put("speechesCount", speechCount);
|
||||
attributes.put("pic", MongoPprUtils.getMemberPhoto(pd.getId()));
|
||||
if (speechCount == 0) {
|
||||
attributes.put("speechesPlaceholder", null);
|
||||
} else {
|
||||
attributes.put("speechesPlaceholder", new ArrayList<>());
|
||||
}
|
||||
|
||||
ctx.render("parlamentarierDetails.ftl", attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liste alle Reden eines Parlamentariers an
|
||||
* @param ctx Javalin Context
|
||||
/*
|
||||
TODO: Achtung: showSpeech gibt es ab jetzt LEDIGLICH im SpeechController!
|
||||
*/
|
||||
@OpenApi(
|
||||
summary = "Liste alle Reden eines Parlamentariers an",
|
||||
description = "Liste alle Reden eines Parlamentariers an",
|
||||
operationId = "listSpeeches",
|
||||
path = "/reden/{id}",
|
||||
methods = HttpMethod.GET,
|
||||
tags = {"Rede"},
|
||||
pathParams = {
|
||||
@OpenApiParam(name = "id", description = "id des Parlamentariers", required = true),
|
||||
},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = Speech[].class)})
|
||||
})
|
||||
public static void listSpeeches(Context ctx) {
|
||||
String parlamentarierId = ctx.pathParam("id");
|
||||
|
||||
ParlamentarierDetails p = MongoPprUtils.getParlamentarierDetailsByID(parlamentarierId);
|
||||
List<SpeechMetaData> speechMetaDataList = MongoPprUtils.getSpeechesMetadataForSpeaker(parlamentarierId);
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("p", p);
|
||||
attributes.put("speechesMetaDataList", speechMetaDataList);
|
||||
ctx.render("showSpeechesList.ftl", attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zeige eine bestimmte Rede des Parlamentariers an
|
||||
* @param ctx Javalin Context
|
||||
/*
|
||||
TODO: Achtung: showSpeech gibt es ab jetzt LEDIGLICH im SpeechController!
|
||||
*/
|
||||
@OpenApi(
|
||||
summary = "Zeige eine bestimmte Rede des Parlamentariers an",
|
||||
description = "Zeige eine bestimmte Rede des Parlamentariers an",
|
||||
operationId = "showSpeech",
|
||||
path = "/reden/{id}/{redeID}",
|
||||
methods = HttpMethod.GET,
|
||||
tags = {"Rede"},
|
||||
pathParams = {
|
||||
@OpenApiParam(name = "id", description = "id des Parlamentariers", required = true),
|
||||
@OpenApiParam(name = "redeId", description = "id der Rede", required = true),
|
||||
},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200", content = {@OpenApiContent(from = Speech.class)})
|
||||
})
|
||||
public static void showSpeech(Context ctx) {
|
||||
String parlamentarierId = ctx.pathParam("id");
|
||||
String redeId = ctx.pathParam("redeId");
|
||||
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
|
||||
HtmlSpeech speech = MongoPprUtils.getSpeechByKey(redeId);
|
||||
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: 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());
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// NLP: Sentiments
|
||||
Sentiment sentimentObj = null;
|
||||
if (speech.getNlp() != null && speech.getNlp().getSentiments() != null && !speech.getNlp().getSentiments().isEmpty()) {
|
||||
Sentiment first = speech.getNlp().getSentiments().get(0);
|
||||
sentimentObj = new Sentiment(
|
||||
first.getBegin(),
|
||||
first.getEnd(),
|
||||
first.getSentiment(),
|
||||
first.getNegative(),
|
||||
first.getNeutral(),
|
||||
first.getPositive()
|
||||
);
|
||||
|
||||
|
||||
} else {
|
||||
// No sentiment found: use a default sentiment with zero values
|
||||
sentimentObj = new Sentiment(0, 0, 0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
Logger.debug("Speech Sentiment - " + sentimentObj);
|
||||
attributes.put("sentiment", sentimentObj);
|
||||
|
||||
ctx.render("speech.ftl", attributes);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ public class RESTHandler {
|
|||
app.get("/portfolio/{id}", ParlamentarierController::getParlamentarierDetails);
|
||||
|
||||
// Reden
|
||||
app.get("/reden/{id}", FrontEndController::listSpeeches); // zeige Reden eines Parlamentariers an
|
||||
app.get("/reden/{id}/{redeId}", FrontEndController::showSpeech); // zeige eine bestimmte Rede des Parlamentariers an
|
||||
app.get("/reden/{id}", SpeechController::listSpeeches); // zeige Reden eines Parlamentariers an
|
||||
app.get("/reden/{id}/{redeId}", SpeechController::showSpeech); // zeige eine bestimmte Rede des Parlamentariers an
|
||||
|
||||
app.get("/reden", SpeechController::listAllSpeeches); // zeige alle Reden an (Filtern möglich)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ 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.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;
|
||||
|
@ -99,7 +100,7 @@ public class SpeechController {
|
|||
}
|
||||
|
||||
// NLP: POS
|
||||
if (speech.getNlp().getTokens() != null) {
|
||||
if (speech.getNlp() != null && speech.getNlp().getTokens() != null) {
|
||||
List<Token> tokens = speech.getNlp().getTokens();
|
||||
|
||||
Map<String, Integer> posCounts = Token.countPOS(tokens);
|
||||
|
@ -136,13 +137,7 @@ public class SpeechController {
|
|||
text,
|
||||
typeAppearance.get(text) + 1) ;
|
||||
} else {
|
||||
// ... aber der Text unbekannt --> erstelle einen neuen Eintrag für den Text und füge diesen dem Type-Eintrag hinzu
|
||||
// TODO: DELETE
|
||||
//Map<String, Integer> firstTextAppearance = new HashMap<>();
|
||||
//firstTextAppearance.put(type, 1);
|
||||
|
||||
typeAppearance.put(text, 1);
|
||||
//namedEntitiesMapOfMaps.put(type, firstTextAppearance);
|
||||
}
|
||||
} else {
|
||||
// Named Entity Type unbekannt: erstelle einen neuen Eintrag für Type sowie einen Eintrag für den ihm gehörigen Text
|
||||
|
@ -159,10 +154,18 @@ public class SpeechController {
|
|||
|
||||
// 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 - TODO
|
||||
if (speech.getNlp().getSentiments() != null) {
|
||||
|
||||
// NLP: Sentiments
|
||||
// Der erste Sentiment gilt der gesamten Rede. Die weitere Sentiments entsprechen die Sätze.
|
||||
List<Sentiment> sentiments = speech.getNlp().getSentiments();
|
||||
if ((sentiments != null) && ! sentiments.isEmpty()) {
|
||||
Sentiment overallSentiment = sentiments.get(0);
|
||||
attributes.put("overallSentiment", overallSentiment);
|
||||
sentiments.remove(0);
|
||||
} else {
|
||||
attributes.put("overallSentiment", null);
|
||||
}
|
||||
attributes.put("sentiments", sentiments);
|
||||
|
||||
}
|
||||
|
||||
ctx.render("speech.ftl", attributes);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</div>
|
||||
|
||||
<div class="chart">
|
||||
<#if sentiment??>
|
||||
<#if overallSentiment??>
|
||||
<h3>Sentiments Information (als Radar Chart)</h3>
|
||||
<#include "sentimentsRadarChart.ftl">
|
||||
<#else>
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<svg class="chart-svg" id="sentimentsRadarChart"></svg>
|
||||
<script src="https://d3js.org/d3.v6.min.js"></script>
|
||||
<script>
|
||||
// Retrieve sentiment values from the passed attribute "sentiment"
|
||||
// Retrieve sentiment values from the passed attribute "overallSentiment"
|
||||
var sentimentData = {
|
||||
pos: ${sentiment.positive?number},
|
||||
neu: ${sentiment.neutral?number},
|
||||
neg: ${sentiment.negative?number}
|
||||
pos: ${overallSentiment.positive?string?replace(',', '.')},
|
||||
neu: ${overallSentiment.neutral?string?replace(',', '.')},
|
||||
neg: ${overallSentiment.negative?string?replace(',', '.')}
|
||||
};
|
||||
console.log("Sentiment Data:", sentimentData);
|
||||
|
||||
|
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.9 KiB |
Loading…
Add table
Add a link
Reference in a new issue