sentiments colors, topics in dashboard

master
Giò Diani 2025-01-17 08:54:42 +01:00
parent f7c0df98b2
commit 40057f7971
6 changed files with 84 additions and 63 deletions

View File

@ -238,6 +238,10 @@ main {
gap: 1em; gap: 1em;
} }
ol{
padding-left: 1em
}
#video { #video {
grid-area: video; grid-area: video;
} }
@ -343,3 +347,30 @@ ul.segments li{
.track-viz svg{ .track-viz svg{
width: 100% !important; width: 100% !important;
} }
#sentiments-list{
list-style: none;
padding: 0;
}
#sentiments-list li{
margin-top: .5em;
}
#sentiments-list span{
display: inline-block;
background: #d01c8b;
width: 1.5em;
height: 1.5em;
border-radius: 50%;
text-align: center;
}
#sentiments-list span.pos{
background: #4dac26;
}
#sentiments-list span.neut{
background: #f7f7f7;
color: #000;
}

View File

@ -47,6 +47,8 @@ function setWordCountChart(){
// let max = totalWordCount / count; // let max = totalWordCount / count;
let data = []; let data = [];
let wordWordsLen = wordWords.length; let wordWordsLen = wordWords.length;
let chunks = Math.floor(wordWordsLen / count); let chunks = Math.floor(wordWordsLen / count);
@ -69,8 +71,6 @@ function setWordCountChart(){
} }
}) })
console.log(max)
for(let i = 0; i < count; i++){ for(let i = 0; i < count; i++){
grid.push({ grid.push({
left: `${i * (100 / count)}%`, left: `${i * (100 / count)}%`,
@ -170,12 +170,22 @@ const chartSentimentsOptions = {
type: "category", type: "category",
data: ["-1", "0", "1"] data: ["-1", "0", "1"]
}, },
color: '#fff',
series: [ series: [
{ {
symbolSize: sentiWeights, symbolSize: sentiWeights,
data: sentiPol, data: sentiPol,
type: 'scatter' type: 'scatter',
itemStyle: {
color: (e) => {
if(e.data == -1){
return '#d01c8b'
}else if(e.data == 0){
return '#f7f7f7'
}else{
return '#4dac26'
}
}
}
} }
] ]
}; };
@ -288,40 +298,5 @@ document.querySelector('#timeline-bar').addEventListener('click', e => {
player.currentTime(calcCurrenttimeByPosition(x)); player.currentTime(calcCurrenttimeByPosition(x));
}) })
*/ */
const topics = [
["Topic1 Topic2 Topic3"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic6 Topic7 Topic8"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3"],
["Topic1 Topic2 Topic3", "Topic3 Topic4 Topic5", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3", "Topic1 Topic2 Topic3"],
];
function setTopicSegments(count){
let html = '';
topics[count - 1].forEach(t => {
html += `<li>${t}</li>`;
})
let list = document.querySelector('#topic-segement-list');
list.innerHTML = html;
list.style.gridTemplate = `1fr / repeat(${count}, 1fr)`;
}
let topicSegmentCtrl = document.getElementById('topic-track-segment-ctrl');
topicSegmentCtrl.addEventListener('change', e => {
setTopicSegments(e.target.value);
})
setTopicSegments(topicSegmentCtrl.value);

View File

@ -31,7 +31,7 @@
<div class="control"> <div class="control">
<input class="visually-hidden" id="tablist_panel_terms" name="tablist" type="radio" /><label <input class="visually-hidden" id="tablist_panel_terms" name="tablist" type="radio" /><label
for="tablist_panel_terms"><span class="visually-hidden">Zeige Tabinhalt for="tablist_panel_terms"><span class="visually-hidden">Zeige Tabinhalt
</span>Dokumentbegriffe</label> </span>Topics</label>
</div> </div>
</fieldset> </fieldset>
<div class="panel" id="tablist_panel_episode_panel"> <div class="panel" id="tablist_panel_episode_panel">
@ -69,9 +69,15 @@
</div> </div>
<div class="panel" id="tablist_panel_terms_panel" hidden> <div class="panel" id="tablist_panel_terms_panel" hidden>
<h2 class="visually-hidden"> <h2 class="visually-hidden">
Begriffe (Tabinhalt) Topics (Tabinhalt)
</h2> </h2>
<div id="metagrid-widget"></div> <ol>
@foreach($topics as $topic)
<li>
{{ implode(', ', $topic) }}
</li>
@endforeach
</ol>
</div> </div>
</div> </div>
@ -109,27 +115,13 @@
<div class="track"> <div class="track">
<div class="track-ctrl"> <div class="track-ctrl">
<h2>Sentiment</h2> <h2>Sentiment</h2>
<p>1 = Positiv<br >0 = Neutral<br >-1 = Negativ</p> <ul id="sentiments-list">
<li><span class="pos">1</span> = Positiv ({{ round($senti_subdata['verteilung_perc']['positive']) }}%)</li>
<li><span class="neut">0</span> = Neutral ({{ round($senti_subdata['verteilung_perc']['neutral']) }}%)</li >
<li><span class="neg">-1</span> = Negativ ({{ round($senti_subdata['verteilung_perc']['negative']) }}%)</li></p>
</div> </div>
<div class="track-viz" id="sentiment-track" data-time="{{ implode(',', $senti_subdata['time']) }}" data-sentiments="{{ $senti_subdata['data'] }}" data-weights="{{ $senti_subdata['weights'] }}"></div> <div class="track-viz" id="sentiment-track" data-time="{{ implode(',', $senti_subdata['time']) }}" data-sentiments="{{ $senti_subdata['data'] }}" data-weights="{{ $senti_subdata['weights'] }}"></div>
</div> </div>
<div class="track">
<div class="track-ctrl">
<h2>Topics</h2>
<label>
Segmente:
<input type="number" min="1" max="10" value="4" id="topic-track-segment-ctrl">
</label>
</div>
<div class="track-viz">
<ul id="topic-segement-list" class="segments">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
</div>
</div> </div>
</div> </div>
</main> </main>

View File

@ -23,23 +23,40 @@ Route::get('/detail/{id}', function(int $id) {
$subtitles = $ep->subtitles; $subtitles = $ep->subtitles;
$mediacomposition = json_decode($ep->mediacomposition, 1); $mediacomposition = json_decode($ep->mediacomposition, 1);
$durationSteps = $mediacomposition['chapterList'][0]['duration'] / 1000 / 10; $durationSteps = $mediacomposition['chapterList'][0]['duration'] / 1000 / 10;
$topics = json_decode($ep->topics);
$subdata = json_decode($ep->subtitle_data, 1); $subdata = json_decode($ep->subtitle_data, 1);
$subdata_senti = json_decode($ep->sentiments_from_sub, 1); $subdata_senti = json_decode($ep->sentiments_from_sub, 1);
$subdata_senti['data'] = ""; $subdata_senti['data'] = "";
$subdata_senti['weights'] = ""; $subdata_senti['weights'] = "";
$subdata_senti['verteilung'] = ['neutral' => 0, 'negative' => 0, 'positive' => 0];
foreach ($subdata_senti['sentiments'] as $value) { foreach ($subdata_senti['sentiments'] as $value) {
$subdata_senti['data'] .= $value[0].","; $subdata_senti['data'] .= $value[0].",";
$subdata_senti['weights'] .= (30 * $value[1]).","; $subdata_senti['weights'] .= (50 * $value[1]).",";
if($value[0] === 0){
$subdata_senti['verteilung']['neutral']++;
}else if($value[0] === 1){
$subdata_senti['verteilung']['positive']++;
}else{
$subdata_senti['verteilung']['negative']++;
}
} }
$subdata_senti_all = $subdata_senti['verteilung']['neutral'] + $subdata_senti['verteilung']['negative'] + $subdata_senti['verteilung']['positive'];
$subdata_senti['verteilung_perc'] = ['negative' => (100 / $subdata_senti_all) * $subdata_senti['verteilung']['negative'], 'neutral' => (100 / $subdata_senti_all) * $subdata_senti['verteilung']['neutral'], 'positive' => (100 / $subdata_senti_all) * $subdata_senti['verteilung']['positive']];
$wordsPerMinute = array_slice($subdata['word_count'], -1)[0] / (($mediacomposition['chapterList'][0]['duration'] / 1000) / 60); $wordsPerMinute = array_slice($subdata['word_count'], -1)[0] / (($mediacomposition['chapterList'][0]['duration'] / 1000) / 60);
$parser = new Podlove\Webvtt\Parser(); $parser = new Podlove\Webvtt\Parser();
$subtitles = $parser->parse($subtitles); $subtitles = $parser->parse($subtitles);
return view('detail', ['title' => $title, 'subtitles' => $subtitles, 'mediacomposition' => $mediacomposition, 'durationSteps' => $durationSteps, 'dom_color' => $ep->viz_data, 'subdata' => $subdata, 'senti_subdata' => $subdata_senti, 'wpm' => $wordsPerMinute]);
return view('detail', ['title' => $title, 'subtitles' => $subtitles, 'mediacomposition' => $mediacomposition, 'durationSteps' => $durationSteps, 'dom_color' => $ep->viz_data, 'subdata' => $subdata, 'senti_subdata' => $subdata_senti, 'wpm' => $wordsPerMinute, 'topics' => $topics]);
}); });

View File

@ -14,8 +14,14 @@ Zählt die Wortanzahl pro Satz.
python src/normalize_subtitles/count_words.py -ep <int> python src/normalize_subtitles/count_words.py -ep <int>
``` ```
## count_words.py ## sentence_sentiment.py
Rechnet die Sentimente pro Satz. Rechnet die Sentimente pro Satz.
```bash ```bash
python src/normalize_subtitles/sentence_sentiment.py -ep <int> python src/normalize_subtitles/sentence_sentiment.py -ep <int>
``` ```
## topics.py
Generiert Topics mittels LDA.
```bash
python src/normalize_subtitles/topics.py -ep <int>
```

Binary file not shown.