var SECONDS = 1000,
MINUTES = 60 * SECONDS,
HOURS = 60 * MINUTES;
var config = {
partnerCode: 'B00015838755',
originalDuration: 24 * HOURS,
vizDuration: 8 * MINUTES,
colorIds: {
"-2.0": 2,
"0.5": 0, "1.0": 0, "1.5": 0, "2.0": 0,
"2.5": 1, "3.0": 1, "3.5": 1,
"4.0": 2, "4.5": 2, "5.0": 2
},
movieCount: 10,
opinionsPerPage: 100,
colors: [ "#f62a43", "#f3c000", "#2d9252"],
refreshRate: 500,
columnSpacing: 40,
columnWidth: 150,
tokenHeight: 16
}
$(function() {
var originalStart = Date.now() - config.originalDuration,
timeScale = config.vizDuration / config.originalDuration,
movies,
moviesToLoad,
opinions = [],
loadTime = Date.now(),
clockInterval,
tzDelta = 0,
tzSuffix = 'Z';
function addPatterns() {
if (!$("pattern").length) {
var xml = '<svg style="position: absolute;" width="1" height="1"><defs>'
+ config.colors.map(function(color, i) {
return '<pattern id="pattern_'
+ i
+ '" x="0" y="0" width="3" height="3" patternUnits="userSpaceOnUse"><rect x="0" y="0" width="3" height="3" fill="'
+ color
+ '" /><path d="M0 0L3 3" stroke="#333333" stroke-width=".3" opacity=".8" /></pattern>';
}).join("")
+ '</defs></svg>';
$("body").append(xml);
}
}
function resizeTimer() {
var w = Math.max(80, $(window).width() - 170),
n = Math.min(12, Math.floor(w / 80));
$('.timer-bar').width(w);
var html = '';
for (var k = 0; k < n + 1; k++) {
html += '<li style="left:'
+ Math.floor(k * w / n)
+ 'px;">'
+ new Date(originalStart + k * config.originalDuration / n).toTimeString().substr(0,5)
+ '</li>';
}
$('.hours').html(html);
}
resizeTimer();
$(window).resize(resizeTimer);
var vsHeight = $(window).height() - $('footer').height() - $('header').height() - 300,
vsWidth = config.movieCount * (config.columnWidth + config.columnSpacing);
$("#data-viz").css('height', vsHeight);
$('.posters').css('width', vsWidth);
function startViz() {
opinions.sort(function(a,b) {
return a._timestamp > b._timestamp;
});
$("#data-viz").html("").css("text-align","left");
var barChartSettings = {
width : vsWidth,
height : vsHeight,
chart : {
spacer : config.columnSpacing / 2,
y: 0,
height: vsHeight
},
options : {
layout: false
},
data : {
model : movies.map(function(movie) {
return {
label: movie.title
};
}),
strata : function() {
if (typeof barChart === "undefined") {
var flocculated = [];
_(function() {
addPatterns();
_.range(3).map(function(colorId) {
$(".layer_"+colorId).css({
fill: "url(#pattern_" +colorId + ")",
stroke: "#ffffff",
"stroke-opacity": .2
});
});
}).defer();
} else {
var flocculated = barChart.selectAll("state",2);
}
var res = movies.map(function(movie) {
var movieTokens = flocculated.filter(function(t) {
return t.attr("movie") === movie.id;
});
return _.range(3).map(function(colorId) {
var stratumTokens = movieTokens.filter(function(t) {
return t.attr("colorId") === colorId;
}).length;
return {
value: function() {
return stratumTokens
}
};
});
});
return res;
},
stream : {
provider : "tokens",
refresh: config.refreshRate,
now : 0
},
tokens: opinions.map(function(opinion) {
return {
category: opinion._column,
datetime: opinion.datetime,
movie: opinion._movie,
colorId: opinion._colorId,
fillStyle: opinion._color,
size: 30,
texture: {
src: "iri/img/star-icon.png"
},
strokeStyle: "rgba(255,255,255,.2)",
t: Math.floor((opinion._timestamp - originalStart) * timeScale / config.refreshRate),
shape:{
type:'box',
width: config.columnWidth / 2 - 1,
height: config.tokenHeight / 2
},
callback:{
suspension: function(token) {
var currentT = config.refreshRate * token.attr("t");
deltaT = Date.now() - currentT;
setTimeout(function() {
token.flocculate();
barChart.strata.update(barChart);
}, 5000);
}
}
}
})
},
sedimentation: {
token: {
size: {
original:12,
minimum:0
}
},
aggregation:{
height: vsHeight - 80,
maxData: Math.max.apply(Math, movies.map(function(m) { return m.opinions.length; }))
},
suspension:{
decay:{
power:1.001
}
}
}
}
console.log(barChartSettings);
var barChart = $("#data-viz").vs(barChartSettings).data('visualSedimentation');
$(".timer-bar-value").width(0);
clearInterval(clockInterval);
deltaT = Date.now();
clockInterval = setInterval(function() {
var t = Date.now() - deltaT,
w = $('.timer-bar').width() * Math.min(1, t / config.vizDuration);
$(".timer-bar-value").width(w);
}, 200);
}
function loadMovie(movie) {
$.getJSON(
"http://api.allocine.fr/rest/v3/opinionlist",
{
partner: config.partnerCode,
format: "json",
subject: "movie:" + movie.id,
count: config.opinionsPerPage,
refresh: refreshtoken(),
page: movie.opinionPage
},
function(d) {
if (d.feed && d.feed.activity) {
var tokens = d.feed.activity.filter(function(a) {
return a.action.type !== "notinterested" && a.action.value !== "-3.0";
});
} else {
var tokens = [];
}
tokens.forEach(function(a) {
a._colorId = config.colorIds[a.action.value];
a._color = config.colors[a._colorId];
a._timestamp = Date.parse(a.datetime + tzSuffix) - tzDelta;
a._movie = movie.id;
a._column = movie.column;
});
var tokcount = tokens.length;
tokens = tokens.filter(function(a) {
return a._timestamp >= originalStart;
});
movie.opinions = movie.opinions.concat(tokens);
opinions = opinions.concat(tokens);
$("#data-viz").append(".");
if (tokens.length === tokcount) {
console.log("Page " + movie.opinionPage + " of '" + movie.title + "' loaded");
movie.opinionPage ++;
loadMovie(movie);
} else {
console.log("Page " + movie.opinionPage + " of '" + movie.title + "' -- total : " + movie.opinions.length + " opinions loaded");
moviesToLoad--;
if (!moviesToLoad) {
console.log("**** Everything is loaded, in " + (Date.now() - loadTime) / 1000 + " seconds");
startViz();
}
}
}
);
}
var acimgserv = 0, acimgservcount = 6;
function resizeAcPicture(pic, w, h) {
var path = pic.path || pic.href || pic || "";
if (/^https?:\/\//.test(path)) {
path = path.replace(/^https?:\/\/[^\/]+/,'');
}
return "http://fr.web.img"
+ ( 1 + (acimgserv++ % acimgservcount))
+ ".acsta.net/r_"
+ w
+ "_"
+ h
+ path;
}
$.getJSON(
"http://api.allocine.fr/rest/v3/movielist",
{
partner: config.partnerCode,
format: "json",
filter: "top:week",
count: config.movieCount,
refresh: refreshtoken()
},
function(d) {
$("#data-viz").html("Chargement des flux d'opinions<br />");
console.log("Movie List Loaded");
tzDelta = .5 * HOURS * Math.round((Date.parse(d.feed.updated) - loadTime) / (.5 * HOURS));
tzSuffix = d.feed.updated.replace(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/,'');
movies = d.feed.movie.map(function(movie, i) {
return {
id: movie.code,
column: i,
title: movie.title,
poster: movie.poster.href,
opinions: [],
opinionPage: 1
};
});
moviesToLoad = movies.length;
movies.forEach(loadMovie);
$('.posters').html(movies.map(function(movie) {
return '<li style=" margin: 0 '
+ Math.floor(config.columnSpacing / 2)
+ 'px"><img width="150" height="200" src="'
+ resizeAcPicture(movie.poster,150,200)
+ '" alt="'
+ movie.title
+'" /></li>';
}).join(""));
}
);
function refreshtoken() {
return Math.floor(0x100000000 * Math.random()).toString(16) + "-" + (Date.now() % 0x100000000).toString(16);
}
$(".rejouer").click(function() {
startViz();
return false;
})
});