Skip to content

Commit

Permalink
Add sentiment analysis:
Browse files Browse the repository at this point in the history
- move some libs to cdn to reduce watch times
- sentiment analysis could use some refactoring
  • Loading branch information
evanmarshall committed Feb 27, 2018
1 parent 967e783 commit 59ad36c
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 7 deletions.
4 changes: 2 additions & 2 deletions build/js/index.js

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
<title>HTML Reference</title>
<title>Steemit Word Cloud</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" />
<style>
.demo-title {
Expand All @@ -20,6 +20,8 @@
}

</style>
<script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.js"></script>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
Expand All @@ -46,6 +48,19 @@
<canvas id='word-cloud-canvas'></canvas>
</div>
</div>
<div class="row">
<div id='sentiment' class="col-sm-8 offset-sm-2">
<canvas id='sentiment-canvas'></canvas>
</div>
</div>
<div class="row">
<div id='sentiment' class="col-sm-6 offset-sm-3">
Sentiment analysis determines automatically how positive or negative some text is with 0 being neutral sentiment.
The analysis isn't perfect but it should help you see if a user's post is worded using positive or negative language.

5 is the most extreme positive and -5 is the most extreme negative.
</div>
</div>
<script src="build/js/index.js"></script>
</body>
</html>
5 changes: 5 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@
"dependencies": {
"babel-loader": "^7.1.3",
"babel-plugin-transform-runtime": "^6.23.0",
"chart.js": "^2.7.1",
"gulp": "^3.9.1",
"gulp-util": "^3.0.8",
"sentiment": "^4.2.0",
"source-map-loader": "^0.2.3",
"steem": "^0.7.1",
"transform-runtime": "^0.0.0",
Expand Down
88 changes: 85 additions & 3 deletions src/steemit-stats.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
// External Dependencies
import * as steem from 'steem';
import WordCloud from 'wordcloud';
var sentiment = require('sentiment');
import Chart from 'chart.js';

// Internal Dependencies
import { ignoredWords } from './ignored-words';
import { demoWordFrequencies } from './demo-word-frequencies';

let currentChart = null;

/**
* getAccountHistory
* returns:
Expand All @@ -16,7 +20,6 @@ import { demoWordFrequencies } from './demo-word-frequencies';
* Operation: ( typeOfOperation: string, opInfo: OperationInfo )
* OperationInfo: { body: string, title: string, json_metadata: stringified_json }
*/

const extractDataFromBlocks = (account, blocks) => {
const permlinkSet = new Set();
const allCommentBodies = [];
Expand All @@ -33,6 +36,7 @@ const extractDataFromBlocks = (account, blocks) => {
}
});

getSentiment(allCommentBodies);
const wordAndCount = extractWordAndCounts(allCommentBodies.join(' '));
const words = Object.keys(wordAndCount);
words.sort((word1, word2) => wordAndCount[word2] - wordAndCount[word1]);
Expand All @@ -54,6 +58,74 @@ const extractDataFromBlocks = (account, blocks) => {
WordCloud(document.getElementById('word-cloud-canvas'), { list: listToPrint, minSize: 4, drawOutOfBound: true, weightFactor: 5.5 } );
};

function precisionRound(number, precision) {
var factor = Math.pow(10, precision);
return Math.round(number * factor) / factor;
}

const getSentiment = (texts) => {
const scoreRange = 10;
const factor = 20;
const scores = texts.map(text => sentiment(text).comparative);
const buckets = Array.apply(null, Array(scoreRange * factor)).map(Number.prototype.valueOf,0);
scores.forEach(score => {
const normalizedScore = Math.min(scoreRange * factor, Math.max(0, Math.round((score + 5) * factor)));
buckets[normalizedScore]++;
});

const ctx = document.getElementById('sentiment-canvas').getContext("2d");
let colors = [];
let labels = [];
Array.apply(null, Array(scoreRange * factor)).map(Number.prototype.valueOf,0).map(
(_, i) => {
const opacity = Math.max(1, scoreRange * factor / Math.max(1, Math.abs(i - scoreRange * factor / 2)));

if (i - scoreRange * factor / 2 === 0) {
colors.push(`rgba(0, 0, 255, 1`);
}
else if (i <= scoreRange * factor / 2 - 1) {
colors.push(`rgba(255, 0, 0, ${opacity}`);
}
else {
colors.push(`rgba(0, 255, 0, ${opacity}`);
}
labels.push(precisionRound(i / factor - 5, 2));
}
);
// const ctx = document.getElementById('sentiment-canvas').getContext("2d");
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: [{
label: 'Sentiment Analysis of Posts',
data: buckets,
backgroundColor: colors
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero:true
},
scaleLabel: {
display: true,
labelString: 'Number of posts and comments'
}
}],
xAxes: [{
scaleLabel: {
display: true,
labelString: 'Positivity'
}
}]
}
}
});
console.log(chart);
};

const extractWordAndCounts = (text) => {
const wordAndCount = { };
const words = text.split(/[ ,.\n]+/);
Expand All @@ -78,17 +150,27 @@ const extractWordAndCounts = (text) => {
*/
$(document).ready(() => {
$('.submit-button').click(function () {
var account = $('.username-input').val();
var account = $('.username-input').val() || 'egmracer01';
steem.api.getAccountHistory(account, -1, 10000, function(err, result) {
console.log(err, (result || []).length);
if (result)
if (currentChart) {
myLineChart.destroy();
}
if (result) {
extractDataFromBlocks(account, result);
}
});
});
setTimeout(() => {
$('.submit-button').click();
}, 1000);

var canvas = document.getElementById('word-cloud-canvas');
canvas.height = window.innerHeight * .75; // sizing canvas' sucks
canvas.width = window.innerWidth * .6666;
var sentimentCanvas = document.getElementById('sentiment-canvas');
sentimentCanvas.height = window.innerHeight * .75; // sizing canvas' sucks
sentimentCanvas.width = window.innerWidth * .6666;

WordCloud(document.getElementById('word-cloud-canvas'), { list: demoWordFrequencies, minSize: 4, drawOutOfBound: true, weightFactor: 5.5 } );
});
4 changes: 4 additions & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ module.exports = {
}
}
]
},
externals: {
steem: 'steem',
'chart.js': 'Chart'
}
}
34 changes: 33 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,26 @@ chardet@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2"

chart.js@^2.7.1:
version "2.7.1"
resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.7.1.tgz#ae90b4aa4ff1f02decd6b1a2a8dabfd73c9f9886"
dependencies:
chartjs-color "~2.2.0"
moment "~2.18.0"

chartjs-color-string@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.5.0.tgz#8d3752d8581d86687c35bfe2cb80ac5213ceb8c1"
dependencies:
color-name "^1.0.0"

chartjs-color@~2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.2.0.tgz#84a2fb755787ed85c39dd6dd8c7b1d88429baeae"
dependencies:
chartjs-color-string "^0.5.0"
color-convert "^0.5.3"

chokidar@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
Expand Down Expand Up @@ -1237,13 +1257,17 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"

color-convert@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"

color-convert@^1.9.0:
version "1.9.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed"
dependencies:
color-name "^1.1.1"

color-name@^1.1.1:
color-name@^1.0.0, color-name@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"

Expand Down Expand Up @@ -3321,6 +3345,10 @@ mixin-deep@^1.2.0:
dependencies:
minimist "0.0.8"

moment@~2.18.0:
version "2.18.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"

move-concurrently@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
Expand Down Expand Up @@ -4246,6 +4274,10 @@ semver@^4.1.0:
version "4.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"

sentiment@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/sentiment/-/sentiment-4.2.0.tgz#02e3e59972d754e81d427f7a3a8c25b43ed8d4f0"

sequencify@~0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c"
Expand Down

0 comments on commit 59ad36c

Please sign in to comment.