<commit_before>var Window          = require('pex-sys/Window');
var PerspCamera     = require('pex-cam/PerspCamera');
var Arcball         = require('pex-cam/Arcball');
var createCube      = require('primitive-cube');
var glslify         = require('glslify-promise');
var isBrowser       = require('is-browser');
var random          = require('pex-random')
var fx              = require('pex-fx')
var SSAOv2          = require('./SSAO')
var Vec3            = require('pex-math/Vec3')
var MathUtils       = require('pex-math/Utils')
var R               = require('ramda')
var GUI             = require('pex-gui')
var glslifySync     = require('glslify-sync')
var fs              = require('fs')

var MAX_DEPTH = 20

function divide(parent, rects) {
    rects.push(parent);

    var depth = parent[4]

    var shouldDivide = random.chance(0.1 + 1/(depth*0.5+1));
    if (depth <= 1) {
        shouldDivide = true
    }

    if (depth >= MAX_DEPTH || !shouldDivide) {
        return rects
    }

    var numDivisions = random.int(2, 5)
    var horizontal = random.chance(0.5);
    if (depth == 0) horizontal = false;
    if (depth == 1) horizontal = true;

    for(var i=0; i<numDivisions; i++) {
        var child = null
        if (horizontal) {
            child = [
                parent[0] + parent[2] * i * 1 / numDivisions,
                parent[1],
                parent[2] * 1 / numDivisions,
                parent[3],
                depth + 1
            ]
        }
        else {
            child = [
                parent[0],
                parent[1] + parent[3] * i * 1 / numDivisions,
                parent[2],
                parent[3] * 1 / numDivisions,
                depth + 1
            ]
        }
        var offset = 0.002;
        child[0] += offset
        child[1] += offset
        child[2] -= 2*offset
        child[3] -= 2*offset
        divide(child, rects)
    }
    return rects
}

Window.create({
    settings: {
        width:  1280,
        height: 720,
        fullScreen: isBrowser ? true : false
    },
    resources: {
        showNormalsVert: { glsl: glslify(__dirname + '/assets/ShowNormals.vert') },
        showNormalsFrag: { glsl: glslify(__dirname + '/assets/ShowNormals.frag') },
        solidColorVert: { glsl: glslify(__dirname + '/assets/SolidColor.vert') },
        solidColorFrag: { glsl: glslify(__dirname + '/assets/SolidColor.frag') },
    },
    init: function() {
        var ctx = this.getContext();
        var res = this.getResources();

        this.gui = new GUI(ctx, this.getWidth(), this.getHeight())

        random.seed(1)

        var ssaoKernel = [];
        for(var i=0; i<64; i++) {
            var sample = [
                random.float() * 2 - 1,
                random.float() * 2 - 1,
                random.float() * 2 - 1,
                1
            ]
            Vec3.normalize(sample)
            var scale = random.float()
            scale = MathUtils.lerp(0.1, 1.0, scale * scale);
            Vec3.scale(sample, scale)
            ssaoKernel.push(sample)
        }
        var ssaoKernelData = new Float32Array(R.flatten(ssaoKernel))

        var ssaoNoise = [];
        for(var i=0; i<64; i++) {
            var sample = [
                random.float() * 2 - 1,
                random.float() * 2 - 1,
                0,
                1
            ]
            ssaoNoise.push(sample)
        }
        var ssaoNoiseData = new Float32Array(R.flatten(ssaoNoise))

        this.depthMap = ctx.createTexture2D(null, this.getWidth(), this.getHeight(), { format: ctx.DEPTH_COMPONENT, type: ctx.UNSIGNED_SHORT });
        this.ssaoKernelMap = ctx.createTexture2D(ssaoKernelData, 8, 8, { format: ctx.RGBA, type: ctx.FLOAT, minFilter: ctx.NEAREST, magFilter: ctx.NEAREST, repeat: true });
        this.ssaoNoiseMap = ctx.createTexture2D(ssaoNoiseData, 4, 4, { format: ctx.RGBA, type: ctx.FLOAT, minFilter: ctx.NEAREST, magFilter: ctx.NEAREST, repeat: true });
        //this.rects = divide([-1, -0.5, 2, 1, 0], [])
        this.rects = divide([-2, -1, 4, 2, 0], [])
        this.rects.forEach(function(rect) {
            if (rect[4] <= 2) rect.push([0,1,0.5,1])
        })

        this.camera  = new PerspCamera(45,this.getAspectRatio(), 0.1, 10.0);
        this.camera.lookAt([0, 1, 3], [0, 0, 0]);
        ctx.setProjectionMatrix(this.camera.getProjectionMatrix());

        this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight());
        this.arcball.setDistance(3.0);
        this.addEventListener(this.arcball);

        this.showNormalsProgram = ctx.createProgram(res.showNormalsVert, res.showNormalsFrag);
        ctx.bindProgram(this.showNormalsProgram);

        this.solidColorProgram = ctx.createProgram(res.solidColorVert, res.solidColorFrag);
        ctx.bindProgram(this.solidColorProgram);

        var cube = createCube();
        var cubeAttributes = [
            { data: cube.positions, location: ctx.ATTRIB_POSITION },
            { data: cube.normals, location: ctx.ATTRIB_NORMAL }
        ];
        var cubeIndices = { data: cube.cells };
        this.cubeMesh = ctx.createMesh(cubeAttributes, cubeIndices, ctx.TRIANGLES);

        var cubeWireIndices = { data: cube.cells };
        this.cubeWireMesh = ctx.createMesh(cubeAttributes, cubeWireIndices, ctx.LINES);

        this.fx = fx(ctx)

        this.gui.addHeader('Settings')
        this.gui.addTexture2D('Kernel', this.ssaoKernelMap)
        this.gui.addTexture2D('Noise', this.ssaoNoiseMap)

        var prevCode = '';
        var shaderFile = __dirname + '/SSAO.frag';
        var vert = fs.readFileSync(__dirname + '/ScreenImage.vert', 'utf8');
        fs.watch(shaderFile, { persistent: true, recursive: false }, function(e, filename) {
            var frag = fs.readFileSync(shaderFile, 'utf8');
            if (frag != prevCode) {
                try {
                    console.log('COMPILE >>>> ')
                    var prop = ctx.createProgram(vert, frag)
                    prop.dispose()
                    this.fx.ssao.updateFrag(frag)
                }
                catch(e) {
                    console.log(e)
                }
            }
            prevCode = frag;
        }.bind(this));
    },
    drawScene: function() {
        var ctx = this.getContext()
        ctx.setClearColor(1, 0.2, 0.2, 1);
        ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT);
        ctx.setDepthTest(true);

        var levelHeight = 0.04;
        ctx.bindProgram(this.solidColorProgram);
        ctx.setLineWidth(2)
        this.rects.forEach(function(rect) {
            ctx.pushModelMatrix()
            ctx.translate([rect[0] + rect[2]/2, levelHeight*(1+rect[4])/2, rect[1] + rect[3]/2])
            ctx.scale([rect[2], levelHeight*(1+rect[4]), rect[3]])
            this.solidColorProgram.setUniform('uColor', rect[5] || [1,1,1,1])
            ctx.bindMesh(this.cubeMesh);
            ctx.drawMesh();
            this.solidColorProgram.setUniform('uColor', [0.5,0.5,0.5,1])
            ctx.bindMesh(this.cubeWireMesh);
            ctx.drawMesh();
            ctx.popModelMatrix()
        }.bind(this))
    },
    drawSceneNormals: function() {
        var ctx = this.getContext()
        ctx.setClearColor(1, 0.2, 0.2, 1);
        ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT);
        ctx.setDepthTest(true);

        var levelHeight = 0.04;
        ctx.bindProgram(this.showNormalsProgram);
        ctx.setLineWidth(2)
        this.rects.forEach(function(rect) {
            ctx.pushModelMatrix()
            ctx.translate([rect[0] + rect[2]/2, levelHeight*(1+rect[4])/2, rect[1] + rect[3]/2])
            ctx.scale([rect[2], levelHeight*(1+rect[4]), rect[3]])
            this.solidColorProgram.setUniform('uColor', [1,1,1,1])
            ctx.bindMesh(this.cubeMesh);
            ctx.drawMesh();
            ctx.popModelMatrix()
        }.bind(this))
    },
    draw: function() {
        var ctx = this.getContext();

        this.arcball.apply();
        ctx.setViewMatrix(this.camera.getViewMatrix());

        var W = this.getWidth();
        var H = this.getHeight()

        ctx.setViewport(0, 0, W, H);

        var root = this.fx.reset();
        var color = root.render({ drawFunc: this.drawScene.bind(this), depth: this.depthMap });
        var normals = root.render({ drawFunc: this.drawSceneNormals.bind(this), depth: this.depthMap });
        var ssao = root.ssao({ depthMap: this.depthMap, normalMap: normals, kernelMap: this.ssaoKernelMap, noiseMap: this.ssaoNoiseMap, camera: this.camera, strength: 1, offset: 0.2, width: W, height: H });//.blur3().blur3();
        var fin = color.mult(ssao);

        color.blit({x: 0, y: H/2, width: W/2, height: H/2});
        root.asFXStage(this.depthMap, 'bla').blit({x: W/2, y: H/2, width: W/2, height: H/2});
        normals.blit({x: W/2, y: H/2, width: W/2, height: H/2});
        ssao.blit({x: 0, y: 0, width:W/2, height: H/2});
        fin.blit({x: W/2, y: 0, width: W/2, height: H/2});

        //this.gui.draw();
    }
})
<commit_msg>block removed dead code<commit_after>var Window          = require('pex-sys/Window');
var PerspCamera     = require('pex-cam/PerspCamera');
var Arcball         = require('pex-cam/Arcball');
var createCube      = require('primitive-cube');
var glslify         = require('glslify-promise');
var isBrowser       = require('is-browser');
var random          = require('pex-random')
var fx              = require('pex-fx')
var SSAOv2          = require('./SSAO')
var Vec3            = require('pex-math/Vec3')
var MathUtils       = require('pex-math/Utils')
var R               = require('ramda')
var GUI             = require('pex-gui')
var fs              = require('fs')

var MAX_DEPTH = 20

function divide(parent, rects) {
    rects.push(parent);

    var depth = parent[4]

    var shouldDivide = random.chance(0.1 + 1/(depth*0.5+1));
    if (depth <= 1) {
        shouldDivide = true
    }

    if (depth >= MAX_DEPTH || !shouldDivide) {
        return rects
    }

    var numDivisions = random.int(2, 5)
    var horizontal = random.chance(0.5);
    if (depth == 0) horizontal = false;
    if (depth == 1) horizontal = true;

    for(var i=0; i<numDivisions; i++) {
        var child = null
        if (horizontal) {
            child = [
                parent[0] + parent[2] * i * 1 / numDivisions,
                parent[1],
                parent[2] * 1 / numDivisions,
                parent[3],
                depth + 1
            ]
        }
        else {
            child = [
                parent[0],
                parent[1] + parent[3] * i * 1 / numDivisions,
                parent[2],
                parent[3] * 1 / numDivisions,
                depth + 1
            ]
        }
        var offset = 0.002;
        child[0] += offset
        child[1] += offset
        child[2] -= 2*offset
        child[3] -= 2*offset
        divide(child, rects)
    }
    return rects
}

Window.create({
    settings: {
        width:  1280,
        height: 720,
        fullScreen: isBrowser ? true : false
    },
    resources: {
        showNormalsVert: { glsl: glslify(__dirname + '/assets/ShowNormals.vert') },
        showNormalsFrag: { glsl: glslify(__dirname + '/assets/ShowNormals.frag') },
        solidColorVert: { glsl: glslify(__dirname + '/assets/SolidColor.vert') },
        solidColorFrag: { glsl: glslify(__dirname + '/assets/SolidColor.frag') },
    },
    init: function() {
        var ctx = this.getContext();
        var res = this.getResources();

        this.gui = new GUI(ctx, this.getWidth(), this.getHeight())

        random.seed(1)

        var ssaoKernel = [];
        for(var i=0; i<64; i++) {
            var sample = [
                random.float() * 2 - 1,
                random.float() * 2 - 1,
                random.float() * 2 - 1,
                1
            ]
            Vec3.normalize(sample)
            var scale = random.float()
            scale = MathUtils.lerp(0.1, 1.0, scale * scale);
            Vec3.scale(sample, scale)
            ssaoKernel.push(sample)
        }
        var ssaoKernelData = new Float32Array(R.flatten(ssaoKernel))

        var ssaoNoise = [];
        for(var i=0; i<64; i++) {
            var sample = [
                random.float() * 2 - 1,
                random.float() * 2 - 1,
                0,
                1
            ]
            ssaoNoise.push(sample)
        }
        var ssaoNoiseData = new Float32Array(R.flatten(ssaoNoise))

        this.depthMap = ctx.createTexture2D(null, this.getWidth(), this.getHeight(), { format: ctx.DEPTH_COMPONENT, type: ctx.UNSIGNED_SHORT });
        this.ssaoKernelMap = ctx.createTexture2D(ssaoKernelData, 8, 8, { format: ctx.RGBA, type: ctx.FLOAT, minFilter: ctx.NEAREST, magFilter: ctx.NEAREST, repeat: true });
        this.ssaoNoiseMap = ctx.createTexture2D(ssaoNoiseData, 4, 4, { format: ctx.RGBA, type: ctx.FLOAT, minFilter: ctx.NEAREST, magFilter: ctx.NEAREST, repeat: true });
        //this.rects = divide([-1, -0.5, 2, 1, 0], [])
        this.rects = divide([-2, -1, 4, 2, 0], [])
        this.rects.forEach(function(rect) {
            if (rect[4] <= 2) rect.push([0,1,0.5,1])
        })

        this.camera  = new PerspCamera(45,this.getAspectRatio(), 0.1, 10.0);
        this.camera.lookAt([0, 1, 3], [0, 0, 0]);
        ctx.setProjectionMatrix(this.camera.getProjectionMatrix());

        this.arcball = new Arcball(this.camera, this.getWidth(), this.getHeight());
        this.arcball.setDistance(3.0);
        this.addEventListener(this.arcball);

        this.showNormalsProgram = ctx.createProgram(res.showNormalsVert, res.showNormalsFrag);
        ctx.bindProgram(this.showNormalsProgram);

        this.solidColorProgram = ctx.createProgram(res.solidColorVert, res.solidColorFrag);
        ctx.bindProgram(this.solidColorProgram);

        var cube = createCube();
        var cubeAttributes = [
            { data: cube.positions, location: ctx.ATTRIB_POSITION },
            { data: cube.normals, location: ctx.ATTRIB_NORMAL }
        ];
        var cubeIndices = { data: cube.cells };
        this.cubeMesh = ctx.createMesh(cubeAttributes, cubeIndices, ctx.TRIANGLES);

        var cubeWireIndices = { data: cube.cells };
        this.cubeWireMesh = ctx.createMesh(cubeAttributes, cubeWireIndices, ctx.LINES);

        this.fx = fx(ctx)

        this.gui.addHeader('Settings')
        this.gui.addTexture2D('Kernel', this.ssaoKernelMap)
        this.gui.addTexture2D('Noise', this.ssaoNoiseMap)

        var prevCode = '';
        var shaderFile = __dirname + '/SSAO.frag';
        if (false)
        var vert = fs.readFileSync(__dirname + '/ScreenImage.vert', 'utf8');
        if (false)
        fs.watch(shaderFile, { persistent: true, recursive: false }, function(e, filename) {
            var frag = fs.readFileSync(shaderFile, 'utf8');
            if (frag != prevCode) {
                try {
                    console.log('COMPILE >>>> ')
                    var prop = ctx.createProgram(vert, frag)
                    prop.dispose()
                    this.fx.ssao.updateFrag(frag)
                }
                catch(e) {
                    console.log(e)
                }
            }
            prevCode = frag;
        }.bind(this));
    },
    drawScene: function() {
        var ctx = this.getContext()
        ctx.setClearColor(1, 0.2, 0.2, 1);
        ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT);
        ctx.setDepthTest(true);

        var levelHeight = 0.04;
        ctx.bindProgram(this.solidColorProgram);
        ctx.setLineWidth(2)
        this.rects.forEach(function(rect) {
            ctx.pushModelMatrix()
            ctx.translate([rect[0] + rect[2]/2, levelHeight*(1+rect[4])/2, rect[1] + rect[3]/2])
            ctx.scale([rect[2], levelHeight*(1+rect[4]), rect[3]])
            this.solidColorProgram.setUniform('uColor', rect[5] || [1,1,1,1])
            ctx.bindMesh(this.cubeMesh);
            ctx.drawMesh();
            this.solidColorProgram.setUniform('uColor', [0.5,0.5,0.5,1])
            ctx.bindMesh(this.cubeWireMesh);
            ctx.drawMesh();
            ctx.popModelMatrix()
        }.bind(this))
    },
    drawSceneNormals: function() {
        var ctx = this.getContext()
        ctx.setClearColor(1, 0.2, 0.2, 1);
        ctx.clear(ctx.COLOR_BIT | ctx.DEPTH_BIT);
        ctx.setDepthTest(true);

        var levelHeight = 0.04;
        ctx.bindProgram(this.showNormalsProgram);
        ctx.setLineWidth(2)
        this.rects.forEach(function(rect) {
            ctx.pushModelMatrix()
            ctx.translate([rect[0] + rect[2]/2, levelHeight*(1+rect[4])/2, rect[1] + rect[3]/2])
            ctx.scale([rect[2], levelHeight*(1+rect[4]), rect[3]])
            this.solidColorProgram.setUniform('uColor', [1,1,1,1])
            ctx.bindMesh(this.cubeMesh);
            ctx.drawMesh();
            ctx.popModelMatrix()
        }.bind(this))
    },
    draw: function() {
        var ctx = this.getContext();

        this.arcball.apply();
        ctx.setViewMatrix(this.camera.getViewMatrix());

        var W = this.getWidth();
        var H = this.getHeight()

        ctx.setViewport(0, 0, W, H);

        var root = this.fx.reset();
        var color = root.render({ drawFunc: this.drawScene.bind(this), depth: this.depthMap });
        var normals = root.render({ drawFunc: this.drawSceneNormals.bind(this), depth: this.depthMap });
        var ssao = root.ssao({ depthMap: this.depthMap, normalMap: normals, kernelMap: this.ssaoKernelMap, noiseMap: this.ssaoNoiseMap, camera: this.camera, strength: 1, offset: 0.2, width: W, height: H });//.blur3().blur3();
        var fin = color.mult(ssao);

        color.blit({x: 0, y: H/2, width: W/2, height: H/2});
        root.asFXStage(this.depthMap, 'bla').blit({x: W/2, y: H/2, width: W/2, height: H/2});
        normals.blit({x: W/2, y: H/2, width: W/2, height: H/2});
        ssao.blit({x: 0, y: 0, width:W/2, height: H/2});
        fin.blit({x: W/2, y: 0, width: W/2, height: H/2});

        //this.gui.draw();
    }
})
<|endoftext|>


<commit_before>function requestTimestamps() {

  $.getJSON('/fb_data', function(data) {
    activities[Service.FACEBOOK] = data;
    $('.btn-facebook+p').html(data.length + " Posts & Likes").show();
    showCheckMark($('.btn-facebook'));
    visualize();
  });

  $.getJSON('/ig_data', function(data) {
    activities[Service.INSTAGRAM] = data;
    var stats =
    $('.btn-instagram+p').html(data.length + " Photos").show();
    showCheckMark($('.btn-instagram'));
    visualize();
  });

  $.getJSON('/gh_data', function(data) {
    activities[Service.GITHUB] = data;
    $('.btn-github+p').html(data.length + " Events").show();
    showCheckMark($('.btn-github'));
    visualize();
  });

  $.getJSON('/fsq_data', function(data) {
    activities[Service.FOURSQUARE] = data;
    $('.btn-foursquare+p').html(data.length + " Check-ins").show();
    showCheckMark($('.btn-foursquare'));
    visualize();
  });
}

function showCheckMark($btn) {
  $btn.find('.progress-indicator')
      .toggleClass("fa-circle-o-notch")
      .toggleClass("fa-spin")
      .toggleClass("fa-check")
      .show();
}

function clearCanvas() {
  d3.selectAll('.bar').remove();
}

var Service = Object.freeze({FACEBOOK: 0, INSTAGRAM: 1, GITHUB: 2, FOURSQUARE: 3});
var className = {};
className[Service.FACEBOOK] = 'fb';
className[Service.INSTAGRAM] = 'ig';
className[Service.GITHUB] = 'gh';
className[Service.FOURSQUARE] = 'fsq';

var activities = {}

var hourFormat = d3.time.format("%H");
var minuteFormat = d3.time.format("%M");

function timestampsToMinuteInDay(t) {
  return parseInt(hourFormat(new Date(t))) * 60 + parseInt(minuteFormat(new Date(t)));
}

function visualize() {
  clearCanvas();
  var margin = {top: 20, right: 20, bottom: 30, left: 20},
    width = 1000 - margin.left - margin.right,
    height = 450 - margin.top - margin.bottom;

  var svg = d3.select('#traces')
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
    .append('g')
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var x = d3.scale.linear()
    .domain([0, 24 * 60])
    .range([0, width]);

  var ticks = [];
  for(var i = 0; i <= 2400; i += 120){
    ticks.push(i);
  }
  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickValues(ticks)
    .tickFormat(function(x){return d3.round(x/60)+":00"});

  var bins = {};

  for (service in activities) {

    var minuteInDay = activities[service];

    var data = d3.layout.histogram()
      .bins(x.ticks(24))
      (minuteInDay);

    bins[service] = data;
  }

  var allBins = []
  for (service in activities) {
    allBins = allBins.concat(bins[service]);
  }

  var y = d3.scale.linear()
    .domain([0, d3.max(allBins, function(d) { return d.y; })])
    .range([height, 0]);

  for (service in activities) {

    if (service in bins) {
      var data = bins[service];

      var bar = svg.selectAll('.' + className[service])
          .data(data)
        .enter().append('g')
          .attr('class', 'bar ' + className[service])
          .attr('transform', function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

      bar.append("rect")
        .attr("x", x(data[0].dx) / 4 * service)
        .attr("width", x(data[0].dx) / 4)
        .attr("height", function(d) { return height - y(d.y); });
    }
  }

  // bar.append("text")
  //   .attr("dy", ".75em")
  //   .attr("y", 6)
  //   .attr("x", x(data[0].dx) / 2)
  //   .attr("text-anchor", "middle")
  //   .text(function(d) { return d.y; });

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
}

$(function() {
  $('#fb-login-btn').click(function() {
    FB.login(function(response){
      console.log(response.authResponse.accessToken);
      $.get( '/fb_login', {'access_token': response.authResponse.accessToken } )
      .done(function() {
        window.location.replace('/');
      });
    }, {scope: 'user_posts,user_likes'});
  });
});<commit_msg>Changed hour format to am/pm<commit_after>function requestTimestamps() {

  $.getJSON('/fb_data', function(data) {
    activities[Service.FACEBOOK] = data;
    $('.btn-facebook+p').html(data.length + " Posts & Likes").show();
    showCheckMark($('.btn-facebook'));
    visualize();
  });

  $.getJSON('/ig_data', function(data) {
    activities[Service.INSTAGRAM] = data;
    var stats =
    $('.btn-instagram+p').html(data.length + " Photos").show();
    showCheckMark($('.btn-instagram'));
    visualize();
  });

  $.getJSON('/gh_data', function(data) {
    activities[Service.GITHUB] = data;
    $('.btn-github+p').html(data.length + " Events").show();
    showCheckMark($('.btn-github'));
    visualize();
  });

  $.getJSON('/fsq_data', function(data) {
    activities[Service.FOURSQUARE] = data;
    $('.btn-foursquare+p').html(data.length + " Check-ins").show();
    showCheckMark($('.btn-foursquare'));
    visualize();
  });
}

function showCheckMark($btn) {
  $btn.find('.progress-indicator')
      .toggleClass("fa-circle-o-notch")
      .toggleClass("fa-spin")
      .toggleClass("fa-check")
      .show();
}

function clearCanvas() {
  d3.selectAll('.bar').remove();
}

var Service = Object.freeze({FACEBOOK: 0, INSTAGRAM: 1, GITHUB: 2, FOURSQUARE: 3});
var className = {};
className[Service.FACEBOOK] = 'fb';
className[Service.INSTAGRAM] = 'ig';
className[Service.GITHUB] = 'gh';
className[Service.FOURSQUARE] = 'fsq';

var activities = {}

var hourFormat = d3.time.format("%H");
var minuteFormat = d3.time.format("%M");

function timestampsToMinuteInDay(t) {
  return parseInt(hourFormat(new Date(t))) * 60 + parseInt(minuteFormat(new Date(t)));
}

function visualize() {
  clearCanvas();
  var margin = {top: 20, right: 20, bottom: 30, left: 20},
    width = 1000 - margin.left - margin.right,
    height = 450 - margin.top - margin.bottom;

  var svg = d3.select('#traces')
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
    .append('g')
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var x = d3.scale.linear()
    .domain([0, 24 * 60])
    .range([0, width]);

  var ticks = [];
  for(var i = 0; i <= 1440; i += 120){
    ticks.push(i);
  }
  var timeFormat = function(x){
    var hour = d3.round(x/60);
    if(hour%24 === 0){
      return "12am"
    } else if (hour === 12){
      return "12pm"
    } else if (hour < 12){
      return hour + "am"
    } else {
      return hour%12 + "pm"
    }
    return +":00"
  }
  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickValues(ticks)
    .tickFormat(timeFormat);

  var bins = {};

  for (service in activities) {

    var minuteInDay = activities[service];

    var data = d3.layout.histogram()
      .bins(x.ticks(24))
      (minuteInDay);

    bins[service] = data;
  }

  var allBins = []
  for (service in activities) {
    allBins = allBins.concat(bins[service]);
  }

  var y = d3.scale.linear()
    .domain([0, d3.max(allBins, function(d) { return d.y; })])
    .range([height, 0]);

  for (service in activities) {

    if (service in bins) {
      var data = bins[service];

      var bar = svg.selectAll('.' + className[service])
          .data(data)
        .enter().append('g')
          .attr('class', 'bar ' + className[service])
          .attr('transform', function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

      bar.append("rect")
        .attr("x", x(data[0].dx) / 4 * service)
        .attr("width", x(data[0].dx) / 4)
        .attr("height", function(d) { return height - y(d.y); });
    }
  }

  // bar.append("text")
  //   .attr("dy", ".75em")
  //   .attr("y", 6)
  //   .attr("x", x(data[0].dx) / 2)
  //   .attr("text-anchor", "middle")
  //   .text(function(d) { return d.y; });

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
}

$(function() {
  $('#fb-login-btn').click(function() {
    FB.login(function(response){
      console.log(response.authResponse.accessToken);
      $.get( '/fb_login', {'access_token': response.authResponse.accessToken } )
      .done(function() {
        window.location.replace('/');
      });
    }, {scope: 'user_posts,user_likes'});
  });
});<|endoftext|>


<commit_before>$(document).ready(function(){
  console.log("READY")
  // base URI
  url = 'https://data.sfgov.org/resource/7a3q-s79u.json';

  //Map
  window.initMap = function() {
    //map center
    var myLatLng = {lat: 37.784691, lng:  -122.397804};
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 12,
      center: myLatLng
    });

    //parsing data from JSON
    var markersData = [];
    $.ajax({
      url: url,
      dataType: 'json',
      async: false,
      success: function(data){
          data.forEach(function(data){
            latLngCat = {
              latLng: {lat: parseFloat(data.y), lng: parseFloat(data.x)},
              crime: data.category }
            markersData.push(latLngCat)
          });
      }
    });

    //adding markers to map
    markersData.forEach(function(data){
      var marker = new google.maps.Marker({
        position: data.latLng,
        map: map,
        title: data.crime
      });
    })
  }
})
<commit_msg>added filter function to remove DUI, NON-CRIMINAL & OTHER OFFENSES from markers<commit_after>$(document).ready(function(){
  console.log("READY")
  // base URI
  url = 'https://data.sfgov.org/resource/7a3q-s79u.json';

  //Map
  window.initMap = function() {
    //map center
    var myLatLng = {lat: 37.784691, lng:  -122.397804};
    var map = new google.maps.Map(document.getElementById('map'), {
      zoom: 12,
      center: myLatLng
    });

    //parsing data from JSON

    var markersData = [];

    var filterCategory = function(data) {
      if (data.category !== "DRIVING UNDER THE INFLUENCE" ||
          data.category !== "NON-CRIMINAL" ||
          data.category !== "OTHER OFFENSES") {
            latLngCat = {
              latLng: {lat: parseFloat(data.y), lng: parseFloat(data.x)},
              crime: data.category }
            markersData.push(latLngCat)
          }
    };

    $.ajax({
      url: url,
      dataType: 'json',
      async: false,
      success: function(data){
          data.forEach(function(data){
            filterCategory(data)
          });
      }
    });

    //adding markers to map
    markersData.forEach(function(data){
      var marker = new google.maps.Marker({
        position: data.latLng,
        map: map,
        title: data.crime
      });
    })
  }
})
<|endoftext|>


<commit_before>/*global StateMachine, tnetbin, mozRTCIceCandidate */

(function(exports) {
  "use strict";

  var defaultConstraints = {video: false, audio: false, fake: false};

  /**
   * WebRTC object constructor.
   *
   * Options are:
   * - {Boolean} forceFake:  Forces fake media streams (default: false)
   *
   * @param {Object}                   options  Options
   */
  function WebRTC(options) {
    this.pc = undefined;
    this.dc = undefined;
    this._constraints = {};
    this.options = options || {};

    this.state = StateMachine.create({
      initial: 'ready',
      events: [
        {name: 'initiate',  from: 'ready',     to: 'pending'},
        {name: 'establish', from: 'pending',   to: 'ongoing'},
        {name: 'upgrade',   from: 'ongoing',   to: 'pending'},
        {name: 'answer',    from: ['ready',
                                   'ongoing'], to: 'ongoing'},
        {name: 'terminate', from: '*',         to: 'terminated'},
        {name: 'reset',     from: '*',         to: 'ready'}
      ],
      callbacks: {
        onenterstate: function(event, from, to) {
          this.trigger("change:state", to, from, event);
          this.trigger("transition:" + event);
          this.trigger("state:to:" + to);
        }.bind(this)
      }
    });
  }
  exports.WebRTC = WebRTC;

  _.extend(WebRTC.prototype, Backbone.Events);

  // public properties

  /* jshint camelcase:false */
  WebRTC.prototype.__defineGetter__('constraints', function() {
    var _constraints = this._constraints || defaultConstraints;

    if (!!this.options.forceFake)
      _constraints.fake = true;

    return _constraints;
  });

  WebRTC.prototype.__defineSetter__('constraints', function(constraints) {
    this._constraints = constraints || defaultConstraints;

    if (!!this.options.forceFake)
      this._constraints.fake = true;
  });
  /* jshint camelcase:true */

  // static methods

  /**
   * Extracts media constraints from an offer SDP.
   * @param  {Object}  offer  Offer object
   * @return {Object}         Media constraints object
   * @private
   */
  WebRTC.parseOfferConstraints = function(offer) {
    var sdp = offer && offer.sdp;

    if (!sdp)
      throw new Error('No SDP offer to parse');

    return {
      video: sdp.contains('\nm=video '),
      audio: sdp.contains('\nm=audio ')
    };
  };

  // public prototype

  /**
   * Initiates an outgoing connection.
   * @param  {Object}  constraints  Media constraints
   * @return {WebRTC}
   * @event  `local-stream:ready` {LocalMediaStream}
   * @public
   */
  WebRTC.prototype.initiate = function(constraints) {
    this.state.initiate();
    this._setupPeerConnection();
    this.constraints = constraints;

    if (!this.constraints.video && !this.constraints.audio)
      return this._createOffer();

    return this._getMedia(function(localStream) {
      this.trigger('local-stream:ready', localStream)
          ._addLocalStream(localStream)
          ._createOffer();
    });
  };

  /**
   * Upgrades an established peer connection with new constraints.
   * @param  {Object} constraints User media constraints
   * @return {WebRTC}
   */
  WebRTC.prototype.upgrade = function(constraints) {
    this.state.upgrade();

    if (!constraints || typeof constraints !== 'object')
      throw new Error('upgrading needs new media constraints');
    this.constraints = constraints;

    // XXX: renegotiate connection once supported by the WebRTC API;
    //      right now, reinitialize the current peer connection.
    this.once('connection-terminated', function() {
      this.state.current = "ready";
      this.once('ice:connected', function() {
        this.trigger('connection-upgraded');
      }).initiate(constraints);
    }).terminate();

    // force state to pending as we're actually waiting for pc reinitiation
    this.state.current = "pending";

    return this;
  };

  /**
   * Establishes the connection using the received answer.
   * @param  {Object} answer
   * @return {WebRTC}
   * @event  `connection-established`
   * @public
   */
  WebRTC.prototype.establish = function(answer) {
    this.state.establish();
    this._prepareEstablishment();

    this.pc.setRemoteDescription(
      new mozRTCSessionDescription(answer),
      function() {},
      this._handleError.bind(this, 'Unable to set remote answer description')
    );

    return this;
  };

  /**
   * Answers an incoming initial or upgraded connection offer.
   * @param  {Object}  offer  Connection offer
   * @return {WebRTC}
   * @public
   */
  WebRTC.prototype.answer = function(offer) {
    this.state.answer();
    this._setupPeerConnection();
    this.constraints = WebRTC.parseOfferConstraints(offer);

    if (!this.constraints.video && !this.constraints.audio)
      return this._prepareAnswer(offer);

    return this._getMedia(function(localStream) {
      this.trigger('local-stream:ready', localStream)
          ._addLocalStream(localStream)
          ._prepareAnswer(offer);
    });
  };

  /**
   * Adds an ice candidate to the peer connection.
   * @param {Object} candidate Object containing the data for a
   *                           mozRTCIceCandidate.
   */
  WebRTC.prototype.addIceCandidate = function(candidate) {
    this.pc.addIceCandidate(new mozRTCIceCandidate(candidate));
  };

  /**
   * Resets the peer connection.
   * @return {WebRTC}
   */
  WebRTC.prototype.reset = function() {
    this.state.reset();
    this._setupPeerConnection();

    return this;
  };

  /**
   * Sends data over data channel.
   * @param  {Object} data
   * @return {WebRTC}
   * @event  `dc:message-out` {Object}
   * @public
   */
  WebRTC.prototype.send = function(data) {
    if (this.state.current !== 'ongoing')
      return this._handleError("Not connected, can't send data");

    data = tnetbin.encode(data);
    try {
      this.dc.send(data);
    } catch(err) {
      return this._handleError("Couldn't send data", err);
    }

    return this.trigger('dc:message-out', data);
  };

  /**
   * Terminates an ongoing communication.
   * @return {WebRTC}
   * @event  `connection-terminated`
   * @public
   */
  WebRTC.prototype.terminate = function() {
    this.state.terminate();

    if (!this.pc || this.pc.signalingState === 'closed')
      return this;

    // Tell everyone that we're terminating the streams
    this.trigger('local-stream:terminated');
    this.trigger('remote-stream:terminated');

    // Actually stop the local stream, so that we don't keep hold of the media
    // elements.
    var streams = this.pc.getLocalStreams();
    streams.forEach(function(stream) {
      stream.stop();
    });

    this.once('ice:closed', this.trigger.bind(this, 'connection-terminated'));
    this.pc.close();

    return this;
  };

  /**
   * Mutes all the video or audio streams on the connection
   * @param {String}  type  The type of stream to mute, values are
   *                        'local' or 'remote'
   * @param {String}  media The type of media stream to mute, values are
   *                        'audio' or 'video'
   * @param {Boolean} mute  True to mute the stream, false to unmute
   */
  WebRTC.prototype.setMuteState = function(type, media, mute) {
    var streams;

    if (type === 'local')
      streams = this.pc.getLocalStreams();
    else if (type === 'remote')
      streams = this.pc.getRemoteStreams();
    else
      throw new Error("Unsupported stream type: " + type);

    function muteTrack(track) {
      track.enabled = !mute;
    }

    streams.forEach(function(stream) {
      if (media === 'audio')
        stream.getAudioTracks().forEach(muteTrack, this);
      else if (media === 'video')
        stream.getVideoTracks().forEach(muteTrack, this);
    }, this);
  };

  // "private" methods

  /**
   * Adds a local media stream to the peer connection.
   * @param  {LocalMediaStream} localStream
   * @return {WebRTC}
   */
  WebRTC.prototype._addLocalStream = function(localStream) {
    try {
      this.pc.addStream(localStream);
    } catch (err) {
      return this._handleError('Unable to add local stream', err);
    }

    return this;
  };

  /**
   * Creates an answer.
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._createAnswer = function() {
    this.pc.createAnswer(
      this._setAnswerDescription.bind(this),
      this._handleError.bind(this, 'Unable to create answer')
    );

    return this;
  };

  /**
   * Creates an offer.
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._createOffer = function() {
    this.pc.createOffer(
      this._setOfferDescription.bind(this),
      this._handleError.bind(this, 'Unable to create offer')
    );

    return this;
  };

  /**
   * gUM proxy.
   * @param  {Function} callback    Callback
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._getMedia = function(callback) {
    navigator.mozGetUserMedia(
      this.constraints,
      callback.bind(this),
      this._handleError.bind(this, 'Unable to get user media, constraints=' +
                                   this.constraints.toSource())
    );

    return this;
  };

  /**
   * Handles a WebRTC error.
   * @param  {String} message
   * @param  {Object} err
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._handleError = function(description, err) {
    var messageParts = [description];

    if (err && typeof err === "object")
      messageParts = messageParts.concat([':', err.name, err.message]);

    return this.trigger('error', messageParts.join(' '));
  };

  /**
   * Executed when a remote media stream is added to current peer connection.
   * @param  {Event} event
   */
  WebRTC.prototype._onAddStream = function(event) {
    this.trigger('remote-stream:ready', event.stream);
  };

  /**
   * Executed on incoming data channel.
   * @param  {RTCDataChannelEvent} event
   */
  WebRTC.prototype._onDataChannel = function() {
    console.error("Unexpected call to _onDataChannel - negotiated channel?");
  };

  /**
   * Executed when the ICE connection state changes.
   *
   * Emits the `ice:change` event with the new state name as a parameter, and
   * one of these depending on the new connection state:
   * - ice:new
   * - ice:checking
   * - ice:connected
   * - ice:completed
   * - ice:failed
   * - ice:disconnected
   * - ice:closed
   */
  WebRTC.prototype._onIceConnectionStateChange = function() {
    this.trigger('ice:' + this.pc.iceConnectionState);
    this.trigger('ice:change', this.pc.iceConnectionState);
  };

  /**
   * Executed when an ICE candidate is received.
   * @param  {mozRTCIceCandidate} event.candidate
   * @event  `ice:candidate-ready` {Object}
   */
  WebRTC.prototype._onIceCandidate = function(event) {
    // XXX Manually translate this until bug 928304 is incorporated in all
    // versions we support, i.e. Firefox 27.0a2 onwards.
    // The last candidate event is a null event, so we don't need to do
    // anything with that.
    if (event && event.candidate) {
      this.trigger('ice:candidate-ready', {
        candidate: event.candidate.candidate,
        sdpMid: event.candidate.sdpMid,
        sdpMLineIndex: event.candidate.sdpMLineIndex
      });
    }
  };

  /**
   * Executed when a remote media stream is removed from the current peer
   * connection.
   * @param  {Event} event
   */
  WebRTC.prototype._onRemoveStream = function(event) {
    this.trigger('remote-stream:remove', event.stream);
  };

  /**
   * Executed when the current signaling state changes.
   * @param  {Event} event
   */
  WebRTC.prototype._onSignalingStateChange = function(event) {
    this.trigger('signaling:' + event);
    this.trigger('signaling:change', event);
  };

  /**
   * Prepares connection establishment.
   */
  WebRTC.prototype._prepareEstablishment = function() {
    this.on('ice:connected', this.trigger.bind(this, 'connection-established'));
  };

  /**
   * Prepares an answer based on passed offer.
   * @param  {Object} offer
   * @return {WebRTC}
   */
  WebRTC.prototype._prepareAnswer = function(offer) {
    this.pc.setRemoteDescription(
      new mozRTCSessionDescription(offer),
      this._createAnswer.bind(this),
      this._handleError.bind(this, 'Unable to set remote offer description')
    );

    return this;
  };

  /**
   * Sets local session description from a connection answer object.
   * @param  {Object} answer
   * @return {WebRTC}
   * @event  `answer-ready` {Object}
   * @private
   */
  WebRTC.prototype._setAnswerDescription = function(answer) {
    this.pc.setLocalDescription(
      answer,
      this.trigger.bind(this, 'answer-ready', answer),
      this._handleError.bind(this, 'Unable to set local answer description')
    );

    return this;
  };

  /**
   * Sets local session description from a connection offer object.
   * @param  {Object} offer
   * @return {WebRTC}
   * @event  `offer-ready` {Object}
   * @private
   */
  WebRTC.prototype._setOfferDescription = function(offer) {
    this.pc.setLocalDescription(
      offer,
      this.trigger.bind(this, 'offer-ready', offer),
      this._handleError.bind(this, 'Unable to set local offer description')
    );

    return this;
  };

  /**
   * Configures a peer connection, registering local event listeners.
   *
   * @param {RTCPeerConnection} pc
   */
  WebRTC.prototype._setupPeerConnection = function() {
    this.pc = new mozRTCPeerConnection();
    this.dc = this._setupDataChannel(this.pc, 0);

    this.pc.onaddstream = this._onAddStream.bind(this);
    this.pc.ondatachannel = this._onDataChannel.bind(this);
    this.pc.onicecandidate = this._onIceCandidate.bind(this);
    this.pc.oniceconnectionstatechange =
      this._onIceConnectionStateChange.bind(this);
    this.pc.onremovestream = this._onRemoveStream.bind(this);
    this.pc.onsignalingstatechange = this._onSignalingStateChange.bind(this);
  };

  /**
   * Configures a data channel, registering local event listeners.
   *
   * @param {RTCPeerConnection} pc
   * @param {short}             id of the data channel to create
   */
  WebRTC.prototype._setupDataChannel = function(pc, id) {
    var dc = pc.createDataChannel('dc', {
      // We set up a pre-negotiated channel with a specific id, this
      // way we know exactly which channel we're expecting to communicate
      // with.
      id: id,
      negotiated: true
    });

    dc.onopen  = this.trigger.bind(this, "dc:ready", dc);
    dc.onerror = this.trigger.bind(this, "dc:error");
    dc.onclose = this.trigger.bind(this, "dc:close");
    dc.onmessage = function(event) {
      var data = tnetbin.decode(event.data).value;
      this.trigger("dc:message-in", data);
    }.bind(this);

    return dc;
  };
})(this);
<commit_msg>added link to ice candidate state specification<commit_after>/*global StateMachine, tnetbin, mozRTCIceCandidate */

(function(exports) {
  "use strict";

  var defaultConstraints = {video: false, audio: false, fake: false};

  /**
   * WebRTC object constructor.
   *
   * Options are:
   * - {Boolean} forceFake:  Forces fake media streams (default: false)
   *
   * @param {Object}                   options  Options
   */
  function WebRTC(options) {
    this.pc = undefined;
    this.dc = undefined;
    this._constraints = {};
    this.options = options || {};

    this.state = StateMachine.create({
      initial: 'ready',
      events: [
        {name: 'initiate',  from: 'ready',     to: 'pending'},
        {name: 'establish', from: 'pending',   to: 'ongoing'},
        {name: 'upgrade',   from: 'ongoing',   to: 'pending'},
        {name: 'answer',    from: ['ready',
                                   'ongoing'], to: 'ongoing'},
        {name: 'terminate', from: '*',         to: 'terminated'},
        {name: 'reset',     from: '*',         to: 'ready'}
      ],
      callbacks: {
        onenterstate: function(event, from, to) {
          this.trigger("change:state", to, from, event);
          this.trigger("transition:" + event);
          this.trigger("state:to:" + to);
        }.bind(this)
      }
    });
  }
  exports.WebRTC = WebRTC;

  _.extend(WebRTC.prototype, Backbone.Events);

  // public properties

  /* jshint camelcase:false */
  WebRTC.prototype.__defineGetter__('constraints', function() {
    var _constraints = this._constraints || defaultConstraints;

    if (!!this.options.forceFake)
      _constraints.fake = true;

    return _constraints;
  });

  WebRTC.prototype.__defineSetter__('constraints', function(constraints) {
    this._constraints = constraints || defaultConstraints;

    if (!!this.options.forceFake)
      this._constraints.fake = true;
  });
  /* jshint camelcase:true */

  // static methods

  /**
   * Extracts media constraints from an offer SDP.
   * @param  {Object}  offer  Offer object
   * @return {Object}         Media constraints object
   * @private
   */
  WebRTC.parseOfferConstraints = function(offer) {
    var sdp = offer && offer.sdp;

    if (!sdp)
      throw new Error('No SDP offer to parse');

    return {
      video: sdp.contains('\nm=video '),
      audio: sdp.contains('\nm=audio ')
    };
  };

  // public prototype

  /**
   * Initiates an outgoing connection.
   * @param  {Object}  constraints  Media constraints
   * @return {WebRTC}
   * @event  `local-stream:ready` {LocalMediaStream}
   * @public
   */
  WebRTC.prototype.initiate = function(constraints) {
    this.state.initiate();
    this._setupPeerConnection();
    this.constraints = constraints;

    if (!this.constraints.video && !this.constraints.audio)
      return this._createOffer();

    return this._getMedia(function(localStream) {
      this.trigger('local-stream:ready', localStream)
          ._addLocalStream(localStream)
          ._createOffer();
    });
  };

  /**
   * Upgrades an established peer connection with new constraints.
   * @param  {Object} constraints User media constraints
   * @return {WebRTC}
   */
  WebRTC.prototype.upgrade = function(constraints) {
    this.state.upgrade();

    if (!constraints || typeof constraints !== 'object')
      throw new Error('upgrading needs new media constraints');
    this.constraints = constraints;

    // XXX: renegotiate connection once supported by the WebRTC API;
    //      right now, reinitialize the current peer connection.
    this.once('connection-terminated', function() {
      this.state.current = "ready";
      this.once('ice:connected', function() {
        this.trigger('connection-upgraded');
      }).initiate(constraints);
    }).terminate();

    // force state to pending as we're actually waiting for pc reinitiation
    this.state.current = "pending";

    return this;
  };

  /**
   * Establishes the connection using the received answer.
   * @param  {Object} answer
   * @return {WebRTC}
   * @event  `connection-established`
   * @public
   */
  WebRTC.prototype.establish = function(answer) {
    this.state.establish();
    this._prepareEstablishment();

    this.pc.setRemoteDescription(
      new mozRTCSessionDescription(answer),
      function() {},
      this._handleError.bind(this, 'Unable to set remote answer description')
    );

    return this;
  };

  /**
   * Answers an incoming initial or upgraded connection offer.
   * @param  {Object}  offer  Connection offer
   * @return {WebRTC}
   * @public
   */
  WebRTC.prototype.answer = function(offer) {
    this.state.answer();
    this._setupPeerConnection();
    this.constraints = WebRTC.parseOfferConstraints(offer);

    if (!this.constraints.video && !this.constraints.audio)
      return this._prepareAnswer(offer);

    return this._getMedia(function(localStream) {
      this.trigger('local-stream:ready', localStream)
          ._addLocalStream(localStream)
          ._prepareAnswer(offer);
    });
  };

  /**
   * Adds an ice candidate to the peer connection.
   * @param {Object} candidate Object containing the data for a
   *                           mozRTCIceCandidate.
   */
  WebRTC.prototype.addIceCandidate = function(candidate) {
    this.pc.addIceCandidate(new mozRTCIceCandidate(candidate));
  };

  /**
   * Resets the peer connection.
   * @return {WebRTC}
   */
  WebRTC.prototype.reset = function() {
    this.state.reset();
    this._setupPeerConnection();

    return this;
  };

  /**
   * Sends data over data channel.
   * @param  {Object} data
   * @return {WebRTC}
   * @event  `dc:message-out` {Object}
   * @public
   */
  WebRTC.prototype.send = function(data) {
    if (this.state.current !== 'ongoing')
      return this._handleError("Not connected, can't send data");

    data = tnetbin.encode(data);
    try {
      this.dc.send(data);
    } catch(err) {
      return this._handleError("Couldn't send data", err);
    }

    return this.trigger('dc:message-out', data);
  };

  /**
   * Terminates an ongoing communication.
   * @return {WebRTC}
   * @event  `connection-terminated`
   * @public
   */
  WebRTC.prototype.terminate = function() {
    this.state.terminate();

    if (!this.pc || this.pc.signalingState === 'closed')
      return this;

    // Tell everyone that we're terminating the streams
    this.trigger('local-stream:terminated');
    this.trigger('remote-stream:terminated');

    // Actually stop the local stream, so that we don't keep hold of the media
    // elements.
    var streams = this.pc.getLocalStreams();
    streams.forEach(function(stream) {
      stream.stop();
    });

    this.once('ice:closed', this.trigger.bind(this, 'connection-terminated'));
    this.pc.close();

    return this;
  };

  /**
   * Mutes all the video or audio streams on the connection
   * @param {String}  type  The type of stream to mute, values are
   *                        'local' or 'remote'
   * @param {String}  media The type of media stream to mute, values are
   *                        'audio' or 'video'
   * @param {Boolean} mute  True to mute the stream, false to unmute
   */
  WebRTC.prototype.setMuteState = function(type, media, mute) {
    var streams;

    if (type === 'local')
      streams = this.pc.getLocalStreams();
    else if (type === 'remote')
      streams = this.pc.getRemoteStreams();
    else
      throw new Error("Unsupported stream type: " + type);

    function muteTrack(track) {
      track.enabled = !mute;
    }

    streams.forEach(function(stream) {
      if (media === 'audio')
        stream.getAudioTracks().forEach(muteTrack, this);
      else if (media === 'video')
        stream.getVideoTracks().forEach(muteTrack, this);
    }, this);
  };

  // "private" methods

  /**
   * Adds a local media stream to the peer connection.
   * @param  {LocalMediaStream} localStream
   * @return {WebRTC}
   */
  WebRTC.prototype._addLocalStream = function(localStream) {
    try {
      this.pc.addStream(localStream);
    } catch (err) {
      return this._handleError('Unable to add local stream', err);
    }

    return this;
  };

  /**
   * Creates an answer.
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._createAnswer = function() {
    this.pc.createAnswer(
      this._setAnswerDescription.bind(this),
      this._handleError.bind(this, 'Unable to create answer')
    );

    return this;
  };

  /**
   * Creates an offer.
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._createOffer = function() {
    this.pc.createOffer(
      this._setOfferDescription.bind(this),
      this._handleError.bind(this, 'Unable to create offer')
    );

    return this;
  };

  /**
   * gUM proxy.
   * @param  {Function} callback    Callback
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._getMedia = function(callback) {
    navigator.mozGetUserMedia(
      this.constraints,
      callback.bind(this),
      this._handleError.bind(this, 'Unable to get user media, constraints=' +
                                   this.constraints.toSource())
    );

    return this;
  };

  /**
   * Handles a WebRTC error.
   * @param  {String} message
   * @param  {Object} err
   * @return {WebRTC}
   * @private
   */
  WebRTC.prototype._handleError = function(description, err) {
    var messageParts = [description];

    if (err && typeof err === "object")
      messageParts = messageParts.concat([':', err.name, err.message]);

    return this.trigger('error', messageParts.join(' '));
  };

  /**
   * Executed when a remote media stream is added to current peer connection.
   * @param  {Event} event
   */
  WebRTC.prototype._onAddStream = function(event) {
    this.trigger('remote-stream:ready', event.stream);
  };

  /**
   * Executed on incoming data channel.
   * @param  {RTCDataChannelEvent} event
   */
  WebRTC.prototype._onDataChannel = function() {
    console.error("Unexpected call to _onDataChannel - negotiated channel?");
  };

  /**
   * Executed when the ICE connection state changes.
   *
   * Emits the `ice:change` event with the new state name as a parameter, and
   * one of these depending on the new connection state:
   * - ice:new
   * - ice:checking
   * - ice:connected
   * - ice:completed
   * - ice:failed
   * - ice:disconnected
   * - ice:closed
   *
   * @link http://www.w3.org/TR/webrtc/#h4_rtciceconnectionstate-enum
   */
  WebRTC.prototype._onIceConnectionStateChange = function() {
    this.trigger('ice:' + this.pc.iceConnectionState);
    this.trigger('ice:change', this.pc.iceConnectionState);
  };

  /**
   * Executed when an ICE candidate is received.
   * @param  {mozRTCIceCandidate} event.candidate
   * @event  `ice:candidate-ready` {Object}
   */
  WebRTC.prototype._onIceCandidate = function(event) {
    // XXX Manually translate this until bug 928304 is incorporated in all
    // versions we support, i.e. Firefox 27.0a2 onwards.
    // The last candidate event is a null event, so we don't need to do
    // anything with that.
    if (event && event.candidate) {
      this.trigger('ice:candidate-ready', {
        candidate: event.candidate.candidate,
        sdpMid: event.candidate.sdpMid,
        sdpMLineIndex: event.candidate.sdpMLineIndex
      });
    }
  };

  /**
   * Executed when a remote media stream is removed from the current peer
   * connection.
   * @param  {Event} event
   */
  WebRTC.prototype._onRemoveStream = function(event) {
    this.trigger('remote-stream:remove', event.stream);
  };

  /**
   * Executed when the current signaling state changes.
   * @param  {Event} event
   */
  WebRTC.prototype._onSignalingStateChange = function(event) {
    this.trigger('signaling:' + event);
    this.trigger('signaling:change', event);
  };

  /**
   * Prepares connection establishment.
   */
  WebRTC.prototype._prepareEstablishment = function() {
    this.on('ice:connected', this.trigger.bind(this, 'connection-established'));
  };

  /**
   * Prepares an answer based on passed offer.
   * @param  {Object} offer
   * @return {WebRTC}
   */
  WebRTC.prototype._prepareAnswer = function(offer) {
    this.pc.setRemoteDescription(
      new mozRTCSessionDescription(offer),
      this._createAnswer.bind(this),
      this._handleError.bind(this, 'Unable to set remote offer description')
    );

    return this;
  };

  /**
   * Sets local session description from a connection answer object.
   * @param  {Object} answer
   * @return {WebRTC}
   * @event  `answer-ready` {Object}
   * @private
   */
  WebRTC.prototype._setAnswerDescription = function(answer) {
    this.pc.setLocalDescription(
      answer,
      this.trigger.bind(this, 'answer-ready', answer),
      this._handleError.bind(this, 'Unable to set local answer description')
    );

    return this;
  };

  /**
   * Sets local session description from a connection offer object.
   * @param  {Object} offer
   * @return {WebRTC}
   * @event  `offer-ready` {Object}
   * @private
   */
  WebRTC.prototype._setOfferDescription = function(offer) {
    this.pc.setLocalDescription(
      offer,
      this.trigger.bind(this, 'offer-ready', offer),
      this._handleError.bind(this, 'Unable to set local offer description')
    );

    return this;
  };

  /**
   * Configures a peer connection, registering local event listeners.
   *
   * @param {RTCPeerConnection} pc
   */
  WebRTC.prototype._setupPeerConnection = function() {
    this.pc = new mozRTCPeerConnection();
    this.dc = this._setupDataChannel(this.pc, 0);

    this.pc.onaddstream = this._onAddStream.bind(this);
    this.pc.ondatachannel = this._onDataChannel.bind(this);
    this.pc.onicecandidate = this._onIceCandidate.bind(this);
    this.pc.oniceconnectionstatechange =
      this._onIceConnectionStateChange.bind(this);
    this.pc.onremovestream = this._onRemoveStream.bind(this);
    this.pc.onsignalingstatechange = this._onSignalingStateChange.bind(this);
  };

  /**
   * Configures a data channel, registering local event listeners.
   *
   * @param {RTCPeerConnection} pc
   * @param {short}             id of the data channel to create
   */
  WebRTC.prototype._setupDataChannel = function(pc, id) {
    var dc = pc.createDataChannel('dc', {
      // We set up a pre-negotiated channel with a specific id, this
      // way we know exactly which channel we're expecting to communicate
      // with.
      id: id,
      negotiated: true
    });

    dc.onopen  = this.trigger.bind(this, "dc:ready", dc);
    dc.onerror = this.trigger.bind(this, "dc:error");
    dc.onclose = this.trigger.bind(this, "dc:close");
    dc.onmessage = function(event) {
      var data = tnetbin.decode(event.data).value;
      this.trigger("dc:message-in", data);
    }.bind(this);

    return dc;
  };
})(this);
<|endoftext|>


<commit_before>'use strict';

var models = require('../models');
var Event = models.Event;
var Post = models.Post;

var ical = require('ical');
var FeedParser = require('feedparser');
var request = require('request');
var striptags = require('striptags');
var debug = require('debug')('echo:fetch');
var findDate = require('./find-date');

// = iCal ===================================================== //

function iCalDataToEvent(item) {
	return Event.build({
		title: item.summary.trim(),
		startdt: item.start,
		enddt: item.end,
		location_text: item.location,
		blurb: item.description.trim(),
		url: item.url,
		state: 'imported',
		importid: item.uid
	});
}

function processICalEntry(entry, opts) {
	if (!entry.start || entry.start < new Date()) return;
	if (opts.filter && opts.filter(entry)) return;

	// Don't duplicate events
	Event.count({ where: { importid: entry.uid } })
			.then(function(count) {
		if (count > 0) return;

		if (opts.transform) opts.transform(entry);

		debug('Adding new event: ' + entry.summary);
		return iCalDataToEvent(entry).saveAndGenerateSlug({ validate: false });
	}).catch(opts.error);
}

function fetchICal(opts) {
	debug('Fetching iCal ' + opts.url);

	ical.fromURL(opts.url, {}, function useICalData(data) {
		for (var k in data) {
			if (!data.hasOwnProperty(k)) continue;
			processICalEntry(data[k], opts);
		}
	});
}

// = Atom/RSS ================================================= //

// Returns a Promise, if anything
function checkPostForEvent(post, error) {
	const now = new Date();

	// Check it's not too far in the past
	if (post.pubDate.getTime() < (now.getTime() - 7.88923e9)) // 1.578e10 == 3 months in ms
		return;

	// Check if it's like an event
	let date = findDate(post.pubDate, post.description);
	if (!date) return;

	// Check it's not too far in the future
	if (date.getTime() < now.getTime() ||
			date.getTime() > (now.getTime() + 7.88923e9)) // 1.578e10 == 3 months in ms
		return;

	return Event.findById(post.guid).then(function(anyFound) {
		// Don't add duplicates
		if (anyFound === null) {
			debug('Adding new event: ' + post.title);

			return Event.build({
				title: post.title,
				startdt: date,
				url: post.link,
				blurb: striptags(post.description),
				state: 'imported',
				importid: post.guid
			}).save({ validate: false });
		}
	});
}

// The following URL is useful for understanding the contents of 'post'
// https://github.com/danmactough/node-feedparser#what-is-the-parsed-output-produced-by-feedparser
//
// Returns a Promise
function processPost(feed, post) {
	if (!post.title || !post.guid) {
		debug("Post with no title");
		return;
	}

	return Post.findById(post.guid).then(function(anyFound) {
		// Don't add duplicates
		if (anyFound === null) {
			debug('Adding new post: ' + post.title);

			Post.build({
				id: post.guid,
				title: post.title,
				link: post.link,
				date: post.pubDate,
				feedId: feed.id,
			}).save();

			return checkPostForEvent(post);
		}
	})
}

function fetchFeed(feed) {
	feed.errors = null;
	feed.lastFetched = new Date();
	feed.save();

	let req = request(feed.feedURL);
	let feedparser = new FeedParser();

	let errorHandler = function(error) {
		feed.errors = error.toString();
		debug(error);
		feed.save();
	}

	req.on('error', errorHandler);
	req.on('response', function(res) {
		if (res.statusCode != 200)
			return this.emit('error', new Error('Bad status code'));

		this.pipe(feedparser);
	});

	debug('Fetching feed id ' + feed.id + ', URL: '+ feed.feedURL);

	feedparser.on('error', errorHandler);
	feedparser.on('readable', function() {
		let post;
		while ((post = this.read())) {
			processPost(feed, post);
		}
	});
}

// = Exports ================================================== //

module.exports = {
	ical: fetchICal,
	feed: fetchFeed,
	findDate: findDate,

	_processICalEntry: processICalEntry,
	_iCalDataToEvent: iCalDataToEvent
};
<commit_msg>Use promises better in fetch code<commit_after>'use strict';

var models = require('../models');
var Event = models.Event;
var Post = models.Post;

var ical = require('ical');
var FeedParser = require('feedparser');
var request = require('request');
var striptags = require('striptags');
var debug = require('debug')('echo:fetch');
var findDate = require('./find-date');

// = iCal ===================================================== //

function iCalDataToEvent(item) {
	return Event.build({
		title: item.summary.trim(),
		startdt: item.start,
		enddt: item.end,
		location_text: item.location,
		blurb: item.description.trim(),
		url: item.url,
		state: 'imported',
		importid: item.uid
	});
}

function processICalEntry(entry, opts) {
	if (!entry.start || entry.start < new Date()) return;
	if (opts.filter && opts.filter(entry)) return;

	// Don't duplicate events
	Event.count({ where: { importid: entry.uid } })
			.then(function(count) {
		if (count > 0) return;

		if (opts.transform) opts.transform(entry);

		debug('Adding new event: ' + entry.summary);
		return iCalDataToEvent(entry).saveAndGenerateSlug({ validate: false });
	}).catch(opts.error);
}

function fetchICal(opts) {
	debug('Fetching iCal ' + opts.url);

	ical.fromURL(opts.url, {}, function useICalData(data) {
		for (var k in data) {
			if (!data.hasOwnProperty(k)) continue;
			processICalEntry(data[k], opts);
		}
	});
}

// = Atom/RSS ================================================= //

// Returns a Promise, if anything
function checkPostForEvent(post) {
	const now = new Date();

	// Check it's not too far in the past
	if (post.pubDate.getTime() < (now.getTime() - 7.88923e9)) // 1.578e10 == 3 months in ms
		return;

	// Check if it's like an event
	let date = findDate(post.pubDate, post.description);
	if (!date) return;

	// Check it's not too far in the future
	if (date.getTime() < now.getTime() ||
			date.getTime() > (now.getTime() + 7.88923e9)) // 1.578e10 == 3 months in ms
		return;

	return Event.findById(post.guid).then(function(anyFound) {
		// Don't add duplicates
		if (anyFound === null) {
			debug('Adding new event: ' + post.title);

			return Event.build({
				title: post.title,
				startdt: date,
				url: post.link,
				blurb: striptags(post.description),
				state: 'imported',
				importid: post.guid
			}).save({ validate: false });
		}
	});
}

// The following URL is useful for understanding the contents of 'post'
// https://github.com/danmactough/node-feedparser#what-is-the-parsed-output-produced-by-feedparser
//
// Returns a Promise
function processPost(feed, post) {
	if (!post.title || !post.guid) {
		debug("Post with no title");
		return;
	}

	return Post.findById(post.guid).then(function(anyFound) {
		// Don't add duplicates
		if (anyFound === null) {
			debug('Adding new post: ' + post.title);

			return Post.build({
				id: post.guid,
				title: post.title,
				link: post.link,
				date: post.pubDate,
				feedId: feed.id,
			}).save().then(checkPostForEvent);
		}
	})
}

function fetchFeed(feed) {
	feed.errors = null;
	feed.lastFetched = new Date();
	feed.save();

	let req = request(feed.feedURL);
	let feedparser = new FeedParser();

	let errorHandler = function(error) {
		feed.errors = error.toString();
		debug(error);
		feed.save();
	}

	req.on('error', errorHandler);
	req.on('response', function(res) {
		if (res.statusCode != 200)
			return this.emit('error', new Error('Bad status code'));

		this.pipe(feedparser);
	});

	debug('Fetching feed id ' + feed.id + ', URL: '+ feed.feedURL);

	feedparser.on('error', errorHandler);
	feedparser.on('readable', function() {
		let post;
		while ((post = this.read())) {
			processPost(feed, post);
		}
	});
}

// = Exports ================================================== //

module.exports = {
	ical: fetchICal,
	feed: fetchFeed,
	findDate: findDate,

	_processICalEntry: processICalEntry,
	_iCalDataToEvent: iCalDataToEvent
};
<|endoftext|>


<commit_before>var util = require('util');
var vm = require('vm');

var debug;

var emit_stats = function (socket, ts, metrics) {
  socket.emit('timestamp', ts);
  socket.get('stats', function (err, stats) {
    stats.forEach(function (stat) {
      if (stat == 'all') {
        socket.emit('all', metrics);
      }
      else {
        var stat_val = vm.runInNewContext(stat, metrics);
        socket.emit(stat, stat_val);
      }
    });
  });
};

exports.init = function (startup_time, config, events) {
  debug = config.debug;

  if (!config.socketPort) {
    util.log('socketPort must be specified');
    return false;
  }

  var io = require('socket.io').listen(config.socketPort);

  if (debug) {
    io.set('log level', 4);
  }
  else {
    io.set('log level', 1)
  }

  io.sockets.on('connection', function (socket) {
    socket.set('stats', []);

    var emitter = function (ts, metrics) {
      emit_stats(socket, ts, metrics);
    };
    events.on('flush', emitter);

    socket.on('subscribe', function (stat) {
      socket.get('stats', function (err, stats) {
        stats.push(stat);
        socket.set('stats', stats);
      });
    });

    socket.on('unsubscribe', function (stat) {
      socket.get('stats', function (err, stats) {
        for (var i = 0; i < stats.length; i++) {
          if (stats[i] == stat) {
            stats.splice(i, 1);
          }
        }
        socket.set('stats', stats);
      });
    });

    socket.on('disconnect', function () {
      events.removeListener('flush', emitter);
    });
  });

  return true;
};
<commit_msg>Splitting stats strings into nested objects to subscribe on any level<commit_after>var util = require('util');
var vm = require('vm');

var debug;

var emit_stats = function (socket, ts, metrics) {
  socket.emit('timestamp', ts);

  //Convert dot separated metrics into nested object
  ['gauges','timers','counters'].forEach(function (metric_type) {
    metrics[metric_type] = deepen(metrics[metric_type])[metric_type];
  });

  socket.get('stats', function (err, stats) {
    stats.forEach(function (stat) {
      if (stat == 'all') {
        socket.emit('all', metrics);
      }
      else {
        try {
          var stat_val = vm.runInNewContext(stat, metrics);
          socket.emit(stat, stat_val);
        }
        catch (e) {
          socket.emit(stat, undefined);
        }
      }
    });
  });
};

var deepen = function (o) {
  var oo = {}, t, parts, part;
  for (var k in o) {
    t = oo;
    parts = k.split('.');
    var key = parts.pop();
    while (parts.length) {
      part = parts.shift();
      t = t[part] = t[part] || {};
    }
    t[key] = o[k];
  }
  return oo;
};

exports.init = function (startup_time, config, events) {
  debug = config.debug;

  if (!config.socketPort) {
    util.log('socketPort must be specified');
    return false;
  }

  var io = require('socket.io').listen(config.socketPort);

  if (debug) {
    io.set('log level', 4);
  }
  else {
    io.set('log level', 1);
  }

  io.sockets.on('connection', function (socket) {
    socket.set('stats', []);

    var emitter = function (ts, metrics) {
      emit_stats(socket, ts, metrics);
    };
    events.on('flush', emitter);

    socket.on('subscribe', function (stat) {
      socket.get('stats', function (err, stats) {
        stats.push(stat);
        socket.set('stats', stats);
      });
    });

    socket.on('unsubscribe', function (stat) {
      socket.get('stats', function (err, stats) {
        for (var i = 0; i < stats.length; i++) {
          if (stats[i] == stat) {
            stats.splice(i, 1);
          }
        }
        socket.set('stats', stats);
      });
    });

    socket.on('disconnect', function () {
      events.removeListener('flush', emitter);
    });
  });

  return true;
};
<|endoftext|>


<commit_before>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name DomEvent
 * @namespace
 * @private
 */
var DomEvent = {
	add: function(el, events) {
		for (var type in events)
			el.addEventListener(type, events[type], false);
	},

	remove: function(el, events) {
		for (var type in events)
			el.removeEventListener(type, events[type], false);
	},

	getPoint: function(event) {
		var pos = event.targetTouches
				? event.targetTouches.length
					? event.targetTouches[0]
					: event.changedTouches[0]
				: event;
		return new Point(
			pos.pageX || pos.clientX + document.documentElement.scrollLeft,
			pos.pageY || pos.clientY + document.documentElement.scrollTop
		);
	},

	getTarget: function(event) {
		return event.target || event.srcElement;
	},

	getOffset: function(event, target) {
		// Remove target offsets from page coordinates
		return DomEvent.getPoint(event).subtract(DomElement.getOffset(
				target || DomEvent.getTarget(event)));
	},

	stop: function(event) {
		event.stopPropagation();
		event.preventDefault();
	}
};

DomEvent.requestAnimationFrame = new function() {
	var nativeRequest = DomElement.getPrefixValue(window,
			'requestAnimationFrame'),
		requested = false,
		callbacks = [],
		focused = true,
		timer;

	DomEvent.add(window, {
		focus: function() {
			focused = true;
		},
		blur: function() {
			focused = false;
		}
	});

	function handleCallbacks() {
		// Checks all installed callbacks for element visibility and
		// execute if needed.
		for (var i = callbacks.length - 1; i >= 0; i--) {
			var entry = callbacks[i],
				func = entry[0],
				el = entry[1];
			if (!el || (PaperScope.getAttribute(el, 'keepalive') == 'true'
					|| focused) && DomElement.isInView(el)) {
				// Only remove from the list once the callback was called. This
				// could take a long time based on visibility. But this way we
				// are sure to keep the animation loop running.
				callbacks.splice(i, 1);
				func();
			}
		}
		if (nativeRequest) {
			if (callbacks.length) {
				// If we haven't processed all callbacks yet, we need to keep
				// the loop running, as otherwise it would die off.
				nativeRequest(handleCallbacks);
			} else {
				requested = false;
			}
		}
	}

	return function(callback, element) {
		// Add to the list of callbacks to be called in the next animation
		// frame.
		callbacks.push([callback, element]);
		if (nativeRequest) {
			// Handle animation natively. We only need to request the frame
			// once for all collected callbacks.
			if (!requested) {
				nativeRequest(handleCallbacks);
				requested = true;
			}
		} else if (!timer) {
			// Install interval timer that checks all callbacks. This
			// results in faster animations than repeatedly installing
			// timout timers.
			timer = setInterval(handleCallbacks, 1000 / 60);
		}
	};
};
<commit_msg>Correctly handle mousemove events when switching between canvases or leaving the document.<commit_after>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2013, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name DomEvent
 * @namespace
 * @private
 */
var DomEvent = {
	add: function(el, events) {
		for (var type in events)
			el.addEventListener(type, events[type], false);
	},

	remove: function(el, events) {
		for (var type in events)
			el.removeEventListener(type, events[type], false);
	},

	getPoint: function(event) {
		var pos = event.targetTouches
				? event.targetTouches.length
					? event.targetTouches[0]
					: event.changedTouches[0]
				: event;
		return new Point(
			pos.pageX || pos.clientX + document.documentElement.scrollLeft,
			pos.pageY || pos.clientY + document.documentElement.scrollTop
		);
	},

	getTarget: function(event) {
		return event.target || event.srcElement;
	},

	getRelatedTarget: function(event) {
		return event.relatedTarget || event.toElement;
	},

	getOffset: function(event, target) {
		// Remove target offsets from page coordinates
		return DomEvent.getPoint(event).subtract(DomElement.getOffset(
				target || DomEvent.getTarget(event)));
	},

	stop: function(event) {
		event.stopPropagation();
		event.preventDefault();
	}
};

DomEvent.requestAnimationFrame = new function() {
	var nativeRequest = DomElement.getPrefixValue(window,
			'requestAnimationFrame'),
		requested = false,
		callbacks = [],
		focused = true,
		timer;

	DomEvent.add(window, {
		focus: function() {
			focused = true;
		},
		blur: function() {
			focused = false;
		}
	});

	function handleCallbacks() {
		// Checks all installed callbacks for element visibility and
		// execute if needed.
		for (var i = callbacks.length - 1; i >= 0; i--) {
			var entry = callbacks[i],
				func = entry[0],
				el = entry[1];
			if (!el || (PaperScope.getAttribute(el, 'keepalive') == 'true'
					|| focused) && DomElement.isInView(el)) {
				// Only remove from the list once the callback was called. This
				// could take a long time based on visibility. But this way we
				// are sure to keep the animation loop running.
				callbacks.splice(i, 1);
				func();
			}
		}
		if (nativeRequest) {
			if (callbacks.length) {
				// If we haven't processed all callbacks yet, we need to keep
				// the loop running, as otherwise it would die off.
				nativeRequest(handleCallbacks);
			} else {
				requested = false;
			}
		}
	}

	return function(callback, element) {
		// Add to the list of callbacks to be called in the next animation
		// frame.
		callbacks.push([callback, element]);
		if (nativeRequest) {
			// Handle animation natively. We only need to request the frame
			// once for all collected callbacks.
			if (!requested) {
				nativeRequest(handleCallbacks);
				requested = true;
			}
		} else if (!timer) {
			// Install interval timer that checks all callbacks. This
			// results in faster animations than repeatedly installing
			// timout timers.
			timer = setInterval(handleCallbacks, 1000 / 60);
		}
	};
};
<|endoftext|>


<commit_before>angular.module('utils.packetHandlers', ['utils.webRTC', 'utils.fileUpload', 'utils.linkGeneration'])

.factory('packetHandlers', ['webRTC', 'fileUpload', 'linkGeneration', 'fileTransfer', '$q', function(webRTC, fileUpload, linkGeneration, fileTransfer, $q) {
  var packetHandlerObj = {};
  var chunkCount = 0;
  var fullArray = [];
  packetHandlerObj.accepted = function(data, conn, scope) {
    var fileKey = linkGeneration.fuid();

    fileTransfer.myItems.forEach(function(val) {
      if (val.name === data.name && val.size === data.size) {
        webRTC.sendDataInChunks(conn, {
          file: val,
          name: data.name,
          size: data.size,
          id: fileKey,
          scopeRef: scope
        });
      }
    });
  };

  packetHandlerObj.offer = function(data, conn, scope) {
    scope.$apply(function() {
      var index = fileTransfer.offers.length;
      fileTransfer.offers.push({
        name: data.name,
        size: fileUpload.convert(data.size),
        accept: function() {
          conn.send({
            name: data.name,
            size: data.size,
            type: 'file-accepted'
          });
          fileTransfer.offers.splice(index, 1);
        }
      });
    });
  };

  packetHandlerObj.chunk = function(data, scope) {
    if (data.count === 0) {
      scope.$apply(function() {
        fileTransfer.activeFileTransfers[data.id] = {
          buffer: [],
          id: data.id,
          name: data.name,
          size: data.size,
          progress: 0
        };
      });
    }
    var transferObj = fileTransfer.activeFileTransfers[data.id];
    transferObj.buffer.push(data.chunk);
    scope.$apply(function() {
      transferObj.progress += 16348;
    });
    // this code takes the data off browser memory and stores to user's temp storage every 5000 packets.
    if (transferObj.buffer.length >= 5000) {
      // console.log('saved chunk at', transferObj.buffer.length);
      var blobChunk = new Blob(transferObj.buffer);
      transferObj.buffer = [];
      localforage.setItem(chunkCount.toString(), blobChunk);
      chunkCount++;
    }

    if (data.last) {
      var lastBlob = new Blob(transferObj.buffer);
      transferObj.buffer = [];
      localforage.setItem(chunkCount.toString(), lastBlob, function() {
          console.log('saved last chunk');
        })
        .then(
          function(result) {
            // console.log('first promise resolved');
            chunkCount++;
            localforage.iterate(function(value, key, iterationNumber) {
                fullArray[key] = value;
              }, function(err) {
                if (!err) {
                  console.log('Iteration has completed');
                }
              })
              .then(function() {
                // console.log('all promise resolved');
                var newFile = fileUpload.convertFromBinary({
                  file: new Blob(fullArray),
                  name: transferObj.name,
                  size: transferObj.size
                });
                fullArray = [];
                localforage.clear(function(err) {
                  console.log('local db cleared');
                });
                fileTransfer.finishedTransfers.push(newFile);
                var downloadAnchor = document.getElementById('fileLink');
                downloadAnchor.download = newFile.name;
                downloadAnchor.href = newFile.href;
              });
          }
        );
    }
  };

  return packetHandlerObj;

}]);
<commit_msg>[feat] Add ability to receieve multiple files with no db conflicts in packetHandlersFactory.js<commit_after>angular.module('utils.packetHandlers', ['utils.webRTC', 'utils.fileUpload', 'utils.linkGeneration'])

.factory('packetHandlers', ['webRTC', 'fileUpload', 'linkGeneration', 'fileTransfer', '$q', function(webRTC, fileUpload, linkGeneration, fileTransfer, $q) {
  var packetHandlerObj = {};
  var chunkCount = 0;
  var fullArray = [];
  packetHandlerObj.accepted = function(data, conn, scope) {
    var fileKey = linkGeneration.fuid();

    fileTransfer.myItems.forEach(function(val) {
      if (val.name === data.name && val.size === data.size) {
        webRTC.sendDataInChunks(conn, {
          file: val,
          name: data.name,
          size: data.size,
          id: fileKey,
          scopeRef: scope
        });
      }
    });
  };

  packetHandlerObj.offer = function(data, conn, scope) {
    scope.$apply(function() {
      var index = fileTransfer.offers.length;
      fileTransfer.offers.push({
        name: data.name,
        size: fileUpload.convert(data.size),
        accept: function() {
          conn.send({
            name: data.name,
            size: data.size,
            type: 'file-accepted'
          });
          fileTransfer.offers.splice(index, 1);
        }
      });
    });
  };

  packetHandlerObj.chunk = function(data, scope) {
    if (data.count === 0) {
      scope.$apply(function() {
        fileTransfer.activeFileTransfers[data.id] = {
          buffer: [],
          id: data.id,
          name: data.name,
          size: data.size,
          progress: 0
        };
      });
    }
    var transferObj = fileTransfer.activeFileTransfers[data.id];
    transferObj.buffer.push(data.chunk);
    scope.$apply(function() {
      transferObj.progress += 16348;
    });
    // this code takes the data off browser memory and stores to user's temp storage every 5000 packets.
    if (transferObj.buffer.length >= 5000) {
      console.log('saved chunk at', transferObj.buffer.length);
      var blobChunk = new Blob(transferObj.buffer);
      transferObj.buffer = [];
      localforage.setItem(data.id + chunkCount.toString(), blobChunk);
      chunkCount++;
    }

    if (data.last) {
      var lastBlob = new Blob(transferObj.buffer);
      transferObj.buffer = [];
      localforage.setItem(data.id + chunkCount.toString(), lastBlob, function() {
          console.log('saved last chunk');
        })
        .then(
          function(result) {
            // console.log('first promise resolved');
            chunkCount++;
            localforage.iterate(function(value, key, iterationNumber) {
                if (key.startsWith(data.id)) {
                  fullArray[key[data.id.length]] = value;
                  // delete doucment after appending
                  localforage.removeItem(data.id + (iterationNumber - 1));
                  console.log('Removed key:', data.id + (iterationNumber - 1))
                }
                // clear this document from db after
              }, function(err) {
                if (!err) {
                  console.log('Iteration has completed');
                }
              })
              .then(function() {
                // console.log('all promise resolved');
                var newFile = fileUpload.convertFromBinary({
                  file: new Blob(fullArray),
                  name: transferObj.name,
                  size: transferObj.size
                });
                fullArray = [];

                fileTransfer.finishedTransfers.push(newFile);
                var downloadAnchor = document.getElementById('fileLink');
                downloadAnchor.download = newFile.name;
                downloadAnchor.href = newFile.href;
              });
          }
        );
    }
  };

  return packetHandlerObj;

}]);
<|endoftext|>


<commit_before>require(["gitbook", "jQuery"], function(gitbook, $) {

  function expand(chapter) {
    chapter.show();
    if (chapter.parent().attr('class') != 'summary'
        && chapter.parent().attr('class') != 'book-summary'
      && chapter.length != 0
       ) {
         expand(chapter.parent());
       }
  }

  gitbook.events.bind("page.change", function() {
    $('li.chapter').children('ul.articles').hide();
    $chapter = $('li.chapter.active');
    $children = $chapter.children('ul.articles');
    $parent = $chapter.parent();
    $siblings = $chapter.siblings().children('ul.articles');

    expand($chapter);

    if ($children.length > 0) {
      $children.show();
    }
  });

});
<commit_msg>Indentation.<commit_after>require(["gitbook", "jQuery"], function(gitbook, $) {

  function expand(chapter) {
    chapter.show();

    if (chapter.parent().attr('class') != 'summary' &&
      chapter.parent().attr('class') != 'book-summary' &&
      chapter.length != 0
    ) {
      expand(chapter.parent());
    }
  }

  gitbook.events.bind("page.change", function() {
    $('li.chapter').children('ul.articles').hide();
    $chapter = $('li.chapter.active');
    $children = $chapter.children('ul.articles');
    $parent = $chapter.parent();
    $siblings = $chapter.siblings().children('ul.articles');

    expand($chapter);

    if ($children.length > 0) {
      $children.show();
    }
  });

});
<|endoftext|>