Skip to content

Commit 009ee25

Browse files
committed
adaptive time series
1 parent 160ee03 commit 009ee25

File tree

5 files changed

+39
-20
lines changed

5 files changed

+39
-20
lines changed

app/assets/javascripts/controllers.js

+3-7
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
angular.module('birdwatch.controllers', ['birdwatch.services', 'charts.barchart', 'charts.wordcloud', 'ui.bootstrap']).
55
controller('BirdWatchCtrl',function ($scope, $location, utils, barchart, wordcloud, $timeout, wordCount, cf, tweets) {
66
$scope.prevSizeOpts = ['100', '500', '1000', '2000', '5000', '10000', '20000'];
7-
$scope.prevSize = $scope.prevSizeOpts[2];
7+
$scope.prevSize = $scope.prevSizeOpts[3];
88
$scope.pageSizeOpts = [5, 10, 25, 50, 100];
99
$scope.pageSize = $scope.pageSizeOpts[1];
1010
$scope.live = true;
@@ -18,7 +18,6 @@ angular.module('birdwatch.controllers', ['birdwatch.services', 'charts.barchart'
1818
$scope.cf = cf;
1919
$scope.sortModel = 'latest';
2020
$scope.words = [];
21-
$scope.tsdata1 = cf.timeseries();
2221

2322
/** Add a string to the search bar when for example clicking on a chart element */
2423
$scope.addSearchString = function (searchString) {
@@ -28,11 +27,8 @@ angular.module('birdwatch.controllers', ['birdwatch.services', 'charts.barchart'
2827
$scope.search();
2928
};
3029

31-
/** update UI every two seconds to keep time ago for tweets accurate */
32-
var onTimeout = function () {
33-
$scope.tsdata1 = cf.timeseries();
34-
updateTimeout = $timeout(onTimeout, 2000);
35-
};
30+
/** update UI every ten seconds to keep time ago for tweets accurate */
31+
var onTimeout = function () { updateTimeout = $timeout(onTimeout, 10000); };
3632
var updateTimeout = onTimeout();
3733

3834
var insertionCache = [];

app/assets/javascripts/directives.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,14 @@ angular.module('birdwatch.directives', ['charts.barchart', 'charts.wordcloud'])
6868
series: [ {
6969
color: 'steelblue',
7070
name: 'Tweets',
71-
data: [{ x: 0, y: 0 }, { x: 12*60*60, y: 0 }]
71+
data: [{ x: 0, y: 0 }]
7272
} ]
7373
} );
7474
new Rickshaw.Graph.Axis.Time({ graph: graph });
7575
graph.render();
7676

7777
new Rickshaw.Graph.HoverDetail({
7878
graph: graph,
79-
xFormatter: function(x) { return x/3600+ "" },
8079
yFormatter: function(y) { return y === null ? y : y.toFixed(0); }
8180
});
8281

app/assets/javascripts/services/crossfilter.js

+20-9
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,26 @@ angular.module('birdwatch.services').factory('cf', function (utils) {
1818
else return 0;
1919
});
2020

21-
var hour = cf.dimension(function(t) {
22-
var created = new Date(Date.parse(t.created_at));
23-
return created.getHours() + created.getMinutes() / 60;
24-
});
25-
exports.hours = hour.group(Math.floor);
26-
exports.timeseries = function() { return exports.hours.all()
27-
.map(function(el) {
28-
return { x: el.key * 60 * 60, y: el.value }
29-
});
21+
var rsMapper = function(el) { return { x: el.key, y: el.value }};
22+
23+
var parseDateRoundedByMin = function(t) { return 60 * Math.floor(Date.parse(t.created_at) / 60000) };
24+
var parseDateRoundedBy15Min = function(t) { return 900 * Math.floor(Date.parse(t.created_at) / 900000) };
25+
var parseDateRoundedByHour = function(t) { return 3600 * Math.floor(Date.parse(t.created_at) / 3600000) };
26+
var parseDateRoundedBy6Hour = function(t) { return 6*3600 * Math.floor(Date.parse(t.created_at) / 3600000 / 6) };
27+
var parseDateRoundedByDay = function(t) { return 24*3600 * Math.floor(Date.parse(t.created_at) / 3600000 / 24) };
28+
29+
var byMinGrp = cf.dimension(parseDateRoundedByMin).group();
30+
var by15MinGrp = cf.dimension(parseDateRoundedBy15Min).group();
31+
var byHourGrp = cf.dimension(parseDateRoundedByHour).group();
32+
var by6HourGrp = cf.dimension(parseDateRoundedBy6Hour).group();
33+
var byDayGrp = cf.dimension(parseDateRoundedByDay).group();
34+
35+
exports.timeseries = function() {
36+
if (byMinGrp.size() < 60) { return byMinGrp.all().map(rsMapper); }
37+
else if (by15MinGrp.size() < 48) { return by15MinGrp.all().map(rsMapper); }
38+
else if (byHourGrp.size() < 96) { return byHourGrp.all().map(rsMapper); }
39+
else if (by6HourGrp.size() < 40) { return by6HourGrp.all().map(rsMapper); }
40+
else { return byDayGrp.all().map(rsMapper); }
3041
};
3142

3243
// freeze imposes filter on crossfilter that only shows anything older than and including the latest

app/views/index.scala.html

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@
119119
<!-- Charts column -->
120120
<div class="col-lg-8">
121121

122-
<h6>Activity by Hour of the Day</h6>
123-
<div id="timeseries1" class="timeseries" data-tsdata="tsdata1" data-live="live" data-height="100"></div>
122+
<h6>Activity by Time Unit (mouse over for details)</h6>
123+
<div id="timeseries1" class="timeseries" data-tsdata="cf.timeseries()" data-live="live" data-height="100"></div>
124124
<hr />
125125

126126
<h6>Word Frequency</h6>

public/stylesheets/main.css

+13
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,16 @@ a {
102102
.container {
103103
max-width: 1600px;
104104
}
105+
106+
.x_label {
107+
font-family: Arial, sans-serif;
108+
border-radius: 3px;
109+
padding: 6px;
110+
opacity: .5;
111+
border: 1px solid #e0e0e0;
112+
font-size: 12px;
113+
position: absolute;
114+
top: 100px;
115+
background: #fff;
116+
white-space: nowrap
117+
}

0 commit comments

Comments
 (0)