├── Procfile ├── .gitignore ├── images ├── hex.png ├── info.png ├── favicon.ico ├── keyboard.png ├── twitter.png ├── fullscreen.png ├── markertop.png ├── scanlines.png ├── screenshot.jpeg ├── thumbprint.png ├── encom_folder_big.png ├── encom_folder_xl.png ├── encom_folder_small.png ├── github-screensaver.gif ├── not_available_large.png ├── not_available_small.png ├── screenshot_lighttable.jpg ├── GitHub-Mark-Light-32px.png └── equirectangle_projection.png ├── css ├── terminator.woff ├── global.css ├── light-table-styles.css └── boardroom-styles.css ├── package.json ├── src ├── Utils.js ├── Logo.js ├── SimpleClock.js ├── TimerTrees.js ├── SatBar.js ├── StockChartSmall.js ├── main.js ├── Swirls.js ├── StockChart.js ├── LightTable.js ├── Box.js └── Boardroom.js ├── Gruntfile.js ├── README.md ├── stream-server.js └── js └── github-2013.js /Procfile: -------------------------------------------------------------------------------- 1 | web: node stream-server.js 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | bower_components/ 3 | npm-debug.log 4 | production/ -------------------------------------------------------------------------------- /images/hex.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/hex.png -------------------------------------------------------------------------------- /images/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/info.png -------------------------------------------------------------------------------- /css/terminator.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/css/terminator.woff -------------------------------------------------------------------------------- /images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/favicon.ico -------------------------------------------------------------------------------- /images/keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/keyboard.png -------------------------------------------------------------------------------- /images/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/twitter.png -------------------------------------------------------------------------------- /images/fullscreen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/fullscreen.png -------------------------------------------------------------------------------- /images/markertop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/markertop.png -------------------------------------------------------------------------------- /images/scanlines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/scanlines.png -------------------------------------------------------------------------------- /images/screenshot.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/screenshot.jpeg -------------------------------------------------------------------------------- /images/thumbprint.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/thumbprint.png -------------------------------------------------------------------------------- /images/encom_folder_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/encom_folder_big.png -------------------------------------------------------------------------------- /images/encom_folder_xl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/encom_folder_xl.png -------------------------------------------------------------------------------- /images/encom_folder_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/encom_folder_small.png -------------------------------------------------------------------------------- /images/github-screensaver.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/github-screensaver.gif -------------------------------------------------------------------------------- /images/not_available_large.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/not_available_large.png -------------------------------------------------------------------------------- /images/not_available_small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/not_available_small.png -------------------------------------------------------------------------------- /images/screenshot_lighttable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/screenshot_lighttable.jpg -------------------------------------------------------------------------------- /images/GitHub-Mark-Light-32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/GitHub-Mark-Light-32px.png -------------------------------------------------------------------------------- /images/equirectangle_projection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bwinchester/seckc-encom-boardroom/HEAD/images/equirectangle_projection.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "encom-boardroom", 3 | "version": "0.10.7", 4 | "description": "encom-boardroom", 5 | "main": "index.html", 6 | "dependencies": { 7 | "encom-globe": "*", 8 | "event-source": "~0.1.0", 9 | "express": "~4.3.0", 10 | "github-timeline-stream": "*", 11 | "grunt": "~0.4.2", 12 | "jquery": "~2.1.0", 13 | "jquery-ui": "~1.10.5", 14 | "map-stream": "~0.1.0", 15 | "moment": "^2.6.0", 16 | "moment-timezone": "0.0.6", 17 | "pleaserotate.js": "*", 18 | "pusher.color": "~0.2.4", 19 | "request": "~2.34.0", 20 | "serve-favicon": "~2.0.0", 21 | "three": "~0.66.2", 22 | "wikipedia-stream": "*" 23 | }, 24 | "devDependencies": { 25 | "browserify": "~3.44.2", 26 | "grunt": "~0.4.2", 27 | "grunt-browserify": "~2.0.8", 28 | "grunt-contrib-clean": "^1.1.0", 29 | "grunt-contrib-copy": "^0.5.0", 30 | "grunt-contrib-uglify": "~0.4.0", 31 | "grunt-contrib-watch": "~0.5.3" 32 | }, 33 | "scripts": { 34 | "test": "echo \"Error: no test specified\" && exit 1", 35 | "start": "nodejs stream-server.js" 36 | }, 37 | "repository": { 38 | "type": "git", 39 | "url": "git://github.com/arscan/encom-boardroom.git" 40 | }, 41 | "author": "rscanlon@mit.edu", 42 | "license": "MIT" 43 | } 44 | -------------------------------------------------------------------------------- /src/Utils.js: -------------------------------------------------------------------------------- 1 | var Utils = {}; 2 | 3 | Utils.renderToCanvas = function (width, height, renderFunction) { 4 | var buffer = document.createElement('canvas'); 5 | buffer.width = width; 6 | buffer.height = height; 7 | renderFunction(buffer.getContext('2d')); 8 | return buffer; 9 | }; 10 | 11 | Utils.extend = function(first, second) { 12 | for(var i in first){ 13 | second[i] = first[i]; 14 | } 15 | }; 16 | 17 | Utils.sCurve = function(t) { 18 | return 1/(1 + Math.exp(-t*12 + 6)); 19 | }; 20 | 21 | // http://stackoverflow.com/a/13542669 22 | Utils.shadeColor = function(color, percent) { 23 | var num = parseInt(color.slice(1),16), 24 | amt = Math.round(2.55 * percent), 25 | R = (num >> 16) + amt, 26 | G = (num >> 8 & 0x00FF) + amt, 27 | B = (num & 0x0000FF) + amt; 28 | 29 | return "#" + (0x1000000 + (R<255?R<1?0:R:255)*0x10000 + (G<255?G<1?0:G:255)*0x100 + (B<255?B<1?0:B:255)).toString(16).slice(1); 30 | } 31 | 32 | Utils.drawCurvedRectangle = function(ctx, left, top, width, height, radius){ 33 | 34 | ctx.beginPath(); 35 | ctx.moveTo(left + radius, top); 36 | ctx.lineTo(left + width - radius, top); 37 | ctx.quadraticCurveTo(left + width, top, left + width, top + radius); 38 | ctx.lineTo(left + width, top + height - radius); 39 | ctx.quadraticCurveTo(left + width, top + height, left + width - radius, top + height); 40 | ctx.lineTo(left + radius, top + height); 41 | ctx.quadraticCurveTo(left, top + height, left, top + height - radius); 42 | ctx.lineTo(left, top + radius); 43 | ctx.quadraticCurveTo(left, top, left + radius, top); 44 | ctx.stroke(); 45 | ctx.fill(); 46 | ctx.closePath(); 47 | } 48 | 49 | module.exports = Utils; 50 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | grunt.initConfig({ 3 | pkg: grunt.file.readJSON('package.json'), 4 | watch: { 5 | options: { 6 | livereload: true 7 | }, 8 | tasks: ['browserify'/*, 'uglify'*/], 9 | files: ['src/*.js', 'index.html', 'css/*', 'Gruntfile.js', 'browserify.js'] 10 | }, 11 | browserify: { 12 | 'build/<%= pkg.name %>.js': ['src/main.js'] 13 | }, 14 | uglify: { 15 | main: { 16 | files: { 17 | 'build/<%= pkg.name%>.min.js': 'build/<%= pkg.name %>.js' 18 | } 19 | } 20 | }, 21 | clean:{ 22 | production: { 23 | options: { force: true }, 24 | src: ["production/"] 25 | }, 26 | }, 27 | copy:{ 28 | build: { 29 | expand: true, 30 | //cwd: "public/tmp/", 31 | src: [ 32 | 'build/**.min.js', 33 | 'index.html', 34 | 'css/**', 35 | 'images/**', 36 | 'js/**' 37 | ], 38 | dest: "production/" 39 | } 40 | } 41 | 42 | }); 43 | 44 | grunt.loadNpmTasks('grunt-contrib-watch'); 45 | grunt.loadNpmTasks('grunt-contrib-copy'); 46 | grunt.loadNpmTasks('grunt-browserify'); 47 | grunt.loadNpmTasks('grunt-contrib-uglify'); 48 | grunt.loadNpmTasks('grunt-contrib-clean'); 49 | grunt.loadNpmTasks('grunt-contrib-copy'); 50 | 51 | grunt.registerTask('release', ['browserify', 'uglify','clean:production','copy:build']); 52 | 53 | 54 | }; 55 | -------------------------------------------------------------------------------- /src/Logo.js: -------------------------------------------------------------------------------- 1 | var Utils = require("./Utils.js"); 2 | 3 | var Logo = function(containerId, text){ 4 | 5 | if(typeof text == "undefined"){ 6 | text = "GITHUB"; 7 | } 8 | 9 | this.container = document.getElementById(containerId); 10 | this.container.width = 180; 11 | this.container.height = 100 12 | this.canvas = document.createElement("canvas"); 13 | this.canvas.width = this.container.width; 14 | this.canvas.height = this.container.height; 15 | this.context = this.canvas.getContext("2d"); 16 | this.container.appendChild(this.canvas); 17 | 18 | this.width = this.container.width; 19 | this.height = this.container.height; 20 | 21 | this.context.strokeStyle = "#00eeee"; 22 | this.context.lineWidth = 3; 23 | 24 | this.context.font = "14px Terminator"; 25 | var textWidth = this.context.measureText(text).width; 26 | 27 | Utils.drawCurvedRectangle(this.context, (this.width - textWidth -24)/2, 30, textWidth + 24, 60, 3); 28 | Utils.drawCurvedRectangle(this.context, (this.width - textWidth -10)/2, 65, textWidth + 10, 20, 3); 29 | 30 | this.context.textAlign = "center"; 31 | this.context.fillStyle="#00eeee"; 32 | this.context.textBaseline = "bottom"; 33 | this.context.fillText(text, this.width/2, 85); 34 | 35 | 36 | var buffer = 4; 37 | var startPos = (this.width-textWidth-24)/2 + buffer + 2; 38 | var barWidth = (textWidth + 20 - buffer * 6) / 5; 39 | 40 | for(var i = 0; i < 5; i++){ 41 | var height = Math.floor(Math.random() * 25); 42 | if(Math.random() < .5){ 43 | this.context.fillStyle = "#ffcc00"; 44 | } else { 45 | this.context.fillStyle = "#ff9933"; 46 | } 47 | this.context.fillRect(startPos + i * (barWidth + buffer), 36 + (25 - height), barWidth, height); 48 | } 49 | 50 | 51 | }; 52 | 53 | module.exports = Logo; 54 | -------------------------------------------------------------------------------- /src/SimpleClock.js: -------------------------------------------------------------------------------- 1 | var Utils = require("./Utils"); 2 | 3 | var SimpleClock = function(canvasId){ 4 | 5 | if(this.firstTick == undefined){ 6 | this.firstTick = new Date(); 7 | } 8 | 9 | var canvas = document.getElementById(canvasId); 10 | this.context = canvas.getContext("2d"); 11 | 12 | this.width = canvas.width; 13 | this.height = canvas.height; 14 | 15 | this.centerx = this.width/2; 16 | this.centery = this.height/2; 17 | 18 | this.backBuffer = Utils.renderToCanvas(this.width, this.height, function(ctx){ 19 | var x = canvas.width / 2; 20 | var y = canvas.height / 2; 21 | 22 | ctx.beginPath(); 23 | ctx.strokeStyle="#666"; 24 | ctx.arc(x, y, 8, 0, Math.PI*2); 25 | ctx.stroke(); 26 | ctx.closePath(); 27 | ctx.beginPath(); 28 | ctx.strokeStyle="#333"; 29 | ctx.arc(x, y, 16, 0, Math.PI*2); 30 | ctx.stroke(); 31 | ctx.beginPath(); 32 | ctx.strokeStyle="#666"; 33 | ctx.arc(x, y, 24, 0, Math.PI*2); 34 | ctx.stroke(); 35 | ctx.closePath(); 36 | 37 | 38 | ctx.strokeStyle="#333"; 39 | ctx.beginPath(); 40 | ctx.moveTo(x,y+8) 41 | ctx.lineTo(x,y+24) 42 | ctx.moveTo(x,y-8) 43 | ctx.lineTo(x,y-24) 44 | ctx.moveTo(x+8,y) 45 | ctx.lineTo(x+24,y) 46 | ctx.moveTo(x-8,y) 47 | ctx.lineTo(x-24,y) 48 | ctx.stroke(); 49 | ctx.closePath(); 50 | 51 | }); 52 | } 53 | 54 | SimpleClock.prototype.tick = function(){ 55 | var timeSinceStarted = new Date() - this.firstTick; 56 | 57 | this.context.clearRect(0,0,this.width, this.height); 58 | this.context.drawImage(this.backBuffer, 0, 0); 59 | 60 | this.context.strokeStyle="#666"; 61 | this.context.beginPath(); 62 | this.context.moveTo(this.centerx, this.centery); 63 | this.context.lineTo(this.centerx + 24*Math.sin(timeSinceStarted/10000), this.centery - 24*Math.cos(timeSinceStarted/10000)); 64 | this.context.moveTo(this.centerx, this.centery); 65 | this.context.lineTo(this.centerx + 24*Math.sin(timeSinceStarted/100000), this.centery - 24*Math.cos(timeSinceStarted/100000)); 66 | this.context.stroke(); 67 | this.context.closePath(); 68 | 69 | }; 70 | 71 | 72 | module.exports = SimpleClock; 73 | -------------------------------------------------------------------------------- /css/global.css: -------------------------------------------------------------------------------- 1 | /* 2 | terminator font: 3 | Allen R. Walden's Friendly Fonts (Unprotected. Please distribute freely.) | Software Friends, Inc. © 1993 (Friendly Fonts) 4 | From: http://www.fontspace.com/allen-r-walden/terminator-cyr 5 | */ 6 | @font-face { 7 | font-family: 'terminator'; 8 | src: url('terminator.woff') format('woff'); 9 | } 10 | 11 | html { 12 | background-color: #000; 13 | } 14 | 15 | body { 16 | background-color: black; 17 | font-size:6pt; 18 | /* color: #6fc0ba; */ 19 | color: #fff; 20 | } 21 | 22 | #error-message{ 23 | visibility: hidden; 24 | width: 600px; 25 | } 26 | 27 | #error-message p{ 28 | font-size: 16pt; 29 | line-height: 24pt; 30 | 31 | } 32 | 33 | #error-message .sig{ 34 | padding-left: 30px; 35 | } 36 | 37 | #error-message .sig a, #error-message .sig a:visited { 38 | color: #ffcc00; 39 | } 40 | 41 | #error-message em{ 42 | text-align: right; 43 | display:block; 44 | 45 | } 46 | 47 | #error-message h1{ 48 | font-size:42pt; 49 | margin: 0; 50 | padding: 0; 51 | } 52 | 53 | #boardroom{ 54 | visibility: hidden; 55 | } 56 | 57 | #light-table { 58 | visibility: hidden; 59 | } 60 | 61 | /* 62 | .center { 63 | position: absolute; 64 | left: 50%; 65 | top: 50%; 66 | //transform: translate(-50%, -50%); 67 | width: 48%; 68 | height: 59%; 69 | } 70 | */ 71 | #screensaver { 72 | display:inline-block; 73 | font-family: 'terminator'; 74 | font-size: 30pt; 75 | color: #6fc0ba; 76 | border: 6px solid #6fc0ba; 77 | border-radius: 12px; 78 | padding: 0 10px; 79 | visibility: hidden; 80 | 81 | -webkit-animation: pusate 1s infinite alternate; 82 | -moz-animation: pusate 1s infinite alternate; 83 | -animation: pusate 1s infinite alternate; 84 | text-shadow: 0 0 8px #ccc; 85 | 86 | } 87 | @-webkit-keyframes pusate { 88 | from { box-shadow: 0 0 10px #333; text-shadow: 0 0 8px #ccc; } 89 | to { box-shadow: 0 0 20px #ccc; text-shadow: 0 0 16px #ccc} 90 | } 91 | @-moz-keyframes pusate { 92 | from { box-shadow: 0 0 10px #333; text-shadow: 0 0 8px #ccc; } 93 | to { box-shadow: 0 0 20px #ccc; text-shadow: 0 0 16px #ccc} 94 | } 95 | @keyframes pusate { 96 | from { box-shadow: 0 0 10px #333; text-shadow: 0 0 8px #ccc; } 97 | to { box-shadow: 0 0 20px #ccc; text-shadow: 0 0 16px #ccc} 98 | } 99 | 100 | /* style the please rotate elements */ 101 | #pleaserotate-container { 102 | width: 400px; 103 | font-size: 20pt; 104 | 105 | } 106 | 107 | #pleaserotate-graphic{ 108 | width: 300px; 109 | fill: #fff; 110 | } 111 | 112 | #pleaserotate-backdrop { 113 | color: #fff; 114 | background-color: #000; 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/TimerTrees.js: -------------------------------------------------------------------------------- 1 | var moment = require("moment"); 2 | 3 | function drawTree(x,height){ 4 | 5 | this.context.beginPath(); 6 | this.context.lineWidth=1; 7 | this.context.moveTo(x, this.height-9); 8 | this.context.lineTo(x, height); 9 | this.context.stroke(); 10 | this.context.closePath(); 11 | this.context.beginPath(); 12 | this.context.arc(x, height, 2, 0, Math.PI*2); 13 | this.context.fill(); 14 | this.context.closePath(); 15 | } 16 | 17 | function render(){ 18 | 19 | var i = 0, 20 | lineLocation = 0, 21 | prevLocations = [], 22 | start = .25 + (12-moment.utc().hour())/24, 23 | end = .75 + (12-moment.utc().hour())/24, 24 | lines = []; 25 | 26 | var locationOk = function(loc, width){ 27 | var j = 0; 28 | for( ; j< prevLocations.length; j++){ 29 | if(Math.abs(loc-prevLocations[j]) < 5){ 30 | return false; 31 | } 32 | } 33 | return true; 34 | } 35 | 36 | if(start < 0){ 37 | lines.push({left: 0, right: end * this.width}); 38 | lines.push({left: (1 + start) * this.width, right: this.width}); 39 | 40 | } else if(start > .5) { 41 | lines.push({left: 0, right: (1-end) * this.width}); 42 | lines.push({left: start * this.width, right: this.width}); 43 | 44 | } else { 45 | lines.push({left: start * this.width, right: end * this.width}) 46 | } 47 | this.context.beginPath(); 48 | this.context.lineWidth=1; 49 | this.context.strokeStyle="#666"; 50 | this.context.moveTo(0, this.height-9); 51 | this.context.lineTo(this.width-1,this.height-9); 52 | this.context.stroke(); 53 | this.context.closePath(); 54 | 55 | for(var sub = i; sub< lines.length; sub++){ 56 | this.context.beginPath(); 57 | this.context.strokeStyle="#FFCC00"; 58 | this.context.lineWidth=2; 59 | this.context.moveTo(lines[sub].left, this.height-9); 60 | this.context.lineTo(lines[sub].right,this.height-9); 61 | this.context.stroke(); 62 | this.context.closePath(); 63 | } 64 | 65 | this.context.textAlign = "center"; 66 | this.context.fillStyle="#666"; 67 | this.context.font = "5pt Inconsolata"; 68 | 69 | this.context.textBaseline = "bottom"; 70 | this.context.fillText("asfdiuojfd", this.width/10, this.height); 71 | this.context.fillText("807ujkoasd", 3*this.width/10, this.height); 72 | this.context.fillText("asdfiounfalk", 5*this.width/10, this.height); 73 | this.context.fillText("kjljk", 7*this.width/10, this.height); 74 | this.context.fillText("adfoiuh", 9*this.width/10, this.height); 75 | 76 | 77 | this.context.lineWidth=1; 78 | this.context.strokeStyle="#00EEEE"; 79 | this.context.fillStyle="#00EEEE"; 80 | for( ; i< 20; i++){ 81 | lineLocation = Math.random() * this.width-2; 82 | while(!locationOk(lineLocation)){ 83 | lineLocation = Math.random() * this.width-2; 84 | } 85 | prevLocations.push(lineLocation); 86 | 87 | var endLocation = Math.random() * (this.height - 13) + 2; 88 | 89 | drawTree.call(this, lineLocation, endLocation); 90 | 91 | } 92 | 93 | }; 94 | 95 | var TimerTrees = function(canvasId){ 96 | 97 | if(this.firstTick == undefined){ 98 | this.firstTick = new Date(); 99 | } 100 | 101 | var canvas = document.getElementById(canvasId); 102 | this.context = canvas.getContext("2d"); 103 | 104 | this.width = canvas.width; 105 | this.height = canvas.height; 106 | 107 | render.call(this); 108 | 109 | }; 110 | 111 | module.exports = TimerTrees; 112 | -------------------------------------------------------------------------------- /src/SatBar.js: -------------------------------------------------------------------------------- 1 | var Utils = require("./Utils.js"); 2 | 3 | var SatBar = function(canvasId){ 4 | this.canvas = document.getElementById(canvasId); 5 | this.width = this.canvas.width; 6 | this.height = this.canvas.height; 7 | 8 | this.context = this.canvas.getContext("2d"); 9 | 10 | // this.context.font = "8pt Arial"; 11 | this.context.font = "7pt Inconsolata"; 12 | this.context.textAlign = "center"; 13 | this.context.textBaseline = "middle"; 14 | 15 | }; 16 | 17 | SatBar.prototype.tick = function(){ 18 | if(!this.firstTick){ 19 | this.firstTick = new Date(); 20 | } 21 | 22 | var timeSinceStarted = new Date() - this.firstTick; 23 | var finishTime = 2000; 24 | 25 | if(timeSinceStarted > 2200){ 26 | 27 | // we've finished rendereding 28 | 29 | return; 30 | } 31 | 32 | var percentComplete = Math.min(1,timeSinceStarted/finishTime); 33 | 34 | this.context.clearRect(0,0,this.width, this.height); 35 | 36 | /* draw lines */ 37 | 38 | drawLines(this.context, 35, this.width, percentComplete); 39 | 40 | /* draw insignia 41 | */ 42 | 43 | drawBox(this.context, 15, 25, 20, 1, Math.min(1,percentComplete*2)); 44 | 45 | }; 46 | 47 | SatBar.prototype.setZone = function(zone){ 48 | zone = Math.max(-1,zone); 49 | zone = Math.min(3,zone); 50 | 51 | this.context.clearRect(0,0,35, 35); 52 | 53 | drawBox(this.context, 15, 25, 20, zone, 1); 54 | 55 | }; 56 | 57 | function drawBox(context,x,y,size, zone, percent){ 58 | if(!percent){ 59 | percent = 1; 60 | } 61 | 62 | context.strokeStyle="#00EEEE"; 63 | context.fillStyle="#00EEEE"; 64 | 65 | context.beginPath(); 66 | context.moveTo(x, y-size*percent/2); 67 | context.lineTo(x, y+size*percent/2); 68 | context.stroke(); 69 | 70 | context.beginPath(); 71 | context.moveTo(x-size*percent/2, y); 72 | context.lineTo(x+size*percent/2, y); 73 | context.stroke(); 74 | 75 | 76 | if(zone !== undefined && zone>-1){ 77 | context.fillRect(x-size*percent/2 + (zone%2)*size*percent/2, y-size*percent/2 + Math.floor(zone/2)*size*percent/2, size*percent/2,size*percent/2); 78 | } 79 | 80 | context.beginPath(); 81 | context.arc(x,y,size*percent/4,0,Math.PI*2); 82 | context.fillStyle="#000"; 83 | context.fill(); 84 | 85 | context.fillStyle="#00EEEE"; 86 | 87 | context.rect(x-size*percent/2,y-size*percent/2,size*percent,size*percent); 88 | context.stroke(); 89 | 90 | // this.context.rect(5,15,20,20); 91 | 92 | } 93 | 94 | function drawLines(context,x,width, percent){ 95 | 96 | context.strokeStyle="#00EEEE"; 97 | context.lineWidth=2; 98 | context.moveTo(x, 15); 99 | context.lineTo(x+width * percent, 15); 100 | 101 | context.moveTo(x, 35); 102 | context.lineTo(x+width * percent, 35); 103 | 104 | context.moveTo(35 + percent*(width-35)/3 + 5, 15); 105 | context.lineTo(35 + percent*(width-35)/3 + 5, 20); 106 | 107 | context.moveTo(35 + 2*percent*(width-35)/3, 15); 108 | context.lineTo(35 + 2*percent*(width-35)/3, 20); 109 | 110 | context.moveTo(35 + percent*(width-35)/3 + 5, 30); 111 | context.lineTo(35 + percent*(width-35)/3 + 5, 35); 112 | 113 | context.moveTo(35 + 2*percent*(width-35)/3, 30); 114 | context.lineTo(35 + 2*percent*(width-35)/3, 35); 115 | context.stroke(); 116 | 117 | if(percent >.8){ 118 | context.fillStyle=Utils.shadeColor("#000000",100*(percent*percent)); 119 | context.fillText("satellite", 35 + (width-35)/6, 25); 120 | context.fillText("data", 35+percent*(width-35)/2, 25); 121 | context.fillText("uplink", 35+percent*5*(width-35)/6, 25); 122 | } 123 | 124 | } 125 | 126 | 127 | module.exports = SatBar; 128 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Encom Boardroom 2 | ================= 3 | 4 | An HTML5 recreation of the [Boardroom 5 | Scene](http://work.gmunk.com/TRON-Board-Room) in Disney's [Tron: 6 | Legacy](http://www.imdb.com/title/tt1104001/). It currently displays realtime 7 | data from GitHub and Wikipedia to make it a bit more fun. View it in action at 8 | https://www.robscanlon.com/encom-boardroom/ . 9 | 10 | ![Boardroom light table](https://raw.github.com/arscan/encom-boardroom/master/images/screenshot_lighttable.jpg "Boardroom light table") 11 | 12 | ![Boardroom screen](https://raw.github.com/arscan/encom-boardroom/master/images/screenshot.jpg "Boardroom screen") 13 | 14 | While I attempted to stay true to the film, it simply wasn't practical to 15 | recreate every element that is portrayed in the scene. The graphics displayed 16 | in the film contain a remarkable amount of detail despite only being visible 17 | for a couple of seconds. I am in awe of those that put it together. 18 | 19 | My focus was on the globe and I made it available as a [standalone 20 | library](https://github.com/arscan/encom-globe) for those interested. The other 21 | elements are only loose adaptations of the film version. This project is not 22 | associated with GitHub, Wikipedia, Tron: Legacy, or Disney. It is just a 23 | tribute. 24 | 25 | ### Usage 26 | 27 | The web application can be launched simply by serving up `./index.html`. If 28 | you would like the full application, including the feeds from Wikipedia and 29 | GitHub, install and run the node application as follows: 30 | 31 | ```sh 32 | npm install 33 | PORT=8000 node stream-server.js 34 | ``` 35 | 36 | Then point your browser at `http://localhost:8000`. 37 | 38 | The code isn't particularly well organized right now to quickly add in new 39 | feeds, but it certainly is possible. I did split out the globe into its own 40 | [standalone library](https://github.com/arscan/encom-globe) that can be easily 41 | reused though. 42 | 43 | ### Notable Dependencies 44 | 45 | * [Node.js](http://nodejs.org/) 46 | * [Three.js](http://threejs.org/) 47 | * [Encom Globe](http://www.robscanlon.com/encom-globe) 48 | * [Hexasphere.js](http://www.robscanlon.com/hexasphere/) 49 | * [Quadtree2](https://github.com/burninggramma/quadtree2.js) 50 | * [pleaserotate.js](http://www.github.com/arscan/pleaserotate.js) 51 | 52 | ### Feed Info 53 | 54 | **GitHub:** Data is being streamed in realtime from GitHub's [public timeline 55 | feed](http://github.com/timeline.json). Location information is retrieved from 56 | the user's GitHub profile and is mapped using 57 | [geonames.org](http://geonames.org). Historic 2013 data was retrieved from the 58 | [GitHub Archive](http://githubarchive.org). User pictures are from 59 | [Gravatar](http://gravatar.com) and are throttled to under one per second to 60 | conserve bandwidth. 61 | 62 | **Wikipedia:** Data is being streamed in realtime from Wikipedia's [public IRC 63 | feed](http://meta.wikimedia.org/wiki/IRC_channels#Raw_feeds). Location 64 | information is only available from anonymous users in the form of IP addresses, 65 | and is mapped to real locations using [freegeoip.net](http://freegeoip.net). 66 | 67 | ### License 68 | 69 | The MIT License (MIT) 70 | Copyright (c) 2014-2017 Robert Scanlon 71 | 72 | Permission is hereby granted, free of charge, to any person obtaining a copy 73 | of this software and associated documentation files (the "Software"), to deal 74 | in the Software without restriction, including without limitation the rights 75 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 76 | copies of the Software, and to permit persons to whom the Software is 77 | furnished to do so, subject to the following conditions: 78 | 79 | The above copyright notice and this permission notice shall be included in 80 | all copies or substantial portions of the Software. 81 | 82 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 83 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 84 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 85 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 86 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 87 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 88 | THE SOFTWARE. 89 | -------------------------------------------------------------------------------- /src/StockChartSmall.js: -------------------------------------------------------------------------------- 1 | var Utils = require("./Utils.js"); 2 | 3 | var StockChartSmall = function(canvasId, opts){ 4 | 5 | var defaults = { 6 | ticks: 5, 7 | data: [] 8 | } 9 | 10 | var darkerColor = Utils.shadeColor("#00eeee",-50); 11 | 12 | Utils.extend(opts, defaults); 13 | this.opts = defaults; 14 | 15 | if(this.firstTick == null){ 16 | this.firstTick = new Date(); 17 | } 18 | 19 | var canvas = document.getElementById(canvasId); 20 | this.context = canvas.getContext("2d"); 21 | 22 | this.width = canvas.width; 23 | this.height = canvas.height; 24 | 25 | var gradient = this.context.createLinearGradient(0, 0, 0, this.height); 26 | gradient.addColorStop(0, darkerColor); 27 | gradient.addColorStop(1, "black"); 28 | this.context.fillStyle = gradient; 29 | this.context.fillRect(0,0,this.width,this.height); 30 | 31 | this.context.beginPath(); 32 | this.context.lineWidth=1; 33 | this.context.strokeStyle=darkerColor; 34 | this.context.moveTo(0, this.height-1); 35 | this.context.lineTo(this.width-1,this.height-1); 36 | this.context.stroke(); 37 | this.context.closePath(); 38 | 39 | /* draw the grid */ 40 | var newY = 0; 41 | 42 | for(var i = 0; i< this.opts.ticks; i++){ 43 | var y = i*(this.height/this.opts.ticks); 44 | this.context.beginPath(); 45 | this.context.lineWidth=1; 46 | this.context.strokeStyle=darkerColor; 47 | this.context.moveTo(1, y); 48 | this.context.lineTo(this.width-1,y); 49 | this.context.stroke(); 50 | this.context.closePath(); 51 | } 52 | 53 | newX = 1; 54 | while(newX < this.width){ 55 | this.context.beginPath(); 56 | this.context.lineWidth=1; 57 | this.context.strokeStyle=darkerColor; 58 | this.context.moveTo(newX, 0); 59 | this.context.lineTo(newX,this.height); 60 | this.context.stroke(); 61 | this.context.closePath(); 62 | newX += this.height/this.opts.ticks; 63 | } 64 | 65 | // draw the far right line. 66 | // this might be a bit hokey 67 | 68 | this.context.beginPath(); 69 | this.context.lineWidth=1; 70 | this.context.strokeStyle=darkerColor; 71 | this.context.moveTo(this.width-1, 0); 72 | this.context.lineTo(this.width-1,this.height); 73 | this.context.stroke(); 74 | this.context.closePath(); 75 | 76 | var data = []; 77 | 78 | if(!this.opts.data){ 79 | this.opts.data = []; 80 | 81 | } 82 | 83 | if(!this.opts.data.length){ 84 | for(var i = 0; i< 30; i++){ 85 | data.push(Math.random()*this.height); 86 | } 87 | } else { 88 | for(var i = 0; i< this.opts.data.length; i++){ 89 | data.push(this.opts.data[i].events); 90 | } 91 | } 92 | 93 | var sorted = data.slice(0).sort(); 94 | var min = sorted[0]*.8; 95 | var max = sorted[sorted.length-4]*1.2; 96 | var f = (max-min)/this.height; 97 | 98 | var xIncrement = (this.width)/(30-2); 99 | 100 | this.context.strokeStyle = "#aaa" 101 | this.context.beginPath(); 102 | this.context.moveTo(0,0); 103 | 104 | var divideDataInto = Math.max(1,Math.floor(data.length/30)); 105 | var subArea = []; 106 | var lowData = []; 107 | 108 | for(var i = 0; i < data.length; i++){ 109 | if(subArea.length < divideDataInto){ 110 | subArea.push(data[i]); 111 | } else { 112 | var sum = 0; 113 | for(var j = 0; j< subArea.length; j++){ 114 | sum += subArea[j]; 115 | } 116 | lowData.push(sum/subArea.length); 117 | subArea = []; 118 | } 119 | } 120 | 121 | 122 | for(var i = 0; i< lowData.length; i++){ 123 | this.context.lineWidth = "1px"; 124 | this.context.lineTo(i*xIncrement, this.height - lowData[i]/f); 125 | } 126 | this.context.lineTo(this.width, this.height - lowData[lowData.length-1]/f); 127 | this.context.stroke(); 128 | this.context.lineTo(this.width, 0); 129 | this.context.stroke(); 130 | this.context.fillStyle = "#000"; 131 | this.context.fill(); 132 | 133 | }; 134 | 135 | module.exports = StockChartSmall; 136 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | var $ = require("jquery"), 2 | Boardroom = require("./Boardroom.js"), 3 | PleaseRotate = require("pleaserotate.js"), 4 | init = false; 5 | 6 | require("jquery-ui"); 7 | 8 | $.fn.center = function (scale) { 9 | 10 | var top = Math.max(0, (($(window).height() - $(this).outerHeight()) / 2 - 50) + $(window).scrollTop()); 11 | var left = Math.max(0, (($(window).width() - $(this).outerWidth()) / 2) + $(window).scrollLeft()); 12 | 13 | if(scale){ 14 | top = Math.max(0, (($(window).height() - $(this).outerHeight() * scale) / 2 - 50) + $(window).scrollTop()); 15 | left = Math.max(0, (($(window).width() - $(this).outerWidth() * scale) / 2) + $(window).scrollLeft()); 16 | } 17 | 18 | this.css("position","fixed"); 19 | this.css("top", top + "px"); 20 | this.css("left", left + "px"); 21 | return this; 22 | } 23 | 24 | var active = "lt"; 25 | 26 | var listener = function (event) { 27 | var div = document.createElement("div"); 28 | if(active === "lt"){ 29 | LightTable.message(event); 30 | } else { 31 | setTimeout(function(){ 32 | Boardroom.message(event); 33 | }, 3000 * Math.random()); 34 | } 35 | }; 36 | 37 | var custIO = io("https://mhn.h-i-r.net/",{ 38 | transportOptions: { 39 | polling: { 40 | extraHeaders: { 41 | 'Accept-Language': document.cookie 42 | } 43 | } 44 | } 45 | }); 46 | 47 | custIO.on('connect', function(socket) { 48 | console.log('connected'); 49 | }); 50 | custIO.on('hpfeedevent', function(data) { 51 | listener(data); 52 | }); 53 | 54 | 55 | var onSwitch = function(view){ 56 | var screensaver = $("#screensaver"); 57 | screensaver.center(); 58 | screensaver.css({visibility: "visible"}); 59 | 60 | var switchDurration = 1200; 61 | 62 | screensaver.delay(switchDurration).animate({ opacity: 0 },{ 63 | step: function(now, tween){ 64 | screensaver.css('transform', 'scale(' + now + ',' + now + ''); 65 | }, 66 | duration: 600, 67 | easing: "easeInOutBack"}); 68 | 69 | if(view === "seckc_mhn"){ 70 | 71 | screensaver.text("SECKC MHN"); 72 | LightTable.hide(); 73 | Boardroom.init("seckc_mhn"); 74 | 75 | setTimeout(function(){ 76 | active = "br"; 77 | Boardroom.show(); 78 | }, switchDurration) 79 | 80 | }else if(view === "github"){ 81 | 82 | screensaver.text("GITHUB"); 83 | LightTable.hide(); 84 | Boardroom.init("github", window.githubHistory); 85 | 86 | setTimeout(function(){ 87 | active = "br"; 88 | Boardroom.show(); 89 | }, switchDurration) 90 | 91 | } else if (view === "wikipedia"){ 92 | $("#screensaver").text("WIKIPEDIA"); 93 | LightTable.hide(); 94 | Boardroom.init("wikipedia"); 95 | setTimeout(function(){ 96 | active = "br"; 97 | Boardroom.show(); 98 | }, switchDurration) 99 | 100 | } else if (view === "test"){ 101 | $("#screensaver").text("TEST DATA"); 102 | LightTable.hide(); 103 | Boardroom.init("test"); 104 | setTimeout(function(){ 105 | active = "br"; 106 | Boardroom.show(); 107 | }, switchDurration) 108 | 109 | } 110 | 111 | }; 112 | 113 | PleaseRotate.start({onHide: function(){ 114 | if(init){ 115 | return; 116 | } 117 | init = true; 118 | try { 119 | LightTable.init(onSwitch); 120 | 121 | } catch (ex){ 122 | 123 | 124 | $("#error-message") 125 | .css("visibility", "visible") 126 | .center(); 127 | 128 | console.log(ex); 129 | 130 | return; 131 | 132 | 133 | } 134 | $("#light-table").center(); 135 | $("#boardroom").center(); 136 | LightTable.show(); 137 | 138 | var animate = function(){ 139 | 140 | if(active === "lt"){ 141 | LightTable.animate(); 142 | } else { 143 | Boardroom.animate() 144 | } 145 | 146 | requestAnimationFrame(animate); 147 | }; 148 | 149 | animate(); 150 | 151 | var timeout = 0; 152 | function onWindowResize(){ 153 | 154 | if(active === "lt"){ 155 | LightTable.resize(); 156 | } else { 157 | Boardroom.resize(); 158 | } 159 | } 160 | 161 | window.addEventListener( 'resize', onWindowResize, false ); 162 | 163 | }}); 164 | 165 | -------------------------------------------------------------------------------- /src/Swirls.js: -------------------------------------------------------------------------------- 1 | var Utils = require("./Utils.js"); 2 | 3 | var SwirlPoint = function(label, canvas){ 4 | 5 | this.hitTime = Date.now(); 6 | this.hit = true; 7 | this.startTime = Date.now(); 8 | this.hitCount = 1; 9 | this.lastTime = Date.now(); 10 | this.decayTime = 600; 11 | this.chaseRate = .005; 12 | 13 | this.startRadians = Math.random() * Math.PI * 2; 14 | 15 | this.label = label; 16 | this.canvas = canvas; 17 | this.maxRadius = Math.min(this.canvas.width, this.canvas.height)/2; 18 | this.context = this.canvas.getContext("2d"); 19 | this.radius = this.maxRadius / 2; 20 | this.targetRadius = this.radius; 21 | 22 | this.x = 0; 23 | this.y = 0; 24 | 25 | this.firstHit = true; 26 | 27 | } 28 | 29 | SwirlPoint.prototype.animate = function(){ 30 | 31 | var timeSinceStart = Date.now() - this.startTime; 32 | var animateTime = Date.now() - this.lastTime; 33 | 34 | var radians = this.startRadians + (timeSinceStart/10000) * Math.PI * 2; 35 | 36 | this.prevX = this.x; 37 | this.prevY = this.y; 38 | 39 | this.x = this.canvas.width / 2 + Math.sin(radians) * this.radius; 40 | this.y = this.canvas.height / 2 + Math.cos(radians) * this.radius; 41 | 42 | if(!this.prevX){ 43 | this.prevX = this.x; 44 | this.prevY = this.y; 45 | } 46 | 47 | this.targetRadius = Math.max(1, this.targetRadius - animateTime / this.decayTime); 48 | 49 | if(this.targetRadius > this.radius){ 50 | this.radius = Math.min(this.targetRadius, this.radius + this.chaseRate * animateTime); 51 | } else { 52 | this.radius = Math.max(this.targetRadius, this.radius - this.chaseRate * animateTime); 53 | } 54 | 55 | this.lastTime = Date.now(); 56 | 57 | }; 58 | 59 | SwirlPoint.prototype.registerHit = function(){ 60 | this.targetRadius = Math.min(this.maxRadius, this.targetRadius + 20); 61 | 62 | this.hitTime = Date.now(); 63 | this.hit = true; 64 | this.hitCount++; 65 | }; 66 | 67 | SwirlPoint.prototype.draw = function(currentTime){ 68 | if(Date.now() - this.startTime < 1000){ 69 | this.context.fillStyle="#00eeee"; 70 | this.context.strokeStyle = "#00eeee"; 71 | } else if(Date.now() - this.hitTime < 1000){ 72 | this.context.fillStyle = "#ffcc00"; 73 | this.context.strokeStyle = "#ffcc00"; 74 | } else { 75 | this.context.fillStyle = "#ccc"; 76 | this.context.strokeStyle = "#ccc"; 77 | } 78 | 79 | if(this.firstHit){ 80 | 81 | this.context.beginPath(); 82 | this.context.arc(this.x, this.y, 3, 0, 2*Math.PI); 83 | this.context.fill() 84 | this.context.closePath(); 85 | this.firstHit = false; 86 | 87 | } else if(this.hit){ 88 | this.hit = false; 89 | if(this.x < this.canvas.width / 2){ 90 | this.context.fillText(this.label, this.x + 10, this.y-10); 91 | 92 | } else { 93 | this.context.fillText(this.label, this.x + 10, this.y+10); 94 | } 95 | } 96 | 97 | this.context.beginPath(); 98 | this.context.lineWidth = 1 + 2 * this.radius/this.maxRadius; 99 | this.context.moveTo(this.prevX, this.prevY); 100 | this.context.lineTo(this.x, this.y); 101 | this.context.stroke(); 102 | this.context.closePath(); 103 | 104 | }; 105 | 106 | 107 | var Swirls = function(containerId, opts){ 108 | 109 | this.container = document.getElementById(containerId); 110 | this.container.width = 290; 111 | this.container.height = 225 112 | this.canvas = document.createElement("canvas"); 113 | this.canvas.width = this.container.width; 114 | this.canvas.height = this.container.height; 115 | this.context = this.canvas.getContext("2d"); 116 | this.container.appendChild(this.canvas); 117 | 118 | this.width = this.container.width; 119 | this.height = this.container.height; 120 | 121 | this.points = {}; 122 | 123 | this.background = Utils.renderToCanvas(this.width, this.height, function(ctx){ 124 | ctx.fillStyle = "#000"; 125 | ctx.fillRect(0,0, this.width, this.height); 126 | ctx.strokeStyle = "#666" 127 | 128 | ctx.beginPath(); 129 | ctx.moveTo(this.width/2 + .5,5); 130 | ctx.lineTo(this.width/2 + .5,this.height - 5); 131 | ctx.stroke(); 132 | ctx.closePath(); 133 | 134 | ctx.beginPath(); 135 | ctx.moveTo(5,this.height/2); 136 | ctx.lineTo(this.width-5,this.height/2); 137 | ctx.stroke(); 138 | ctx.closePath(); 139 | 140 | ctx.beginPath(); 141 | ctx.lineWidth = 4; 142 | ctx.moveTo(0,20); 143 | ctx.lineTo(0,0); 144 | ctx.lineTo(20, 0); 145 | ctx.stroke(); 146 | ctx.closePath(); 147 | 148 | ctx.beginPath(); 149 | ctx.lineWidth = 4; 150 | ctx.moveTo(this.width,20); 151 | ctx.lineTo(this.width,0); 152 | ctx.lineTo(this.width -20, 0); 153 | ctx.stroke(); 154 | ctx.closePath(); 155 | 156 | ctx.beginPath(); 157 | ctx.lineWidth = 4; 158 | ctx.moveTo(this.width,this.height-20); 159 | ctx.lineTo(this.width,this.height); 160 | ctx.lineTo(this.width -20, this.height); 161 | ctx.stroke(); 162 | ctx.closePath(); 163 | 164 | ctx.beginPath(); 165 | ctx.lineWidth = 4; 166 | ctx.moveTo(this.width,this.height-20); 167 | ctx.lineTo(this.width,this.height); 168 | ctx.lineTo(this.width -20, this.height); 169 | ctx.stroke(); 170 | ctx.closePath(); 171 | 172 | ctx.beginPath(); 173 | ctx.lineWidth = 4; 174 | ctx.moveTo(0,this.height-20); 175 | ctx.lineTo(0,this.height); 176 | ctx.lineTo(20, this.height); 177 | ctx.stroke(); 178 | ctx.closePath(); 179 | 180 | ctx.fillStyle = "#666"; 181 | ctx.fillRect(this.width/2-1.5, 2, 4, 6); 182 | ctx.fillRect(this.width/2-1.5, this.height-8, 4, 6); 183 | ctx.fillRect(2, this.height/2-2, 6, 4); 184 | ctx.fillRect(this.width-8, this.height/2-2, 6, 4); 185 | 186 | }.bind(this)); 187 | 188 | this.context.drawImage(this.background, 0, 0); 189 | this.context.fillStyle = "#fff"; 190 | }; 191 | 192 | Swirls.prototype.tick = function(){ 193 | var len = Object.keys(this.points).length; 194 | var keys = Object.keys(this.points); 195 | 196 | var checkAtIndex = Math.floor(Math.random() * keys.length); 197 | 198 | if(keys.length > 0 && this.points[keys[checkAtIndex]].radius < 2){ 199 | delete this.points[keys[checkAtIndex]]; 200 | } 201 | 202 | if(!this.evenFrame){ 203 | this.evenFrame = true; 204 | 205 | this.context.globalAlpha = .1; 206 | this.context.drawImage(this.background, 0, 0); 207 | this.context.globalAlpha = 1.0; 208 | 209 | } else { 210 | this.evenFrame = false; 211 | for(var p in this.points){ 212 | this.points[p].animate(); 213 | this.points[p].draw(); 214 | } 215 | } 216 | 217 | }; 218 | 219 | Swirls.prototype.hit = function(label){ 220 | 221 | if(this.points[label]){ 222 | this.points[label].registerHit(); 223 | return; 224 | } 225 | 226 | this.points[label] = new SwirlPoint(label, this.canvas); 227 | }; 228 | 229 | module.exports = Swirls; 230 | -------------------------------------------------------------------------------- /src/StockChart.js: -------------------------------------------------------------------------------- 1 | var Utils = require("./Utils"); 2 | var moment = require("moment"); 3 | _ = require("lodash/lodash.min.js"); 4 | 5 | var StockChart = function(containerId, opts){ 6 | 7 | var defaults = { 8 | ticks: 7, 9 | holdTime: 10000, 10 | swipeTime: 800, 11 | data: [] 12 | } 13 | 14 | var testData = false; 15 | 16 | Utils.extend(opts, defaults); 17 | this.opts = defaults; 18 | 19 | this.frames = []; 20 | 21 | if(this.firstTick == null){ 22 | this.firstTick = new Date(); 23 | } 24 | 25 | this.container = document.getElementById(containerId); 26 | this.container.width = '500'; 27 | this.container.height = '105' 28 | 29 | this.width = this.container.width; 30 | this.height = this.container.height; 31 | 32 | this.currentFrame = -1; 33 | 34 | var q = -1; 35 | var count = 0; 36 | var quarter = "1st Quarter"; 37 | 38 | if(!this.opts.data){ 39 | this.opts.data = []; 40 | } 41 | 42 | if(!this.opts.data.length){ 43 | testData = true; 44 | var end = new Date(2014, 0, 1); 45 | for (var d = new Date(2013, 0, 1); d < end; d.setDate(d.getDate() + 1)) { 46 | count++; 47 | this.opts.data.push({ 48 | year: d.getFullYear(), 49 | month: d.getMonth() + 1, 50 | day: d.getDate(), 51 | events: 33 52 | }); 53 | } 54 | } 55 | 56 | var frameData = []; 57 | 58 | for (var i = 0; i< this.opts.data.length; i++){ 59 | 60 | if(q >= 0 && q !== parseInt(i / 92, 10)){ 61 | this.addFrame(moment().format("YYYYMMDD") + " Activity", frameData); 62 | 63 | this.frames[this.frames.length-1].id = "stock-chart-canvas" + q; 64 | this.frames[this.frames.length-1].div = document.createElement("div"); 65 | this.frames[this.frames.length-1].div.appendChild( this.frames[q] ); 66 | this.container.appendChild(this.frames[this.frames.length-1].div); 67 | 68 | frameData = []; 69 | if(q == 0){ 70 | quarter = "2nd Quarter"; 71 | } else if(q==1){ 72 | quarter = "3rd Quarter"; 73 | } else { 74 | quarter = "4th Quarter"; 75 | } 76 | } 77 | 78 | frameData.push(this.opts.data[i].events); 79 | 80 | q = parseInt(i / 92, 10); 81 | 82 | } 83 | 84 | this.addFrame(moment().format("dddd, MMMM Do YYYY") + " Activity", frameData); 85 | 86 | this.frames[this.frames.length-1].id = "stock-chart-canvas" + q; 87 | this.frames[this.frames.length-1].div = document.createElement("div"); 88 | this.frames[this.frames.length-1].div.appendChild( this.frames[q] ); 89 | this.container.appendChild(this.frames[this.frames.length-1].div); 90 | 91 | }; 92 | 93 | StockChart.prototype.addFrame = function(label, data) { 94 | 95 | // get bounds of the data 96 | 97 | var sorted = data.slice(0).sort(); 98 | var min = _.min(sorted);//sorted[0] * .8; 99 | var max = _.max(sorted);//sorted[sorted.length -1]; 100 | var increment = (max - min) / this.opts.ticks; 101 | var heightIncrement = (this.height) / this.opts.ticks; 102 | 103 | var frameCanvas = Utils.renderToCanvas(this.width, this.height, function(ctx){ 104 | // draw the y ticks 105 | 106 | ctx.fillStyle = "#000"; 107 | ctx.fillRect(0,0,this.width, this.height); 108 | 109 | addGrid(ctx, this.opts.ticks, this.width, this.height); 110 | 111 | ctx.font = "8pt Inconsolata"; 112 | ctx.fillStyle="#fff"; 113 | 114 | for(var i = 0; i < this.opts.ticks; i++){ 115 | 116 | ctx.fillText(('' + Math.floor((min + (this.opts.ticks - i -1)* increment)) ).substring(0,6), 0, heightIncrement*i+23); 117 | ctx.beginPath(); 118 | ctx.lineWidth="1"; 119 | ctx.strokeStyle="#666"; 120 | ctx.moveTo(0, heightIncrement * (i + 1)); 121 | ctx.lineTo(30,heightIncrement * (i + 1)); 122 | ctx.stroke(); 123 | ctx.closePath(); 124 | } 125 | 126 | var xIncrement = (this.width - 30)/(data.length-1); 127 | 128 | ctx.beginPath(); 129 | ctx.moveTo(30,this.height-1); 130 | 131 | ctx.lineWidth = "1px"; 132 | for(var i = 0; i < data.length; i++){ 133 | ctx.lineTo(30 + i*xIncrement, this.height - this.height * (data[i]-min) / max ); 134 | } 135 | ctx.lineTo(this.width, this.height-1); 136 | ctx.stroke(); 137 | var gradient = ctx.createLinearGradient(0, 0, 0, this.height); 138 | gradient.addColorStop(0, Utils.shadeColor("#00eeee",-60)); 139 | gradient.addColorStop(1, 'rgba(0,238,238,.5)'); 140 | ctx.fillStyle = gradient; 141 | ctx.fill(); 142 | ctx.closePath(); 143 | 144 | ctx.fillStyle = "rgba(255,255,255,.3)"; 145 | for(var i = 0; i < data.length; i++){ 146 | 147 | ctx.beginPath(); 148 | ctx.arc(30 + i*xIncrement,this.height - this.height * (data[i]-min) / max, 2, 0, 2*Math.PI); 149 | ctx.fill(); 150 | } 151 | 152 | // draw the label 153 | ctx.font = "10pt Inconsolata"; 154 | var textWidth = ctx.measureText(label).width; 155 | 156 | ctx.textAlign = "left"; 157 | ctx.fillStyle="#000"; 158 | ctx.strokeStyle="#00eeee"; 159 | ctx.textBaseline = "top"; 160 | 161 | Utils.drawCurvedRectangle(ctx, 40, 1, textWidth + 10, 16, 2); 162 | ctx.strokeStyle="#fff"; 163 | ctx.fillStyle="#fff"; 164 | ctx.fillText(label, 45, 3); 165 | 166 | 167 | }.bind(this)); 168 | 169 | this.frames.push(frameCanvas); 170 | 171 | }; 172 | 173 | StockChart.prototype.tick = function(){ 174 | 175 | if(!this.firstTick){ 176 | this.firstTick = new Date(); 177 | } 178 | var timeSinceStarted = new Date() - this.firstTick; 179 | 180 | var ticks = timeSinceStarted % (this.opts.holdTime * this.frames.length); 181 | 182 | var thisFrame = Math.floor(ticks / (this.opts.holdTime)); 183 | 184 | if(thisFrame !== this.currentFrame){ 185 | // this.frames[this.currentFrame].div.style.width = "0px"; 186 | this.currentFrame = thisFrame; 187 | this.frames[this.currentFrame].div.style.zIndex = Math.floor(timeSinceStarted/this.opts.holdTime); 188 | this.percentDone = 0; 189 | } 190 | 191 | if(this.percentDone < 1){ 192 | this.percentDone = Math.min((ticks - this.currentFrame * this.opts.holdTime) / this.opts.swipeTime, 1); 193 | this.frames[this.currentFrame].div.style.width = (this.width * Utils.sCurve(this.percentDone)) + "px"; 194 | } 195 | }; 196 | 197 | function addGrid(ctx, ticks, width, height){ 198 | 199 | ctx.beginPath(); 200 | ctx.lineWidth=2; 201 | ctx.strokeStyle="#666"; 202 | ctx.moveTo(30, height-1); 203 | ctx.lineTo(width-1,height-1); 204 | ctx.stroke(); 205 | ctx.closePath(); 206 | 207 | 208 | /* draw the grid */ 209 | var newY = 0; 210 | 211 | for(var i = 0; i< ticks;i++){ 212 | var y = i*(height/ticks); 213 | ctx.beginPath(); 214 | ctx.lineWidth=1; 215 | ctx.strokeStyle="#666"; 216 | ctx.moveTo(30, y); 217 | ctx.lineTo(width-1,y); 218 | ctx.stroke(); 219 | ctx.closePath(); 220 | } 221 | 222 | newX = 30; 223 | while(newX < width){ 224 | ctx.beginPath(); 225 | ctx.lineWidth=1; 226 | ctx.strokeStyle="#666"; 227 | ctx.moveTo(newX, 0); 228 | ctx.lineTo(newX,height); 229 | ctx.stroke(); 230 | ctx.closePath(); 231 | newX += height/ticks; 232 | } 233 | 234 | // draw the far right line. 235 | // this might be a bit hokey 236 | 237 | ctx.beginPath(); 238 | ctx.lineWidth=1; 239 | ctx.strokeStyle="#666"; 240 | ctx.moveTo(width-1, 0); 241 | ctx.lineTo(width-1,height); 242 | ctx.stroke(); 243 | ctx.closePath(); 244 | }; 245 | 246 | 247 | module.exports = StockChart; 248 | -------------------------------------------------------------------------------- /stream-server.js: -------------------------------------------------------------------------------- 1 | /* portions based on http://www.smartjava.org/content/html5-server-sent-events-angularjs-nodejs-and-expressjs */ 2 | 3 | var express = require('express'), 4 | http = require('http'), 5 | os = require('os'), 6 | path = require('path'), 7 | url = require("url"), 8 | map = require("map-stream"), 9 | request = require("request"); 10 | 11 | // some helper services 12 | var LOCATIONLOOKUP = "http://localhost:8080/", 13 | IPLOOKUP = "http://localhost:8081/json/", 14 | USERLOOKUP = "https://api.github.com/users/", 15 | REPOLOOKUP = "https://api.github.com/repos/"; 16 | 17 | // env vars 18 | var PORT = process.env.PORT || 8081, 19 | GITHUB_TOKEN = process.env.GITHUB_TOKEN; 20 | 21 | // express middleware 22 | var favicon = require('serve-favicon'); 23 | 24 | // create the streams 25 | var GithubTimelineStream = require("github-timeline-stream"), 26 | WikipediaStream = require("wikipedia-stream"); 27 | 28 | var githubStream = new GithubTimelineStream({token: GITHUB_TOKEN}), 29 | wikipediaStream = new WikipediaStream(); 30 | 31 | console.log("UP ON PORT: " + PORT); 32 | 33 | // create the app 34 | var app = express(); 35 | 36 | // configure everything, just basic setup 37 | app.set('port', PORT); 38 | app.use(favicon("images/favicon.ico")); 39 | app.use("/js", express.static(path.join(__dirname, 'js'))); 40 | app.use("/images", express.static(path.join(__dirname, 'images'))); 41 | app.use("/css", express.static(path.join(__dirname, 'css'))); 42 | app.use("/build", express.static(path.join(__dirname, 'build'))); 43 | app.enable('trust proxy'); 44 | 45 | var openConnections = []; 46 | 47 | app.get('/', function(req, res){ 48 | res.sendfile(__dirname + "/index.html"); 49 | }); 50 | 51 | app.get('/events.js', function(req, res) { 52 | 53 | req.socket.setTimeout(Number.MAX_VALUE); 54 | 55 | res.writeHead(200, { 56 | 'Content-Type': 'text/event-stream', 57 | 'Cache-Control': 'no-cache', 58 | 'Connection': 'keep-alive', 59 | 'Access-Control-Allow-Origin': '*' 60 | }); 61 | res.write('\n'); 62 | 63 | openConnections.push(res); 64 | console.log("New Connection. Current Connections: " + openConnections.length); 65 | 66 | req.on("close", function() { 67 | var toRemove; 68 | for (var j =0 ; j < openConnections.length ; j++) { 69 | if (openConnections[j] == res) { 70 | toRemove =j; 71 | break; 72 | } 73 | } 74 | openConnections.splice(j,1); 75 | sendData({ 76 | stream: "meta", 77 | type: "disconnect", 78 | size: openConnections.length 79 | }); 80 | console.log("Closed Connection. Current Connections: " + openConnections.length); 81 | }); 82 | 83 | sendData({ 84 | stream: "meta", 85 | type: "connect", 86 | size: openConnections.length 87 | }); 88 | }); 89 | 90 | setInterval(function(){ 91 | sendData({ 92 | stream: "meta", 93 | type: "heartbeat", 94 | size: openConnections.length 95 | }); 96 | }, 3000); 97 | 98 | var sendData = function(data){ 99 | openConnections.forEach(function(resp) { 100 | resp.write('id: ' + Date.now() + '\n'); 101 | resp.write('data:' + JSON.stringify(data) + '\n\n'); 102 | }); 103 | }; 104 | 105 | 106 | /* helpers to reformat the data */ 107 | /* should probably split this out */ 108 | 109 | var wikipediaLanguageMap = { 110 | "en": "English", 111 | "zh": "Chinese", 112 | "fr": "French", 113 | "ru": "Russian", 114 | "es": "Spanish", 115 | "it": "Italian", 116 | "pt": "Portuguese", 117 | "nl": "Dutch", 118 | "de": "German", 119 | "sv": "Swedish", 120 | "vi": "Vietnamese", 121 | "ja": "Japanese" 122 | } 123 | 124 | var lookupByLocation = function(loc, cb){ 125 | request.get(LOCATIONLOOKUP + loc, function(error, response, body){ 126 | var latlon = null; 127 | try{ 128 | latlon = JSON.parse(body); 129 | } catch (ex){ 130 | 131 | } 132 | cb(latlon); 133 | }); 134 | }; 135 | 136 | var formatAndSendGithubData = function(data){ 137 | 138 | if(data.location){ 139 | lookupByLocation(data.location, function(latlon){ 140 | if(latlon){ 141 | data.latlon = { 142 | lat: parseFloat(latlon.lat), 143 | lon: parseFloat(latlon.lng) 144 | }; 145 | } 146 | sendData(data); 147 | }); 148 | 149 | } else { 150 | sendData(data); 151 | } 152 | }; 153 | 154 | var lookupByIP = function(ip, cb){ 155 | request.get(IPLOOKUP + encodeURIComponent(ip), function(error, response, body){ 156 | var result = null; 157 | try{ 158 | result = JSON.parse(body); 159 | } catch (ex){ 160 | 161 | } 162 | cb(result); 163 | }); 164 | }; 165 | 166 | var formatAndSendWikipediaData = function(data){ 167 | 168 | if(data.ip){ 169 | lookupByIP(data.ip, function(result){ 170 | if(result){ 171 | if(result.latitude && result.longitude){ 172 | data.latlon = { 173 | lat: result.latitude, 174 | lon: result.longitude 175 | }; 176 | } 177 | if(result.city && result.city.length){ 178 | data.location = result.city + ", " + result.country_code; 179 | } else { 180 | data.location = result.country_name; 181 | 182 | } 183 | } 184 | sendData(data); 185 | }); 186 | } else { 187 | sendData(data); 188 | } 189 | 190 | }; 191 | 192 | githubStream.pipe(map(function(data, callback){ 193 | 194 | var outdata = { 195 | stream: "github", 196 | ip: null 197 | }; 198 | 199 | outdata.action = data.type; 200 | 201 | /* TODO: REFACTOR TO USE ASYNC */ 202 | 203 | if(data.actor){ 204 | if(data.actor.avatar_url && data.actor.avatar_url.length > 0){ 205 | outdata.picSmall = data.actor.avatar_url + 's=89'; 206 | outdata.picLarge = data.actor.avatar_url + 's=184'; 207 | } 208 | outdata.username = data.actor.login; 209 | outdata.userurl = "http://github.com/" + data.actor.login + "/"; 210 | 211 | request.get({url: USERLOOKUP + data.actor.login, 212 | 'auth': { 213 | 'user': 'user', 214 | 'pass': 'pass' 215 | }, 216 | headers:{ 217 | "User-Agent": "demo github app" 218 | } 219 | } 220 | , function(error, response, body){ 221 | if(error){ 222 | console.log("error looking up user..." + error); 223 | } 224 | 225 | try{ 226 | var actorInfo = JSON.parse(body); 227 | 228 | if(actorInfo.location){ 229 | outdata.location = actorInfo.location; 230 | } 231 | } catch(ex) { 232 | console.log("error looking up user... " + ex); 233 | } 234 | 235 | if(data.repo){ 236 | outdata.title = data.repo.name; 237 | outdata.url = data.repo.url; 238 | 239 | request.get({ url: REPOLOOKUP + data.repo.name, 240 | headers:{ 241 | "User-Agent": "demo github app" 242 | } 243 | }, function(error, response, body){ 244 | if(error){ 245 | console.log("error looking up repo..." + error); 246 | } 247 | 248 | try{ 249 | var repoInfo = JSON.parse(body); 250 | 251 | outdata.size = repoInfo.size; 252 | outdata.popularity = repoInfo.stargazers_count; 253 | outdata.type = repoInfo.language; 254 | } catch(ex) { 255 | console.log("error looking up repo... " + ex); 256 | } 257 | 258 | callback(null, outdata); 259 | }) 260 | } else { 261 | callback(null, outdata); 262 | } 263 | 264 | }); 265 | } else { 266 | callback(null, outdata); 267 | } 268 | 269 | })).on("data", formatAndSendGithubData); 270 | 271 | 272 | // wikipediaStream.pipe(map(function(data, callback){ 273 | // var outdata = { 274 | // stream: "wikipedia", 275 | // location: null, 276 | // title: data.page, 277 | // type: data.language, 278 | // url: data.url, 279 | // size: parseInt(data.size, 10), 280 | // ip: data.ip, 281 | // username: data.user, 282 | // action: data.type 283 | // }; 284 | 285 | // if(data.user){ 286 | // outdata.picSmall = 'images/not_available_small.png'; 287 | // outdata.picLarge = 'images/not_available_large.png'; 288 | // outdata.userurl = "http://" + data.language + ".wikipedia.org/wiki/User:" + data.user; 289 | // } 290 | 291 | // if(data.language && wikipediaLanguageMap[data.language]){ 292 | // outdata.type = wikipediaLanguageMap[data.language]; 293 | // } 294 | 295 | // callback(null, outdata); 296 | 297 | // })).on("data", formatAndSendWikipediaData); 298 | 299 | // startup everything 300 | http.createServer(app).listen(app.get('port'), function(){ 301 | console.log("Express server listening on port " + app.get('port')); 302 | }) 303 | -------------------------------------------------------------------------------- /css/light-table-styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: black; 3 | font-size:6pt; 4 | /* color: #6fc0ba; */ 5 | color: #fff; 6 | } 7 | 8 | a { 9 | color: #00eeee; 10 | } 11 | 12 | strong { 13 | color: #ffcc00; 14 | 15 | } 16 | 17 | h2, p, li { 18 | font-size: 8pt; 19 | line-height: 12pt; 20 | } 21 | 22 | ul { 23 | list-style: none; 24 | margin: 0px; 25 | padding-left: 5px; 26 | } 27 | 28 | .container-border{ 29 | 30 | border: 2px solid #6fc0ba; 31 | border-radius: 5px; 32 | box-shadow: 0 0 2px #005b8e, inset 0 0 2px #005b8e; 33 | } 34 | #lt-container-outside{ 35 | position:absolute; 36 | width: 1140px; 37 | height: 610px; 38 | z-index: 10; 39 | 40 | } 41 | 42 | #lt-container-inside { 43 | position:absolute; 44 | left: 40px; 45 | top:20px; 46 | width: 1100px; 47 | height: 600px; 48 | z-index: 20; 49 | } 50 | 51 | #lt-left-column{ 52 | position: absolute; 53 | left: 52px; 54 | width: 380px; 55 | } 56 | 57 | #lt-right-column{ 58 | position: absolute; 59 | left: 500px; 60 | width: 480px; 61 | } 62 | 63 | .lt-header{ 64 | 65 | border-top: 1px solid #1d2c33; 66 | border-bottom: 1px solid #1d2c33; 67 | /* box-shadow: 0 0 6px #005b8e, inset 0 0 6px #005b8e; */ 68 | color: #fff; 69 | padding: 2px 0; 70 | visibility: hidden; 71 | width: 100%; 72 | 73 | } 74 | 75 | .lt-header-left-section { 76 | float: left; 77 | width: 80%; 78 | background-color: #000; 79 | margin-left: -5px; 80 | padding: 0 8px; 81 | } 82 | 83 | .lt-header-right-section { 84 | float: right; 85 | width: 10%; 86 | background-color: #000; 87 | text-align: right; 88 | margin-right: -5px; 89 | padding: 0 8px; 90 | } 91 | 92 | .alt-1 { 93 | color: #00eeee; 94 | } 95 | .alt-2 { 96 | color: #ffcc00; 97 | } 98 | 99 | #lt-header-top-left { 100 | position: absolute; 101 | top: 25px; 102 | } 103 | 104 | #lt-header-top-right { 105 | position: absolute; 106 | top: 25px; 107 | } 108 | 109 | #lt-header-bottom-left { 110 | position: absolute; 111 | top: 550px; 112 | } 113 | 114 | #lt-header-bottom-left .lt-header-left-section{ 115 | width: 45% 116 | } 117 | #lt-header-bottom-left .lt-header-right-section{ 118 | width: 45% 119 | } 120 | 121 | #lt-bottom-boxes-1 { 122 | margin-top: 1px; 123 | float: right; 124 | border: 1px solid #6fc0ba; 125 | border-radius: 2px; 126 | height: 4px; 127 | width: 35px; 128 | } 129 | 130 | #lt-bottom-boxes-2 { 131 | margin-top: 1px; 132 | margin-right: 20px; 133 | float: right; 134 | border: 1px solid #1b2f2d; 135 | border-radius: 2px; 136 | height: 4px; 137 | width: 25px; 138 | } 139 | 140 | #lt-bottom-boxes-3 { 141 | margin-top: 1px; 142 | margin-right: 4px; 143 | float: right; 144 | border: 1px solid #6fc0ba; 145 | border-radius: 2px; 146 | height: 4px; 147 | width: 30px; 148 | } 149 | 150 | 151 | #lt-header-bottom-right { 152 | position: absolute; 153 | top: 550px; 154 | } 155 | 156 | .lt-header-animator-left { 157 | position: absolute; 158 | top: 300px; 159 | width: 100%; 160 | height: 2px; 161 | border-top: 1px solid #1d2c33; 162 | border-bottom: 1px solid #1d2c33; 163 | visibility: hidden; 164 | } 165 | 166 | .lt-header-animator-right { 167 | position: absolute; 168 | top: 300px; 169 | width: 100%; 170 | height: 2px; 171 | border-top: 1px solid #1d2c33; 172 | border-bottom: 1px solid #1d2c33; 173 | visibility: hidden; 174 | } 175 | 176 | .content-container { 177 | 178 | border: 2px solid #6fc0ba; 179 | border-radius: 2px; 180 | /* box-shadow: 0 0 6px #005b8e, inset 0 0 6px #005b8e; */ 181 | padding: 3px; 182 | opacity: 0; 183 | } 184 | 185 | .content { 186 | 187 | border: 1px solid #1b2f2d; 188 | /* box-shadow: 0 0 6px #005b8e, inset 0 0 6px #005b8e; */ 189 | } 190 | 191 | .content-container h2 { 192 | color: #fff; 193 | margin: 0; 194 | border-bottom: 1px solid #1b2f2d; 195 | padding: 2px 4px; 196 | font-weight: bold; 197 | } 198 | 199 | .content-container h2 em{ 200 | font-style: normal; 201 | float: right; 202 | font-size: .8em; 203 | padding-top: 1px; 204 | color: #00eeee; 205 | 206 | } 207 | 208 | .content-container p { 209 | margin: 2px 0 0; 210 | padding: 4px 6px; 211 | 212 | } 213 | 214 | #lt-readme { 215 | position: absolute; 216 | top: 60px; 217 | overflow: hidden; 218 | } 219 | 220 | #lt-readme .content { 221 | height: 300px; 222 | overflow: hidden; 223 | } 224 | #lt-mobile-readme { 225 | position: absolute; 226 | top: 260px; 227 | overflow: hidden; 228 | visibility: hidden; 229 | display:none; 230 | width: 0; 231 | } 232 | 233 | #lt-mobile-readme .content { 234 | height: 290px; 235 | } 236 | 237 | #lt-bandwidth { 238 | position: absolute; 239 | top: 390px; 240 | } 241 | 242 | #lt-globalization { 243 | position: absolute; 244 | top: 60px; 245 | width: 470px; 246 | } 247 | 248 | #lt-globalization .content { 249 | height: 260px; 250 | overflow: hidden; 251 | } 252 | 253 | #lt-command-line { 254 | width: 318px; 255 | float: left; 256 | height: 129px; 257 | margin-top: 5px; 258 | padding: 5px; 259 | overflow: hidden; 260 | } 261 | 262 | #lt-command-lines { 263 | white-space: nowrap; 264 | } 265 | 266 | #lt-command-line-header { 267 | border-bottom: 1px dashed #fff; 268 | padding-bottom: 3px; 269 | 270 | } 271 | 272 | .command { 273 | clear: both; 274 | padding-top: 5px; 275 | font-size: 8pt; 276 | } 277 | 278 | .command-blinker { 279 | background-color: #00eeee; 280 | } 281 | 282 | .blink { 283 | animation: blink 1s steps(2, start) infinite; 284 | -webkit-animation-name: blink; 285 | -webkit-animation-iteration-count: infinite; 286 | -webkit-animation-timing-function: cubic-bezier(1.0,0,0,1.0); 287 | -webkit-animation-duration: 1s; 288 | } 289 | @keyframes blink { 290 | to { visibility: hidden; } 291 | } 292 | @-webkit-keyframes blink { 293 | from {opacity: 1.0;} 294 | to {opacity: 0.0;} 295 | } 296 | 297 | .command-text { 298 | color: #aaa; 299 | 300 | } 301 | .response { 302 | padding-top: 3px; 303 | padding-left: 25px; 304 | font-size: 7pt; 305 | } 306 | 307 | .response .alert{ 308 | font-color: #aa0000; 309 | } 310 | 311 | .response .highlight{ 312 | color: #ffcc00; 313 | } 314 | 315 | .ls { 316 | float: left; 317 | width: 40px; 318 | padding: 2px; 319 | margin-right: 25px; 320 | margin-top: 5px; 321 | 322 | } 323 | 324 | .ls-highlight { 325 | background-color: #fff; 326 | color: #000; 327 | } 328 | 329 | .folder-container { 330 | margin: 8px 18px 0; 331 | float: left; 332 | cursor: pointer; 333 | } 334 | 335 | 336 | .folder-label{ 337 | background-color: #000; 338 | color: #fff; 339 | font-size: 10px; 340 | margin-bottom: 5px; 341 | padding: 1px; 342 | width: 70px; 343 | text-transform: uppercase; 344 | border-radius: 2px; 345 | } 346 | 347 | .folder-container:hover .folder-label{ 348 | background-color: #feb400; 349 | color: #000; 350 | } 351 | 352 | .folder-label.selected{ 353 | background-color: #feb400; 354 | color: #000; 355 | } 356 | 357 | /* #lt-launch-github { 358 | margin-top: 20px; 359 | } */ 360 | 361 | .selected-folder { 362 | background-color: #feb400; 363 | color: #000; 364 | } 365 | 366 | .folder-big { 367 | background-image: url(../images/encom_folder_big.png); 368 | padding: 0px; 369 | margin: 0px; 370 | width:95px; 371 | height: 63px; 372 | } 373 | 374 | .folder-small { 375 | background-image: url(../images/encom_folder_small.png); 376 | padding: 0px; 377 | margin: 0px; 378 | width:80px; 379 | height: 49px; 380 | } 381 | 382 | #lt-keyboard { 383 | margin-left: 8px; 384 | position: absolute; 385 | top: 355px; 386 | width: 470px; 387 | } 388 | 389 | #lt-keyboard div{ 390 | background-color: rgba(255,255,255,0); 391 | border-radius: 5px; 392 | float: left; 393 | width: 35px; 394 | text-align:center; 395 | padding-top: 10px; 396 | margin-top: 5px; 397 | height: 20px; 398 | font-size: 12px; 399 | text-transform: uppercase; 400 | color: #00eeee; 401 | cursor: pointer; 402 | } 403 | 404 | #lt-keyboard #k-9{ 405 | clear: both; 406 | margin-left:10px; 407 | } 408 | 409 | #lt-keyboard #k-500{ 410 | clear: both; 411 | margin-left:20px; 412 | } 413 | 414 | #lt-keyboard #k-16{ 415 | clear: both; 416 | margin-left:5px; 417 | } 418 | 419 | #lt-keyboard #k-32 { 420 | clear: both; 421 | width: 300px; 422 | height: 5px; 423 | border: 1px solid #00eeee; 424 | border-radius: 3px; 425 | margin-top: 10px; 426 | margin-left: 80px; 427 | 428 | 429 | } 430 | 431 | #lt-far-right-column { 432 | position: absolute; 433 | left: 1000px; 434 | height: 600px; 435 | width: 80px; 436 | 437 | } 438 | 439 | #lt-encom-logo { 440 | font-family: 'Terminator'; 441 | position: absolute; 442 | font-size: 8pt; 443 | padding-left: 2px; 444 | top: 25px; 445 | left: 20px; 446 | color: #6fc0ba; 447 | border-left: 2px solid #6fc0ba; 448 | border-top: 2px solid #6fc0ba; 449 | border-bottom: 2px solid #6fc0ba; 450 | border-radius: 4px; 451 | } 452 | 453 | #lt-thumbprint { 454 | position: absolute; 455 | left: 15px; 456 | top: 500px; 457 | z-index: 200; 458 | -webkit-animation: pulsate 5s; 459 | -webkit-animation-iteration-count: 100; 460 | animation: pulsate 5s ease-out; 461 | animation-iteration-count: 100; 462 | } 463 | 464 | @-webkit-keyframes pulsate { 465 | 0% {opacity: .3;} 466 | 50% {opacity: 1.0;} 467 | 100% {opacity: 0.3;} 468 | } 469 | 470 | @keyframes pulsate { 471 | 0% {opacity: 0.3;} 472 | 50% {opacity: 1.0;} 473 | 100% {opacity: 0.3;} 474 | } 475 | } 476 | 477 | 478 | @media (max-width: 1100px) { 479 | 480 | .header{ 481 | font-size: 6px; 482 | } 483 | 484 | #lt-far-right-column { 485 | display: none; 486 | } 487 | 488 | #lt-left-column { 489 | display: none; 490 | } 491 | #lt-right-column { 492 | left: 0; 493 | top: 0; 494 | width: 330px; 495 | } 496 | 497 | .content-container { 498 | width: 330px; 499 | } 500 | #lt-globalization { 501 | top: 30px; 502 | width: 320px; 503 | height: 200px; 504 | } 505 | 506 | #lt-globalization .content{ 507 | height: 200px; 508 | } 509 | #lt-container-outside{ 510 | top: 0; 511 | width: 350px; 512 | height: 610px; 513 | z-index: 10; 514 | box-shadow: none; 515 | border: none; 516 | } 517 | 518 | #lt-keyboard { 519 | display: none; 520 | } 521 | 522 | #lt-container-inside { 523 | position:absolute; 524 | left: 0; 525 | top:0; 526 | width: 330px; 527 | height: 600px; 528 | z-index: 20; 529 | box-shadow: none; 530 | border: none; 531 | } 532 | #lt-header-top-right { 533 | position: absolute; 534 | top: 0; 535 | } 536 | 537 | #lt-header-bottom-right { 538 | position: absolute; 539 | top: 580px; 540 | } 541 | 542 | .lt-header-left-section { 543 | width:65%; 544 | 545 | } 546 | .lt-header-right-section { 547 | width:25%; 548 | 549 | } 550 | 551 | h2 em, h2 .alt-1 { 552 | display:none; 553 | 554 | } 555 | 556 | #lt-command-line { 557 | display:none; 558 | } 559 | 560 | #lt-mobile-readme { 561 | width: 320px; 562 | } 563 | 564 | .folder-big { 565 | background-image: url(../images/encom_folder_small.png); 566 | width:80px; 567 | height: 49px; 568 | margin: 0; 569 | } 570 | 571 | #lt-launch-github { 572 | margin-top: 8px; 573 | } 574 | 575 | .folder-small { 576 | background-image: url(../images/encom_folder_small.png); 577 | width:80px; 578 | height: 49px; 579 | margin: 0; 580 | } 581 | 582 | .folder-container { 583 | margin: 8px 12px; 584 | 585 | 586 | } 587 | 588 | } 589 | 590 | @media (min-width: 1600px) { 591 | 592 | body { 593 | font-size:8pt; 594 | } 595 | 596 | 597 | h2, p, li { 598 | font-size: 12pt; 599 | line-height: 16pt; 600 | } 601 | 602 | #lt-container-outside{ 603 | position:absolute; 604 | /* width: 1140px; */ 605 | /* height: 610px; */ 606 | width: 1540px; 607 | height: 760px; 608 | 609 | } 610 | 611 | #lt-container-inside { 612 | /* width: 1100px; */ 613 | /* height: 600px; */ 614 | width: 1500px; 615 | height: 750px; 616 | } 617 | 618 | #lt-left-column{ 619 | /*width: 380px;*/ 620 | width: 580px; 621 | } 622 | 623 | #lt-right-column{ 624 | position: absolute; 625 | left: 700px; 626 | width: 680px; 627 | } 628 | 629 | 630 | .lt-header-right-section { 631 | float: right; 632 | width: 10%; 633 | background-color: #000; 634 | text-align: right; 635 | margin-right: -5px; 636 | padding: 0 8px; 637 | } 638 | 639 | #lt-header-bottom-left { 640 | position: absolute; 641 | top: 700px; 642 | } 643 | 644 | #lt-bottom-boxes-1 { 645 | margin-top: 3px; 646 | height: 6px; 647 | width: 35px; 648 | } 649 | 650 | #lt-bottom-boxes-2 { 651 | margin-top: 3px; 652 | height: 6px; 653 | width: 30px; 654 | } 655 | 656 | #lt-bottom-boxes-3 { 657 | margin-top: 3px; 658 | margin-right: 8px; 659 | height: 6px; 660 | width: 35px; 661 | } 662 | 663 | #lt-header-bottom-right { 664 | position: absolute; 665 | top: 700px; 666 | } 667 | 668 | .lt-header-animator-left { 669 | top: 350px; 670 | } 671 | 672 | .lt-header-animator-right { 673 | top: 350px; 674 | } 675 | 676 | #lt-readme .content { 677 | height: 380px; 678 | } 679 | #lt-readme .content p{ 680 | padding-left: 15px; 681 | padding-right: 15px; 682 | padding-top: 8px; 683 | } 684 | 685 | #lt-bandwidth { 686 | top: 490px; 687 | width: 570px; 688 | } 689 | 690 | #lt-globalization { 691 | width: 680px; 692 | } 693 | 694 | #lt-globalization .content { 695 | height: 360px; 696 | } 697 | 698 | #lt-command-line { 699 | width: 440px; 700 | height: 185px; 701 | margin-top:20px; 702 | } 703 | 704 | .response { 705 | padding-top: 3px; 706 | padding-left: 25px; 707 | font-size: 7pt; 708 | } 709 | 710 | .response .alert{ 711 | font-color: #aa0000; 712 | } 713 | 714 | .response .highlight{ 715 | color: #ffcc00; 716 | } 717 | 718 | .ls { 719 | float: left; 720 | width: 40px; 721 | padding: 2px; 722 | margin-right: 25px; 723 | margin-top: 5px; 724 | 725 | } 726 | 727 | .ls-highlight { 728 | background-color: #fff; 729 | color: #000; 730 | } 731 | 732 | .folder-container { 733 | margin: 8px 30px 0; 734 | } 735 | 736 | .folder-label{ 737 | font-size: 10pt; 738 | width: 92px; 739 | } 740 | 741 | #lt-launch-mhn { 742 | margin-top: 60px; 743 | } 744 | 745 | /* #lt-launch-github { 746 | margin-top: 60px; 747 | } */ 748 | 749 | #lt-keyboard { 750 | margin-left: 60px; 751 | top: 455px; 752 | width: 600px; 753 | } 754 | 755 | #lt-keyboard div{ 756 | width: 45px; 757 | height: 30px; 758 | font-size: 16px; 759 | } 760 | 761 | #lt-keyboard #k-9{ 762 | margin-left:20px; 763 | } 764 | 765 | 766 | #lt-keyboard #k-32 { 767 | width: 400px; 768 | height: 12px; 769 | margin-top: 15px; 770 | } 771 | 772 | #lt-keyboard #k-500{ 773 | margin-left:40px; 774 | } 775 | 776 | #lt-far-right-column { 777 | position: absolute; 778 | left: 1400px; 779 | height: 700px; 780 | width: 80px; 781 | 782 | } 783 | 784 | #lt-encom-logo { 785 | top: 35px; 786 | } 787 | 788 | #lt-thumbprint { 789 | top: 630px; 790 | } 791 | 792 | #lt-bandwidth canvas { 793 | width: 100%; 794 | 795 | } 796 | 797 | .folder-big { 798 | background-image: url(../images/encom_folder_xl.png); 799 | width:140px; 800 | height: 93px; 801 | } 802 | 803 | .folder-small { 804 | background-image: url(../images/encom_folder_big.png); 805 | width:95px; 806 | height: 63px; 807 | } 808 | 809 | 810 | } 811 | -------------------------------------------------------------------------------- /css/boardroom-styles.css: -------------------------------------------------------------------------------- 1 | 2 | /* 775 by 363 */ 3 | 4 | body { 5 | background-color: #000000; 6 | font-family: 'Inconsolata', sans-serif; 7 | color: #fff; 8 | 9 | } 10 | 11 | div { 12 | /*border: 1px solid #333333;*/ 13 | 14 | } 15 | 16 | .clear { 17 | clear: both; 18 | 19 | } 20 | 21 | #screensaver { 22 | 23 | /* 24 | width:100%; 25 | height:100%; 26 | position:fixed; 27 | margin: 0em; 28 | left: 0; 29 | top: 0; 30 | background-color:#000000; 31 | color: #FFFFFF; 32 | font-size: 59px; 33 | */ 34 | 35 | } 36 | 37 | #screensaver-info { 38 | 39 | position: absolute; 40 | right: 0; 41 | left: 0; 42 | top: 0; 43 | bottom: 0; 44 | margin: auto; 45 | max-width: 100%; 46 | max-height: 100%; 47 | width:600px; 48 | height: 200px; 49 | text-align: center; 50 | line-height: 10px; 51 | color: #333; 52 | } 53 | #screensaver-info span{ 54 | visibility: hidden; 55 | } 56 | 57 | .wf-active #screensaver-info span{ 58 | visibility: inherit; 59 | } 60 | 61 | /* 62 | #container { 63 | width: 1900px; 64 | height: 700px; 65 | margin: auto; 66 | top: 0; 67 | left: 0; 68 | right: 0; 69 | bottom: 0; 70 | position:absolute; 71 | 72 | } 73 | */ 74 | #boardroom { 75 | width: 1900px; 76 | height: 800px; 77 | position:absolute; 78 | } 79 | 80 | 81 | #bottom-border { 82 | position:absolute; 83 | bottom: 0px; 84 | width: 0px; 85 | height: 1px; 86 | margin: 0; 87 | padding: 0; 88 | border-top: 1px solid #333; 89 | } 90 | 91 | .header{ 92 | color: #fff; 93 | text-transform:capitalize; 94 | margin-bottom: 10px; 95 | padding: 3px; 96 | border-top: 3px solid #FFCC00; 97 | border-bottom: 1px solid #FFCC00; 98 | white-space: nowrap; 99 | overflow: hidden; 100 | font-size:10px; 101 | } 102 | 103 | .header:before{ 104 | content: ""; 105 | display: block; 106 | position: absolute; 107 | left: 0px; 108 | top: 25px; 109 | width: 100%; 110 | height: 3px; 111 | background: #FFCC00; 112 | 113 | } 114 | 115 | .header-other{ 116 | border-color: #00EEEE; 117 | } 118 | 119 | .header-other:before{ 120 | content: ""; 121 | display: block; 122 | position: absolute; 123 | left: 0px; 124 | top: 25px; 125 | width: 100%; 126 | height: 3px; 127 | background: #00EEEE; 128 | 129 | } 130 | 131 | .header-other2{ 132 | border-color: #FF9933; 133 | } 134 | 135 | .header-other2:before{ 136 | content: ""; 137 | display: block; 138 | position: absolute; 139 | left: 0px; 140 | top: 25px; 141 | width: 100%; 142 | height: 3px; 143 | background: #FF9933; 144 | 145 | } 146 | 147 | #globalization{ 148 | position: absolute; 149 | top: -10px; 150 | left: -10px; 151 | width: 0px; 152 | overflow: hidden; 153 | background: hsla(0, 0%, 0%, 0.45); 154 | height: 100%; 155 | z-index: 1; 156 | 157 | } 158 | 159 | #satbar { 160 | margin-bottom: 20px; 161 | } 162 | 163 | .location-slider { 164 | font-size: 12pt; 165 | color: #000; 166 | border-bottom: 2px solid #333; 167 | margin-bottom: 15px; 168 | width: 0px; 169 | height: 34px; 170 | overflow: hidden; 171 | white-space: nowrap; 172 | } 173 | 174 | .location-name { 175 | margin: 0; 176 | padding: 0; 177 | } 178 | 179 | .location-area { 180 | background-color: #ffcc00; 181 | padding: 0 2px; 182 | } 183 | 184 | .location-area.other { 185 | background-color: #00eeee; 186 | } 187 | 188 | .location-city { 189 | color: #fff; 190 | padding: 0 2px; 191 | } 192 | 193 | .location-line{ 194 | margin-top: 10px; 195 | border-bottom: 1px solid #00eeee; 196 | 197 | } 198 | .location-slider ul { 199 | margin: 0; 200 | padding-left: 15px; 201 | position: relative; 202 | top: -12px; 203 | height: 10px; 204 | list-style-type:disc; 205 | } 206 | 207 | .location-slider li { 208 | 209 | color: #00eeee; 210 | font-size: 16px; 211 | margin-bottom: -6px; 212 | width: 5px; 213 | float: left; 214 | height:30px; 215 | /*display: inline-block;*/ 216 | 217 | } 218 | 219 | .location-gap { 220 | margin-top: 60px; 221 | 222 | } 223 | 224 | #logo { 225 | position: absolute; 226 | bottom: 10px; 227 | width: 180px; 228 | height: 100px; 229 | } 230 | 231 | #logo-cover-up { 232 | position: absolute; 233 | top: 32px; 234 | height: 58px; 235 | left: 10px; 236 | width: 160px; 237 | background-color: #000; 238 | } 239 | 240 | #logo-cover-side-1 { 241 | position: absolute; 242 | top: 90px; 243 | height: 20px; 244 | left: 10px; 245 | width: 160px; 246 | background-color: #000; 247 | } 248 | 249 | #logo-cover-side-2 { 250 | position: absolute; 251 | top: 25px; 252 | height: 8px; 253 | left: 10px; 254 | width: 160px; 255 | background-color: #000; 256 | } 257 | 258 | #globe{ 259 | position:absolute; 260 | width:600px; 261 | height:650px; 262 | left: 100px; 263 | top: -50px; 264 | z-index: 0; 265 | } 266 | 267 | #globe-footer{ 268 | position:absolute; 269 | height:55px; 270 | bottom: 0; 271 | left: 350px; 272 | overflow: hidden; 273 | } 274 | 275 | .footer-bar{ 276 | width: 1px; 277 | height: 200px; 278 | border-left: 1px solid #333; 279 | float:left; 280 | margin-right:15px; 281 | margin-top:100px; 282 | } 283 | 284 | #globe-footer a{ 285 | padding-top:5px; 286 | float:left; 287 | margin-right: 30px; 288 | } 289 | 290 | #globe-footer img{ 291 | opacity: 0; 292 | } 293 | 294 | #twitter { 295 | width: 30px; 296 | } 297 | 298 | #info-image { 299 | width: 25px; 300 | } 301 | 302 | #fullscreen-image { 303 | width: 25px; 304 | } 305 | 306 | #keyboard-image { 307 | width: 40px; 308 | } 309 | 310 | #github-image { 311 | width: 25px; 312 | } 313 | 314 | #about { 315 | 316 | display: inline-block; 317 | font-size: 18pt; 318 | } 319 | #logout { 320 | 321 | display: inline-block; 322 | font-size: 18pt; 323 | } 324 | 325 | #infect { 326 | 327 | display: inline-block; 328 | font-size: 18pt; 329 | } 330 | 331 | 332 | #user-interaction{ 333 | position: absolute; 334 | top: 0px; 335 | left: 820px; 336 | width: 0px; 337 | height: 595px; 338 | overflow: hidden; 339 | background: hsla(0, 0%, 0%, 0.45); 340 | } 341 | #user-interaction-container{ 342 | width: 600px; 343 | height: 100%; 344 | } 345 | #user-interaction h3{ 346 | padding: 4px; 347 | font-size: 3pt; 348 | margin: 0px; 349 | } 350 | 351 | #interaction { 352 | padding: 2px 8px; 353 | margin-top:6px; 354 | border-right: 1px solid #333; 355 | height: 545px; 356 | font-size: 16px; 357 | overflow: hidden; 358 | } 359 | 360 | .stream-table{ 361 | width: 100%; 362 | } 363 | 364 | .attack-map-message{ 365 | background-color: rgba(0,0,0,0.75); 366 | position: absolute; 367 | z-index: 10000; 368 | margin: 3px 0; 369 | font-size: 14px; 370 | } 371 | 372 | .attacker.interaction-data{ 373 | cursor: pointer; 374 | font-size: 14px; 375 | } 376 | .attacker.interaction-data:hover{ 377 | background-color: rgba(191, 146, 255, 0.5); 378 | } 379 | .interaction-data { 380 | padding: 1px 5px; 381 | white-space: nowrap; 382 | color: #00eeee; 383 | padding: 0px; 384 | margin: 5px; 385 | } 386 | 387 | .interaction-data li { 388 | display: inline-block; 389 | padding: 0px; 390 | padding-right: 10px; 391 | font-size: 15px; 392 | line-height: 1em; 393 | } 394 | 395 | .interaction-username { 396 | color: #fff; 397 | } 398 | 399 | .interaction-title { 400 | color: #00eeee; 401 | } 402 | 403 | .interaction-type { 404 | color: #ffcc00; 405 | } 406 | 407 | .interaction-size { 408 | color: #fff; 409 | } 410 | 411 | .interaction-popularity { 412 | color: #00eeee; 413 | } 414 | 415 | .interaction-popular { 416 | color: #00eeee; 417 | margin-left: -15px; 418 | padding: 0; 419 | margin-right: 0; 420 | } 421 | 422 | 423 | #interaction-overlay { 424 | position:absolute; 425 | width: 100%; 426 | height: 200px; 427 | bottom: 0px; 428 | background: -webkit-linear-gradient(transparent, #000); /* For Safari */ 429 | background: -o-linear-gradient(transparent, #000); /* For Opera 11.1 to 12.0 */ 430 | background: -moz-linear-gradient(transparent, #000); /* For Firefox 3.6 to 15 */ 431 | background: linear-gradient(transparent, #000); /* Standard syntax */ 432 | } 433 | #cube { 434 | position: absolute; 435 | left: 302px; 436 | width: 290px; 437 | height: 225px; 438 | border-bottom: 1px solid #333; 439 | padding:4px; 440 | } 441 | #cube-labels { 442 | position: absolute; 443 | bottom: 5px; 444 | left: 5px; 445 | font-size: 4pt; 446 | padding: 0; 447 | margin: 0; 448 | } 449 | 450 | #cube-labels div { 451 | margin: 3px 0 0 0; 452 | padding:0 0 0 3px; 453 | } 454 | 455 | #cube-label-1{ 456 | border-left: 42px solid #00eeee; 457 | } 458 | #cube-label-2{ 459 | border-left: 10px solid #ffcc00; 460 | } 461 | #cube-label-3{ 462 | border-left: 25px solid #aaa; 463 | } 464 | 465 | #swirls { 466 | position: absolute; 467 | bottom: 0; 468 | height: 225px; 469 | width: 225px; 470 | left: 305px; 471 | } 472 | 473 | #growth{ 474 | position: absolute; 475 | bottom: 0; 476 | left: 820px; 477 | width: 0px; 478 | height: 195px; 479 | overflow: hidden; 480 | background: hsla(0, 0%, 0%, 0.45); 481 | transition: height 1s; 482 | } 483 | .unauth #growth{ 484 | height: 0px; 485 | } 486 | 487 | #growth-container{ 488 | width: 600px; 489 | height: 100%; 490 | } 491 | 492 | #ticker { 493 | float: left; 494 | width: 90px; 495 | height: 105px; 496 | margin-top: 10px; 497 | margin-left: 10px; 498 | color: #fff; 499 | } 500 | 501 | #ticker-text{ 502 | margin: 0px; 503 | padding: 0px; 504 | font-weight:bold; 505 | font-size: 18pt; 506 | line-height: 17pt; 507 | margin-top: 8px; 508 | } 509 | #ticker-subtext{ 510 | margin: 0px; 511 | vertical-align: top; 512 | padding: 0px; 513 | font-size: 10pt; 514 | display: inline-block; 515 | width: 34px; 516 | } 517 | 518 | #ticker-lines{ 519 | display: inline-block; 520 | vertical-align: top; 521 | width: 34px; 522 | margin: 0px; 523 | padding: 0px; 524 | overflow: hidden; 525 | margin-top: 2px; 526 | margin-left: -5px; 527 | } 528 | .ticker-line{ 529 | margin: 0; 530 | padding: 0; 531 | font-size: 3px; 532 | border-left: 20px solid #00eeee; 533 | background-color: #666; 534 | } 535 | 536 | #ticker-value{ 537 | font-size: 18pt; 538 | font-weight: bold; 539 | margin-top: 10px; 540 | } 541 | #ticker-sensor{ 542 | font-size: 8pt; 543 | border-bottom: 1px solid #333; 544 | padding-bottom: 10px; 545 | margin-right: 18px; 546 | margin-bottom: 5px; 547 | } 548 | 549 | #ticker-line-1{ 550 | border-left: 8px solid #00eeee; 551 | margin-bottom: 2px; 552 | 553 | } 554 | 555 | #stock-chart 556 | { 557 | position: absolute; 558 | top: 50px; 559 | left: 100px; 560 | width: 496px; 561 | height:105px; 562 | overflow: hidden; 563 | } 564 | 565 | #stock-chart.unauth { 566 | border: 1px solid #00eeee; 567 | } 568 | #stock-chart canvas { 569 | 570 | } 571 | 572 | #stock-chart div { 573 | position: absolute; 574 | top: 0px; 575 | left: -2px; 576 | width: 0px; 577 | overflow: hidden; 578 | height: 105px; 579 | border-right: 1px solid #ffcc00; 580 | } 581 | 582 | #stock-chart div canvas{ 583 | margin-left: 2px; 584 | 585 | } 586 | 587 | #stock-subcharts 588 | { 589 | position: absolute; 590 | top: 161px; 591 | left: 110px; 592 | border: 0px; 593 | color: #fff; 594 | width: 500px; 595 | height: 28px; 596 | 597 | 598 | } 599 | 600 | .stock-subchart{ 601 | display: block; 602 | float: left; 603 | width: 100px; 604 | height: 25px; 605 | overflow: hidden; 606 | } 607 | 608 | .stock-subchart-label{ 609 | display: inline-block; 610 | font-size: 5pt; 611 | 612 | } 613 | 614 | .stock-subchart-chart{ 615 | display: inline-block; 616 | width: 60px; 617 | height: 25px; 618 | opacity: .3; 619 | 620 | } 621 | 622 | .stock-subchart-chart:hover{ 623 | opacity: 1; 624 | 625 | } 626 | 627 | .stock-subchart-bar{ 628 | 629 | float: left; 630 | background-color: #000; 631 | width: 3px; 632 | margin-left: 1px; 633 | height: 20px; 634 | border-bottom: 10px solid #00eeee; 635 | } 636 | 637 | .stock-subchart-bar.subchart-5{ 638 | height: 20px; 639 | border-bottom: 5px solid #00eeee; 640 | 641 | 642 | } 643 | .stock-subchart-bar.subchart-10{ 644 | height: 15px; 645 | border-bottom: 10px solid #00eeee; 646 | } 647 | .stock-subchart-bar.subchart-15{ 648 | height: 10px; 649 | border-bottom: 15px solid #00eeee; 650 | } 651 | .stock-subchart-bar.subchart-20{ 652 | height: 5px; 653 | border-bottom: 20px solid #00eeee; 654 | } 655 | 656 | .stock-subchart-bar.subchart-yellow{ 657 | border-color: #ffcc00; 658 | } 659 | .stock-subchart-bar.subchart-white{ 660 | border-color: #aaa; 661 | } 662 | 663 | #media{ 664 | position: absolute; 665 | top: 0px; 666 | left: 1440px; 667 | width: 0px; 668 | height: 595px; 669 | overflow: hidden; 670 | } 671 | #media-container{ 672 | width: 450px; 673 | height: 100%; 674 | } 675 | 676 | #attacker-data{ 677 | position: absolute; 678 | z-index: 10000; 679 | background-color: rgba(0,0,0,0.75); 680 | } 681 | 682 | .media-box{ 683 | float: left; 684 | width: 350px; 685 | height: 225px; 686 | padding: 3px; 687 | margin: 5px; 688 | border: 1px solid #00eeee; 689 | overflow: auto; 690 | } 691 | 692 | .user-pic{ 693 | position: relative; 694 | margin: 3px; 695 | height: 89px; 696 | width: 89px; 697 | float: left; 698 | cursor: pointer; 699 | 700 | } 701 | #media-bottom .user-pic{ 702 | float: right; 703 | } 704 | 705 | 706 | .user-pic.larger{ 707 | height: 184px; 708 | width: 184px; 709 | } 710 | .user-pic span{ 711 | display: box; 712 | position: absolute; 713 | bottom: 0px; 714 | background: hsla(0, 0%, 100%, 0.45); 715 | color: #000; 716 | width: 100%; 717 | font-size: 10px; 718 | text-align: center; 719 | } 720 | 721 | .user-pic.larger span{ 722 | font-size: 13px; 723 | text-align: center; 724 | } 725 | 726 | 727 | .media-blinkies{ 728 | float: left; 729 | height: 225px; 730 | width: 50px; 731 | color: #fff; 732 | font-size: 4px; 733 | overflow:hidden; 734 | } 735 | 736 | .media-blinkies h3{ 737 | margin-top: 5px; 738 | padding: 0px; 739 | font-size: 4px; 740 | } 741 | 742 | .media-blinkies .bar{ 743 | border-left: 20px solid #fff; 744 | margin-top: 2px; 745 | padding-left: 3px; 746 | 747 | } 748 | 749 | .blinkies-big-number{ 750 | display: inline-block; 751 | width: 35px; 752 | font-size: 50px; 753 | text-align: center; 754 | line-height: 40px; 755 | } 756 | .blinkies-big-label{ 757 | display: inline-block; 758 | width: 35px; 759 | font-size: 6px; 760 | text-align: center; 761 | } 762 | .blinkies-small-number{ 763 | display: inline-block; 764 | width: 10px; 765 | font-size: 20px; 766 | text-align: center; 767 | line-height: 20px; 768 | } 769 | .blinkies-small-label{ 770 | display: inline-block; 771 | width: 10px; 772 | font-size: 6px; 773 | text-align: center; 774 | } 775 | 776 | .blinky{ 777 | display: inline-block; 778 | width: 2px; 779 | height: 3px; 780 | background-color: #fff; 781 | margin: 3px; 782 | } 783 | 784 | .blinky.blue{ 785 | background-color: #00eeee; 786 | } 787 | .blinky.blank{ 788 | background-color: #000; 789 | } 790 | .blinky.yellow{ 791 | background-color: #ffcc00; 792 | 793 | } 794 | .bar.border-10{ 795 | border-left: 20px solid #fff; 796 | } 797 | .bar.border-20{ 798 | border-left: 20px solid #fff; 799 | } 800 | .bar.border-25{ 801 | border-left: 25px solid #fff; 802 | } 803 | .bar.border-30{ 804 | border-left: 30px solid #fff; 805 | } 806 | .bar.border-35{ 807 | border-left: 35px solid #fff; 808 | } 809 | .bar.border-40{ 810 | border-left: 40px solid #fff; 811 | } 812 | .bar.border-blue{ 813 | border-color: #00eeee; 814 | } 815 | .bar.border-yellow{ 816 | border-color: #ffcc00; 817 | } 818 | .bar.border-white{ 819 | border-color: #fff; 820 | } 821 | .bar.last{ 822 | margin-bottom: 10px; 823 | 824 | } 825 | 826 | .media-info{ 827 | padding-top: 3px; 828 | margin:0 5px; 829 | font-size: 6px; 830 | color: #fff; 831 | float: left; 832 | width: 500px; 833 | border-bottom: 1px solid #aaa; 834 | margin-bottom: 10px; 835 | opacity: .4; 836 | } 837 | 838 | .media-info span{ 839 | 840 | padding-right: 30px; 841 | 842 | } 843 | 844 | #timer{ 845 | position: absolute; 846 | bottom: 0; 847 | left: 1440px; 848 | width: 0px; 849 | height: 195px; 850 | overflow: hidden; 851 | } 852 | 853 | #clock { 854 | float: left; 855 | font-size: 66px; 856 | color: #AAA; 857 | overflow: hidden; 858 | margin-top:8px; 859 | } 860 | 861 | /* 862 | #globe-footer-reveal{ 863 | position:absolute; 864 | width:600px; 865 | height:35px; 866 | top: 665px; 867 | left: 190px; 868 | } 869 | */ 870 | 871 | 872 | #fps { 873 | position: absolute; 874 | left: 0; 875 | bottom: 0px; 876 | padding:0 0 3px 3px; 877 | text-align:left; 878 | background-color:#000; 879 | /*width: 180px;*/ 880 | width: 0px; 881 | height: 0px; 882 | overflow:hidden; 883 | 884 | border-left: 1px solid #aaa; 885 | } 886 | 887 | #fpsDescription { 888 | 889 | position: absolute; 890 | top: 0px; 891 | left: 10px; 892 | width:100px; 893 | 894 | color:#fff; 895 | font-family:Helvetica,Arial,sans-serif; 896 | font-size:7px; 897 | font-weight:bold; 898 | line-height:15px; 899 | 900 | } 901 | #fpsText { 902 | position: absolute; 903 | top: 12px; 904 | left: 10px; 905 | width:100px; 906 | 907 | color:#FFCC00; 908 | font-family:Helvetica,Arial,sans-serif; 909 | font-size:7px; 910 | font-weight:bold; 911 | line-height:15px; 912 | 913 | } 914 | #fpsGraph { 915 | position: absolute; 916 | bottom: 4px; 917 | left: 90px; 918 | 919 | width:74px; 920 | height:26px; 921 | background-color:#aaa; 922 | border-bottom: 1px solid #666; 923 | 924 | } 925 | #fpsGraph span { 926 | 927 | width:1px; 928 | height:26px; 929 | float:right; 930 | background-color:#000; 931 | } 932 | 933 | #ms { 934 | position: absolute; 935 | left: 200px; 936 | bottom: 0px; 937 | 938 | padding:0 0 3px 3px; 939 | text-align:left; 940 | background-color:#000; 941 | /*width: 200px;*/ 942 | /*height: 31px;*/ 943 | width: 0px; 944 | height: 0px; 945 | overflow:hidden; 946 | 947 | border-left: 1px solid #aaa; 948 | } 949 | #msDescription { 950 | position: absolute; 951 | top: 0px; 952 | left: 10px; 953 | width:100px; 954 | 955 | color:#fff; 956 | font-family:Helvetica,Arial,sans-serif; 957 | font-size:7px; 958 | font-weight:bold; 959 | line-height:15px; 960 | } 961 | 962 | #msText { 963 | position: absolute; 964 | top: 12px; 965 | left: 10px; 966 | width:100px; 967 | 968 | color:#00EEEE; 969 | font-family:Helvetica,Arial,sans-serif; 970 | font-size:7px; 971 | font-weight:bold; 972 | line-height:15px; 973 | } 974 | 975 | #msGraph { 976 | position: absolute; 977 | bottom: 4px; 978 | left: 80px; 979 | 980 | width:74px; 981 | height:26px; 982 | background-color:#aaa; 983 | order: 1px solid #666; 984 | border-bottom: 1px solid #666; 985 | 986 | } 987 | 988 | #msGraph span { 989 | 990 | width:1px; 991 | height:26px; 992 | float:right; 993 | background-color:#000; 994 | } 995 | 996 | #clockbar { 997 | overflow: hidden; 998 | height: 80px; 999 | } 1000 | #simpleclock { 1001 | float: right; 1002 | margin-top: 5px; 1003 | margin-left: 5px; 1004 | } 1005 | 1006 | #timerbar { 1007 | clear: both; 1008 | margin:10px 0; 1009 | overflow: hidden; 1010 | height: 28px; 1011 | width: 500px; 1012 | } 1013 | 1014 | .section-timerbar{ 1015 | width: 65px; 1016 | border: 1px solid #00EEEE; 1017 | float:left; 1018 | color: #FFFFFF; 1019 | font-size: 8px; 1020 | padding:4px; 1021 | margin-bottom: 10px; 1022 | text-align: center; 1023 | } 1024 | 1025 | .buffer-timerbar{ 1026 | margin-left: -5px; 1027 | background-color: #000; 1028 | padding-left:5px; 1029 | width: 110%; 1030 | height: 17px; 1031 | overflow: hidden; 1032 | } 1033 | 1034 | .buffer-timerbar > small { 1035 | font-size: 8px; 1036 | display: block; 1037 | color: #aaa; 1038 | } 1039 | 1040 | .boardroom-readme { 1041 | 1042 | border: 2px solid #6fc0ba; 1043 | border-radius: 2px; 1044 | /* box-shadow: 0 0 6px #005b8e, inset 0 0 6px #005b8e; */ 1045 | padding: 3px; 1046 | visibility: hidden; 1047 | background-color: #000; 1048 | position: absolute; 1049 | width: 500px; 1050 | top: 50px; 1051 | left: 600px; 1052 | z-index:250; 1053 | } 1054 | 1055 | .boardroom-readme .content{ 1056 | padding: 0; 1057 | margin: 0; 1058 | } 1059 | 1060 | .boardroom-readme h2 { 1061 | color: #fff; 1062 | margin: 0; 1063 | border-bottom: 1px solid #1b2f2d; 1064 | padding: 2px 4px; 1065 | font-weight: bold; 1066 | } 1067 | 1068 | .boardroom-readme h2 em{ 1069 | font-style: normal; 1070 | float: right; 1071 | font-size: .8em; 1072 | padding-top: 1px; 1073 | color: #00eeee; 1074 | cursor: pointer; 1075 | 1076 | } 1077 | 1078 | .boardroom-readme p { 1079 | font-size: 10pt; 1080 | margin: 4px 4px 0; 1081 | padding: 4px 6px; 1082 | line-height: 1.8em; 1083 | 1084 | } 1085 | -------------------------------------------------------------------------------- /src/LightTable.js: -------------------------------------------------------------------------------- 1 | var $ = require("jquery"), 2 | THREE = require("three"); 3 | 4 | var webglTest, 5 | active = false, 6 | initialized = false, 7 | currentWidth = 0, 8 | currentHeight = 0, 9 | hideFn = function(){} 10 | LightTable = {}, 11 | lastMessageTime = null, 12 | numUsers = 1, 13 | dataStreamOn = false; 14 | 15 | window.firstTimeViewingLT = getUrlParameter('redirect') === "" ? true : false; 16 | 17 | function getUrlParameter(name) { 18 | name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); 19 | var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'); 20 | var results = regex.exec(location.search); 21 | return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' ')); 22 | }; 23 | 24 | /* public function */ 25 | 26 | LightTable.init = function(_hideFn){ 27 | 28 | hideFn = _hideFn; 29 | 30 | $(".lt-header").css("visibility", "hidden"); 31 | $(".content-container").css("visibility", "hidden"); 32 | 33 | 34 | $("#lt-keyboard").css("opacity", 0); 35 | 36 | 37 | webglTest = createWebGlTest(); 38 | 39 | $("#light-table").css("visibility", "visible"); 40 | 41 | currentWidth = $(window).width(); 42 | currentHeight = $(window).height(); 43 | 44 | 45 | /* set events */ 46 | 47 | $("#lt-launch-github").click(function(){ 48 | $(this).find(".folder-big").css("background-color", "#fff"); 49 | simulateCommand("|cd github$"); 50 | simulateCommand("ls$"); 51 | simulateCommand("run github.exe$"); 52 | $(document).off(); 53 | $(".folder-container").off(); 54 | }); 55 | 56 | $("#lt-launch-mhn").click(function(){ 57 | $(this).find(".folder-big").css("background-color", "#fff"); 58 | simulateCommand("|cd seckcmhn$"); 59 | simulateCommand("ls$"); 60 | simulateCommand("run seckcmhn.exe$"); 61 | $(document).off(); 62 | $(".folder-container").off(); 63 | }); 64 | 65 | $("#lt-launch-wikipedia").click(function(){ 66 | $(this).find(".folder-small").css("background-color", "#fff"); 67 | simulateCommand("|cd wikipedia$"); 68 | simulateCommand("ls$"); 69 | simulateCommand("run wikipedia.exe$"); 70 | $(document).off(); 71 | $(".folder-container").off(); 72 | }); 73 | 74 | $("#lt-launch-test").click(function(){ 75 | $(this).find(".folder-small").css("background-color", "#fff"); 76 | simulateCommand("|cd test$"); 77 | simulateCommand("ls$"); 78 | simulateCommand("run test.exe$"); 79 | $(document).off(); 80 | $(".folder-container").off(); 81 | 82 | }); 83 | 84 | $("#lt-launch-bitcoin").click(function(){ 85 | $(this).find(".folder-big").css("background-color", "#fff"); 86 | simulateCommand("cd bitcoin$"); 87 | }); 88 | 89 | $("#lt-launch-unknown").click(function(){ 90 | $(this).find(".folder-big").css("background-color", "#fff"); 91 | simulateCommand("cd unknown$"); 92 | }); 93 | 94 | $("#lt-keyboard div").mousedown(function(event){ 95 | event.preventDefault(); 96 | keyClick(parseInt($(this).attr("id").split("-")[1])); 97 | }); 98 | 99 | initialized = true; 100 | 101 | if(window.firstTimeViewingLT){ 102 | window.firstTimeViewingLT = false; 103 | setTimeout(function(){ 104 | $("#lt-launch-mhn").find(".folder-big").css("background-color", "#fff"); 105 | simulateCommand("|cd seckcmhn$"); 106 | simulateCommand("ls$"); 107 | simulateCommand("run seckcmhn.exe$"); 108 | $(document).off(); 109 | $(".folder-container").off(); 110 | },1500); 111 | } 112 | 113 | }; 114 | 115 | LightTable.show = function(cb){ 116 | 117 | $("#light-table").css("opacity", 1); 118 | // do the intro animations 119 | showContainer(); 120 | setTimeout(showHeaders, 500); 121 | showContentBoxes($("#lt-readme"), 0); 122 | 123 | showContentBoxes($("#lt-bandwidth"), 100); 124 | showContentBoxes($("#lt-globalization"), 200); 125 | showKeyboard(); 126 | 127 | if($("#lt-mobile-readme").width() > 0){ 128 | showContentBoxes($("#lt-mobile-readme"), 0); 129 | } 130 | 131 | $(document).keydown(function(event){ 132 | 133 | if(!event.ctrlKey && (event.which < 112 || event.which > 134) && event.which != 91) { // let them do f1-f12, windows key 134 | var keycode = event.which; 135 | event.preventDefault(); 136 | keyClick(keycode); 137 | } 138 | }); 139 | 140 | if(typeof cb == "function"){ 141 | setTimeout(cb, 500); 142 | } 143 | 144 | active = true; 145 | }; 146 | 147 | LightTable.hide = function(cb) { 148 | // reset everything 149 | 150 | active = false; 151 | $("#lt-mobile-readme").attr("style",""); 152 | $("#k-32").attr("style",""); 153 | $(".lt-header-animator-right").attr("style",""); 154 | $(".lt-header-animator-left").attr("style",""); 155 | 156 | $("#light-table").animate({ 157 | opacity: 0 158 | }, 500); 159 | 160 | setTimeout(function(){ 161 | hideKeyboard(); 162 | hideContainer(); 163 | hideWebgl(); 164 | }, 500); 165 | 166 | webglTest.reset(); 167 | 168 | $(document).off(); 169 | 170 | if(typeof cb == "function"){ 171 | cb(); 172 | } 173 | }; 174 | 175 | LightTable.animate = function(){ 176 | if(active && initialized){ 177 | webglTest.tick(); 178 | } 179 | }; 180 | 181 | var resizing = false; 182 | LightTable.resize = function(){ 183 | $("#light-table").center(); 184 | if(!resizing && (currentWidth > 1600 && $(window).width() <= 1600) || (currentWidth <= 1600 && $(window).width() > 1600)){ 185 | 186 | currentWidth = $(window).width(); 187 | resizing = true; 188 | LightTable.hide(); 189 | setTimeout(LightTable.show,1000); 190 | 191 | setTimeout(function(){ 192 | resizing = false; 193 | }, 3000); 194 | } 195 | }; 196 | 197 | 198 | LightTable.message = function(message){ 199 | lastMessageTime = Date.now(); 200 | 201 | if(message.stream === "meta" && message.size > 0){ 202 | $("#datalink-status").text("CONNECTED. " + message.size + " USER" + (parseInt(message.size,10) === 1 ? "" : "S ")); 203 | $("#datalink-status").css("color", "green"); 204 | } 205 | 206 | }; 207 | 208 | /* private functions */ 209 | 210 | function showContainer(){ 211 | var outside = $("#lt-container-outside"); 212 | var inside = $("#lt-container-inside"); 213 | 214 | outside.center(); 215 | inside.center(); 216 | 217 | var outsideOffset = outside.offset(); 218 | var insideOffset = inside.offset(); 219 | 220 | var outsideWidth = outside.width(); 221 | var outsideHeight = outside.height(); 222 | 223 | var insideWidth = inside.width(); 224 | var insideHeight = inside.height(); 225 | 226 | var outsideBlockerTopRight = $("
"); 227 | var outsideBlockerBottomLeft = $("
"); 228 | var insideBlockerTopRight = $("
"); 229 | var insideBlockerBottomLeft = $("
"); 230 | 231 | $('body').append(outsideBlockerTopRight) 232 | .append(outsideBlockerBottomLeft) 233 | .append(insideBlockerTopRight) 234 | .append(insideBlockerBottomLeft); 235 | 236 | outsideBlockerTopRight.css({ 237 | "background-color": "#000", 238 | // "background-color": "#aa0000", 239 | // opacity: .5, 240 | position: "absolute", 241 | top: outsideOffset.top - 5, 242 | left: outsideOffset.left - 5, 243 | width: outside.outerWidth() + 10, 244 | height: outside.outerHeight(), 245 | "z-index": 15 246 | }); 247 | 248 | outsideBlockerBottomLeft.css({ 249 | "background-color": "#000", 250 | // "background-color": "#00aa00", 251 | // opacity: .5, 252 | position: "absolute", 253 | top: outsideOffset.top + 5, 254 | left: outsideOffset.left - 5, 255 | width: outsideWidth, 256 | height: outsideHeight + 10, 257 | "z-index": 15 258 | }); 259 | 260 | insideBlockerTopRight.css({ 261 | "background-color": "#000", 262 | // "background-color": "#0000aa", 263 | // opacity: .5, 264 | position: "absolute", 265 | top: insideOffset.top-3, 266 | left: insideOffset.left-5, 267 | width: insideWidth + 15, 268 | height: insideHeight, 269 | "z-index": 25 270 | }); 271 | 272 | insideBlockerBottomLeft.css({ 273 | "background-color": "#000", 274 | // "background-color": "#aa00aa", 275 | // opacity: .5, 276 | position: "absolute", 277 | top: insideOffset.top +5, 278 | left: insideOffset.left -3, 279 | width: insideWidth, 280 | height: insideHeight, 281 | "z-index": 25 282 | }); 283 | 284 | outsideBlockerTopRight.animate({ 285 | height: 10, 286 | }, 500).animate({ 287 | width: 0, 288 | 289 | }, 500); 290 | 291 | outsideBlockerBottomLeft.animate({ 292 | width: 20, 293 | }, 500); 294 | 295 | outsideBlockerBottomLeft.delay(500).animate({ 296 | height: 0, 297 | top: (outsideOffset.top + outsideHeight)/2, 298 | }, 500); 299 | 300 | 301 | insideBlockerBottomLeft.animate({ 302 | width: 0, 303 | }, 300); 304 | 305 | insideBlockerTopRight.delay(300).animate({ 306 | height: 10, 307 | }, 500); 308 | 309 | insideBlockerTopRight.animate({ 310 | width: 0, 311 | left: insideOffset.left + insideWidth 312 | }, 500); 313 | 314 | setTimeout(function(){ 315 | outsideBlockerTopRight.remove(); 316 | outsideBlockerBottomLeft.remove(); 317 | insideBlockerTopRight.remove(); 318 | insideBlockerBottomLeft.remove(); 319 | }, 3000); 320 | 321 | } 322 | 323 | function hideContainer(){ 324 | $(".lt-header").css("visibility", "hidden"); 325 | $(".content-container").css("opacity", 0); 326 | } 327 | 328 | function showHeaders(){ 329 | 330 | var aHeight = $("#lt-header-bottom-right").position().top - 35; 331 | 332 | setTimeout(function doHeaderAnimations(){ 333 | 334 | $(".lt-header-animator-outside").css({visibility: "visible"}).animate({ 335 | top: "25px", 336 | height: aHeight + 28 + "px" 337 | }, 500); 338 | 339 | $(".lt-header-animator-inside").css({visibility: "visible"}).delay(100).animate({ 340 | top: "39px", 341 | height: aHeight + "px" 342 | }, 500); 343 | }, 500); 344 | 345 | setTimeout(function showHeaders(){ 346 | $(".lt-header").css("visibility", "visible"); 347 | $(".content-container").css("visibility", "visible"); 348 | 349 | }, 1000); 350 | 351 | setTimeout(function hideAnimations(){ 352 | $(".lt-header-animator-outside").css("display", "none"); 353 | $(".lt-header-animator-inside").css("display", "none"); 354 | }, 1000); 355 | 356 | } 357 | 358 | function showContentBoxes(item, extraDelay) { 359 | 360 | var itemContent = item.find(".content"); 361 | 362 | item.removeAttr("style"); 363 | 364 | var height = item.height(); 365 | var width = item.width(); 366 | var left = item.position().left; 367 | var top = item.position().top; 368 | 369 | var border = item.css("border"); 370 | var boxShadow = item.css("box-shadow"); 371 | 372 | var contentBorder = itemContent.css("border"); 373 | var contentBoxShadow = itemContent.css("box-shadow"); 374 | 375 | itemContent.children().each(function(index, element){ 376 | $(element).css("visibility", "hidden"); 377 | }); 378 | 379 | item.height(0) 380 | .width(0) 381 | .css("top", top + height/2) 382 | .css("left", left + width/2); 383 | 384 | setTimeout(function doHeaderAnimations(){ 385 | 386 | item.animate({ 387 | height: height, 388 | width: "100%", 389 | left: left, 390 | top: top 391 | 392 | }, 500); 393 | item.css({ 394 | opacity: 1 395 | }); 396 | }, 1500 + extraDelay); 397 | 398 | setTimeout(function(){ 399 | 400 | itemContent.children().each(function(index, element){ 401 | $(element).css("visibility", "visible"); 402 | }); 403 | 404 | 405 | }, 2200); 406 | 407 | } 408 | 409 | function hideContentBoxes(){ 410 | var itemContent = item.find(".content"); 411 | itemContent.children().each(function(index, element){ 412 | $(element).css("visibility", "hidden"); 413 | }); 414 | } 415 | 416 | function showKeyboard(){ 417 | 418 | var keyboard = $("#lt-keyboard"); 419 | var spaceBar = $("#k-32"); 420 | var spaceBarWidth = spaceBar.width(); 421 | 422 | spaceBar.width(0); 423 | 424 | 425 | keyboard.delay(2000).animate({ 426 | opacity: 1 427 | }, 2000); 428 | 429 | spaceBar.delay(2200).animate({ 430 | width: spaceBarWidth 431 | },500); 432 | 433 | } 434 | 435 | function hideKeyboard(){ 436 | var keyboard = $("#lt-keyboard"); 437 | keyboard.css("opacity", 0); 438 | } 439 | 440 | function createWebGlTest(){ 441 | var canvas = document.getElementById('lt-webglCanvas'); 442 | var renderer = new THREE.WebGLRenderer( { antialias : true, canvas: canvas } ); 443 | var cameraDistance = 100; 444 | var camera = new THREE.PerspectiveCamera( 50, canvas.width / canvas.height, 1, 400 ); 445 | var cameraAngle=0; 446 | var scene = new THREE.Scene(); 447 | var splineGeometry = new THREE.Geometry(); 448 | var splineMaterial = new THREE.LineBasicMaterial({ 449 | color: 0x6FC0BA, 450 | opacity: 0, 451 | transparent: true 452 | }); 453 | 454 | var backdropGeometry = new THREE.Geometry(); 455 | var backdropMaterial = new THREE.LineBasicMaterial({ 456 | color: 0x1b2f2d, 457 | opacity: 1, 458 | transparent: true 459 | }); 460 | 461 | var cameraUp = false; 462 | 463 | renderer.setSize(canvas.width, canvas.height); 464 | camera.position.z = cameraDistance; 465 | camera.lookAt(scene.position); 466 | 467 | lastRenderDate = new Date(); 468 | 469 | var calc = function(x){ 470 | return (x+200)*(x+100)*(x+280)*(x+10)*(x-300)*(x-250)*(x-150) / Math.pow(10,14)/1.5; 471 | } 472 | 473 | for(var i = 0; i< 500; i++){ 474 | var y = calc(i-250) * Math.sin(2 * Math.PI * (i % 6) / 6 + i/500) + Math.cos(i) * 5; 475 | var z = calc(i-250) * Math.cos(2 * Math.PI * (i % 6) / 6 + i/500); 476 | splineGeometry.vertices.push(new THREE.Vector3(i - 250, y, z)); 477 | } 478 | splineGeometry.verticesNeedUpdate = true; 479 | 480 | var splineLine = new THREE.Line(splineGeometry, splineMaterial); 481 | scene.add(splineLine); 482 | 483 | for(var i = 0; i< 25; i++){ 484 | backdropGeometry.vertices.push(new THREE.Vector3(-500,100-i*8,-100)); 485 | backdropGeometry.vertices.push(new THREE.Vector3(500,100-i*8,-100)); 486 | } 487 | var backdropLine = new THREE.Line(backdropGeometry, backdropMaterial, THREE.LinePieces); 488 | scene.add(backdropLine); 489 | 490 | renderer.render( scene, camera ); 491 | 492 | var firstRun = null; 493 | var introAnimationDone = false; 494 | 495 | return { 496 | tick: function (){ 497 | if(firstRun === null){ 498 | firstRun = Date.now() + 2500; 499 | } 500 | // renderer.render( this.scene, this.camera ); 501 | var renderTime = new Date() - lastRenderDate; 502 | var timeSinceStart = Date.now() - firstRun; 503 | lastRenderDate = new Date(); 504 | 505 | var rotateCameraBy = (2 * Math.PI)/(10000/renderTime); 506 | cameraAngle += rotateCameraBy; 507 | 508 | if(timeSinceStart < 3000){ 509 | backdropMaterial.opacity = Math.max(0,(timeSinceStart-2000)/3000); 510 | splineMaterial.opacity = timeSinceStart/3000; 511 | } else if(!introAnimationDone){ 512 | introAnimationDone = true; 513 | backdropMaterial.opacity = .333; 514 | splineMaterial.opacity = 1; 515 | } 516 | 517 | if(lastMessageTime !== null && !dataStreamOn){ 518 | dataStreamOn = true; 519 | $("#datalink-status").text("CONNECTED"); 520 | $("#datalink-status").css("color", "green"); 521 | } 522 | 523 | if(Math.random() < .1){ 524 | if((lastMessageTime === null && timeSinceStart > 8000) || (lastMessageTime !== null && Date.now() - lastMessageTime > 8000)){ 525 | $("#datalink-status").text("ERROR"); 526 | $("#datalink-status").css("color", "red"); 527 | } 528 | } 529 | 530 | 531 | camera.position.x = Math.sin(cameraAngle) * 20; 532 | renderer.render(scene, camera ); 533 | 534 | splineLine.rotation.x += .01; 535 | 536 | }, 537 | reset: function(){ 538 | firstRun = null; 539 | } 540 | }; 541 | 542 | } 543 | 544 | function hideWebgl(){ 545 | $('#lt-bandwidth').css("opacity", 0); 546 | } 547 | 548 | function writeResponse(txt){ 549 | $("#lt-command-lines").append("
>>encom-sh: " + txt + "
"); 550 | } 551 | 552 | var currentDir = "encom_root"; 553 | 554 | function writePrompt(){ 555 | $(".command-blinker").removeClass("blink").removeClass("command-blinker"); 556 | 557 | $("#lt-command-lines").append('
encom-sh:' + currentDir + '$  
'); 558 | } 559 | 560 | function writeLs(exec){ 561 | var output = ""; 562 | if(typeof exec != "undefined"){ 563 | output = [ 564 | '
encom_root
', 565 | '
bandwidth
', 566 | '
framework
', 567 | '
@arscan
', 568 | '
' + exec + '
', 569 | '
webgl_test
', 570 | '
flynn_5
', 571 | '
 
', 572 | '
os12_demo
', 573 | '
munkowitz
', 574 | ].join(''); 575 | 576 | } else { 577 | output = [ 578 | '
github
', 579 | '
test
', 580 | '
wikipedia
', 581 | '
bitcoin
', 582 | '
unknown
' 583 | ].join(''); 584 | } 585 | 586 | $("#lt-command-lines").append(output); 587 | 588 | } 589 | 590 | 591 | /* I could make this much more involved, but i'm not really interested in spending time on this part of the app */ 592 | /* sorry for disappointing anybody looking at this to see how much functionality there is */ 593 | 594 | function executeCommand(){ 595 | var command = $(".command-text").last().text(); 596 | 597 | if(command == "run seckcmhn.exe"){ 598 | if(currentDir == "seckcmhn"){ 599 | $(".ls-exec").addClass("ls-highlight") 600 | $(".container-border").animate({opacity: 0}, 250); 601 | 602 | setTimeout(function(){ 603 | hideFn("seckc_mhn"); 604 | }, 250); 605 | } else { 606 | writeResponse("Error: No such file"); 607 | writePrompt(); 608 | } 609 | 610 | }else if(command == "run github.exe"){ 611 | if(currentDir == "github"){ 612 | $(".ls-exec").addClass("ls-highlight") 613 | $(".container-border").animate({opacity: 0}, 500); 614 | 615 | setTimeout(function(){ 616 | hideFn("github"); 617 | }, 500); 618 | } else { 619 | writeResponse("Error: No such file"); 620 | writePrompt(); 621 | } 622 | 623 | } else if(command == "run wikipedia.exe"){ 624 | if(currentDir == "wikipedia"){ 625 | $(".ls-exec").addClass("ls-highlight") 626 | $(".container-border").animate({opacity: 0}, 500); 627 | 628 | setTimeout(function(){ 629 | hideFn("wikipedia"); 630 | }, 500); 631 | 632 | } else { 633 | writeResponse("Error: No such file"); 634 | writePrompt(); 635 | } 636 | } else if(command == "run test.exe"){ 637 | if(currentDir == "test"){ 638 | $(".ls-exec").addClass("ls-highlight") 639 | $(".container-border").animate({opacity: 0}, 500); 640 | 641 | setTimeout(function(){ 642 | hideFn("test"); 643 | }, 500); 644 | 645 | } else { 646 | writeResponse("Error: No such file"); 647 | writePrompt(); 648 | } 649 | 650 | } else if(command == "cd seckcmhn"){ 651 | $(".ls-github").addClass("ls-highlight") 652 | currentDir = "seckcmhn"; 653 | $(".folder-label").removeClass("selected"); 654 | $("#lt-launch-github .folder-label").addClass("selected"); 655 | writeResponse("Changed directory to seckcmhn"); 656 | writePrompt(); 657 | 658 | } else if(command == "cd github"){ 659 | $(".ls-github").addClass("ls-highlight") 660 | currentDir = "github"; 661 | $(".folder-label").removeClass("selected"); 662 | $("#lt-launch-github .folder-label").addClass("selected"); 663 | writeResponse("Changed directory to github"); 664 | writePrompt(); 665 | 666 | } else if(command == "cd wikipedia"){ 667 | $(".ls-wikipedia").addClass("ls-highlight") 668 | $(".folder-label").removeClass("selected"); 669 | $("#lt-launch-wikipedia .folder-label").addClass("selected"); 670 | currentDir = "wikipedia"; 671 | writeResponse("Changed directory to wikipedia"); 672 | writePrompt(); 673 | 674 | } else if(command == "cd test"){ 675 | $(".ls-test").addClass("ls-highlight") 676 | $(".folder-label").removeClass("selected"); 677 | $("#lt-launch-test .folder-label").addClass("selected"); 678 | currentDir = "test"; 679 | writeResponse("Changed directory to test"); 680 | writePrompt(); 681 | } else if(command == "cd bitcoin") { 682 | writeResponse("Not yet implemented"); 683 | writePrompt(); 684 | } else if(command.indexOf("cd encom") == 0 || command == "cd /"){ 685 | currentDir = "encom_root"; 686 | writeResponse("Changed directory to encom_root"); 687 | writePrompt(); 688 | } else if(command.indexOf("cd ") == 0){ 689 | writeResponse("Access denied"); 690 | writePrompt(); 691 | } else if(command.indexOf("ls") == 0 && currentDir == "encom_root"){ 692 | writeLs(); 693 | writePrompt(); 694 | 695 | } else if(command.indexOf("ls") == 0){ 696 | writeLs(currentDir + ".exe"); 697 | writePrompt(); 698 | 699 | } else if(command.indexOf("run") == 0){ 700 | writeResponse("Access denied"); 701 | writePrompt(); 702 | } else { 703 | writeResponse("command not found"); 704 | writePrompt(); 705 | } 706 | var cl = $("#lt-command-lines"); 707 | $("#lt-command-line").scrollTop(cl.height()) 708 | 709 | } 710 | 711 | var keyBuffer = []; 712 | var keysRunning = false; 713 | 714 | function runKeySimulator(){ 715 | var key = keyBuffer.shift(); 716 | 717 | keyClick(key); 718 | 719 | if(keyBuffer.length > 0){ 720 | setTimeout(runKeySimulator,10 + Math.random() * 150); 721 | } else { 722 | keysRunning = false; 723 | } 724 | 725 | } 726 | 727 | function simulateKey(key){ 728 | keyBuffer.push(key); 729 | if(!keysRunning){ 730 | keysRunning = true; 731 | setTimeout(runKeySimulator,100); 732 | } 733 | } 734 | 735 | function simulateCommand(command){ 736 | var cs = command.split(""); 737 | for(var i = 0; i < cs.length; i++){ 738 | simulateKey(charToKeyCode(cs[i])); 739 | } 740 | 741 | } 742 | 743 | function charToKeyCode(char){ 744 | var cc = char.charCodeAt(0); 745 | if(cc <= 122 && cc >=97){ 746 | return cc - 32; 747 | } else if (char === "."){ 748 | return 190; 749 | } else if (char === " "){ 750 | return 32; 751 | } else if (char === "$"){ 752 | return 13; 753 | } else if (char === "|"){ 754 | return 27; 755 | } 756 | 757 | return 0; 758 | 759 | } 760 | 761 | function toggleKey(element){ 762 | element.css({ 763 | "background-color": "#fff", 764 | "color": "#000" 765 | }); 766 | 767 | setTimeout(function(){ 768 | element.css({ 769 | "background-color": "#888", 770 | "color": "#888" 771 | }); 772 | }, 200); 773 | setTimeout(function(){ 774 | element.css({ 775 | "background-color": "#000", 776 | "color": "#00eeee" 777 | }); 778 | }, 300); 779 | } 780 | 781 | function writeKeyStroke(keycode){ 782 | var txt = $(".command-text").last(); 783 | switch(keycode){ 784 | case 8: 785 | txt.text(txt.text().substring(0,txt.text().length-1)); 786 | break; 787 | case 27: 788 | txt.text(""); 789 | break; 790 | case 13: 791 | executeCommand(); 792 | break; 793 | case 189: 794 | txt.append("_"); 795 | break; 796 | case 187: 797 | txt.append("="); 798 | break; 799 | case 219: 800 | txt.append("{"); 801 | break; 802 | case 221: 803 | txt.append("}"); 804 | break; 805 | case 186: 806 | txt.append(";"); 807 | break; 808 | case 222: 809 | txt.append("'"); 810 | break; 811 | case 188: 812 | txt.append(","); 813 | break; 814 | case 190: 815 | txt.append("."); 816 | break; 817 | case 191: 818 | txt.append("/"); 819 | break; 820 | case 192: 821 | txt.append("~"); 822 | break; 823 | case 500: 824 | txt.append(""); 825 | break; 826 | default: 827 | var key = String.fromCharCode(keycode).toLowerCase(); 828 | txt.append(key) 829 | }; 830 | 831 | } 832 | 833 | function keyClick(keycode){ 834 | 835 | // light up the keyboard 836 | 837 | toggleKey($("#k-" + keycode)); 838 | 839 | if(keycode === 16){ 840 | toggleKey($("#k-0")); 841 | } 842 | 843 | // write it to the screen 844 | writeKeyStroke(keycode); 845 | 846 | } 847 | 848 | module.exports = LightTable; 849 | -------------------------------------------------------------------------------- /src/Box.js: -------------------------------------------------------------------------------- 1 | var THREE = require("three"), 2 | Utils = require("./Utils"), 3 | pushercolor = require("pusher.color"); 4 | 5 | var createSideCanvas = function(){ 6 | 7 | var sideCanvas = Utils.renderToCanvas(200, 100, function(ctx){ 8 | 9 | 10 | var gradient = ctx.createLinearGradient(0, -100, 0, 100); 11 | gradient.addColorStop(0, "#fff"); 12 | gradient.addColorStop(1, "transparent"); 13 | ctx.fillStyle = gradient; 14 | ctx.fillRect(0,0,200, 100); 15 | 16 | }.bind(this)); 17 | 18 | // this.container.appendChild( sideCanvas ); 19 | 20 | return sideCanvas; 21 | 22 | }; 23 | 24 | var Box = function(opts){ 25 | 26 | // create the webgl context, renderer and camera 27 | if(opts.containerId){ 28 | this.container = document.getElementById(opts.containerId); 29 | this.width = this.container.clientWidth - 5; 30 | this.height = this.container.clientHeight - 5; 31 | } else { 32 | this.container = document.createElement( 'div' ); 33 | this.container.width = this.width; 34 | this.container.height = this.height; 35 | document.body.appendChild( this.container ); 36 | } 37 | 38 | this.cameraDistance = 75; 39 | 40 | this.trackers = []; 41 | this.trackerBalls = []; 42 | 43 | // TEMP 44 | // _this.container.appendChild( _this.specialPointCanvas); 45 | 46 | this.renderer = new THREE.WebGLRenderer( { antialias : true } ); 47 | // this.renderer = new THREE.CanvasRenderer( { clearAlpha: 1 } ); 48 | this.renderer.setSize( this.width, this.height); 49 | // this.renderer.autoClear = false; 50 | this.container.appendChild( this.renderer.domElement ); 51 | 52 | 53 | this.camera = new THREE.PerspectiveCamera( 50, this.width / this.height, 1, 500 ); 54 | // this.camera = new THREE.OrthographicCamera( this.width/-2, this.width /2, this.height /2, this.height/-2, 1, 1000 ); 55 | this.camera.position.z = this.cameraDistance; 56 | 57 | this.cameraAngle=(Math.PI * 2) * .5; 58 | 59 | this.boxWidth = 50; 60 | this.boxHeight = 20; 61 | this.boxDepth = 50; 62 | 63 | this.scene = new THREE.Scene(); 64 | 65 | this.scene.fog = new THREE.Fog( 0x000000, this.cameraDistance-200, this.cameraDistance+550 ); 66 | 67 | /* tracker */ 68 | var tracker = {}; 69 | this.trackerGeometry = new THREE.Geometry(); 70 | var trackerMaterial = new THREE.LineBasicMaterial({ 71 | color: 0xFFFFFF, 72 | opacity: .3, 73 | transparent: true 74 | }); 75 | 76 | var trackerBallCanvas = Utils.renderToCanvas(10, 10, function(ctx){ 77 | ctx.beginPath(); 78 | ctx.fillStyle = "#aaa"; 79 | ctx.arc(5,5,3,0, 2* Math.PI, true); 80 | ctx.closePath(); 81 | ctx.fill(); 82 | 83 | }); 84 | this.trackerBallTexture = new THREE.Texture(trackerBallCanvas); 85 | this.trackerBallTexture.needsUpdate = true; 86 | 87 | // this.container.appendChild(this.trackerBallCanvas); 88 | 89 | this.trackerBallMaterial = new THREE.SpriteMaterial({size: 10, 90 | map: this.trackerBallTexture, 91 | opacity: 0, 92 | depthTest: false}); 93 | 94 | var forwardToBackCount = 0; 95 | 96 | for(var i = 0; i< 7; i++){ 97 | var trackerX = Math.random() * this.boxWidth - this.boxWidth/2; 98 | var trackerY = Math.floor(.5 + Math.random()) * this.boxHeight; 99 | var trackerZ = Math.random() * this.boxDepth - this.boxDepth/2; 100 | var verts = []; 101 | var count = 0; 102 | var randSeed = Math.random(); 103 | var randSeed2 = Math.random() + .3; 104 | var randSeed3 = Math.random(); 105 | 106 | 107 | if(Math.random() < .5 && forwardToBackCount < 5){ 108 | // x axis 109 | 110 | forwardToBackCount++; 111 | 112 | var vert0 = new THREE.Vector3(trackerX, trackerY, this.boxDepth/2); 113 | var vert1 = new THREE.Vector3(trackerX, trackerY, -this.boxDepth/2); 114 | this.trackerGeometry.vertices.push(vert0); 115 | this.trackerGeometry.vertices.push(vert1); 116 | 117 | var ball = new THREE.Sprite(this.trackerBallMaterial); 118 | ball.position.set(10,10,10); 119 | ball.scale.set(1,1); 120 | this.scene.add(ball); 121 | this.trackerBalls.push(ball); 122 | 123 | this.trackers.push({ 124 | update: (function(geo, a, balls, l, w, d, h, rand, rand2, rand3){ 125 | return function(time){ 126 | var posTime = Math.max(time, 3000); 127 | geo.vertices[a-2].x = Math.max(-w*rand3/2,Math.min(w*rand3/2, w * Math.cos(rand2 * (rand * w + posTime/1000)) / 2)); 128 | geo.vertices[a-2].z = Utils.sCurve(Math.min(1, time/2000)) * d/2; 129 | geo.vertices[a-1].x = Math.max(-w*rand3/2,Math.min(w*rand3/2, w * Math.cos(rand2 * (rand * w + posTime/1000)) / 2)); 130 | geo.vertices[a-1].z = -Utils.sCurve(Math.min(1, time/2000)) * d/2; 131 | geo.verticesNeedUpdate = true; 132 | 133 | balls[l-1].position.set(geo.vertices[a-2].x, geo.vertices[a-2].y, geo.vertices[a-2].z); 134 | 135 | } 136 | })(this.trackerGeometry, this.trackerGeometry.vertices.length, this.trackerBalls, this.trackerBalls.length, this.boxWidth, this.boxDepth, this.boxHeight,randSeed, randSeed2, randSeed3) 137 | }); 138 | 139 | if(Math.random() < .3){ 140 | 141 | var vert2 = new THREE.Vector3(trackerX, this.boxHeight, this.boxDepth/2); 142 | var vert3 = new THREE.Vector3(trackerX, 0, this.boxDepth/2); 143 | this.trackerGeometry.vertices.push(vert2); 144 | this.trackerGeometry.vertices.push(vert3); 145 | 146 | var ball = new THREE.Sprite(this.trackerBallMaterial); 147 | ball.position.set(10,10,10); 148 | ball.scale.set(1,1); 149 | this.scene.add(ball); 150 | this.trackerBalls.push(ball); 151 | 152 | this.trackers.push({ 153 | update: (function(geo, a, balls, l, w, d, h, rand, rand2, rand3){ 154 | return function(time){ 155 | var posTime = Math.max(time, 3000); 156 | geo.vertices[a-2].x = Math.max(-w*rand3/2,Math.min(w*rand3/2,w * Math.cos(rand2 * (rand * w + posTime/1000)) / 2)); 157 | geo.vertices[a-2].y = Utils.sCurve(Math.min(1, time/2000)) * h/2 + h/2; 158 | geo.vertices[a-1].x = Math.max(-w*rand3/2, Math.min(w*rand3/2,w * Math.cos(rand2 * (rand * w + posTime/1000)) / 2)); 159 | geo.vertices[a-1].y = h/2 -Utils.sCurve(Math.min(1, time/2000)) * h/2; 160 | geo.verticesNeedUpdate = true; 161 | 162 | balls[l-1].position.set(geo.vertices[a-2].x, geo.vertices[a-2].y, geo.vertices[a-2].z); 163 | 164 | } 165 | })(this.trackerGeometry, this.trackerGeometry.vertices.length, this.trackerBalls, this.trackerBalls.length, this.boxWidth, this.boxDepth,this.boxHeight, randSeed, randSeed2, randSeed3) 166 | }); 167 | 168 | } else if(Math.random() > .7){ 169 | var vert2 = new THREE.Vector3(trackerX, this.boxHeight, -this.boxDepth/2); 170 | var vert3 = new THREE.Vector3(trackerX, 0, -this.boxDepth/2); 171 | this.trackerGeometry.vertices.push(vert2); 172 | this.trackerGeometry.vertices.push(vert3); 173 | 174 | var ball = new THREE.Sprite(this.trackerBallMaterial); 175 | ball.position.set(10,10,10); 176 | ball.scale.set(1,1); 177 | this.scene.add(ball); 178 | this.trackerBalls.push(ball); 179 | 180 | this.trackers.push({ 181 | update: (function(geo, a, balls, l, w, d, h, rand, rand2, rand3){ 182 | return function(time){ 183 | var posTime = Math.max(time, 3000); 184 | geo.vertices[a-2].x = Math.max(-w*rand3/2,Math.min(w*rand3/2,w * Math.cos(rand2 * (rand * w + posTime/1000)) / 2)); 185 | geo.vertices[a-2].y = Utils.sCurve(Math.min(1, time/2000)) * h/2 + h/2; 186 | geo.vertices[a-1].x = Math.max(-w*rand3/2,Math.min(w*rand3/2,w * Math.cos(rand2 * (rand * w + posTime/1000)) / 2)); 187 | geo.vertices[a-1].y = h/2-Utils.sCurve(Math.min(1, time/2000)) * h/2; 188 | geo.verticesNeedUpdate = true; 189 | 190 | balls[l-1].position.set(geo.vertices[a-2].x, 0, geo.vertices[a-2].z); 191 | 192 | } 193 | })(this.trackerGeometry, this.trackerGeometry.vertices.length, this.trackerBalls, this.trackerBalls.length, this.boxWidth, this.boxDepth, this.boxHeight, randSeed, randSeed2, randSeed3) 194 | }); 195 | } 196 | 197 | } else { 198 | // y axis 199 | var vert0 = new THREE.Vector3(this.boxWidth/2, trackerY, trackerZ); 200 | var vert1 = new THREE.Vector3(-this.boxWidth/2, trackerY, trackerZ); 201 | 202 | this.trackerGeometry.vertices.push(vert0); 203 | this.trackerGeometry.vertices.push(vert1); 204 | 205 | var ball = new THREE.Sprite(this.trackerBallMaterial); 206 | ball.position.set(10,10,10); 207 | ball.scale.set(1,1); 208 | this.scene.add(ball); 209 | this.trackerBalls.push(ball); 210 | 211 | this.trackers.push({ 212 | update: (function(geo, a, balls, l, w, d, h, rand, rand2, rand3){ 213 | return function(time){ 214 | var posTime = Math.max(time, 3000); 215 | geo.vertices[a-2].z = Math.max(-d*rand3/2, Math.min(d*rand3/2, d * Math.cos(rand2 * (rand * d + posTime/1000)) / 2)); 216 | geo.vertices[a-1].z = Math.max(-d*rand3/2, Math.min(d*rand3/2, d * Math.cos(rand2 * (rand * d + posTime/1000)) / 2)); 217 | geo.vertices[a-2].x = Utils.sCurve(Math.min(1, time/2000)) * w/2; 218 | geo.vertices[a-1].x = -Utils.sCurve(Math.min(1, time/2000)) * w/2 219 | geo.verticesNeedUpdate = true; 220 | 221 | balls[l-1].position.set(geo.vertices[a-2].x, geo.vertices[a-2].y, geo.vertices[a-2].z); 222 | } 223 | })(this.trackerGeometry, this.trackerGeometry.vertices.length, this.trackerBalls, this.trackerBalls.length, this.boxWidth, this.boxDepth, this.boxHeight, randSeed, randSeed2, randSeed3) 224 | }); 225 | 226 | if(Math.random() < .3){ 227 | var vert2 = new THREE.Vector3(this.boxWidth/2, this.boxHeight, trackerZ); 228 | var vert3 = new THREE.Vector3(this.boxWidth/2, 0, trackerZ); 229 | 230 | this.trackerGeometry.vertices.push(vert2); 231 | this.trackerGeometry.vertices.push(vert3); 232 | 233 | var ball = new THREE.Sprite(this.trackerBallMaterial); 234 | ball.position.set(10,10,10); 235 | ball.scale.set(1,1); 236 | this.scene.add(ball); 237 | this.trackerBalls.push(ball); 238 | 239 | this.trackers.push({ 240 | update: (function(geo, a, balls, l, w, d, h, rand, rand2, rand3){ 241 | return function(time){ 242 | var posTime = Math.max(time, 3000); 243 | geo.vertices[a-2].z = Math.max(-d*rand3/2, Math.min(d*rand3/2, d * Math.cos(rand2 * (rand * d + posTime/1000)) / 2)); 244 | geo.vertices[a-1].z = Math.max(-d*rand3/2, Math.min(d*rand3/2, d * Math.cos(rand2 * (rand * d + posTime/1000)) / 2)); 245 | geo.vertices[a-2].y = h/2 + Utils.sCurve(Math.min(1, time/2000)) * h/2; 246 | geo.vertices[a-1].y = h/2 - Utils.sCurve(Math.min(1, time/2000)) * h/2; 247 | geo.verticesNeedUpdate = true; 248 | 249 | balls[l-1].position.set(geo.vertices[a-2].x, geo.vertices[a-2].y, geo.vertices[a-2].z); 250 | } 251 | })(this.trackerGeometry, this.trackerGeometry.vertices.length, this.trackerBalls, this.trackerBalls.length, this.boxWidth, this.boxDepth, this.boxHeight, randSeed, randSeed2, randSeed3) 252 | }); 253 | 254 | } else if(Math.random() > .7){ 255 | var vert2 = new THREE.Vector3(-this.boxWidth/2, this.boxHeight, trackerZ); 256 | var vert3 = new THREE.Vector3(-this.boxWidth/2, 0, trackerZ); 257 | 258 | this.trackerGeometry.vertices.push(vert2); 259 | this.trackerGeometry.vertices.push(vert3); 260 | 261 | var ball = new THREE.Sprite(this.trackerBallMaterial); 262 | ball.position.set(10,10,10); 263 | ball.scale.set(1,1); 264 | this.scene.add(ball); 265 | this.trackerBalls.push(ball); 266 | 267 | this.trackers.push({ 268 | update: (function(geo, a, balls, l, w, d, h, rand, rand2, rand3){ 269 | return function(time){ 270 | var posTime = Math.max(time, 3000); 271 | geo.vertices[a-2].z = Math.max(-d*rand3/2, Math.min(d*rand3/2, d * Math.cos(rand2 * (rand * d + time/1000)) / 2)); 272 | geo.vertices[a-1].z = Math.max(-d*rand3/2, Math.min(d*rand3/2, d * Math.cos(rand2 * (rand * d + time/1000)) / 2)); 273 | geo.vertices[a-2].y = h/2 + Utils.sCurve(Math.min(1, time/2000)) * h/2; 274 | geo.vertices[a-1].y = h/2 - Utils.sCurve(Math.min(1, time/2000)) * h/2; 275 | geo.verticesNeedUpdate = true; 276 | 277 | balls[l-1].position.set(geo.vertices[a-2].x, geo.vertices[a-2].y, geo.vertices[a-2].z); 278 | } 279 | })(this.trackerGeometry, this.trackerGeometry.vertices.length, this.trackerBalls, this.trackerBalls.length, this.boxWidth, this.boxDepth, this.boxHeight, randSeed, randSeed2, randSeed3) 280 | }); 281 | 282 | } 283 | } 284 | 285 | } 286 | 287 | 288 | this.scene.add(new THREE.Line(this.trackerGeometry, trackerMaterial, THREE.LinePieces)); 289 | 290 | /* sides of box */ 291 | 292 | var boxTexture = new THREE.Texture(createSideCanvas.call(this)); 293 | boxTexture.needsUpdate = true; 294 | 295 | // this.container.appendChild( this.satelliteCanvas); 296 | this.sideMaterial = new THREE.MeshBasicMaterial({ 297 | map : boxTexture, 298 | transparent: true, 299 | opacity: 0 300 | }); 301 | 302 | this.sideMaterial.side = THREE.DoubleSide; 303 | 304 | var face1 = new THREE.PlaneGeometry(this.boxWidth,this.boxHeight/4,1,1); 305 | var face2 = new THREE.PlaneGeometry(this.boxWidth,this.boxHeight/4,1,1); 306 | var face3 = new THREE.PlaneGeometry(this.boxDepth,this.boxHeight/4,1,1); 307 | var face4 = new THREE.PlaneGeometry(this.boxDepth,this.boxHeight/4,1,1); 308 | 309 | 310 | var mesh1 = new THREE.Mesh(face1, this.sideMaterial); 311 | var mesh2 = new THREE.Mesh(face2, this.sideMaterial); 312 | var mesh3 = new THREE.Mesh(face3, this.sideMaterial); 313 | var mesh4 = new THREE.Mesh(face4, this.sideMaterial); 314 | 315 | mesh1.position = {x: 0, y: 7*this.boxHeight/8, z: this.boxDepth/2}; 316 | mesh2.position = {x: 0, y: 7*this.boxHeight/8, z: -this.boxDepth/2}; 317 | mesh3.position = {x: -this.boxWidth/2, y: 7*this.boxHeight/8, z: 0}; 318 | mesh4.position = {x: this.boxWidth/2, y: 7*this.boxHeight/8, z: 0}; 319 | mesh3.rotateY(Math.PI/2); 320 | mesh4.rotateY(Math.PI/2); 321 | 322 | this.scene.add(mesh1); 323 | this.scene.add(mesh2); 324 | this.scene.add(mesh3); 325 | this.scene.add(mesh4); 326 | 327 | // create particle system 328 | this.particleGeometry = new THREE.Geometry(); 329 | 330 | this.particleVertexShader = [ 331 | "attribute vec3 color;", 332 | "attribute float opacity;", 333 | "varying vec4 vColor;", 334 | "void main()", 335 | "{", 336 | "vColor = vec4( color, opacity );", // set color associated to vertex; use later in fragment shader. 337 | "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );", 338 | "gl_PointSize = 1.0;", 339 | "gl_Position = projectionMatrix * mvPosition;", 340 | "}" 341 | ].join("\n"); 342 | 343 | this.particleFragmentShader = [ 344 | "varying vec4 vColor;", 345 | "void main()", 346 | "{", 347 | "gl_FragColor = vColor;", 348 | "}" 349 | ].join("\n"); 350 | 351 | this.shaderAttributes = { 352 | color: { type: 'c', value: []}, 353 | opacity: {type: 'f', value: []} 354 | }; 355 | 356 | this.shaderMaterial = new THREE.ShaderMaterial( { 357 | uniforms: {}, 358 | attributes: this.shaderAttributes, 359 | vertexShader: this.particleVertexShader, 360 | fragmentShader: this.particleFragmentShader, 361 | transparent: true 362 | }); 363 | 364 | 365 | for(var i = 0; i< this.boxWidth * this.boxDepth; i++){ 366 | var x = i % this.boxWidth - this.boxWidth/2; 367 | var z = (Math.floor(i / this.boxDepth) -this.boxDepth/2 ); 368 | var vertex = new THREE.Vector3(); 369 | vertex.x = x; 370 | vertex.y = (this.boxHeight)*Math.sin(x/8)*Math.cos(z/8) * (((this.boxDepth/2)-Math.abs(x))/this.boxWidth/2) * ((this.boxDepth/2-Math.abs(z))/this.boxDepth/2); 371 | vertex.z = z; 372 | this.particleGeometry.vertices.push( vertex ); 373 | this.shaderAttributes.color.value[i] = new THREE.Color(0x00eeee); 374 | this.shaderAttributes.opacity.value[i] = 0.0; 375 | } 376 | 377 | this.particleColors = []; 378 | 379 | for(var i = 0; i< 5; i++){ 380 | this.particleColors.push(new THREE.Color(pushercolor("#00eeee").blend("#ffcc00", i/4).hex6())); 381 | } 382 | 383 | var particleSystem = new THREE.ParticleSystem( this.particleGeometry, this.shaderMaterial); 384 | 385 | this.scene.add( particleSystem); 386 | 387 | this.frameGeometry = new THREE.Geometry(); 388 | var frameMaterial = new THREE.LineBasicMaterial({ 389 | color: 0xFFFFFF, 390 | opacity: .5, 391 | transparent: true 392 | }); 393 | 394 | var maxTime = 2000; 395 | 396 | this.frameSegments = []; 397 | 398 | var addFrameAnimation = function(point, start, end, startTime, endTime){ 399 | 400 | this.frameSegments.push({ 401 | point: point, 402 | startTime: 1000 + startTime + start[1] * 200, 403 | endTime: 1000 + endTime + start[1] * 200, 404 | func: function(t){ 405 | return {x: start[0] + (end[0]-start[0])*(t/(endTime-startTime)), 406 | y: start[1] + (end[1]-start[1])*(t/(endTime-startTime)), 407 | z: start[2] + (end[2]-start[2])*(t/(endTime-startTime)) 408 | }; 409 | } 410 | }); 411 | 412 | } 413 | 414 | for(var i = 0; i < 2; i++){ 415 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, i*2 - 2, this.boxDepth/2)); 416 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, i*2 - 2, this.boxDepth/2)); 417 | 418 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [this.boxWidth/2, i*2 - 2, this.boxDepth/2], [this.boxWidth/2, i*2 - 2, -this.boxDepth/2], 0, 1000); 419 | 420 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, i*2 -2, -this.boxDepth/2)); 421 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, i*2 - 2, -this.boxDepth/2)); 422 | 423 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [this.boxWidth/2, i*2 - 2, -this.boxDepth/2], [-this.boxWidth/2, i*2 - 2, -this.boxDepth/2], 500, 1500); 424 | 425 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, i*2 - 2, -this.boxDepth/2)); 426 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, i*2 - 2, -this.boxDepth/2)); 427 | 428 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [-this.boxWidth/2, i*2 - 2, -this.boxDepth/2], [-this.boxWidth/2, i*2 - 2, this.boxDepth/2], 1000, 2000); 429 | 430 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, i*2 - 2, this.boxDepth/2)); 431 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, i*2 - 2, this.boxDepth/2)); 432 | 433 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [-this.boxWidth/2, i*2 - 2, this.boxDepth/2], [this.boxWidth/2, i*2 - 2, this.boxDepth/2], 1500, 2500); 434 | 435 | } 436 | 437 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, -2, this.boxDepth/2)); 438 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, -2, this.boxDepth/2)); 439 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [this.boxWidth/2, -2, this.boxDepth/2], [this.boxWidth/2, 0, this.boxDepth/2], 0, 500); 440 | 441 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, -2, -this.boxDepth/2)); 442 | this.frameGeometry.vertices.push(new THREE.Vector3(this.boxWidth/2, -2, -this.boxDepth/2)); 443 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [this.boxWidth/2, -2, -this.boxDepth/2], [this.boxWidth/2, 0, -this.boxDepth/2], 500, 1000); 444 | 445 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, -2, -this.boxDepth/2)); 446 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, -2, -this.boxDepth/2)); 447 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [-this.boxWidth/2, -2, -this.boxDepth/2], [-this.boxWidth/2, 0, -this.boxDepth/2], 1000, 1500); 448 | 449 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, -2, this.boxDepth/2)); 450 | this.frameGeometry.vertices.push(new THREE.Vector3(-this.boxWidth/2, -2, this.boxDepth/2)); 451 | addFrameAnimation.call(this, this.frameGeometry.vertices[this.frameGeometry.vertices.length-1], [-this.boxWidth/2, -2, this.boxDepth/2], [-this.boxWidth/2, 0, this.boxDepth/2], 1500, 2000); 452 | 453 | var line = new THREE.Line(this.frameGeometry, frameMaterial, THREE.LinePieces); 454 | 455 | this.scene.add(line); 456 | 457 | }; 458 | 459 | Box.prototype.tick = function(){ 460 | 461 | var startTime = 2000; 462 | var maxTime = 5000; 463 | 464 | if(!this.lastRenderDate){ 465 | this.lastRenderDate = new Date(); 466 | } 467 | 468 | if(!this.firstRenderDate){ 469 | this.firstRenderDate = new Date(); 470 | } 471 | 472 | var totalRunTime = new Date() - this.firstRenderDate - startTime; 473 | 474 | if(totalRunTime < 0) 475 | return; 476 | 477 | var renderTime = new Date() - this.lastRenderDate; 478 | this.lastRenderDate = new Date(); 479 | 480 | 481 | /* run intro animations */ 482 | var percentComplete = Math.min(totalRunTime, maxTime - startTime) / (maxTime - startTime); 483 | 484 | if(!this.animationsDone){ 485 | 486 | if(totalRunTime > maxTime){ 487 | this.animationsDone = true; 488 | totalRunTime = maxTime; 489 | } 490 | 491 | 492 | /* do the frame */ 493 | 494 | for(var i = 0; i fStartTime){ 499 | var point = this.frameSegments[i].point; 500 | var func = this.frameSegments[i].func; 501 | 502 | var newPoint = func(Math.min(totalRunTime,fEndTime) - fStartTime); 503 | 504 | if(point.x !== newPoint.x || point.y !== newPoint.y || point.z !== newPoint.z){ 505 | point.x = newPoint.x; 506 | point.y = newPoint.y; 507 | point.z = newPoint.z; 508 | 509 | this.frameGeometry.verticesNeedUpdate = true; 510 | } 511 | 512 | } 513 | } 514 | 515 | 516 | /* do the particles */ 517 | 518 | // this.particleMaterial.opacity = Math.pow(percentComplete, 2) / 2; 519 | 520 | /* do the sides */ 521 | 522 | this.trackerBallMaterial.opacity = Utils.sCurve(percentComplete); 523 | 524 | if(totalRunTime > 1000){ 525 | this.sideMaterial.opacity = Math.pow((Math.min(totalRunTime, maxTime)-1000) / (maxTime-1000), 2); 526 | } 527 | } 528 | 529 | /* move the lines */ 530 | 531 | for(var i = 0; i< this.trackers.length; i++){ 532 | this.trackers[i].update(totalRunTime); 533 | } 534 | 535 | /* move the particles inside */ 536 | 537 | for(var i = 0; i< this.particleGeometry.vertices.length; i++){ 538 | var x = (i %this.boxWidth) - this.boxWidth/2; 539 | var z = (Math.floor(i / this.boxDepth) -this.boxDepth/2 ); 540 | var y = Math.sin(Math.PI * 2 * (((totalRunTime / 100) % this.boxHeight)/this.boxHeight)) * this.boxHeight * Math.sin(x/8)*Math.cos(z/8) * (((this.boxWidth/2)-Math.abs(x))/(this.boxWidth/2)) * (((this.boxDepth/2)-Math.abs(z))/(this.boxDepth/2)); 541 | 542 | var maxColors = this.particleColors.length - 1; 543 | 544 | this.particleGeometry.vertices[i].x = x; 545 | this.particleGeometry.vertices[i].y = y 546 | this.particleGeometry.vertices[i].z = z; 547 | 548 | // fix that 36... 549 | if(!this.animationsDone){ 550 | this.shaderAttributes.opacity.value[i] = Math.min(1,(36 - Math.sqrt(Math.pow(x,2) + Math.pow(z,2)))/36 * Utils.sCurve(percentComplete) + Math.max(y,0)/10); 551 | } 552 | this.shaderAttributes.color.value[i] = this.particleColors[Math.min(maxColors,Math.max(0,Math.floor(y)))]; 553 | } 554 | if(!this.animationsDone){ 555 | this.shaderAttributes.opacity.needsUpdate = true; 556 | } 557 | this.shaderAttributes.color.needsUpdate = true; 558 | this.particleGeometry.verticesNeedUpdate = true; 559 | 560 | 561 | 562 | var rotateCameraBy = (2 * Math.PI)/(20000/renderTime); 563 | 564 | this.cameraAngle += rotateCameraBy; 565 | 566 | this.camera.position.x = this.cameraDistance * Math.cos(this.cameraAngle); 567 | this.camera.position.y = this.cameraDistance/2; 568 | this.camera.position.z = this.cameraDistance * Math.sin(this.cameraAngle); 569 | this.camera.lookAt( this.scene.position ); 570 | this.renderer.render( this.scene, this.camera ); 571 | }; 572 | 573 | module.exports = Box; 574 | -------------------------------------------------------------------------------- /src/Boardroom.js: -------------------------------------------------------------------------------- 1 | var $ = require("jquery"), 2 | pushercolor = require("pusher.color"), 3 | moment = require("moment"), 4 | LightTable = require("./LightTable.js"), 5 | EncomGlobe = require("encom-globe"), 6 | SimpleClock = require("./SimpleClock.js"), 7 | SatBar = require("./SatBar.js"), 8 | TimerTrees = require("./TimerTrees.js"), 9 | StockChart = require("./StockChart.js"), 10 | StockChartSmall = require("./StockChartSmall.js"), 11 | Logo = require("./Logo.js"), 12 | _ = require("lodash/lodash.min.js") 13 | attackerMap = null; 14 | 15 | moment.tz = require("moment-timezone"); 16 | 17 | var boardroomActive = false, 18 | globe, 19 | satbar, 20 | simpleclock, 21 | startDate, 22 | box, 23 | swirls, 24 | sliderHeads, 25 | slider, 26 | stockchart, 27 | lastTime, 28 | screensaver, 29 | locationAreas, 30 | locationAreaColors = [], 31 | interactionContainer, 32 | topattacksContainer, 33 | logo, 34 | blinkies, 35 | blinkiesColors = ["#000", "#ffcc00", "#00eeee", "#fff"], 36 | picIndex = 0, 37 | currentPics = [], 38 | lastPicDate = Date.now(), 39 | streamType, 40 | readmeContainer, 41 | authenticatedUser = false; 42 | 43 | sliderHeads = {}; 44 | var Boardroom = {}; 45 | 46 | Boardroom.init = function(_streamType, data){ 47 | 48 | streamType = _streamType; 49 | blinkies = $('.blinky'); 50 | mediaBoxes = $('.media-box .user-pic'); 51 | 52 | var ratio = $(window).width() / 1918; 53 | $("#boardroom").css({ 54 | "zoom": ratio, 55 | "-moz-transform": "scale(" + ratio + ")", 56 | "-moz-transform-origin": "0 0" 57 | }); 58 | $("#boardroom").center(ratio); 59 | 60 | readmeContainer = $("#boardroom-readme-" + _streamType); 61 | 62 | //Boardroom.data = data; 63 | 64 | 65 | $("#fullscreen-link").click(function(e){ 66 | e.preventDefault(); 67 | var el = document.documentElement, 68 | rfs = el.requestFullScreen || el.webkitRequestFullScreen || el.mozRequestFullScreen; 69 | 70 | rfs.call(el); 71 | 72 | }); 73 | 74 | $("#info-link").click(function(e){ 75 | e.preventDefault(); 76 | showReadme(); 77 | }); 78 | 79 | $(".boardroom-readme h2 em").click(function(e){ 80 | e.preventDefault(); 81 | hideReadme(); 82 | }); 83 | 84 | setInterval(function(){ 85 | if(boardroomActive){ 86 | $("#las-vegas-time").text(moment().tz("America/Los_Angeles").format("HH:mm:ss")); 87 | $("#kansas-city-time").text(moment().tz("America/Chicago").format("HH:mm:ss")), 88 | $("#london-time").text(moment().tz("Europe/London").format("HH:mm:ss")); 89 | $("#berlin-time").text(moment().tz("Europe/Berlin").format("HH:mm:ss")); 90 | $("#bangalore-time").text(moment().tz("Asia/Colombo").format("HH:mm:ss")); 91 | $("#sydney-time").text(moment().tz("Australia/Sydney").format("HH:mm:ss")); 92 | } 93 | }, 1000); 94 | 95 | locationAreas = { 96 | antarctica: {count: 10, ref: $("#location-area-antarctica")}, 97 | northamerica: {count: 10, ref: $("#location-area-northamerica")}, 98 | southamerica: {count: 10, ref: $("#location-area-southamerica")}, 99 | europe: {count: 10, ref: $("#location-area-europe")}, 100 | asia: {count: 10, ref: $("#location-area-asia")}, 101 | australia: {count: 10, ref: $("#location-area-australia")}, 102 | africa: {count: 10, ref: $("#location-area-africa")}, 103 | other: {count: 10, ref: $("#location-area-other")}, 104 | unknown: {count: 10, ref: $("#location-area-unknown")} 105 | }; 106 | 107 | $("#user-interaction-header").text(streamType.toUpperCase() + " LIVE DATA FEED"); 108 | $("#globalization-header").text(streamType.toUpperCase() + " GLOBALIZATION"); 109 | $("#growth-header").text(streamType.toUpperCase() + " EVENTS :: LAST 24 HOURS"); 110 | // $("#media-header").text(streamType.toUpperCase() + " USERS"); 111 | 112 | $("#ticker-text").text(streamType.toUpperCase()); 113 | if(streamType.length > 6){ 114 | $("#ticker-text").css("font-size", "12pt"); 115 | } 116 | 117 | if(data){ 118 | $("#ticker-value").text(formatYTD(data[0].events, data[data.length-1].events)); 119 | } 120 | 121 | setInterval(function(){ 122 | if(boardroomActive){ 123 | for(var a in locationAreas){ 124 | var loc = locationAreas[a]; 125 | loc.count = loc.count -1; 126 | loc.count = Math.max(loc.count, 0); 127 | 128 | loc.ref.css("background-color", locationAreaColors[loc.count]); 129 | 130 | } 131 | } 132 | }, 3000); 133 | 134 | initAuth(); 135 | 136 | interactionContainer = $("#interaction > table > tbody"); 137 | topattacksMessage = $("#media-top > h3"); 138 | topattacksContainer = $("#media-top > table > tbody"); 139 | attackerContainer = $("#attacker-data"); 140 | attackerContainerHeader = $("#media-bottom > h3"); 141 | 142 | for(var i = 0; i< 50; i++){ 143 | interactionContainer.append(''); 144 | } 145 | }; 146 | 147 | function initAuth(){ 148 | $.ajax({ 149 | url: "https://mhn.h-i-r.net/seckcapi" + "/auth/me", 150 | }) 151 | .done(function( data ) { 152 | authenticatedUser = data.active ? data.active : false; 153 | 154 | }); 155 | } 156 | 157 | function getSensors(){ 158 | return $.ajax({ 159 | url: "https://mhn.h-i-r.net/seckcapi"+ "/sensors/locations", 160 | }) 161 | .done(function( data ) { 162 | if(data.length && data.length > 0){ 163 | data.forEach(function(sensor){ 164 | var lat = sensor.location.latitude ? sensor.location.latitude : "0", 165 | lon = sensor.location.longitude ? sensor.location.longitude : "0"; 166 | 167 | var opts = { 168 | coreColor: "#BF92FF", 169 | numWaves: 4 170 | } 171 | 172 | globe.addSatellite(lat, lon, 1.4 + Math.random()/10, opts/* opts, texture, animator*/); 173 | }) 174 | } 175 | }); 176 | } 177 | 178 | function getSensorLocation(sensor){ 179 | $.ajax({ 180 | url: "https://mhn.h-i-r.net/seckcapi"+ "/geocode/" + sensor.ip//"https://mhn.h-i-r.net/seckcapi" + "/geocode/" + sensor.ip, 181 | }) 182 | .done(function( data ) { 183 | 184 | var lat = data.location.latitude ? data.location.latitude : "0", 185 | lon = data.location.longitude ? data.location.longitude : "0"; 186 | 187 | var opts = { 188 | coreColor: "#BF92FF", 189 | numWaves: 4 190 | } 191 | 192 | globe.addSatellite(lat, lon, 1.4 + Math.random()/10, opts/* opts, texture, animator*/); 193 | }); 194 | } 195 | 196 | function getTopAttackers(){ 197 | return $.ajax({ 198 | url: "https://mhn.h-i-r.net/seckcapi/stats/attackers", 199 | }) 200 | .done(function( data ) { 201 | //topattacksContainer 202 | topattacksMessage.remove(); 203 | topattacksContainer[0].innerHTML = ""; 204 | data.data.forEach(function(attacker){ 205 | if(topattacksContainer){ 206 | var lastChild = document.createElement("tr"); 207 | lastChild.onclick = function(){ 208 | getAttackerStats(attacker.source_ip); 209 | }; 210 | lastChild.classList.add("interaction-data", "attacker"); 211 | lastChild.innerHTML = '' + attacker.count + '' + 212 | '' + attacker.source_ip + '' + 213 | '' + attacker.honeypot + ''; 214 | topattacksContainer.append(lastChild); 215 | } 216 | }); 217 | }); 218 | } 219 | 220 | function getAttackerStats(attackIP){ 221 | $.ajax({ 222 | url: "https://mhn.h-i-r.net/seckcapi/stats/attacker/" + attackIP, 223 | }) 224 | .done(function( data ) { 225 | //topattacksContainer 226 | attackerContainerHeader[0].setAttribute("style", "display:none;"); 227 | if(attackerContainer){ 228 | attackerContainer[0].innerHTML = ""; 229 | var lastChild = document.createElement("div"); 230 | lastChild.classList.add("interaction-data"); 231 | lastChild.innerHTML = '
  • ' + attackIP + '
' + 232 | '
  • Count: ' + data.data.count + '
' + 233 | '
  • Seen by: ' + data.data.num_sensors + '
' + 234 | '
  • Ports: ' + data.data.ports.join(", ") + '
' + 235 | '
  • First seen:
    ' + moment.utc(data.data.first_seen).fromNow() + '
' + 236 | '
  • Last seen:
    ' + moment.utc(data.data.last_seen).fromNow() + '
'; 237 | attackerContainer.append(lastChild); 238 | } 239 | 240 | }); 241 | getAttackerLocation(attackIP); 242 | } 243 | window.getAttackerStats = getAttackerStats; 244 | 245 | function getSensorStats(){ 246 | Boardroom.data = []; 247 | var test = {}; 248 | var yesterdaysHours = []; 249 | var today = moment.utc(); 250 | var yesterday = moment.utc().subtract(1, 'days'); 251 | 252 | $('#ticker-sensor').text(today.year()); 253 | 254 | var currentUTCHours = moment.utc().hours(); 255 | 256 | for(var h = 0; h < 24; h++){ 257 | test[h] = 0; 258 | } 259 | for(var yh = currentUTCHours + 1; yh < 24; yh++){ 260 | yesterdaysHours.push(yh); 261 | } 262 | 263 | var getYesterday = $.ajax({ 264 | url: "https://mhn.h-i-r.net/seckcapi" + "/stats/attacks?date=" + yesterday.format("YYYYMMDD") 265 | }) 266 | .done(function( data ) { 267 | _.forEach(data, function(set){ 268 | _.forEach(set.hourly,function(value, key){ 269 | if(yesterdaysHours.indexOf(parseInt(key, 10)) > -1){ 270 | test[key] += value; 271 | } 272 | }); 273 | }); 274 | _.forEach(test, function(count, key){ 275 | if(yesterdaysHours.indexOf(parseInt(key, 10)) > -1){ 276 | year = yesterday.format("YYYY"); 277 | month = yesterday.format("MM"); 278 | day = yesterday.format("DD"); 279 | 280 | Boardroom.data.push({ 281 | year: year, 282 | month: month, 283 | day: day, 284 | hour: key, 285 | date: moment.utc([yesterday.year(), yesterday.month(), yesterday.date(), parseInt(key, 10)]), 286 | events: count 287 | }); 288 | } 289 | }); 290 | }); 291 | 292 | var getToday = $.ajax({ 293 | url: "https://mhn.h-i-r.net/seckcapi" + "/stats/attacks?date=" + today.format("YYYYMMDD") 294 | }) 295 | .done(function( data ) { 296 | _.forEach(data, function(set){ 297 | _.forEach(set.hourly,function(value, key){ 298 | if(parseInt(key, 10) <= currentUTCHours){ 299 | test[key] += value; 300 | } 301 | }); 302 | }); 303 | _.forEach(test, function(count, key){ 304 | if(parseInt(key, 10) <= currentUTCHours){ 305 | year = today.format("YYYY"); 306 | month = today.format("MM"); 307 | day = today.format("DD"); 308 | 309 | Boardroom.data.push({ 310 | year: year, 311 | month: month, 312 | day: day, 313 | hour: key, 314 | date: moment.utc([today.year(), today.month(), today.date(), parseInt(key, 10)]), 315 | events: count 316 | }); 317 | } 318 | }); 319 | }); 320 | 321 | $.when(getYesterday, getToday).then(function(){ 322 | Boardroom.data = _.sortBy(Boardroom.data,function(datum){ 323 | return datum.date.valueOf(); 324 | }); 325 | stockchart = new StockChart("stock-chart", {data: Boardroom.data, ticks: 4}); 326 | }) 327 | } 328 | 329 | var attackmarker = null; 330 | function getAttackerLocation(attackIP){ 331 | if(attackmarker !== null){ 332 | attackerMap.removeLayer(attackmarker); 333 | } 334 | 335 | $.ajax({ 336 | url: "https://mhn.h-i-r.net/seckcapi" + "/geocode/" + attackIP//"https://mhn.h-i-r.net/seckcapi" + "/geocode/" + attackIP, 337 | }) 338 | .done(function( data ) { 339 | var lat = data.location.latitude ? data.location.latitude : "0", 340 | lon = data.location.longitude ? data.location.longitude : "0"; 341 | attackerMap.setView([lat, lon], 9); 342 | attackmarker = L.marker([lat, lon]).addTo(attackerMap); 343 | }); 344 | } 345 | 346 | function getActivity(){ 347 | return $.ajax({ 348 | url: "https://mhn.h-i-r.net/api/intel_feed/?hours_ago=24", 349 | }) 350 | .done(function( data ) { 351 | console.log(data); 352 | }); 353 | } 354 | 355 | Boardroom.show = function(cb){ 356 | startDate = moment();//new Date(); 357 | lastTime = Date.now(); 358 | 359 | $("#boardroom").css({"visibility": "visible"}); 360 | for(var i = 0; i< 20; i++){ 361 | locationAreaColors[i] = pushercolor('#00eeee').blend('#ffcc00', i/20).hex6(); 362 | } 363 | 364 | //animate(); 365 | 366 | // render the other elements intro animations 367 | 368 | $(".footer-bar").delay(1000).animate({"margin-top": "0"}, 500); 369 | 370 | $("#globe-footer img").delay(1500).animate({"opacity": "1"}, 1000); 371 | 372 | $("#globalization").delay(600).animate({ 373 | top: "0px", 374 | left: "0px", 375 | width: "180px" 376 | }, 500); 377 | 378 | $("#globalization .location-slider").each(function(index, element){ 379 | $(element).delay(600 + index * 200).animate({ 380 | width: "180px" 381 | }, 1000); 382 | }); 383 | 384 | $("#logo-cover-up").delay(3000).animate({ 385 | height: "0px" 386 | }, 2500); 387 | 388 | $("#logo-cover-side-1").delay(3000).animate({ 389 | left: "200px" 390 | }, 2500); 391 | 392 | $("#logo-cover-side-2").delay(3000).animate({ 393 | width: "0px" 394 | }, 2500); 395 | 396 | $("#user-interaction").delay(500).animate({ 397 | width: "600px" 398 | }, 1500); 399 | 400 | $("#growth").delay(1000).animate({ 401 | width: "600px" 402 | }, 1500); 403 | 404 | $("#media").delay(1500).animate({ 405 | width: "450px" 406 | }, 1500); 407 | 408 | $("#timer").delay(2000).animate({ 409 | width: "450px" 410 | }, 1500); 411 | 412 | $("#bottom-border").delay(100).animate({ 413 | width: "1900px" 414 | }, 2000); 415 | 416 | // addSatellite(lat, lon, altitude, opts, texture, animator) 417 | // var opts = { 418 | // numWaves: 8, 419 | // waveColor: "#FFF",#725798 420 | // coreColor: "#FF0000", 421 | // shieldColor: "#FFF", 422 | // size: 1 423 | // } 424 | 425 | //if(authenticatedUser === true){ 426 | $.when(getSensors(),getTopAttackers(), getSensorStats()).then(function(){ 427 | //console.log("all done"); 428 | }); 429 | //getTopAttackers 430 | setInterval(getTopAttackers, 1000 * 60); 431 | setInterval(getSensorStats, 1000 * 60); 432 | //} 433 | 434 | setInterval(function(){ 435 | satbar.setZone(Math.floor(Math.random()*4-1)); 436 | }, 7000); 437 | 438 | setTimeout(function(){ 439 | globe.addMarker(36.114647, -115.172813, "LV"); 440 | globe.addMarker(39.114, -94.627, "KC"); 441 | globe.addMarker(41.600545, -93.609106, "DSM"); 442 | globe.addMarker(38.907192, -77.036871, "DC"); 443 | attackerMap = L.map('attacker-map',{zoomControl:false}).setView([0, 0], 1); 444 | L.tileLayer('https://api.mapbox.com/styles/v1/wintelseckc/cj7c70wocaonm2spgkpuubn9y/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoid2ludGVsc2Vja2MiLCJhIjoiY2o3OWNkcWUyMDBjdzJ3cnNydGl0Nml6NCJ9.iLffndfFTZeV3I5VVF3-kA', { 445 | attribution: '© OpenStreetMap, CC-BY-SA, © Mapbox', 446 | maxZoom: 18, 447 | // id: 'Dark-encom', 448 | // accessToken: 'pk.eyJ1Ijoid2ludGVsc2Vja2MiLCJhIjoiY2o3OWNkcWUyMDBjdzJ3cnNydGl0Nml6NCJ9.iLffndfFTZeV3I5VVF3-kA' 449 | }).addTo(attackerMap); 450 | }, 2000); 451 | 452 | globe = new EncomGlobe(800, 800, { 453 | tiles: grid.tiles, 454 | pinColor: "#8FD8D8", 455 | viewAngle: .1, 456 | baseColor: "#000000", 457 | pointsPerDegree: 4 458 | }); 459 | $("#globe").append(globe.domElement); 460 | 461 | 462 | simpleclock = new SimpleClock("simpleclock"); 463 | 464 | globe.init(function(){ 465 | // called after the globe is complete 466 | 467 | // give anything else on the other side a second before starting 468 | setTimeout(function(){ 469 | satbar = new SatBar("satbar"); 470 | timertrees = new TimerTrees("timer-trees"); 471 | //stockchart = new StockChart("stock-chart", {data: Boardroom.data}); 472 | stockchartsmall = new StockChartSmall("stock-chart-small", {data: Boardroom.data}); 473 | logo = new Logo("logo", streamType.toUpperCase()); 474 | boardroomActive = true; 475 | }, 1000); 476 | 477 | if(typeof cb === "function"){ 478 | cb(); 479 | } 480 | }); 481 | 482 | }; 483 | 484 | Boardroom.hide = function(){ 485 | boardroomActive = false; 486 | 487 | box = null; 488 | satbar = null; 489 | timertrees =null; 490 | stockchart = null; 491 | stockchartsmall = null; 492 | swirls = null; 493 | logo = null; 494 | 495 | LightTable.show(); 496 | }; 497 | 498 | Boardroom.animate = function(){ 499 | if(boardroomActive){ 500 | var animateTime = Date.now() - lastTime; 501 | lastTime = Date.now(); 502 | 503 | globe.tick(); 504 | satbar.tick(); 505 | $("#clock").text(getTime()); 506 | simpleclock.tick(); 507 | if(stockchart !== undefined){ 508 | stockchart.tick(); 509 | } 510 | updateSliders(animateTime); 511 | } 512 | 513 | }; 514 | 515 | Boardroom.message = function(message){ 516 | 517 | if(!globe){ 518 | return; 519 | } 520 | 521 | if(message.latlon){ 522 | var latlon = message.latlon; 523 | globe.addPin(latlon.lat, latlon.lon, message.location); 524 | } 525 | 526 | if(message.picSmall || message.picLarge){ 527 | addPic(message); 528 | } 529 | 530 | if(message.commands && swirls){ 531 | swirls.hit(message.commands.join(", ")); 532 | } 533 | 534 | message.title = message.peerIP || message.attackerIP || message.remote_host; 535 | message.displayHostPort = message.hostPort || message.victimPort || ""; 536 | message.displayActivity = message.loggedin || message.connectionType || ""; 537 | 538 | changeBlinkies(); 539 | 540 | if(interactionContainer && interactionContainer[0].lastChild){ 541 | var lastChild = interactionContainer[0].lastChild; 542 | lastChild.innerHTML = '' + (message.loggedin ? message.loggedin.join(", ") : message.displayActivity) + '' + 543 | '' + message.title + '' + 544 | '' + message.displayHostPort + '' + 545 | '' + (message.startTime ? message.startTime : "")+ ''; 546 | 547 | interactionContainer[0].insertBefore(interactionContainer[0].lastChild, interactionContainer[0].firstChild); 548 | } 549 | 550 | $.ajax({ 551 | url: "https://mhn.h-i-r.net/seckcapi" + "/geocode/" + (message.peerIP || message.attackerIP || message.remote_host), 552 | }) 553 | .done(function( data ) { 554 | message.ipinfo = data; 555 | 556 | message.latlon = { 557 | lat:data.location.latitude ? data.location.latitude : "0", 558 | lon:data.location.longitude ? data.location.longitude : "0" 559 | } 560 | globe.addPin(data.location.latitude, data.location.longitude, data.city ? data.city.names.en : ""); 561 | createZipdot(message) 562 | }); 563 | 564 | }; 565 | // Boardroom.message = function(message){ 566 | 567 | // if(message.stream != streamType || !globe){ 568 | // return; 569 | // } 570 | 571 | // if(message.latlon){ 572 | // var latlon = message.latlon; 573 | // globe.addPin(latlon.lat, latlon.lon, message.location); 574 | // } 575 | 576 | // if(message.picSmall || message.picLarge){ 577 | // addPic(message); 578 | // } 579 | 580 | // if(message.type && swirls){ 581 | // swirls.hit(message.type); 582 | // } 583 | 584 | // changeBlinkies(); 585 | 586 | // if(interactionContainer && interactionContainer[0].lastChild){ 587 | // var lastChild = interactionContainer[0].lastChild; 588 | // lastChild.innerHTML = '
  • ' + message.username + '
  • ' + 589 | // '
  • ' + message.title + '
  • ' + 590 | // '
  • ' + (message.type ? message.type : "") + '
  • ' + 591 | // '
  • ' + (message.size ? message.size : "") + '
  • ' + 592 | // '
  • ' + (message.popularity ? message.popularity : "")+ '
  • '; 593 | 594 | // if(message.popularity > 100){ 595 | // lastChild.innerHTML = '' + lastChild.innerHTML; 596 | // } 597 | 598 | // interactionContainer[0].insertBefore(interactionContainer[0].lastChild, interactionContainer[0].firstChild); 599 | // } 600 | 601 | // createZipdot(message); 602 | 603 | 604 | // }; 605 | 606 | Boardroom.resize = function(){ 607 | var ratio = $(window).width() / 1918; 608 | $("#boardroom").css({ 609 | "zoom": ratio, 610 | "-moz-transform": "scale(" + ratio + ")", 611 | "-moz-transform-origin": "0 0" 612 | }); 613 | 614 | $("#boardroom").center(ratio); 615 | }; 616 | 617 | function showReadme() { 618 | 619 | var itemContent = readmeContainer.find(".content"); 620 | 621 | readmeContainer.removeAttr("style"); 622 | 623 | var height = readmeContainer.height(); 624 | var width = readmeContainer.width(); 625 | var left = ($(window).width() - 500)/ 2; 626 | var top = ($(window).height() - 500) / 2; 627 | 628 | var border = readmeContainer.css("border"); 629 | var boxShadow = readmeContainer.css("box-shadow"); 630 | 631 | var contentBorder = itemContent.css("border"); 632 | var contentBoxShadow = itemContent.css("box-shadow"); 633 | 634 | itemContent.children().each(function(index, element){ 635 | $(element).css("visibility", "hidden"); 636 | }); 637 | 638 | readmeContainer.height(0) 639 | .width(0) 640 | .css("top", top + height/2) 641 | .css("left", left + width/2) 642 | .css("visibility", "visible"); 643 | 644 | 645 | readmeContainer.animate({ 646 | height: height, 647 | width: "500px", 648 | left: left, 649 | top: top 650 | 651 | }, 500); 652 | readmeContainer.css({ 653 | opacity: 1 654 | }); 655 | 656 | setTimeout(function(){ 657 | 658 | itemContent.children().each(function(index, element){ 659 | $(element).css("visibility", "visible"); 660 | }); 661 | 662 | 663 | }, 1000); 664 | 665 | } 666 | 667 | function hideReadme(){ 668 | readmeContainer.css("visibility", "hidden"); 669 | readmeContainer.children().each(function(index, element){ 670 | $(element).removeAttr("style"); 671 | $(element).children().each(function(index, element){ 672 | $(element).removeAttr("style"); 673 | }); 674 | }); 675 | } 676 | 677 | function createZipdot(message){ 678 | 679 | var area = "unknown"; 680 | 681 | if(message.latlon){ 682 | area = findArea(message.latlon.lat, message.latlon.lon); 683 | $("#location-city-" + area).text(message.ipinfo.city ? message.ipinfo.city.names.en : ""); 684 | } 685 | 686 | locationAreas[area].count = locationAreas[area].count + 1; 687 | locationAreas[area].count = Math.min(19,locationAreas[area].count); 688 | locationAreas[area].ref.css("background-color", locationAreaColors[locationAreas[area].count]); 689 | 690 | $("#location-slider-" + area + " ul :first-child").css("margin-left", "-=5px"); 691 | $("#location-slider-" + area + " ul").prepend("
  • "); 692 | sliderHeads[area] = {area: area, element: $("#location-slider-" + area + " ul :first-child"), margin: 0}; 693 | 694 | }; 695 | 696 | function changeBlinkies(){ 697 | $(blinkies[Math.floor(Math.random() * blinkies.length)]).css('background-color', blinkiesColors[Math.floor(Math.random() * blinkiesColors.length)]); 698 | } 699 | 700 | function addPic(data){ 701 | var pic = data.picSmall; 702 | var showPic = true; 703 | 704 | if(currentPics.length < 10 || Date.now() - lastPicDate > 2000){ 705 | 706 | if($(mediaBoxes[picIndex]).width() > 100){ 707 | pic = data.picLarge; 708 | } 709 | 710 | for(var i = 0; i< currentPics.length && showPic; i++){ 711 | if(pic.indexOf("http") === 0 && (currentPics[i] == data.picSmall || currentPics[i] == data.picLarge)){ 712 | showPic = false; 713 | } 714 | } 715 | 716 | if(showPic){ 717 | 718 | 719 | 720 | var profileImageLoaded = function(ui){ 721 | var mb = $(mediaBoxes[ui]); 722 | mb.css('background-image', 'url(' + pic + ')'); 723 | mb.find('span').text(data.username); 724 | mb.off(); 725 | mb.click(function(){window.open(data.userurl, "_blank")}); 726 | }; 727 | 728 | if(pic.indexOf("http") === 0){ 729 | var img = document.createElement('img'); 730 | img.addEventListener('load', profileImageLoaded.bind(this, picIndex)); 731 | img.src = pic; 732 | } else { 733 | profileImageLoaded(picIndex); 734 | } 735 | 736 | currentPics[picIndex] = pic; 737 | 738 | picIndex++; 739 | picIndex = picIndex % 10; 740 | 741 | lastPicDate = Date.now(); 742 | 743 | } 744 | } 745 | } 746 | 747 | 748 | function updateSliders(animateTime){ 749 | 750 | var incDistance = Math.floor(200 * animateTime / 1000); 751 | 752 | var rem = []; 753 | for(var s in sliderHeads){ 754 | var slider = sliderHeads[s]; 755 | slider.margin += incDistance; 756 | if(slider.margin > 200){ 757 | rem.push(slider); 758 | } else { 759 | slider.element.css("margin-left", slider.margin + "px"); 760 | } 761 | } 762 | 763 | for(var i = 0; i< rem.length; i++){ 764 | delete sliderHeads[rem[i].area]; 765 | rem[i].element.siblings().remove(); 766 | } 767 | 768 | if(Math.random()<.1){ 769 | $(".location-slider ul").each(function(index, val){ 770 | var ch = $(val).children(); 771 | if(ch.length > 10){ 772 | ch.slice(10-ch.length).remove(); 773 | } 774 | }); 775 | } 776 | } 777 | 778 | function findArea(lat, lng){ 779 | if(lat <= -40){ 780 | return "antarctica"; 781 | } 782 | if(lat > 12 && lng > -180 && lng < -45){ 783 | return "northamerica"; 784 | } 785 | if(lat <= 12 && lat > -40 && lng > -90 && lng < -30){ 786 | return "southamerica"; 787 | } 788 | if(lat < -10 && lng >= 105 && lng <=155){ 789 | return "australia"; 790 | } 791 | if(lat > 20 && lng >= 60 && lng <=160){ 792 | return "asia"; 793 | } 794 | if(lat > 10 && lat < 40 && lng >= 35 && lng <=60){ 795 | return "asia"; 796 | } 797 | if(lat > -40 && lat < 35 && lng >= -20 && lng <=50){ 798 | return "africa"; 799 | } 800 | if(lat >= 35 && lng >= -10 && lng <=40){ 801 | return "europe"; 802 | } 803 | 804 | return "other"; 805 | } 806 | 807 | 808 | function getTime(){ 809 | 810 | var now = moment.duration(moment().diff(startDate)); 811 | //var elapsed = startDate; 812 | 813 | // var mili = Math.floor((elapsed/10) % 100); 814 | var seconds = Math.floor(now.seconds());//Math.floor((elapsed / 1000) % 60); 815 | var minutes = Math.floor(now.minutes());//Math.floor((elapsed / 60000) % 100); 816 | var hours = Math.floor(now.hours());//Math.floor((elapsed / 3600000) % 100); 817 | 818 | return (hours < 10 ? "0":"") + hours + ":" + (minutes < 10 ? "0":"") + minutes + ":" + (seconds< 10? "0": "") + seconds /*+ ":" + (mili < 10? "0" : "") + mili*/; 819 | 820 | } 821 | 822 | function formatYTD(first, last){ 823 | var percentage = 100 * (((last- first) / first) - 1); 824 | var output = percentage.toFixed(1) + "%"; 825 | if(percentage > 0 && percentage < 100){ 826 | output = "+" + output; 827 | } 828 | 829 | return output; 830 | }; 831 | 832 | module.exports = Boardroom; 833 | 834 | -------------------------------------------------------------------------------- /js/github-2013.js: -------------------------------------------------------------------------------- 1 | /* data from the github archive http://githubarchive.org */ 2 | 3 | window.githubHistory = [ 4 | { 5 | "year":2013, 6 | "month":1, 7 | "day":1, 8 | "events":83456 9 | }, 10 | { 11 | "year":2013, 12 | "month":1, 13 | "day":2, 14 | "events":134643 15 | }, 16 | { 17 | "year":2013, 18 | "month":1, 19 | "day":3, 20 | "events":168703 21 | }, 22 | { 23 | "year":2013, 24 | "month":1, 25 | "day":4, 26 | "events":161804 27 | }, 28 | { 29 | "year":2013, 30 | "month":1, 31 | "day":5, 32 | "events":119567 33 | }, 34 | { 35 | "year":2013, 36 | "month":1, 37 | "day":6, 38 | "events":120508 39 | }, 40 | { 41 | "year":2013, 42 | "month":1, 43 | "day":7, 44 | "events":169348 45 | }, 46 | { 47 | "year":2013, 48 | "month":1, 49 | "day":8, 50 | "events":183054 51 | }, 52 | { 53 | "year":2013, 54 | "month":1, 55 | "day":9, 56 | "events":180483 57 | }, 58 | { 59 | "year":2013, 60 | "month":1, 61 | "day":10, 62 | "events":191821 63 | }, 64 | { 65 | "year":2013, 66 | "month":1, 67 | "day":11, 68 | "events":172566 69 | }, 70 | { 71 | "year":2013, 72 | "month":1, 73 | "day":12, 74 | "events":124008 75 | }, 76 | { 77 | "year":2013, 78 | "month":1, 79 | "day":13, 80 | "events":130952 81 | }, 82 | { 83 | "year":2013, 84 | "month":1, 85 | "day":14, 86 | "events":186881 87 | }, 88 | { 89 | "year":2013, 90 | "month":1, 91 | "day":15, 92 | "events":193796 93 | }, 94 | { 95 | "year":2013, 96 | "month":1, 97 | "day":16, 98 | "events":173633 99 | }, 100 | { 101 | "year":2013, 102 | "month":1, 103 | "day":17, 104 | "events":192911 105 | }, 106 | { 107 | "year":2013, 108 | "month":1, 109 | "day":18, 110 | "events":179245 111 | }, 112 | { 113 | "year":2013, 114 | "month":1, 115 | "day":19, 116 | "events":118052 117 | }, 118 | { 119 | "year":2013, 120 | "month":1, 121 | "day":20, 122 | "events":134309 123 | }, 124 | { 125 | "year":2013, 126 | "month":1, 127 | "day":21, 128 | "events":180378 129 | }, 130 | { 131 | "year":2013, 132 | "month":1, 133 | "day":22, 134 | "events":195762 135 | }, 136 | { 137 | "year":2013, 138 | "month":1, 139 | "day":23, 140 | "events":204843 141 | }, 142 | { 143 | "year":2013, 144 | "month":1, 145 | "day":24, 146 | "events":205520 147 | }, 148 | { 149 | "year":2013, 150 | "month":1, 151 | "day":25, 152 | "events":193660 153 | }, 154 | { 155 | "year":2013, 156 | "month":1, 157 | "day":26, 158 | "events":141212 159 | }, 160 | { 161 | "year":2013, 162 | "month":1, 163 | "day":27, 164 | "events":153185 165 | }, 166 | { 167 | "year":2013, 168 | "month":1, 169 | "day":28, 170 | "events":196738 171 | }, 172 | { 173 | "year":2013, 174 | "month":1, 175 | "day":29, 176 | "events":206929 177 | }, 178 | { 179 | "year":2013, 180 | "month":1, 181 | "day":30, 182 | "events":212479 183 | }, 184 | { 185 | "year":2013, 186 | "month":1, 187 | "day":31, 188 | "events":198753 189 | }, 190 | { 191 | "year":2013, 192 | "month":2, 193 | "day":1, 194 | "events":175649 195 | }, 196 | { 197 | "year":2013, 198 | "month":2, 199 | "day":2, 200 | "events":127830 201 | }, 202 | { 203 | "year":2013, 204 | "month":2, 205 | "day":3, 206 | "events":145458 207 | }, 208 | { 209 | "year":2013, 210 | "month":2, 211 | "day":4, 212 | "events":193854 213 | }, 214 | { 215 | "year":2013, 216 | "month":2, 217 | "day":5, 218 | "events":205608 219 | }, 220 | { 221 | "year":2013, 222 | "month":2, 223 | "day":6, 224 | "events":207844 225 | }, 226 | { 227 | "year":2013, 228 | "month":2, 229 | "day":7, 230 | "events":213980 231 | }, 232 | { 233 | "year":2013, 234 | "month":2, 235 | "day":8, 236 | "events":189120 237 | }, 238 | { 239 | "year":2013, 240 | "month":2, 241 | "day":9, 242 | "events":131167 243 | }, 244 | { 245 | "year":2013, 246 | "month":2, 247 | "day":10, 248 | "events":145902 249 | }, 250 | { 251 | "year":2013, 252 | "month":2, 253 | "day":11, 254 | "events":209419 255 | }, 256 | { 257 | "year":2013, 258 | "month":2, 259 | "day":12, 260 | "events":204459 261 | }, 262 | { 263 | "year":2013, 264 | "month":2, 265 | "day":13, 266 | "events":301134 267 | }, 268 | { 269 | "year":2013, 270 | "month":2, 271 | "day":14, 272 | "events":195348 273 | }, 274 | { 275 | "year":2013, 276 | "month":2, 277 | "day":15, 278 | "events":185785 279 | }, 280 | { 281 | "year":2013, 282 | "month":2, 283 | "day":16, 284 | "events":167472 285 | }, 286 | { 287 | "year":2013, 288 | "month":2, 289 | "day":17, 290 | "events":154283 291 | }, 292 | { 293 | "year":2013, 294 | "month":2, 295 | "day":18, 296 | "events":207184 297 | }, 298 | { 299 | "year":2013, 300 | "month":2, 301 | "day":19, 302 | "events":221713 303 | }, 304 | { 305 | "year":2013, 306 | "month":2, 307 | "day":20, 308 | "events":222953 309 | }, 310 | { 311 | "year":2013, 312 | "month":2, 313 | "day":21, 314 | "events":210025 315 | }, 316 | { 317 | "year":2013, 318 | "month":2, 319 | "day":22, 320 | "events":209837 321 | }, 322 | { 323 | "year":2013, 324 | "month":2, 325 | "day":23, 326 | "events":148265 327 | }, 328 | { 329 | "year":2013, 330 | "month":2, 331 | "day":24, 332 | "events":155210 333 | }, 334 | { 335 | "year":2013, 336 | "month":2, 337 | "day":25, 338 | "events":179699 339 | }, 340 | { 341 | "year":2013, 342 | "month":2, 343 | "day":26, 344 | "events":226044 345 | }, 346 | { 347 | "year":2013, 348 | "month":2, 349 | "day":27, 350 | "events":229681 351 | }, 352 | { 353 | "year":2013, 354 | "month":2, 355 | "day":28, 356 | "events":220866 357 | }, 358 | { 359 | "year":2013, 360 | "month":3, 361 | "day":1, 362 | "events":209088 363 | }, 364 | { 365 | "year":2013, 366 | "month":3, 367 | "day":2, 368 | "events":150319 369 | }, 370 | { 371 | "year":2013, 372 | "month":3, 373 | "day":3, 374 | "events":149584 375 | }, 376 | { 377 | "year":2013, 378 | "month":3, 379 | "day":4, 380 | "events":222926 381 | }, 382 | { 383 | "year":2013, 384 | "month":3, 385 | "day":5, 386 | "events":225117 387 | }, 388 | { 389 | "year":2013, 390 | "month":3, 391 | "day":6, 392 | "events":219171 393 | }, 394 | { 395 | "year":2013, 396 | "month":3, 397 | "day":7, 398 | "events":225899 399 | }, 400 | { 401 | "year":2013, 402 | "month":3, 403 | "day":8, 404 | "events":218415 405 | }, 406 | { 407 | "year":2013, 408 | "month":3, 409 | "day":9, 410 | "events":150205 411 | }, 412 | { 413 | "year":2013, 414 | "month":3, 415 | "day":10, 416 | "events":152119 417 | }, 418 | { 419 | "year":2013, 420 | "month":3, 421 | "day":11, 422 | "events":208787 423 | }, 424 | { 425 | "year":2013, 426 | "month":3, 427 | "day":12, 428 | "events":231737 429 | }, 430 | { 431 | "year":2013, 432 | "month":3, 433 | "day":13, 434 | "events":230333 435 | }, 436 | { 437 | "year":2013, 438 | "month":3, 439 | "day":14, 440 | "events":208045 441 | }, 442 | { 443 | "year":2013, 444 | "month":3, 445 | "day":15, 446 | "events":217951 447 | }, 448 | { 449 | "year":2013, 450 | "month":3, 451 | "day":16, 452 | "events":143018 453 | }, 454 | { 455 | "year":2013, 456 | "month":3, 457 | "day":17, 458 | "events":159173 459 | }, 460 | { 461 | "year":2013, 462 | "month":3, 463 | "day":18, 464 | "events":205989 465 | }, 466 | { 467 | "year":2013, 468 | "month":3, 469 | "day":19, 470 | "events":240318 471 | }, 472 | { 473 | "year":2013, 474 | "month":3, 475 | "day":20, 476 | "events":241391 477 | }, 478 | { 479 | "year":2013, 480 | "month":3, 481 | "day":21, 482 | "events":234232 483 | }, 484 | { 485 | "year":2013, 486 | "month":3, 487 | "day":22, 488 | "events":218327 489 | }, 490 | { 491 | "year":2013, 492 | "month":3, 493 | "day":23, 494 | "events":145025 495 | }, 496 | { 497 | "year":2013, 498 | "month":3, 499 | "day":24, 500 | "events":168845 501 | }, 502 | { 503 | "year":2013, 504 | "month":3, 505 | "day":25, 506 | "events":232083 507 | }, 508 | { 509 | "year":2013, 510 | "month":3, 511 | "day":26, 512 | "events":225718 513 | }, 514 | { 515 | "year":2013, 516 | "month":3, 517 | "day":27, 518 | "events":259285 519 | }, 520 | { 521 | "year":2013, 522 | "month":3, 523 | "day":28, 524 | "events":224977 525 | }, 526 | { 527 | "year":2013, 528 | "month":3, 529 | "day":29, 530 | "events":205268 531 | }, 532 | { 533 | "year":2013, 534 | "month":3, 535 | "day":30, 536 | "events":149570 537 | }, 538 | { 539 | "year":2013, 540 | "month":3, 541 | "day":31, 542 | "events":147565 543 | }, 544 | { 545 | "year":2013, 546 | "month":4, 547 | "day":1, 548 | "events":205743 549 | }, 550 | { 551 | "year":2013, 552 | "month":4, 553 | "day":2, 554 | "events":240968 555 | }, 556 | { 557 | "year":2013, 558 | "month":4, 559 | "day":3, 560 | "events":238269 561 | }, 562 | { 563 | "year":2013, 564 | "month":4, 565 | "day":4, 566 | "events":226227 567 | }, 568 | { 569 | "year":2013, 570 | "month":4, 571 | "day":5, 572 | "events":221757 573 | }, 574 | { 575 | "year":2013, 576 | "month":4, 577 | "day":6, 578 | "events":156070 579 | }, 580 | { 581 | "year":2013, 582 | "month":4, 583 | "day":7, 584 | "events":169618 585 | }, 586 | { 587 | "year":2013, 588 | "month":4, 589 | "day":8, 590 | "events":235361 591 | }, 592 | { 593 | "year":2013, 594 | "month":4, 595 | "day":9, 596 | "events":243090 597 | }, 598 | { 599 | "year":2013, 600 | "month":4, 601 | "day":10, 602 | "events":242261 603 | }, 604 | { 605 | "year":2013, 606 | "month":4, 607 | "day":11, 608 | "events":241890 609 | }, 610 | { 611 | "year":2013, 612 | "month":4, 613 | "day":12, 614 | "events":222459 615 | }, 616 | { 617 | "year":2013, 618 | "month":4, 619 | "day":13, 620 | "events":153033 621 | }, 622 | { 623 | "year":2013, 624 | "month":4, 625 | "day":14, 626 | "events":156876 627 | }, 628 | { 629 | "year":2013, 630 | "month":4, 631 | "day":15, 632 | "events":219866 633 | }, 634 | { 635 | "year":2013, 636 | "month":4, 637 | "day":16, 638 | "events":214627 639 | }, 640 | { 641 | "year":2013, 642 | "month":4, 643 | "day":17, 644 | "events":205826 645 | }, 646 | { 647 | "year":2013, 648 | "month":4, 649 | "day":18, 650 | "events":248470 651 | }, 652 | { 653 | "year":2013, 654 | "month":4, 655 | "day":19, 656 | "events":250279 657 | }, 658 | { 659 | "year":2013, 660 | "month":4, 661 | "day":20, 662 | "events":161305 663 | }, 664 | { 665 | "year":2013, 666 | "month":4, 667 | "day":21, 668 | "events":168304 669 | }, 670 | { 671 | "year":2013, 672 | "month":4, 673 | "day":22, 674 | "events":252793 675 | }, 676 | { 677 | "year":2013, 678 | "month":4, 679 | "day":23, 680 | "events":249648 681 | }, 682 | { 683 | "year":2013, 684 | "month":4, 685 | "day":24, 686 | "events":267755 687 | }, 688 | { 689 | "year":2013, 690 | "month":4, 691 | "day":25, 692 | "events":243935 693 | }, 694 | { 695 | "year":2013, 696 | "month":4, 697 | "day":26, 698 | "events":204833 699 | }, 700 | { 701 | "year":2013, 702 | "month":4, 703 | "day":27, 704 | "events":154759 705 | }, 706 | { 707 | "year":2013, 708 | "month":4, 709 | "day":28, 710 | "events":162915 711 | }, 712 | { 713 | "year":2013, 714 | "month":4, 715 | "day":29, 716 | "events":211118 717 | }, 718 | { 719 | "year":2013, 720 | "month":4, 721 | "day":30, 722 | "events":221799 723 | }, 724 | { 725 | "year":2013, 726 | "month":5, 727 | "day":1, 728 | "events":202735 729 | }, 730 | { 731 | "year":2013, 732 | "month":5, 733 | "day":2, 734 | "events":228019 735 | }, 736 | { 737 | "year":2013, 738 | "month":5, 739 | "day":3, 740 | "events":219324 741 | }, 742 | { 743 | "year":2013, 744 | "month":5, 745 | "day":4, 746 | "events":148432 747 | }, 748 | { 749 | "year":2013, 750 | "month":5, 751 | "day":5, 752 | "events":149476 753 | }, 754 | { 755 | "year":2013, 756 | "month":5, 757 | "day":6, 758 | "events":224361 759 | }, 760 | { 761 | "year":2013, 762 | "month":5, 763 | "day":7, 764 | "events":228443 765 | }, 766 | { 767 | "year":2013, 768 | "month":5, 769 | "day":8, 770 | "events":237722 771 | }, 772 | { 773 | "year":2013, 774 | "month":5, 775 | "day":9, 776 | "events":229172 777 | }, 778 | { 779 | "year":2013, 780 | "month":5, 781 | "day":10, 782 | "events":216952 783 | }, 784 | { 785 | "year":2013, 786 | "month":5, 787 | "day":11, 788 | "events":146843 789 | }, 790 | { 791 | "year":2013, 792 | "month":5, 793 | "day":12, 794 | "events":143181 795 | }, 796 | { 797 | "year":2013, 798 | "month":5, 799 | "day":13, 800 | "events":231725 801 | }, 802 | { 803 | "year":2013, 804 | "month":5, 805 | "day":14, 806 | "events":235816 807 | }, 808 | { 809 | "year":2013, 810 | "month":5, 811 | "day":15, 812 | "events":232317 813 | }, 814 | { 815 | "year":2013, 816 | "month":5, 817 | "day":16, 818 | "events":215268 819 | }, 820 | { 821 | "year":2013, 822 | "month":5, 823 | "day":17, 824 | "events":221351 825 | }, 826 | { 827 | "year":2013, 828 | "month":5, 829 | "day":18, 830 | "events":143079 831 | }, 832 | { 833 | "year":2013, 834 | "month":5, 835 | "day":19, 836 | "events":151879 837 | }, 838 | { 839 | "year":2013, 840 | "month":5, 841 | "day":20, 842 | "events":218324 843 | }, 844 | { 845 | "year":2013, 846 | "month":5, 847 | "day":21, 848 | "events":239385 849 | }, 850 | { 851 | "year":2013, 852 | "month":5, 853 | "day":22, 854 | "events":238171 855 | }, 856 | { 857 | "year":2013, 858 | "month":5, 859 | "day":23, 860 | "events":238100 861 | }, 862 | { 863 | "year":2013, 864 | "month":5, 865 | "day":24, 866 | "events":224065 867 | }, 868 | { 869 | "year":2013, 870 | "month":5, 871 | "day":25, 872 | "events":142861 873 | }, 874 | { 875 | "year":2013, 876 | "month":5, 877 | "day":26, 878 | "events":145988 879 | }, 880 | { 881 | "year":2013, 882 | "month":5, 883 | "day":27, 884 | "events":209779 885 | }, 886 | { 887 | "year":2013, 888 | "month":5, 889 | "day":28, 890 | "events":238637 891 | }, 892 | { 893 | "year":2013, 894 | "month":5, 895 | "day":29, 896 | "events":240536 897 | }, 898 | { 899 | "year":2013, 900 | "month":5, 901 | "day":30, 902 | "events":231312 903 | }, 904 | { 905 | "year":2013, 906 | "month":5, 907 | "day":31, 908 | "events":218667 909 | }, 910 | { 911 | "year":2013, 912 | "month":6, 913 | "day":1, 914 | "events":141688 915 | }, 916 | { 917 | "year":2013, 918 | "month":6, 919 | "day":2, 920 | "events":153603 921 | }, 922 | { 923 | "year":2013, 924 | "month":6, 925 | "day":3, 926 | "events":236253 927 | }, 928 | { 929 | "year":2013, 930 | "month":6, 931 | "day":4, 932 | "events":243778 933 | }, 934 | { 935 | "year":2013, 936 | "month":6, 937 | "day":5, 938 | "events":244404 939 | }, 940 | { 941 | "year":2013, 942 | "month":6, 943 | "day":6, 944 | "events":242000 945 | }, 946 | { 947 | "year":2013, 948 | "month":6, 949 | "day":7, 950 | "events":223382 951 | }, 952 | { 953 | "year":2013, 954 | "month":6, 955 | "day":8, 956 | "events":143375 957 | }, 958 | { 959 | "year":2013, 960 | "month":6, 961 | "day":9, 962 | "events":152442 963 | }, 964 | { 965 | "year":2013, 966 | "month":6, 967 | "day":10, 968 | "events":218484 969 | }, 970 | { 971 | "year":2013, 972 | "month":6, 973 | "day":11, 974 | "events":222404 975 | }, 976 | { 977 | "year":2013, 978 | "month":6, 979 | "day":12, 980 | "events":228074 981 | }, 982 | { 983 | "year":2013, 984 | "month":6, 985 | "day":13, 986 | "events":242675 987 | }, 988 | { 989 | "year":2013, 990 | "month":6, 991 | "day":14, 992 | "events":217255 993 | }, 994 | { 995 | "year":2013, 996 | "month":6, 997 | "day":15, 998 | "events":137355 999 | }, 1000 | { 1001 | "year":2013, 1002 | "month":6, 1003 | "day":16, 1004 | "events":142723 1005 | }, 1006 | { 1007 | "year":2013, 1008 | "month":6, 1009 | "day":17, 1010 | "events":226952 1011 | }, 1012 | { 1013 | "year":2013, 1014 | "month":6, 1015 | "day":18, 1016 | "events":246688 1017 | }, 1018 | { 1019 | "year":2013, 1020 | "month":6, 1021 | "day":19, 1022 | "events":234076 1023 | }, 1024 | { 1025 | "year":2013, 1026 | "month":6, 1027 | "day":20, 1028 | "events":238165 1029 | }, 1030 | { 1031 | "year":2013, 1032 | "month":6, 1033 | "day":21, 1034 | "events":223296 1035 | }, 1036 | { 1037 | "year":2013, 1038 | "month":6, 1039 | "day":22, 1040 | "events":154365 1041 | }, 1042 | { 1043 | "year":2013, 1044 | "month":6, 1045 | "day":23, 1046 | "events":162192 1047 | }, 1048 | { 1049 | "year":2013, 1050 | "month":6, 1051 | "day":24, 1052 | "events":232367 1053 | }, 1054 | { 1055 | "year":2013, 1056 | "month":6, 1057 | "day":25, 1058 | "events":266228 1059 | }, 1060 | { 1061 | "year":2013, 1062 | "month":6, 1063 | "day":26, 1064 | "events":257701 1065 | }, 1066 | { 1067 | "year":2013, 1068 | "month":6, 1069 | "day":27, 1070 | "events":266304 1071 | }, 1072 | { 1073 | "year":2013, 1074 | "month":6, 1075 | "day":28, 1076 | "events":231117 1077 | }, 1078 | { 1079 | "year":2013, 1080 | "month":6, 1081 | "day":29, 1082 | "events":149362 1083 | }, 1084 | { 1085 | "year":2013, 1086 | "month":6, 1087 | "day":30, 1088 | "events":149774 1089 | }, 1090 | { 1091 | "year":2013, 1092 | "month":7, 1093 | "day":1, 1094 | "events":231918 1095 | }, 1096 | { 1097 | "year":2013, 1098 | "month":7, 1099 | "day":2, 1100 | "events":234755 1101 | }, 1102 | { 1103 | "year":2013, 1104 | "month":7, 1105 | "day":3, 1106 | "events":242278 1107 | }, 1108 | { 1109 | "year":2013, 1110 | "month":7, 1111 | "day":4, 1112 | "events":212751 1113 | }, 1114 | { 1115 | "year":2013, 1116 | "month":7, 1117 | "day":5, 1118 | "events":212736 1119 | }, 1120 | { 1121 | "year":2013, 1122 | "month":7, 1123 | "day":6, 1124 | "events":144648 1125 | }, 1126 | { 1127 | "year":2013, 1128 | "month":7, 1129 | "day":7, 1130 | "events":142869 1131 | }, 1132 | { 1133 | "year":2013, 1134 | "month":7, 1135 | "day":8, 1136 | "events":235064 1137 | }, 1138 | { 1139 | "year":2013, 1140 | "month":7, 1141 | "day":9, 1142 | "events":259842 1143 | }, 1144 | { 1145 | "year":2013, 1146 | "month":7, 1147 | "day":10, 1148 | "events":268243 1149 | }, 1150 | { 1151 | "year":2013, 1152 | "month":7, 1153 | "day":11, 1154 | "events":252420 1155 | }, 1156 | { 1157 | "year":2013, 1158 | "month":7, 1159 | "day":12, 1160 | "events":234047 1161 | }, 1162 | { 1163 | "year":2013, 1164 | "month":7, 1165 | "day":13, 1166 | "events":144598 1167 | }, 1168 | { 1169 | "year":2013, 1170 | "month":7, 1171 | "day":14, 1172 | "events":152796 1173 | }, 1174 | { 1175 | "year":2013, 1176 | "month":7, 1177 | "day":15, 1178 | "events":251897 1179 | }, 1180 | { 1181 | "year":2013, 1182 | "month":7, 1183 | "day":16, 1184 | "events":255420 1185 | }, 1186 | { 1187 | "year":2013, 1188 | "month":7, 1189 | "day":17, 1190 | "events":256590 1191 | }, 1192 | { 1193 | "year":2013, 1194 | "month":7, 1195 | "day":18, 1196 | "events":255113 1197 | }, 1198 | { 1199 | "year":2013, 1200 | "month":7, 1201 | "day":19, 1202 | "events":235825 1203 | }, 1204 | { 1205 | "year":2013, 1206 | "month":7, 1207 | "day":20, 1208 | "events":142873 1209 | }, 1210 | { 1211 | "year":2013, 1212 | "month":7, 1213 | "day":21, 1214 | "events":148951 1215 | }, 1216 | { 1217 | "year":2013, 1218 | "month":7, 1219 | "day":22, 1220 | "events":216164 1221 | }, 1222 | { 1223 | "year":2013, 1224 | "month":7, 1225 | "day":23, 1226 | "events":258683 1227 | }, 1228 | { 1229 | "year":2013, 1230 | "month":7, 1231 | "day":24, 1232 | "events":240745 1233 | }, 1234 | { 1235 | "year":2013, 1236 | "month":7, 1237 | "day":25, 1238 | "events":249559 1239 | }, 1240 | { 1241 | "year":2013, 1242 | "month":7, 1243 | "day":26, 1244 | "events":236111 1245 | }, 1246 | { 1247 | "year":2013, 1248 | "month":7, 1249 | "day":27, 1250 | "events":150640 1251 | }, 1252 | { 1253 | "year":2013, 1254 | "month":7, 1255 | "day":28, 1256 | "events":152441 1257 | }, 1258 | { 1259 | "year":2013, 1260 | "month":7, 1261 | "day":29, 1262 | "events":232659 1263 | }, 1264 | { 1265 | "year":2013, 1266 | "month":7, 1267 | "day":30, 1268 | "events":258301 1269 | }, 1270 | { 1271 | "year":2013, 1272 | "month":7, 1273 | "day":31, 1274 | "events":253814 1275 | }, 1276 | { 1277 | "year":2013, 1278 | "month":8, 1279 | "day":1, 1280 | "events":246335 1281 | }, 1282 | { 1283 | "year":2013, 1284 | "month":8, 1285 | "day":2, 1286 | "events":231448 1287 | }, 1288 | { 1289 | "year":2013, 1290 | "month":8, 1291 | "day":3, 1292 | "events":154674 1293 | }, 1294 | { 1295 | "year":2013, 1296 | "month":8, 1297 | "day":4, 1298 | "events":153852 1299 | }, 1300 | { 1301 | "year":2013, 1302 | "month":8, 1303 | "day":5, 1304 | "events":243318 1305 | }, 1306 | { 1307 | "year":2013, 1308 | "month":8, 1309 | "day":6, 1310 | "events":269089 1311 | }, 1312 | { 1313 | "year":2013, 1314 | "month":8, 1315 | "day":7, 1316 | "events":236476 1317 | }, 1318 | { 1319 | "year":2013, 1320 | "month":8, 1321 | "day":8, 1322 | "events":253242 1323 | }, 1324 | { 1325 | "year":2013, 1326 | "month":8, 1327 | "day":9, 1328 | "events":234484 1329 | }, 1330 | { 1331 | "year":2013, 1332 | "month":8, 1333 | "day":10, 1334 | "events":157174 1335 | }, 1336 | { 1337 | "year":2013, 1338 | "month":8, 1339 | "day":11, 1340 | "events":152980 1341 | }, 1342 | { 1343 | "year":2013, 1344 | "month":8, 1345 | "day":12, 1346 | "events":234129 1347 | }, 1348 | { 1349 | "year":2013, 1350 | "month":8, 1351 | "day":13, 1352 | "events":260370 1353 | }, 1354 | { 1355 | "year":2013, 1356 | "month":8, 1357 | "day":14, 1358 | "events":252631 1359 | }, 1360 | { 1361 | "year":2013, 1362 | "month":8, 1363 | "day":15, 1364 | "events":202729 1365 | }, 1366 | { 1367 | "year":2013, 1368 | "month":8, 1369 | "day":16, 1370 | "events":215547 1371 | }, 1372 | { 1373 | "year":2013, 1374 | "month":8, 1375 | "day":17, 1376 | "events":158466 1377 | }, 1378 | { 1379 | "year":2013, 1380 | "month":8, 1381 | "day":18, 1382 | "events":170507 1383 | }, 1384 | { 1385 | "year":2013, 1386 | "month":8, 1387 | "day":19, 1388 | "events":261967 1389 | }, 1390 | { 1391 | "year":2013, 1392 | "month":8, 1393 | "day":20, 1394 | "events":261230 1395 | }, 1396 | { 1397 | "year":2013, 1398 | "month":8, 1399 | "day":21, 1400 | "events":274227 1401 | }, 1402 | { 1403 | "year":2013, 1404 | "month":8, 1405 | "day":22, 1406 | "events":270025 1407 | }, 1408 | { 1409 | "year":2013, 1410 | "month":8, 1411 | "day":23, 1412 | "events":247083 1413 | }, 1414 | { 1415 | "year":2013, 1416 | "month":8, 1417 | "day":24, 1418 | "events":163550 1419 | }, 1420 | { 1421 | "year":2013, 1422 | "month":8, 1423 | "day":25, 1424 | "events":168466 1425 | }, 1426 | { 1427 | "year":2013, 1428 | "month":8, 1429 | "day":26, 1430 | "events":250058 1431 | }, 1432 | { 1433 | "year":2013, 1434 | "month":8, 1435 | "day":27, 1436 | "events":273251 1437 | }, 1438 | { 1439 | "year":2013, 1440 | "month":8, 1441 | "day":28, 1442 | "events":271072 1443 | }, 1444 | { 1445 | "year":2013, 1446 | "month":8, 1447 | "day":29, 1448 | "events":268425 1449 | }, 1450 | { 1451 | "year":2013, 1452 | "month":8, 1453 | "day":30, 1454 | "events":234812 1455 | }, 1456 | { 1457 | "year":2013, 1458 | "month":8, 1459 | "day":31, 1460 | "events":154760 1461 | }, 1462 | { 1463 | "year":2013, 1464 | "month":9, 1465 | "day":1, 1466 | "events":161903 1467 | }, 1468 | { 1469 | "year":2013, 1470 | "month":9, 1471 | "day":2, 1472 | "events":227648 1473 | }, 1474 | { 1475 | "year":2013, 1476 | "month":9, 1477 | "day":3, 1478 | "events":267082 1479 | }, 1480 | { 1481 | "year":2013, 1482 | "month":9, 1483 | "day":4, 1484 | "events":106917 1485 | }, 1486 | { 1487 | "year":2013, 1488 | "month":9, 1489 | "day":6, 1490 | "events":203485 1491 | }, 1492 | { 1493 | "year":2013, 1494 | "month":9, 1495 | "day":7, 1496 | "events":185266 1497 | }, 1498 | { 1499 | "year":2013, 1500 | "month":9, 1501 | "day":8, 1502 | "events":178420 1503 | }, 1504 | { 1505 | "year":2013, 1506 | "month":9, 1507 | "day":9, 1508 | "events":288342 1509 | }, 1510 | { 1511 | "year":2013, 1512 | "month":9, 1513 | "day":10, 1514 | "events":259633 1515 | }, 1516 | { 1517 | "year":2013, 1518 | "month":9, 1519 | "day":11, 1520 | "events":279871 1521 | }, 1522 | { 1523 | "year":2013, 1524 | "month":9, 1525 | "day":12, 1526 | "events":268658 1527 | }, 1528 | { 1529 | "year":2013, 1530 | "month":9, 1531 | "day":13, 1532 | "events":254576 1533 | }, 1534 | { 1535 | "year":2013, 1536 | "month":9, 1537 | "day":14, 1538 | "events":174814 1539 | }, 1540 | { 1541 | "year":2013, 1542 | "month":9, 1543 | "day":15, 1544 | "events":175866 1545 | }, 1546 | { 1547 | "year":2013, 1548 | "month":9, 1549 | "day":16, 1550 | "events":270177 1551 | }, 1552 | { 1553 | "year":2013, 1554 | "month":9, 1555 | "day":17, 1556 | "events":273932 1557 | }, 1558 | { 1559 | "year":2013, 1560 | "month":9, 1561 | "day":18, 1562 | "events":268243 1563 | }, 1564 | { 1565 | "year":2013, 1566 | "month":9, 1567 | "day":19, 1568 | "events":215770 1569 | }, 1570 | { 1571 | "year":2013, 1572 | "month":9, 1573 | "day":20, 1574 | "events":223172 1575 | }, 1576 | { 1577 | "year":2013, 1578 | "month":9, 1579 | "day":21, 1580 | "events":176997 1581 | }, 1582 | { 1583 | "year":2013, 1584 | "month":9, 1585 | "day":22, 1586 | "events":181854 1587 | }, 1588 | { 1589 | "year":2013, 1590 | "month":9, 1591 | "day":23, 1592 | "events":264768 1593 | }, 1594 | { 1595 | "year":2013, 1596 | "month":9, 1597 | "day":24, 1598 | "events":289860 1599 | }, 1600 | { 1601 | "year":2013, 1602 | "month":9, 1603 | "day":25, 1604 | "events":271239 1605 | }, 1606 | { 1607 | "year":2013, 1608 | "month":9, 1609 | "day":26, 1610 | "events":273982 1611 | }, 1612 | { 1613 | "year":2013, 1614 | "month":9, 1615 | "day":27, 1616 | "events":256392 1617 | }, 1618 | { 1619 | "year":2013, 1620 | "month":9, 1621 | "day":28, 1622 | "events":179681 1623 | }, 1624 | { 1625 | "year":2013, 1626 | "month":9, 1627 | "day":29, 1628 | "events":192917 1629 | }, 1630 | { 1631 | "year":2013, 1632 | "month":9, 1633 | "day":30, 1634 | "events":290012 1635 | }, 1636 | { 1637 | "year":2013, 1638 | "month":10, 1639 | "day":1, 1640 | "events":272149 1641 | }, 1642 | { 1643 | "year":2013, 1644 | "month":10, 1645 | "day":2, 1646 | "events":288063 1647 | }, 1648 | { 1649 | "year":2013, 1650 | "month":10, 1651 | "day":3, 1652 | "events":278572 1653 | }, 1654 | { 1655 | "year":2013, 1656 | "month":10, 1657 | "day":4, 1658 | "events":285491 1659 | }, 1660 | { 1661 | "year":2013, 1662 | "month":10, 1663 | "day":5, 1664 | "events":190447 1665 | }, 1666 | { 1667 | "year":2013, 1668 | "month":10, 1669 | "day":6, 1670 | "events":203652 1671 | }, 1672 | { 1673 | "year":2013, 1674 | "month":10, 1675 | "day":7, 1676 | "events":273351 1677 | }, 1678 | { 1679 | "year":2013, 1680 | "month":10, 1681 | "day":8, 1682 | "events":288878 1683 | }, 1684 | { 1685 | "year":2013, 1686 | "month":10, 1687 | "day":9, 1688 | "events":290023 1689 | }, 1690 | { 1691 | "year":2013, 1692 | "month":10, 1693 | "day":10, 1694 | "events":294181 1695 | }, 1696 | { 1697 | "year":2013, 1698 | "month":10, 1699 | "day":11, 1700 | "events":291969 1701 | }, 1702 | { 1703 | "year":2013, 1704 | "month":10, 1705 | "day":12, 1706 | "events":188903 1707 | }, 1708 | { 1709 | "year":2013, 1710 | "month":10, 1711 | "day":13, 1712 | "events":181515 1713 | }, 1714 | { 1715 | "year":2013, 1716 | "month":10, 1717 | "day":14, 1718 | "events":271324 1719 | }, 1720 | { 1721 | "year":2013, 1722 | "month":10, 1723 | "day":15, 1724 | "events":296266 1725 | }, 1726 | { 1727 | "year":2013, 1728 | "month":10, 1729 | "day":16, 1730 | "events":301759 1731 | }, 1732 | { 1733 | "year":2013, 1734 | "month":10, 1735 | "day":17, 1736 | "events":314404 1737 | }, 1738 | { 1739 | "year":2013, 1740 | "month":10, 1741 | "day":18, 1742 | "events":281653 1743 | }, 1744 | { 1745 | "year":2013, 1746 | "month":10, 1747 | "day":19, 1748 | "events":184262 1749 | }, 1750 | { 1751 | "year":2013, 1752 | "month":10, 1753 | "day":20, 1754 | "events":198603 1755 | }, 1756 | { 1757 | "year":2013, 1758 | "month":10, 1759 | "day":21, 1760 | "events":295580 1761 | }, 1762 | { 1763 | "year":2013, 1764 | "month":10, 1765 | "day":22, 1766 | "events":303547 1767 | }, 1768 | { 1769 | "year":2013, 1770 | "month":10, 1771 | "day":23, 1772 | "events":305046 1773 | }, 1774 | { 1775 | "year":2013, 1776 | "month":10, 1777 | "day":24, 1778 | "events":289157 1779 | }, 1780 | { 1781 | "year":2013, 1782 | "month":10, 1783 | "day":25, 1784 | "events":293859 1785 | }, 1786 | { 1787 | "year":2013, 1788 | "month":10, 1789 | "day":26, 1790 | "events":189477 1791 | }, 1792 | { 1793 | "year":2013, 1794 | "month":10, 1795 | "day":27, 1796 | "events":201662 1797 | }, 1798 | { 1799 | "year":2013, 1800 | "month":10, 1801 | "day":28, 1802 | "events":312417 1803 | }, 1804 | { 1805 | "year":2013, 1806 | "month":10, 1807 | "day":29, 1808 | "events":316077 1809 | }, 1810 | { 1811 | "year":2013, 1812 | "month":10, 1813 | "day":30, 1814 | "events":327472 1815 | }, 1816 | { 1817 | "year":2013, 1818 | "month":10, 1819 | "day":31, 1820 | "events":313236 1821 | }, 1822 | { 1823 | "year":2013, 1824 | "month":11, 1825 | "day":1, 1826 | "events":267167 1827 | }, 1828 | { 1829 | "year":2013, 1830 | "month":11, 1831 | "day":2, 1832 | "events":197198 1833 | }, 1834 | { 1835 | "year":2013, 1836 | "month":11, 1837 | "day":3, 1838 | "events":201452 1839 | }, 1840 | { 1841 | "year":2013, 1842 | "month":11, 1843 | "day":4, 1844 | "events":284385 1845 | }, 1846 | { 1847 | "year":2013, 1848 | "month":11, 1849 | "day":5, 1850 | "events":287854 1851 | }, 1852 | { 1853 | "year":2013, 1854 | "month":11, 1855 | "day":6, 1856 | "events":332291 1857 | }, 1858 | { 1859 | "year":2013, 1860 | "month":11, 1861 | "day":7, 1862 | "events":320494 1863 | }, 1864 | { 1865 | "year":2013, 1866 | "month":11, 1867 | "day":8, 1868 | "events":298466 1869 | }, 1870 | { 1871 | "year":2013, 1872 | "month":11, 1873 | "day":9, 1874 | "events":209209 1875 | }, 1876 | { 1877 | "year":2013, 1878 | "month":11, 1879 | "day":10, 1880 | "events":217257 1881 | }, 1882 | { 1883 | "year":2013, 1884 | "month":11, 1885 | "day":11, 1886 | "events":304134 1887 | }, 1888 | { 1889 | "year":2013, 1890 | "month":11, 1891 | "day":12, 1892 | "events":328830 1893 | }, 1894 | { 1895 | "year":2013, 1896 | "month":11, 1897 | "day":13, 1898 | "events":318766 1899 | }, 1900 | { 1901 | "year":2013, 1902 | "month":11, 1903 | "day":14, 1904 | "events":373716 1905 | }, 1906 | { 1907 | "year":2013, 1908 | "month":11, 1909 | "day":15, 1910 | "events":302264 1911 | }, 1912 | { 1913 | "year":2013, 1914 | "month":11, 1915 | "day":16, 1916 | "events":198767 1917 | }, 1918 | { 1919 | "year":2013, 1920 | "month":11, 1921 | "day":17, 1922 | "events":218236 1923 | }, 1924 | { 1925 | "year":2013, 1926 | "month":11, 1927 | "day":18, 1928 | "events":325322 1929 | }, 1930 | { 1931 | "year":2013, 1932 | "month":11, 1933 | "day":19, 1934 | "events":353611 1935 | }, 1936 | { 1937 | "year":2013, 1938 | "month":11, 1939 | "day":20, 1940 | "events":333544 1941 | }, 1942 | { 1943 | "year":2013, 1944 | "month":11, 1945 | "day":21, 1946 | "events":332447 1947 | }, 1948 | { 1949 | "year":2013, 1950 | "month":11, 1951 | "day":22, 1952 | "events":310739 1953 | }, 1954 | { 1955 | "year":2013, 1956 | "month":11, 1957 | "day":23, 1958 | "events":199522 1959 | }, 1960 | { 1961 | "year":2013, 1962 | "month":11, 1963 | "day":24, 1964 | "events":208291 1965 | }, 1966 | { 1967 | "year":2013, 1968 | "month":11, 1969 | "day":25, 1970 | "events":308541 1971 | }, 1972 | { 1973 | "year":2013, 1974 | "month":11, 1975 | "day":26, 1976 | "events":333828 1977 | }, 1978 | { 1979 | "year":2013, 1980 | "month":11, 1981 | "day":27, 1982 | "events":311114 1983 | }, 1984 | { 1985 | "year":2013, 1986 | "month":11, 1987 | "day":28, 1988 | "events":268121 1989 | }, 1990 | { 1991 | "year":2013, 1992 | "month":11, 1993 | "day":29, 1994 | "events":240725 1995 | }, 1996 | { 1997 | "year":2013, 1998 | "month":11, 1999 | "day":30, 2000 | "events":185625 2001 | }, 2002 | { 2003 | "year":2013, 2004 | "month":12, 2005 | "day":1, 2006 | "events":198824 2007 | }, 2008 | { 2009 | "year":2013, 2010 | "month":12, 2011 | "day":2, 2012 | "events":317636 2013 | }, 2014 | { 2015 | "year":2013, 2016 | "month":12, 2017 | "day":3, 2018 | "events":330791 2019 | }, 2020 | { 2021 | "year":2013, 2022 | "month":12, 2023 | "day":4, 2024 | "events":333531 2025 | }, 2026 | { 2027 | "year":2013, 2028 | "month":12, 2029 | "day":5, 2030 | "events":323850 2031 | }, 2032 | { 2033 | "year":2013, 2034 | "month":12, 2035 | "day":6, 2036 | "events":311232 2037 | }, 2038 | { 2039 | "year":2013, 2040 | "month":12, 2041 | "day":7, 2042 | "events":207124 2043 | }, 2044 | { 2045 | "year":2013, 2046 | "month":12, 2047 | "day":8, 2048 | "events":213241 2049 | }, 2050 | { 2051 | "year":2013, 2052 | "month":12, 2053 | "day":9, 2054 | "events":321263 2055 | }, 2056 | { 2057 | "year":2013, 2058 | "month":12, 2059 | "day":10, 2060 | "events":339604 2061 | }, 2062 | { 2063 | "year":2013, 2064 | "month":12, 2065 | "day":11, 2066 | "events":322104 2067 | }, 2068 | { 2069 | "year":2013, 2070 | "month":12, 2071 | "day":12, 2072 | "events":318806 2073 | }, 2074 | { 2075 | "year":2013, 2076 | "month":12, 2077 | "day":13, 2078 | "events":287724 2079 | }, 2080 | { 2081 | "year":2013, 2082 | "month":12, 2083 | "day":14, 2084 | "events":211850 2085 | }, 2086 | { 2087 | "year":2013, 2088 | "month":12, 2089 | "day":15, 2090 | "events":207318 2091 | }, 2092 | { 2093 | "year":2013, 2094 | "month":12, 2095 | "day":16, 2096 | "events":301496 2097 | }, 2098 | { 2099 | "year":2013, 2100 | "month":12, 2101 | "day":17, 2102 | "events":297312 2103 | }, 2104 | { 2105 | "year":2013, 2106 | "month":12, 2107 | "day":18, 2108 | "events":310718 2109 | }, 2110 | { 2111 | "year":2013, 2112 | "month":12, 2113 | "day":19, 2114 | "events":310390 2115 | }, 2116 | { 2117 | "year":2013, 2118 | "month":12, 2119 | "day":20, 2120 | "events":271868 2121 | }, 2122 | { 2123 | "year":2013, 2124 | "month":12, 2125 | "day":21, 2126 | "events":167784 2127 | }, 2128 | { 2129 | "year":2013, 2130 | "month":12, 2131 | "day":22, 2132 | "events":174100 2133 | }, 2134 | { 2135 | "year":2013, 2136 | "month":12, 2137 | "day":23, 2138 | "events":228551 2139 | }, 2140 | { 2141 | "year":2013, 2142 | "month":12, 2143 | "day":24, 2144 | "events":189114 2145 | }, 2146 | { 2147 | "year":2013, 2148 | "month":12, 2149 | "day":25, 2150 | "events":143946 2151 | }, 2152 | { 2153 | "year":2013, 2154 | "month":12, 2155 | "day":26, 2156 | "events":190690 2157 | }, 2158 | { 2159 | "year":2013, 2160 | "month":12, 2161 | "day":27, 2162 | "events":215008 2163 | }, 2164 | { 2165 | "year":2013, 2166 | "month":12, 2167 | "day":28, 2168 | "events":169861 2169 | }, 2170 | { 2171 | "year":2013, 2172 | "month":12, 2173 | "day":29, 2174 | "events":176488 2175 | }, 2176 | { 2177 | "year":2013, 2178 | "month":12, 2179 | "day":30, 2180 | "events":229294 2181 | }, 2182 | { 2183 | "year":2013, 2184 | "month":12, 2185 | "day":31, 2186 | "events":195902 2187 | } 2188 | ] 2189 | --------------------------------------------------------------------------------