333 }); |
332 }); |
334 higherFiveSecs = paper.path(d).attr({ |
333 higherFiveSecs = paper.path(d).attr({ |
335 "stroke-width": 1, |
334 "stroke-width": 1, |
336 "stroke": "#ffffff" |
335 "stroke": "#ffffff" |
337 }); |
336 }); |
|
337 |
|
338 var imghtm = '', imgrate = localduration / 12, imgstart = imgrate * Math.floor(localstart / imgrate), imgend = imgrate * Math.ceil(localend / imgrate); |
|
339 for (var i = imgstart; i <= imgend; i+= imgrate) { |
|
340 var imgsrc = i + '.png'; |
|
341 while (imgsrc.length < 9) { |
|
342 imgsrc = '0' + imgsrc; |
|
343 } |
|
344 var imgy = Math.floor( localyscale * (i - localstart) - 22.5 ) |
|
345 imghtm += '<img src="thumbnails/' + imgsrc + '" style="top: ' + imgy +'px;" />'; |
|
346 } |
|
347 $(".play-images").html(imghtm); |
|
348 |
|
349 $(".play-localtweets .tweet").each(function() { |
|
350 var el = $(this), |
|
351 t = parseInt(el.attr("data-timestamp")); |
|
352 if (t > localstart && t < localend) { |
|
353 el.show(); |
|
354 } else { |
|
355 el.hide(); |
|
356 } |
|
357 }); |
|
358 |
|
359 throttledGetTweets(); |
|
360 |
338 showTopicViz(); |
361 showTopicViz(); |
339 } |
362 } |
340 |
363 |
341 |
364 |
342 var lastPos, lastDuration, lastTopics; |
365 var lastPos, lastDuration, lastTopics; |
343 |
366 |
344 var tweetTemplate = _.template('<li class="tweet" data-timestamp="<%= _timestamp %>" data-topic-id="<%= _topic %>"><img src="<%- profile_image_url %>" /><p>@<%- from_user_name %>: <%- text %></p></li>'), |
367 var tweetTemplate = _.template('<li class="tweet" data-timestamp="<%= timestamp %>" data-topic-id="<%= topic.topic %>"><img src="<%- data.profile_image_url %>" /><p>@<%- data.from_user_name %>: <%- data.text %></p></li>'), |
345 callnum = 0; |
368 callnum = 0, |
346 |
369 tweetstructure = {}, |
347 function getTweets() { |
370 requestedtweets = {}, |
348 var topicIds = Array.prototype.join.call($(".topic.selected").map(function(){return $(this).attr("data-topic-id")})); |
371 _NTWEETS = 10; |
349 if (localduration === lastDuration && lastTopics === topicIds && Math.abs(localpos - lastPos) < (localduration / 10)) { |
372 |
350 console.log("We already have these tweets, delta =", localpos - lastPos ); |
373 function showTweets() { |
351 return; |
374 |
|
375 var toshow = []; |
|
376 var topics = Array.prototype.join.call($(".topic.selected").map(function(){return $(this).attr("data-topic-id")})).split(","); |
|
377 |
|
378 for (var i = 0; i < localMmsos.length; i++) { |
|
379 var mmso = data.segments[localMmsoDelta + i]; |
|
380 var mmsostruct = tweetstructure[mmso.id]; |
|
381 if (mmsostruct) { |
|
382 for (var j = 0; j < topics.length; j++) { |
|
383 var topicid = topics[j]; |
|
384 if (mmsostruct[topicid]) { |
|
385 var tweetids = mmsostruct[topicid].tweetids; |
|
386 for (var k = 0; k < tweetids.length; k++) { |
|
387 toshow.push(tweetids[k]); |
|
388 } |
|
389 } |
|
390 } |
|
391 } |
352 } |
392 } |
353 if (!topicIds) { |
393 toshow = _(toshow).uniq(); |
354 console.log("No topics selected"); |
394 |
355 return; |
395 var tweetstoshow = toshow.map(function(tid) { |
|
396 return requestedtweets[tid]; |
|
397 }).filter(function(tw) { |
|
398 return ((tw.status == 2) && (tw.timestamp > (localpos - localduration / 2)) && (tw.timestamp < (localpos + localduration / 2))); |
|
399 }); |
|
400 |
|
401 tweetstoshow.forEach(function(tw) { |
|
402 tw.topic = tw.topics.filter(function(t) { |
|
403 return topics.indexOf(t.topic) !== -1; |
|
404 }).sort(function(a,b) { |
|
405 return b.weight - a.weight |
|
406 })[0]; |
|
407 }); |
|
408 |
|
409 tweetstoshow.sort(function(a, b) { |
|
410 return b.topic.weight - a.topic.weight; |
|
411 }); |
|
412 |
|
413 tweetstoshow = tweetstoshow.slice(0,10); |
|
414 |
|
415 tweetstoshow.sort(function(a, b) { |
|
416 return a.timestamp - b.timestamp; |
|
417 }); |
|
418 |
|
419 console.log(tweetstoshow); |
|
420 |
|
421 var html = tweetstoshow.map(tweetTemplate).join(""); |
|
422 |
|
423 $(".play-localtweets").html(html); |
|
424 var h = 0; |
|
425 $(".play-localtweets .tweet").each(function() { |
|
426 h += $(this).outerHeight(); |
|
427 }); |
|
428 $(".play-localtweets .tweet").css("margin-top",Math.max(0,($(".play-bottom").height() - h)/(tweetstoshow.length+1))); |
|
429 showTopicViz(); |
|
430 |
|
431 } |
|
432 |
|
433 function getMmsoTweetIds(mmstruct) { |
|
434 |
|
435 TopicsBean.bestSocialInteractionsIdsMatching(mmstruct.mmso, mmstruct.topic, 0, _NTWEETS, { |
|
436 callback: function(tw) { |
|
437 mmstruct.status = 2; |
|
438 mmstruct.tweetids = tw; |
|
439 for (var k = 0; k < tw.length; k++) { |
|
440 var tweetid = tw[k], |
|
441 relevance = mmstruct.weight * (_NTWEETS - k) / _NTWEETS; |
|
442 if (!requestedtweets[tweetid]) { |
|
443 requestedtweets[tweetid] = { |
|
444 id: tweetid, |
|
445 status: 0, |
|
446 topics: [] |
|
447 } |
|
448 } |
|
449 requestedtweets[tweetid].topics.push({ |
|
450 topic: mmstruct.topic, |
|
451 weight: relevance |
|
452 }); |
|
453 } |
|
454 debouncedGetTweetData(); |
|
455 }, |
|
456 errorHandler: function(err) { |
|
457 mmstruct.status = 0; |
|
458 console.log(err); |
|
459 throttledGetTweetIds(); |
|
460 } |
|
461 }); |
|
462 } |
|
463 |
|
464 var _MAX_BATCH = 20; |
|
465 |
|
466 function getTweetIds() { |
|
467 |
|
468 console.log("getTweetIds"); |
|
469 |
|
470 var toload = []; |
|
471 |
|
472 _(tweetstructure).each(function(v) { |
|
473 _(v).each(function(w) { |
|
474 if (!w.status) { |
|
475 w.status = 1; |
|
476 toload.push(w); |
|
477 } |
|
478 }); |
|
479 }); |
|
480 |
|
481 console.log("Loading tweet ids"); |
|
482 |
|
483 if (toload.length) { |
|
484 |
|
485 if (toload.length > _MAX_BATCH) { |
|
486 toload = _(toload).shuffle().slice(0,_MAX_BATCH); |
|
487 window.setInterval(throttledGetTweetIds,0); |
|
488 } |
|
489 |
|
490 dwr.engine.beginBatch(); |
|
491 toload.forEach(getMmsoTweetIds); |
|
492 dwr.engine.endBatch(); |
356 } |
493 } |
357 var localcall = ++callnum; |
494 } |
358 console.log("getTweets was called",localcall,(function(d){return d.toLocaleTimeString()+"."+d.getMilliseconds()})(new Date())); |
495 |
359 var tweetids = {}, |
496 function getTweetData() { |
360 rqtodo = 0, |
497 |
361 rqdone = 0, |
498 console.log("getTweetData"); |
362 topics = topicIds.split(","); |
499 |
363 |
500 var toload = []; |
364 function getMmsoTopicTweets(mmsoid, topic, ntweets) { |
501 |
365 rqtodo++; |
502 _(requestedtweets).each(function(v) { |
366 TopicsBean.bestSocialInteractionsIdsMatching(mmsoid, topic, 0, ntweets, { |
503 if (!v.status) { |
367 callback: function(tw) { |
504 toload.push(v.id); |
368 for (var k = 0; k < tw.length; k++) { |
505 } |
369 tweetids[tw[k]] = topic; |
506 }); |
370 } |
507 |
371 rqdone++; |
508 console.log("Loading tweet data"); |
372 if (rqdone === rqtodo) { |
509 |
373 loadTweets(); |
510 $.getJSON( |
374 } |
511 solrUrl( |
|
512 "twitter", |
|
513 { |
|
514 q:"id:(" + toload.join(" OR ") + ")", |
|
515 fl: "id_str,created_at,from_user_name,text,profile_image_url", |
|
516 rows: toload.length |
375 } |
517 } |
376 }); |
518 ), |
|
519 function(t) { |
|
520 var tweets = t.response.docs; |
|
521 tweets.forEach(function(tweet) { |
|
522 var timestamp = new Date(tweet.created_at).valueOf() / 1000 - deltaT; |
|
523 requestedtweets[tweet.id_str].data = tweet; |
|
524 requestedtweets[tweet.id_str].status = 2; |
|
525 requestedtweets[tweet.id_str].timestamp = timestamp; |
|
526 }); |
|
527 throttledShowTweets(); |
|
528 } |
|
529 ); |
|
530 |
|
531 } |
|
532 |
|
533 debouncedGetTweetData = _(getTweetData).debounce(125); |
|
534 |
|
535 throttledGetTweetIds = _(getTweetIds).throttle(10000); |
|
536 |
|
537 throttledShowTweets = _(showTweets).throttle(200); |
|
538 |
|
539 function getLocalTweets() { |
|
540 |
|
541 console.log("getLocalTweets"); |
|
542 |
|
543 var topics = Array.prototype.join.call($(".topic.selected").map(function(){return $(this).attr("data-topic-id")})).split(","); |
|
544 |
|
545 for (var i = 0; i < localMmsos.length; i++) { |
|
546 var mmso = data.segments[localMmsoDelta + i]; |
|
547 if (!tweetstructure[mmso.id]) { |
|
548 tweetstructure[mmso.id] = {} |
|
549 } |
|
550 var mmsostruct = tweetstructure[mmso.id]; |
|
551 for (var j = 0; j < topics.length; j++) { |
|
552 var topicid = topics[j], |
|
553 weight = data.topics[topics[j]].weights[localMmsoDelta + i]; |
|
554 if (weight > .1 && !mmsostruct[topicid]) { |
|
555 mmsostruct[topicid] = { |
|
556 topic: topicid, |
|
557 mmso: mmso.id, |
|
558 status: 0, |
|
559 weight: weight, |
|
560 tweetids: [] |
|
561 }; |
|
562 } |
|
563 } |
377 } |
564 } |
378 |
565 |
379 function loadTweets() { |
566 throttledGetTweetIds(); |
380 console.log("Tweet IDs retrieved",localcall,(function(d){return d.toLocaleTimeString()+"."+d.getMilliseconds()})(new Date())); |
567 throttledShowTweets(); |
381 var u = _.keys(tweetids); |
568 } |
382 $.getJSON( |
569 |
383 solrUrl( |
570 var throttledGetTweets = _.throttle(getLocalTweets, 500), |
384 "twitter", |
|
385 { |
|
386 q:"id:(" + u.join(" OR ") + ")", |
|
387 rows: u.length |
|
388 } |
|
389 ), |
|
390 function(t) { |
|
391 console.log("Full tweets retrieved",localcall,(function(d){return d.toLocaleTimeString()+"."+d.getMilliseconds()})(new Date())); |
|
392 var tweets = t.response.docs; |
|
393 var s = 600 / (1+tweets.length); |
|
394 tweets.forEach(function(tweet, i) { |
|
395 tweet._date = new Date(tweet.created_at); |
|
396 tweet._timestamp = tweet._date.valueOf() / 1000 - deltaT; |
|
397 tweet._topic = tweetids[tweet.id_str] |
|
398 }); |
|
399 tweets.sort(function(a,b) { |
|
400 return a._date - b._date; |
|
401 }); |
|
402 var html = tweets.reduce(function(mem, tweet) { |
|
403 return mem + tweetTemplate(tweet); |
|
404 },''); |
|
405 $(".play-localtweets").html(html); |
|
406 var h = 0; |
|
407 $(".play-localtweets .tweet").each(function() { |
|
408 h += $(this).outerHeight(); |
|
409 }); |
|
410 $(".play-localtweets .tweet").css("margin-top",Math.max(0,($(".play-bottom").height() - h)/(tweets.length+1))); |
|
411 showTopicViz(); |
|
412 } |
|
413 ); |
|
414 $(".play-localtweets").html(""); |
|
415 showTopicViz(); |
|
416 } |
|
417 |
|
418 function getMmsoTweets(nmmso) { |
|
419 var mmso = data.segments[nmmso], |
|
420 mmsopixels = localyscale * (Math.min(localpos + localduration / 2, mmso.end) - Math.max(localpos - localduration / 2, mmso.start)); |
|
421 var ntweets = Math.floor(( 50 + mmsopixels ) / 80), |
|
422 mmsotopics = []; |
|
423 if (!ntweets) { |
|
424 return; |
|
425 } |
|
426 for (var j = 0; j < topics.length; j++) { |
|
427 var weight = data.topics[topics[j]].weights[nmmso]; |
|
428 if (weight > .05) { |
|
429 mmsotopics.push({topic:parseInt(topics[j]),weight:weight,ntweets:0}); |
|
430 } |
|
431 } |
|
432 mmsotopics.sort(function(a,b){return b.weight - a.weight}); |
|
433 if (mmsotopics.length) { |
|
434 for (var j = 0; j < ntweets; j++) { |
|
435 mmsotopics[j % mmsotopics.length].ntweets++; |
|
436 } |
|
437 mmsotopics = mmsotopics.filter(function(t) { return !!t.ntweets }); |
|
438 for (var j = 0; j < mmsotopics.length; j++) { |
|
439 getMmsoTopicTweets(mmso.id, mmsotopics[j].topic, mmsotopics[j].ntweets); |
|
440 } |
|
441 } else { |
|
442 var t = [], m = {}; |
|
443 while (t.length < ntweets) { |
|
444 t = t.concat(topics); |
|
445 } |
|
446 for (var j = 0; j < ntweets; j++) { |
|
447 m[t[j]] = 1 + (m[t[j]]||0); |
|
448 } |
|
449 _(m).each(function(v,k) { |
|
450 getMmsoTopicTweets(mmso.id, k, v); |
|
451 }); |
|
452 } |
|
453 } |
|
454 |
|
455 dwr.engine.beginBatch(); |
|
456 for (var i = 0; i < localMmsos.length; i++) { |
|
457 getMmsoTweets(localMmsoDelta + i); |
|
458 } |
|
459 dwr.engine.endBatch(); |
|
460 lastPos = localpos; |
|
461 lastDuration = localduration; |
|
462 lastTopics = topicIds; |
|
463 } |
|
464 |
|
465 var throttledGetTweets = _.throttle(_.debounce(getTweets, 500), 10000), |
|
466 throttledShowLocal = _.throttle(showLocal, 100); |
571 throttledShowLocal = _.throttle(showLocal, 100); |
467 |
572 |
468 showTopics(sortedTopics); |
573 showTopics(sortedTopics); |
469 (topicHash.match(/\d+/g) || []).forEach(function(id) { |
574 (topicHash.match(/\d+/g) || []).forEach(function(id) { |
470 $(".topic[data-topic-id=" + id + "]").addClass("selected").attr("data-timestamp",++ordertag); |
575 $(".topic[data-topic-id=" + id + "]").addClass("selected").attr("data-timestamp",++ordertag); |