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 ea844b3..accc14e 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 @@ -69,7 +69,7 @@ public class HtmlSpeech { nlp.setNamedEntities(NamedEntity.readNamedEntitiesFromMongo(namedEntitiesDocs)); List sentimentDocs = nlpDoc.get("sentiments", MongoDBHandler.DOC_LIST_CLASS); - nlp.setSentiments(List.of(Sentiment.readFirstSentimentFromMongo(sentimentDocs))); + nlp.setSentiments(Sentiment.readSentimentsFromMongo((sentimentDocs))); 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 c63abdf..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 @@ -99,14 +99,24 @@ public class Sentiment { .toString(); } - public static Sentiment readFirstSentimentFromMongo(List 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 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/FrontEndController.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/FrontEndController.java index e3cc361..359d8ad 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 @@ -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 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 speechMetaDataList = MongoPprUtils.getSpeechesMetadataForSpeaker(parlamentarierId); - - Map 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 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 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 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 - } - - // 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); - } } diff --git a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java index 3d6e066..2d50db1 100644 --- a/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java +++ b/src/main/java/org/texttechnologylab/project/gruppe_05_1/rest/RESTHandler.java @@ -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) } 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 c48556d..76745cb 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 @@ -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 tokens = speech.getNlp().getTokens(); Map 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 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 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); diff --git a/src/main/resources/templates/nlp.ftl b/src/main/resources/templates/nlp.ftl index 46adcf4..7e9bf9e 100644 --- a/src/main/resources/templates/nlp.ftl +++ b/src/main/resources/templates/nlp.ftl @@ -20,7 +20,7 @@
- <#if sentiment??> + <#if overallSentiment??>

Sentiments Information (als Radar Chart)

<#include "sentimentsRadarChart.ftl"> <#else> diff --git a/src/main/resources/templates/sentimentsRadarChart.ftl b/src/main/resources/templates/sentimentsRadarChart.ftl index 9ae0d41..16c5f01 100644 --- a/src/main/resources/templates/sentimentsRadarChart.ftl +++ b/src/main/resources/templates/sentimentsRadarChart.ftl @@ -1,11 +1,11 @@