Compare commits
14 commits
e7eb638e29
...
67e117b647
Author | SHA1 | Date | |
---|---|---|---|
|
67e117b647 | ||
|
4db18688b5 | ||
|
a312b7bef0 | ||
|
88cef04f49 | ||
|
5cf33608cf | ||
|
bfb8fb65e8 | ||
|
e8272742db | ||
|
7b68a4988b | ||
|
ac79a35bfb | ||
|
8bd75e1f73 | ||
|
2a1127d68c | ||
|
846e130418 | ||
|
e26bb412aa | ||
|
d2e9cf4dba |
21 changed files with 4207 additions and 3898 deletions
38
Benutzerhandbuch.txt
Normal file
38
Benutzerhandbuch.txt
Normal file
|
@ -0,0 +1,38 @@
|
|||
BENUTZERHANDBUCH MULTIMODAL PARLIAMENT EXPLORER
|
||||
GRUPPE_05_01
|
||||
|
||||
Der Multimodal Parliament Explorer ist eine client-server basierte Anwendung zum automatischen abrufen, analysieren, visualisieren und exportieren aller Reden des Bundestags der aktuellen Legislaturperiode.
|
||||
|
||||
Mit unserem Programm kann man Reden des Bundestags interaktiv erkunden, Statistiken zu den zugehörigen Reden einsehen und diese selbst weiterverwenden.
|
||||
|
||||
|
||||
1. Systemanforderungen
|
||||
|
||||
- Java 17+
|
||||
- Maven
|
||||
- Einen modernen Webbrowser (Chrome, Firefox, Edge)
|
||||
- Einen Internetzugang
|
||||
|
||||
|
||||
2. Hauptfunktionen
|
||||
|
||||
Datenimport:
|
||||
Automatischer Download der XML Protokolle inklusive Videos
|
||||
|
||||
NLP-Analyse:
|
||||
Analyse der Reden durch einen NLP-Docker
|
||||
|
||||
Datenexploration:
|
||||
Filterbar nach Redner, Thema und Datum
|
||||
|
||||
Visualisierung der analysierten Daten:
|
||||
Durch verschiedene Charts werden die Analysedaten anschaulich und verdaubar wiedergegeben
|
||||
|
||||
Export:
|
||||
Alle Reden können als PDF und XML exportiert werden.
|
||||
|
||||
|
||||
3. Support und Weiterführende Dokumentation
|
||||
|
||||
Detaillierte Entwicklungs‑ und Nutzungsanleitungen finden Sie im Repository unter /doc oder auf unserer GitLab-Page bei https://ppr.gitlab.texttechnologylab.org/leonkastner/multimodal-parliament-explorer-docu
|
||||
Bei Fragen oder Fehlern können sie sich gerne bei uns melden.
|
|
@ -154,6 +154,7 @@ Folgende Informationen werden angezeigt:
|
|||
- Informationen zum Redner (Name, Partei, Foto).
|
||||
- Informationen zur Rede (Datum, Uhrzeit, Agendapunkt).
|
||||
- Redetext. Vorstellung und Kommentare werden farblich gekennzeichnet.
|
||||
- Video bei Reden der Sitzung 187 Tagesordnungspunkt 4
|
||||
- NLP Informationen.
|
||||
|
||||
Der NLP-Abschnitt beinhaltet folgende Informationen:
|
||||
|
|
BIN
doc/Gantt_Chart_PPR_Abschlussprojekt.pdf
Normal file
BIN
doc/Gantt_Chart_PPR_Abschlussprojekt.pdf
Normal file
Binary file not shown.
BIN
doc/PPR_Mockup.jpg
Normal file
BIN
doc/PPR_Mockup.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 187 KiB |
77
doc/UseCasePlantUML
Normal file
77
doc/UseCasePlantUML
Normal file
|
@ -0,0 +1,77 @@
|
|||
@startuml
|
||||
left to right direction
|
||||
actor Admin
|
||||
actor Nutzer
|
||||
actor SystemScheduler as "Zeitgesteuerter Dienst"
|
||||
|
||||
rectangle "Multimodal Parliament Explorer" {
|
||||
|
||||
package "Datenimport" {
|
||||
usecase "XML Protokolle herunterladen" as UC1
|
||||
usecase "XML verarbeiten & speichern" as UC2
|
||||
usecase "Videos herunterladen & speichern" as UC3
|
||||
usecase "Fotos der Abgeordneten speichern" as UC4
|
||||
usecase "NLP-Daten einlesen & verarbeiten" as UC5
|
||||
}
|
||||
|
||||
package "NLP Verarbeitung" {
|
||||
usecase "NLP Analyse mit DUUI durchführen" as UC6
|
||||
usecase "NLP-Resultate serialisieren\n& in DB speichern" as UC7
|
||||
}
|
||||
|
||||
package "Export / Serialisierung" {
|
||||
usecase "Rede als PDF exportieren" as UC8
|
||||
usecase "Rede als XML exportieren" as UC9
|
||||
usecase "Rede als XMI exportieren" as UC10
|
||||
}
|
||||
|
||||
package "Visualisierung & UI" {
|
||||
usecase "Reden durchsuchen" as UC11
|
||||
usecase "Rede anzeigen (HTML, NLP, Video)" as UC12
|
||||
usecase "POS / Sentiment / NER / Topics visualisieren" as UC13
|
||||
}
|
||||
|
||||
package "Datenbankoperationen" {
|
||||
usecase "Reden / Sessions / AgendaItems\nin MongoDB speichern" as UC14
|
||||
usecase "Metadaten zu Reden abfragen" as UC15
|
||||
usecase "Video-Referenzen zu Reden abfragen" as UC16
|
||||
}
|
||||
|
||||
package "Systemdienste" {
|
||||
usecase "Auf neue Protokolle automatisch prüfen und herunterladen" as UC17
|
||||
usecase "Neue NLP-Reden automatisch analysieren" as UC18
|
||||
}
|
||||
|
||||
' Verbindungen
|
||||
Admin--> UC1
|
||||
Admin--> UC2
|
||||
Admin--> UC3
|
||||
Admin--> UC4
|
||||
Admin--> UC5
|
||||
Admin--> UC6
|
||||
Admin--> UC7
|
||||
Admin--> UC8
|
||||
Admin--> UC9
|
||||
Admin--> UC10
|
||||
Nutzer--> UC8
|
||||
Nutzer--> UC9
|
||||
Nutzer--> UC10
|
||||
Nutzer --> UC11
|
||||
Nutzer --> UC12
|
||||
Nutzer --> UC13
|
||||
|
||||
UC6 --> UC7
|
||||
UC5 --> UC6
|
||||
UC2 --> UC14
|
||||
UC3 --> UC14
|
||||
UC4 --> UC14
|
||||
UC14 --> UC15
|
||||
UC14 --> UC16
|
||||
|
||||
UC12 --> UC13
|
||||
UC12 --> UC16
|
||||
|
||||
SystemScheduler --> UC17
|
||||
SystemScheduler --> UC18
|
||||
}
|
||||
@enduml
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
File diff suppressed because it is too large
Load diff
BIN
doc/usecasediagram.png
Normal file
BIN
doc/usecasediagram.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 198 KiB |
File diff suppressed because it is too large
Load diff
|
@ -331,6 +331,46 @@ public class MongoPprUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
* Holt alle Reden eines Parlamentariers
|
||||
* @param speakerId
|
||||
* @return
|
||||
*/
|
||||
public static List<SpeechOverview> getSpeechesOverviewForSpeaker(Integer speakerId) {
|
||||
|
||||
List<SpeechOverview> result = new ArrayList<>();
|
||||
|
||||
MongoCollection<Document> collection = getSpeechCollection();
|
||||
|
||||
Document projection = new Document("speechKey", 1)
|
||||
.append("speakerId", 1)
|
||||
.append("dateTimeString", 1)
|
||||
.append("speakerName", 1)
|
||||
.append("fraction", 1)
|
||||
.append("agendaTitel", 1);
|
||||
|
||||
Bson filter = Filters.eq("speakerId", speakerId);
|
||||
|
||||
List<Document> docs = collection.find(filter)
|
||||
.projection(projection)
|
||||
.sort(Sorts.descending("dateTime"))
|
||||
.into(new ArrayList<>());
|
||||
|
||||
for (Document doc : docs) {
|
||||
result.add(new SpeechOverview(
|
||||
doc.getString("speechKey"),
|
||||
doc.getInteger("speakerId"),
|
||||
doc.getString("dateTimeString"),
|
||||
doc.getString("speakerName"),
|
||||
doc.getString("fraction"),
|
||||
doc.getString("agendaTitel")
|
||||
));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementiert von Valentin
|
||||
|
|
|
@ -42,6 +42,20 @@ public class FrontEndController {
|
|||
ctx.render("home.ftl");
|
||||
}
|
||||
|
||||
@OpenApi(
|
||||
summary = "Get the about page.",
|
||||
description = "Get the about",
|
||||
operationId = "getAbout",
|
||||
path = "/about",
|
||||
methods = HttpMethod.GET,
|
||||
tags = {"About"},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200")
|
||||
})
|
||||
public static void getAbout(Context ctx) {
|
||||
ctx.render("about.ftl");
|
||||
}
|
||||
|
||||
/*
|
||||
TODO: getAllParlamentarier gibt es hier UND im ParlamentarierController (etwas unterschiedliche Implementierungen)
|
||||
--> konsolidieren!
|
||||
|
@ -70,6 +84,34 @@ public class FrontEndController {
|
|||
ctx.render("parlamentarier.ftl", attributes);
|
||||
}
|
||||
|
||||
@OpenApi(
|
||||
summary = "Get the export page.",
|
||||
description = "Get the export page",
|
||||
operationId = "getExportPage",
|
||||
path = "/export",
|
||||
methods = HttpMethod.GET,
|
||||
tags = {"Export"},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200")
|
||||
})
|
||||
public static void getExportPage(Context ctx) {
|
||||
ctx.render("export.ftl");
|
||||
}
|
||||
|
||||
@OpenApi(
|
||||
summary = "Get the about page.",
|
||||
description = "Get the about page",
|
||||
operationId = "getAboutPage",
|
||||
path = "/about",
|
||||
methods = HttpMethod.GET,
|
||||
tags = {"About"},
|
||||
responses = {
|
||||
@OpenApiResponse(status = "200")
|
||||
})
|
||||
public static void getAboutPage(Context ctx) {
|
||||
ctx.render("about.ftl");
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregiert für alle Reden die NLP‑Ergebnisse (Topics, POS, Named Entities, erste Sentiment‑Objekte)
|
||||
* und liefert die zusammengefassten Daten an die Charts‑Ansicht.
|
||||
|
|
|
@ -62,6 +62,8 @@ public class RESTHandler {
|
|||
app.get("/", FrontEndController::getHomepage);
|
||||
app.get("/members", FrontEndController::getAllParlamentarier);
|
||||
app.get("/portfolio/{id}", ParlamentarierController::getParlamentarierDetails);
|
||||
app.get("/export", FrontEndController::getExportPage);
|
||||
app.get("/about", FrontEndController::getAboutPage);
|
||||
|
||||
// Reden
|
||||
app.get("/reden/{id}", SpeechController::listSpeeches); // zeige Reden eines Parlamentariers an
|
||||
|
@ -74,12 +76,14 @@ public class RESTHandler {
|
|||
app.get("/charts", FrontEndController::getCharts);
|
||||
|
||||
app.get("/export/pdf/speech/{id}", SpeechesLatexExportController::exportSpeech); // exportiere eine Rede als PDF
|
||||
app.get("/export/pdf/speech", SpeechesLatexExportController::exportSpeech); // exportiere eine Rede als PDF
|
||||
app.get("/export/pdf/speaker/{id}", SpeechesLatexExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als PDF
|
||||
app.get("/export/pdf/topic/{topic}", SpeechesLatexExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als PDF
|
||||
app.get("/export/pdf/all", SpeechesLatexExportController::exportAllSpeeches); // exportiere alle Reden als PDF CAUTION!!!: This will take forever but is required in the exercise
|
||||
app.get("/export/pdf/speeches/{speechIds}", SpeechesLatexExportController::exportSpeeches); // exportiere eine Liste von Reden als PDF
|
||||
|
||||
app.get("/export/xml/speech/{id}", SpeechesXMLExportController::exportSpeech); // exportiere eine Rede als XML
|
||||
app.get("/export/xml/speech", SpeechesXMLExportController::exportSpeech); // exportiere eine Rede als XML
|
||||
app.get("/export/xml/speaker/{id}", SpeechesXMLExportController::exportSpeechesFromSpeaker); // exportiere alle Reden eines Parlamentariers als XML
|
||||
app.get("/export/xml/topic/{topic}", SpeechesXMLExportController::exportSpeechesWithTopic); // exportiere alle Reden zu einem Thema als XML
|
||||
app.get("/export/xml/all", SpeechesXMLExportController::exportAllSpeeches); // exportiere alle Reden als XML
|
||||
|
|
|
@ -45,8 +45,7 @@ public class SpeechController {
|
|||
String parlamentarierId = ctx.pathParam("id");
|
||||
|
||||
ParlamentarierDetails p = MongoPprUtils.getParlamentarierDetailsByID(parlamentarierId);
|
||||
List<SpeechMetaData> speechMetaDataList = MongoPprUtils.getSpeechesMetadataForSpeaker(parlamentarierId);
|
||||
|
||||
List<SpeechOverview> speechMetaDataList = MongoPprUtils.getSpeechesOverviewForSpeaker(Integer.parseInt(parlamentarierId));
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("p", p);
|
||||
attributes.put("speechesMetaDataList", speechMetaDataList);
|
||||
|
|
|
@ -30,11 +30,18 @@ public class SpeechesLatexExportController {
|
|||
@OpenApiResponse(status = "200")
|
||||
})
|
||||
public static void exportSpeech(Context ctx) {
|
||||
String speechId = null;
|
||||
try {
|
||||
speechId = ctx.pathParam("id");
|
||||
} catch (Exception e) {
|
||||
// check query param
|
||||
speechId = ctx.queryParam("speechId");
|
||||
}
|
||||
byte[] pdfBytes = new byte[0];
|
||||
try {
|
||||
pdfBytes = Base64.getDecoder().decode(getExportedSpeechBase64StringBySpeechId(ctx.pathParam("id")));
|
||||
pdfBytes = Base64.getDecoder().decode(getExportedSpeechBase64StringBySpeechId(speechId));
|
||||
} catch (Exception e) {
|
||||
Logger.error("Failed to generate Export of Speech with ID " + ctx.pathParam("id"));
|
||||
Logger.error("Failed to generate Export of Speech with ID " + speechId);
|
||||
Logger.error(e.getMessage());
|
||||
Logger.debug(Arrays.toString(e.getStackTrace()));
|
||||
}
|
||||
|
|
|
@ -32,9 +32,16 @@ public class SpeechesXMLExportController {
|
|||
@OpenApiResponse(status = "200")
|
||||
})
|
||||
public static void exportSpeech(Context ctx) {
|
||||
String speechId = null;
|
||||
try {
|
||||
speechId = ctx.pathParam("id");
|
||||
} catch (Exception e) {
|
||||
// check query param
|
||||
speechId = ctx.queryParam("speechId");
|
||||
}
|
||||
String xmlContent;
|
||||
try {
|
||||
xmlContent = getExportedSpeechById(ctx.pathParam("id"));
|
||||
xmlContent = getExportedSpeechById(speechId);
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(xmlContent.getBytes());
|
||||
if (stream.available() == 0) {
|
||||
Logger.error("XML stream is empty.");
|
||||
|
@ -45,7 +52,7 @@ public class SpeechesXMLExportController {
|
|||
ctx.contentType("application/xml");
|
||||
ctx.result(stream);
|
||||
} catch (Exception e) {
|
||||
Logger.error("Failed to generate Export of Speech with ID " + ctx.pathParam("id"));
|
||||
Logger.error("Failed to generate Export of Speech with ID " + speechId);
|
||||
Logger.error(e.getMessage());
|
||||
Logger.debug(Arrays.toString(e.getStackTrace()));
|
||||
ctx.result("Internal Server Error");
|
||||
|
|
|
@ -2,5 +2,9 @@
|
|||
<link rel="stylesheet" href="index.css">
|
||||
</head>
|
||||
<#include "header.ftl">
|
||||
<h1>About</h1>
|
||||
<h1>Über</h1>
|
||||
<p>Alle Infos zur Nutzung und die Dokumentation kann auf der <a href="https://ppr.gitlab.texttechnologylab.org/leonkastner/multimodal-parliament-explorer-docu">Doku GitLab Repository eingesehen werden</a></p>
|
||||
<br>
|
||||
<br>
|
||||
<p>PPR WS24/25 - Gruppe_05_1</p>
|
||||
<#include "footer.ftl">
|
43
src/main/resources/templates/export.ftl
Normal file
43
src/main/resources/templates/export.ftl
Normal file
|
@ -0,0 +1,43 @@
|
|||
<head>
|
||||
<link rel="stylesheet" href="index.css">
|
||||
<title>Parliament Explorer</title>
|
||||
</head>
|
||||
<#include "header.ftl">
|
||||
<body>
|
||||
<main>
|
||||
<h2>Export von Reden</h2>
|
||||
<p>Export von allen Reden (Dieser Prozess kanne einige Zeit dauern):</p>
|
||||
<div class="export-button centered-flex-button">
|
||||
<div class="red-button centered-flex-button">
|
||||
<a href="/export/pdf/all" target="_blank">PDF Export</a>
|
||||
</div>
|
||||
<br>
|
||||
<div class="red-button centered-flex-button">
|
||||
<a href="/export/xml/all" target="_blank">XML Export</a>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
<p>Export von allen Reden eines Parlamentariers.</p>
|
||||
</div>
|
||||
<#assign formAction = "/members">
|
||||
<#include "filterForm.ftl">
|
||||
<br>
|
||||
<br>
|
||||
<p>Export einer bestimmten Rede nach ID</p>
|
||||
<div class="filter-form">
|
||||
<form name="searchForm" action="/export/pdf/speech" method="GET">
|
||||
|
||||
<input type="text" name="speechId" placeholder="Reden ID">
|
||||
<button type="submit">Als PDF Exportieren</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="filter-form">
|
||||
<form name="searchForm" action="/export/xml/speech" method="GET">
|
||||
|
||||
<input type="text" name="speechId" placeholder="Reden ID">
|
||||
<button type="submit">Als XML Exportieren</button>
|
||||
</form>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
<#include "footer.ftl">
|
|
@ -36,11 +36,11 @@
|
|||
<h2>Reden Export von allen Reden von ${p.vorname} ${p.nachname}</h2>
|
||||
<div class="export-button centered-flex-button">
|
||||
<div class="red-button centered-flex-button">
|
||||
<a href="/export/pdf/speaker/${p.id}">PDF Export</a>
|
||||
<a href="/export/pdf/speaker/${p.id}" target="_blank">PDF Export</a>
|
||||
</div>
|
||||
<br>
|
||||
<div class="red-button centered-flex-button">
|
||||
<a href="/export/xml/speaker/${p.id}">XML Export</a>
|
||||
<a href="/export/xml/speaker/${p.id}" target="_blank">XML Export</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<#list speechesMetaDataList as redeMd>
|
||||
<tr>
|
||||
<td>${redeMd.dateTimeString}</td>
|
||||
<td><a href="/reden/${p.id}/${redeMd.speechKey}">${redeMd.agendaTitle}</a></td>
|
||||
<td><a href="/reden/${p.id}/${redeMd.speechKey}">${redeMd.agendaTitel}</a></td>
|
||||
</tr>
|
||||
</#list>
|
||||
|
||||
|
|
|
@ -51,11 +51,11 @@
|
|||
<h2>Reden Export von dieser Rede</h2>
|
||||
<div class="export-button centered-flex-button">
|
||||
<div class="red-button centered-flex-button">
|
||||
<a href="/export/pdf/speech/${s.speechKey}">PDF Export</a>
|
||||
<a href="/export/pdf/speech/${s.speechKey}" target="_blank">PDF Export</a>
|
||||
</div>
|
||||
<br>
|
||||
<div class="red-button centered-flex-button">
|
||||
<a href="/export/xml/speech/${s.speechKey}">XML Export</a>
|
||||
<a href="/export/xml/speech/${s.speechKey}" target="_blank">XML Export</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue