<commit_before>// (c) 2012 fred6
// This code is released under the MIT license.
define(function() {
    "use strict";

    return function( euclib ) {

        // this is probably not the proper place for the colors, but I need to think about where
        // they should go
        var pub = {},
            red = "#d43700",
            yellow = "#ffb200",
            blue = "#002e5f",
            Unit,
            CanvasGod;

        Unit = function( CG, notes ) {
            this.notes = notes;
            this.CG = CG;
        };

        Unit.prototype.goTo = function( state ) {
            this.CG.setState( state );

        };

        Unit.prototype.load = function() {
            this.goTo( 0 );
        };

        // CanvasGod is an object that has a collection of canvas objects
        // (children). each object has (for now) a single number attached,
        // which indicates the step when the object becomes visible on the canvas
        //
        // for objects that appear and disappear (and possibly reappear again),
        // we can use a list of numbers [a, b, c]
        // where the first number indicates the step when it appears, the second
        // indicates the number where it disappears, the third when it re-appears, etc.
        // I'm starting off with a single number because I'm not certain we need the
        // added functionality
        CanvasGod = function( initfn ) {
            // each child is an object consisting of a Euclib object and a number
            // I could verify that its valid, but I'm the only one using this, so I probably
            // just won't bother!
            this.children = initfn();
            this.numStates = 0;
            for ( var i = 0; i < this.children.length; i++ ) {
                if ( this.children[i].state > this.numStates ) {
                    this.numStates = this.children[i].state;
                }
            }
            this.numStates += 1; // children.state is 0-referenced
        };

        CanvasGod.prototype.setState = function( state ) {
            var i, thisChild;
            for(i = 0; i < this.children.length; i++) {
                thisChild = this.children[i];

                if(thisChild.state <= state) {
                    thisChild.eucObj.show(thisChild.stroke);
                } else {
                    thisChild.eucObj.hide();
                }
            }
        };

        /*** Specific units ***/
        var b1 = {};

        // Book 1 Prop 1

        // helper
        function createCGChild(eucObj, state, stroke) {
            var obj = {
                eucObj: eucObj,
                state: state
            };

            if ( stroke !== undefined) {
                obj["stroke"] = stroke;
            }

            return obj;
        };

        b1.prop1 = {
            init: function() {
                var children = [],
                    A = new euclib.Point(150, 180.5),
                    B = new euclib.Point(220, 180.5),
                    seg = new euclib.Segment(A, B),
                    c1 = euclib.circFromSeg(seg, "A"),
                    c2 = euclib.circFromSeg(seg, "B"),
                    inter = euclib.findCircsIntersection(c1,c2),
                    Lside = new euclib.Segment(A, inter),
                    Rside = new euclib.Segment(B, inter);

                children[0] = createCGChild(seg, 0);
                children[1] = createCGChild(c1, 1, red);
                children[2] = createCGChild(c2, 2, yellow);
                children[3] = createCGChild(inter, 3);
                children[4] = createCGChild(Lside, 4, red);
                children[5] = createCGChild(Rside, 5, yellow);

                return children;
            },

            notes: "
Euclid doesn't really prove that the two circles must intersect, he basically assumes it. You need to add additional postulates to cover this
"

        }; // b1prop1

        // Pythagorean Theorem Logo
        b1.pythag_logo = {
            init: function() {
                var children = [],
                    A = new euclib.Point(105, 213.5),
                    B = new euclib.Point(290, 213.5),
                    segAB = new euclib.Segment(A, B),
                    // calculating the coords of the point that would
                    // make a right triangle at a given ACang
                    ACang = Math.atan(6/4),
                    AClen = segAB.length * Math.cos(ACang),
                    Cx_off = AClen*Math.cos(ACang),
                    Cy_off = AClen*Math.sin(ACang),
                    C = new euclib.Point(A.x + Cx_off, A.y - Cy_off),
                    segBC = new euclib.Segment(B, C),
                    segAC = new euclib.Segment(A, C),
                    group1 = new euclib.logoSquareOnSegment(segAB, "bottom"),
                    group2 = new euclib.logoSquareOnSegment(segBC, "top"),
                    group3 = new euclib.logoSquareOnSegment(segAC, "top"),
                    D = new euclib.Point(C.x, A.y + segAB.length),
                    segCD = new euclib.Segment(C, D),
                    segA_BCT = new euclib.Segment(A, group2.segST.B),
                    segB_ACS = new euclib.Segment(B, group3.segST.A),
                    segC_ABS = new euclib.Segment(C, group1.segST.A),
                    segC_ABT = new euclib.Segment(C, group1.segST.B);

                children[0] = createCGChild(segAB, 0, red);
                children[1] = createCGChild(segBC, 0, yellow);
                children[2] = createCGChild(segAC, 0, blue);
                children[3] = createCGChild(group1, 1, red);
                children[4] = createCGChild(group2, 1, yellow);
                children[5] = createCGChild(group3, 1, blue);
                children[6] = createCGChild(segCD, 2, red);
                children[7] = createCGChild(segA_BCT, 2, yellow);
                children[8] = createCGChild(segB_ACS, 2, blue);
                children[9] = createCGChild(segC_ABS, 3);
                children[10] = createCGChild(segC_ABT, 3);

                return children;

            },

            notes: "
squee
"
        };

        // turn unit definitions into actual unit objects
        // something about this code seems deeply wrong to me but I'm not smart enough
        // to figure out an alternative right now
        var unit, udef, CG;
        for ( unit in b1 ) {
            if ( b1.hasOwnProperty ( unit ) ) {
                udef = b1[unit];
                CG = new CanvasGod ( udef.init );
                pub["b1"+unit] = new Unit ( CG , udef.notes );
            }
        }

        return pub;

    }; // return function

});
<commit_msg>add a unit for prop2. this is borked, it doesnt display step 1 correctly (step 2 masks it because the segment that we display in step 1 is assigned to the EleGroup that we have for step 2), but im committing this because the correct solution will take some more thinking<commit_after>// (c) 2012 fred6
// This code is released under the MIT license.
define(function() {
    "use strict";

    return function( euclib ) {

        // this is probably not the proper place for the colors, but I need to think about where
        // they should go
        var pub = {},
            red = "#d43700",
            yellow = "#ffb200",
            blue = "#002e5f",
            gray = "#666",
            Unit,
            CanvasGod;

        Unit = function( CG, notes ) {
            this.notes = notes;
            this.CG = CG;
        };

        Unit.prototype.goTo = function( state ) {
            this.CG.setState( state );

        };

        Unit.prototype.load = function() {
            this.goTo( 0 );
        };

        // CanvasGod is an object that has a collection of canvas objects
        // (children). each object has (for now) a single number attached,
        // which indicates the step when the object becomes visible on the canvas
        //
        // for objects that appear and disappear (and possibly reappear again),
        // we can use a list of numbers [a, b, c]
        // where the first number indicates the step when it appears, the second
        // indicates the number where it disappears, the third when it re-appears, etc.
        // I'm starting off with a single number because I'm not certain we need the
        // added functionality
        CanvasGod = function( initfn ) {
            // each child is an object consisting of a Euclib object and a number
            // I could verify that its valid, but I'm the only one using this, so I probably
            // just won't bother!
            this.children = initfn();
            this.numStates = 0;
            for ( var i = 0; i < this.children.length; i++ ) {
                if ( this.children[i].state > this.numStates ) {
                    this.numStates = this.children[i].state;
                }
            }
            this.numStates += 1; // children.state is 0-referenced
        };

        CanvasGod.prototype.setState = function( state ) {
            var i, thisChild;
            for(i = 0; i < this.children.length; i++) {
                thisChild = this.children[i];

                if(thisChild.state <= state) {
                    thisChild.eucObj.show(thisChild.stroke);
                } else {
                    thisChild.eucObj.hide();
                }
            }
        };

        /*** Specific units ***/
        var b1 = {};

        // Book 1 Prop 1

        // helper
        function createCGChild(eucObj, state, stroke) {
            var obj = {
                eucObj: eucObj,
                state: state
            };

            if ( stroke !== undefined) {
                obj["stroke"] = stroke;
            }

            return obj;
        };

        b1.prop1 = {
            init: function() {
                var children = [],
                    A = new euclib.Point(150, 180.5),
                    B = new euclib.Point(220, 180.5),
                    seg = new euclib.Segment(A, B),
                    c1 = euclib.circFromSeg(seg, "A"),
                    c2 = euclib.circFromSeg(seg, "B"),
                    inter = euclib.findCircsIntersection(c1,c2),
                    Lside = new euclib.Segment(A, inter),
                    Rside = new euclib.Segment(B, inter);

                children[0] = createCGChild(seg, 0);
                children[1] = createCGChild(c1, 1, red);
                children[2] = createCGChild(c2, 2, yellow);
                children[3] = createCGChild(inter, 3);
                children[4] = createCGChild(Lside, 4, red);
                children[5] = createCGChild(Rside, 5, yellow);

                return children;
            },

            notes: "
Euclid doesn't really prove that the two circles must intersect, he basically assumes it. You need to add additional postulates to cover this
"

        }; // b1prop1

        b1.prop2 = {
            init: function() {
                var children = [],
                    A = new euclib.Point(150, 180.5),
                    B = new euclib.Point(220, 220.5),
                    C = new euclib.Point(260, 170.5),
                    seg = new euclib.Segment(A, B),
                    segBC = new euclib.Segment(B, C),
                    eqtri = euclib.Prop1(segBC),
                    seg_circ = euclib.circFromSeg(seg, "B"),
                    ext_seg = euclib.extendSegment(eqtri.sideA, "B", seg.length + 30, 1),
                    //find intersection of circle and extended line
                    interpt = euclib.findCircCenterSegIntersection(seg_circ, ext_seg),
                    // the other point in the eq tri (not B or C)
                    eqtri_otherpt = eqtri.sideA.A,

                    // line from other point of the eqtri to the intersection of the
                    // extension and the circle
                    ext_inter_seg = new euclib.Segment(eqtri_otherpt, interpt),

                    ext_inter_seg_circ = euclib.circFromSeg(ext_inter_seg, "A"),

                    // extend the remaining side of the eq tri
                    last_ext_seg = euclib.extendSegment(eqtri.sideB, "B", seg.length + 30, 1),
                    // find intersection of the newest circle and the last_ext_seg
                    inter2pt = euclib.findCircCenterSegIntersection(ext_inter_seg_circ, last_ext_seg);

                children[0] = createCGChild(seg, 0);
                children[1] = createCGChild(C, 0);
                children[2] = createCGChild(segBC, 1, gray);
                children[3] = createCGChild(eqtri, 2, red);
                children[4] = createCGChild(seg_circ, 3, blue);
                children[5] = createCGChild(ext_seg, 4, yellow);
                children[6] = createCGChild(ext_inter_seg_circ, 5, red);
                children[7] = createCGChild(last_ext_seg, 6, red);
                children[8] = createCGChild(inter2pt, 7);

                return children;
            },

            notes: ""

        }; // b1prop2

        // Pythagorean Theorem Logo
        b1.pythag_logo = {
            init: function() {
                var children = [],
                    A = new euclib.Point(105, 213.5),
                    B = new euclib.Point(290, 213.5),
                    segAB = new euclib.Segment(A, B),
                    // calculating the coords of the point that would
                    // make a right triangle at a given ACang
                    ACang = Math.atan(6/4),
                    AClen = segAB.length * Math.cos(ACang),
                    Cx_off = AClen*Math.cos(ACang),
                    Cy_off = AClen*Math.sin(ACang),
                    C = new euclib.Point(A.x + Cx_off, A.y - Cy_off),
                    segBC = new euclib.Segment(B, C),
                    segAC = new euclib.Segment(A, C),
                    group1 = new euclib.logoSquareOnSegment(segAB, "bottom"),
                    group2 = new euclib.logoSquareOnSegment(segBC, "top"),
                    group3 = new euclib.logoSquareOnSegment(segAC, "top"),
                    D = new euclib.Point(C.x, A.y + segAB.length),
                    segCD = new euclib.Segment(C, D),
                    segA_BCT = new euclib.Segment(A, group2.segST.B),
                    segB_ACS = new euclib.Segment(B, group3.segST.A),
                    segC_ABS = new euclib.Segment(C, group1.segST.A),
                    segC_ABT = new euclib.Segment(C, group1.segST.B);

                children[0] = createCGChild(segAB, 0, red);
                children[1] = createCGChild(segBC, 0, yellow);
                children[2] = createCGChild(segAC, 0, blue);
                children[3] = createCGChild(group1, 1, red);
                children[4] = createCGChild(group2, 1, yellow);
                children[5] = createCGChild(group3, 1, blue);
                children[6] = createCGChild(segCD, 2, red);
                children[7] = createCGChild(segA_BCT, 2, yellow);
                children[8] = createCGChild(segB_ACS, 2, blue);
                children[9] = createCGChild(segC_ABS, 3);
                children[10] = createCGChild(segC_ABT, 3);

                return children;

            },

            notes: "
squee
"
        };

        // turn unit definitions into actual unit objects
        // something about this code seems deeply wrong to me but I'm not smart enough
        // to figure out an alternative right now
        var unit, udef, CG;
        for ( unit in b1 ) {
            if ( b1.hasOwnProperty ( unit ) ) {
                udef = b1[unit];
                CG = new CanvasGod ( udef.init );
                pub["b1"+unit] = new Unit ( CG , udef.notes );
            }
        }

        return pub;

    }; // return function

});
<|endoftext|>


<commit_before>var shell = require('gl-now')({ clearColor: [1, 1, 1, 0] })
var camera = require('game-shell-orbit-camera')(shell)
var analyze = require('web-audio-analyser')
var badge = require('soundcloud-badge')
var fs = require('fs')

var createTexture = require('gl-texture2d')
var createShader  = require('gl-shader')
var GLMatrix      = require('gl-matrix')
var createBuffer  = require('gl-buffer')
var createVAO     = require('gl-vao')

var mat4 = GLMatrix.mat4
var quat = GLMatrix.quat

shell.on('gl-init', init)
shell.on('gl-render', render)

var analyzer

badge({
    client_id: 'ded451c6d8f9ff1c62f72523f49dab68'
  , song: 'https://soundcloud.com/dylan_king/modern-housing'
  , dark: true
  , getFonts: true
}, function(err, src, json, div) {
  if (err) throw err

  var audio = new Audio

  audio.loop = true
  audio.addEventListener('canplay', function() {
    audio.play()
    analyzer = analyze(audio)
    analyzer.waveform(wave)
  })

  audio.src = src
  document.body.appendChild(div)
})

var waveform = document.createElement('canvas')
var wctx = waveform.getContext('2d')
var wave = new Uint8Array(1024)

waveform.style.position = 'absolute'
waveform.style.left = '0'
waveform.style.bottom = '0'
waveform.style.zIndex = 9999

waveform.height = 1
waveform.width = 1024

wctx.fillStyle = '#000'
wctx.fillRect(0, 0, 1024, 1)

var meshes = []
var shader
var wtex
var gl

function init() {
  gl = shell.gl

  camera.center[0] = +64
  camera.center[1] = +32
  camera.center[2] = -64
  quat.rotateX(camera.rotation, camera.rotation, -0.35)

  meshes.push(createMesh(0, 0))
  wtex = createTexture(gl, waveform)
  wtex.minFilter = gl.LINEAR
  wtex.maxFilter = gl.LINEAR
  shader = createShader(gl
    , fs.readFileSync(__dirname + '/shaders/terrain.vert', 'utf8')
    , fs.readFileSync(__dirname + '/shaders/terrain.frag', 'utf8')
  )
}

var t = 0
function render() {
  gl.enable(gl.CULL_FACE)
  gl.enable(gl.DEPTH_TEST)
  t += 1

  var projection = mat4.perspective(new Float32Array(16), 0.25*Math.PI, shell.width/shell.height, 0.05, 1000)
  var model = mat4.identity(new Float32Array(16))
  var view = camera.view()

  // WebGL won't let you pass through uniforms
  // that are very large, like say 1024 elements
  // large. So, we can hack around that by storing
  // the data in a texture! This is actually a bottleneck
  // at the moment - could be sped up by using an FBO/GLSL
  // instead of a <canvas>, but there hasn't been the
  // need quite yet :)
  if (analyzer) {
    analyzer.waveform(wave)
    for (var i = 0; i < wave.length; i += 1) {
      var r = +Math.abs((wave[i]) - 128)|0
      var g = r & 255
      var b = wave[i] > 0 ? 255 : 0
      wctx.fillStyle = 'rgb('+(r>>8)+','+g+','+b+')'
      wctx.fillRect(i, 0, 1, 1)
    }
  }

  wtex.bind(0)
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, waveform)
  shader.bind()

  shader.uniforms.uProjection = projection
  shader.uniforms.uModel = model
  shader.uniforms.uView = view
  shader.uniforms.uWaveform = 0
  shader.uniforms.tNoise = 1
  shader.uniforms.t = t / 100

  shader.attributes.aPosition.location = 0
  shader.attributes.aVertex1.location = 1
  shader.attributes.aVertex2.location = 2
  shader.attributes.aVertex3.location = 3

  for (var i = 0; i < meshes.length; i += 1) {
    meshes[i].vao.bind()
    gl.drawArrays(gl.TRIANGLES, 0, meshes[i].length)
    meshes[i].vao.unbind()
  }
}

function createMesh(xoffset, yoffset) {
  var count = 64 * 64
  var size = count * 12
  var aPositionData = new Float32Array(size)
  var aVertex1Data  = new Float32Array(size)
  var aVertex2Data  = new Float32Array(size)
  var aVertex3Data  = new Float32Array(size)
  xoffset = xoffset || 0
  yoffset = yoffset || 0
  var xscale = 2
  var yscale = 2

  var i = 0
  for (var X = 0; X < 64; X++)
  for (var Y = 0; Y < 64; Y++, i += 12) {
    var x = X * xscale + xoffset * xscale
    var y = Y * yscale + yoffset * yscale

    // Triangle 1
    aPositionData[i   ] = x+xscale
    aPositionData[i+1 ] = y
    aPositionData[i+2 ] = x
    aPositionData[i+3 ] = y
    aPositionData[i+4 ] = x
    aPositionData[i+5 ] = y+yscale

    // Triangle 2
    aPositionData[i+6 ] = x
    aPositionData[i+7 ] = y+yscale

    aPositionData[i+8 ] = x+xscale
    aPositionData[i+9 ] = y+yscale

    aPositionData[i+10] = x+xscale
    aPositionData[i+11] = y

    aVertex1Data[i   ] = x+xscale
    aVertex1Data[i+1 ] = y
    aVertex1Data[i+2 ] = x+xscale
    aVertex1Data[i+3 ] = y
    aVertex1Data[i+4 ] = x+xscale
    aVertex1Data[i+5 ] = y
    aVertex1Data[i+6 ] = x
    aVertex1Data[i+7 ] = y+yscale
    aVertex1Data[i+8 ] = x
    aVertex1Data[i+9 ] = y+yscale
    aVertex1Data[i+10] = x
    aVertex1Data[i+11] = y+yscale

    aVertex2Data[i   ] = x
    aVertex2Data[i+1 ] = y
    aVertex2Data[i+2 ] = x
    aVertex2Data[i+3 ] = y
    aVertex2Data[i+4 ] = x
    aVertex2Data[i+5 ] = y
    aVertex2Data[i+6 ] = x+xscale
    aVertex2Data[i+7 ] = y+yscale
    aVertex2Data[i+8 ] = x+xscale
    aVertex2Data[i+9 ] = y+yscale
    aVertex2Data[i+10] = x+xscale
    aVertex2Data[i+11] = y+yscale

    aVertex3Data[i   ] = x
    aVertex3Data[i+1 ] = y+yscale
    aVertex3Data[i+2 ] = x
    aVertex3Data[i+3 ] = y+yscale
    aVertex3Data[i+4 ] = x
    aVertex3Data[i+5 ] = y+yscale
    aVertex3Data[i+6 ] = x+xscale
    aVertex3Data[i+7 ] = y
    aVertex3Data[i+8 ] = x+xscale
    aVertex3Data[i+9 ] = y
    aVertex3Data[i+10] = x+xscale
    aVertex3Data[i+11] = y
  }

  function createAttribute(data) {
    return {
      buffer: createBuffer(gl, data)
      , type: gl.FLOAT
      , size: 2
      , offset: 0
      , stride: 0
      , normalized: false
    }
  }

  var attributes
  var vao = createVAO(gl, null, attributes = [
      createAttribute(aPositionData)
    , createAttribute(aVertex1Data)
    , createAttribute(aVertex2Data)
    , createAttribute(aVertex3Data)
  ])

  return { vao: vao, length: size / 2 }
}
<commit_msg>cors issue for playback from soundcloud<commit_after>var shell = require('gl-now')({ clearColor: [1, 1, 1, 0] })
var camera = require('game-shell-orbit-camera')(shell)
var analyze = require('web-audio-analyser')
var badge = require('soundcloud-badge')
var fs = require('fs')

var createTexture = require('gl-texture2d')
var createShader  = require('gl-shader')
var GLMatrix      = require('gl-matrix')
var createBuffer  = require('gl-buffer')
var createVAO     = require('gl-vao')

var mat4 = GLMatrix.mat4
var quat = GLMatrix.quat

shell.on('gl-init', init)
shell.on('gl-render', render)

var analyzer

badge({
    client_id: 'ded451c6d8f9ff1c62f72523f49dab68'
  , song: 'https://soundcloud.com/dylan_king/modern-housing'
  , dark: true
  , getFonts: true
}, function(err, src, json, div) {
  if (err) throw err

  var audio = new Audio

  audio.loop = true
  audio.addEventListener('canplay', function() {
    audio.play()
    analyzer = analyze(audio)
    analyzer.waveform(wave)
  })
  audio.crossOrigin = 'Anonymous'
  audio.src = src
  document.body.appendChild(div)
})

var waveform = document.createElement('canvas')
var wctx = waveform.getContext('2d')
var wave = new Uint8Array(1024)

waveform.style.position = 'absolute'
waveform.style.left = '0'
waveform.style.bottom = '0'
waveform.style.zIndex = 9999

waveform.height = 1
waveform.width = 1024

wctx.fillStyle = '#000'
wctx.fillRect(0, 0, 1024, 1)

var meshes = []
var shader
var wtex
var gl

function init() {
  gl = shell.gl

  camera.center[0] = +64
  camera.center[1] = +32
  camera.center[2] = -64
  quat.rotateX(camera.rotation, camera.rotation, -0.35)

  meshes.push(createMesh(0, 0))
  wtex = createTexture(gl, waveform)
  wtex.minFilter = gl.LINEAR
  wtex.maxFilter = gl.LINEAR
  shader = createShader(gl
    , fs.readFileSync(__dirname + '/shaders/terrain.vert', 'utf8')
    , fs.readFileSync(__dirname + '/shaders/terrain.frag', 'utf8')
  )
}

var t = 0
function render() {
  gl.enable(gl.CULL_FACE)
  gl.enable(gl.DEPTH_TEST)
  t += 1

  var projection = mat4.perspective(new Float32Array(16), 0.25*Math.PI, shell.width/shell.height, 0.05, 1000)
  var model = mat4.identity(new Float32Array(16))
  var view = camera.view()

  // WebGL won't let you pass through uniforms
  // that are very large, like say 1024 elements
  // large. So, we can hack around that by storing
  // the data in a texture! This is actually a bottleneck
  // at the moment - could be sped up by using an FBO/GLSL
  // instead of a <canvas>, but there hasn't been the
  // need quite yet :)
  if (analyzer) {
    analyzer.waveform(wave)
    for (var i = 0; i < wave.length; i += 1) {
      var r = +Math.abs((wave[i]) - 128)|0
      var g = r & 255
      var b = wave[i] > 0 ? 255 : 0
      wctx.fillStyle = 'rgb('+(r>>8)+','+g+','+b+')'
      wctx.fillRect(i, 0, 1, 1)
    }
  }

  wtex.bind(0)
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, waveform)
  shader.bind()

  shader.uniforms.uProjection = projection
  shader.uniforms.uModel = model
  shader.uniforms.uView = view
  shader.uniforms.uWaveform = 0
  shader.uniforms.tNoise = 1
  shader.uniforms.t = t / 100

  shader.attributes.aPosition.location = 0
  shader.attributes.aVertex1.location = 1
  shader.attributes.aVertex2.location = 2
  shader.attributes.aVertex3.location = 3

  for (var i = 0; i < meshes.length; i += 1) {
    meshes[i].vao.bind()
    gl.drawArrays(gl.TRIANGLES, 0, meshes[i].length)
    meshes[i].vao.unbind()
  }
}

function createMesh(xoffset, yoffset) {
  var count = 64 * 64
  var size = count * 12
  var aPositionData = new Float32Array(size)
  var aVertex1Data  = new Float32Array(size)
  var aVertex2Data  = new Float32Array(size)
  var aVertex3Data  = new Float32Array(size)
  xoffset = xoffset || 0
  yoffset = yoffset || 0
  var xscale = 2
  var yscale = 2

  var i = 0
  for (var X = 0; X < 64; X++)
  for (var Y = 0; Y < 64; Y++, i += 12) {
    var x = X * xscale + xoffset * xscale
    var y = Y * yscale + yoffset * yscale

    // Triangle 1
    aPositionData[i   ] = x+xscale
    aPositionData[i+1 ] = y
    aPositionData[i+2 ] = x
    aPositionData[i+3 ] = y
    aPositionData[i+4 ] = x
    aPositionData[i+5 ] = y+yscale

    // Triangle 2
    aPositionData[i+6 ] = x
    aPositionData[i+7 ] = y+yscale

    aPositionData[i+8 ] = x+xscale
    aPositionData[i+9 ] = y+yscale

    aPositionData[i+10] = x+xscale
    aPositionData[i+11] = y

    aVertex1Data[i   ] = x+xscale
    aVertex1Data[i+1 ] = y
    aVertex1Data[i+2 ] = x+xscale
    aVertex1Data[i+3 ] = y
    aVertex1Data[i+4 ] = x+xscale
    aVertex1Data[i+5 ] = y
    aVertex1Data[i+6 ] = x
    aVertex1Data[i+7 ] = y+yscale
    aVertex1Data[i+8 ] = x
    aVertex1Data[i+9 ] = y+yscale
    aVertex1Data[i+10] = x
    aVertex1Data[i+11] = y+yscale

    aVertex2Data[i   ] = x
    aVertex2Data[i+1 ] = y
    aVertex2Data[i+2 ] = x
    aVertex2Data[i+3 ] = y
    aVertex2Data[i+4 ] = x
    aVertex2Data[i+5 ] = y
    aVertex2Data[i+6 ] = x+xscale
    aVertex2Data[i+7 ] = y+yscale
    aVertex2Data[i+8 ] = x+xscale
    aVertex2Data[i+9 ] = y+yscale
    aVertex2Data[i+10] = x+xscale
    aVertex2Data[i+11] = y+yscale

    aVertex3Data[i   ] = x
    aVertex3Data[i+1 ] = y+yscale
    aVertex3Data[i+2 ] = x
    aVertex3Data[i+3 ] = y+yscale
    aVertex3Data[i+4 ] = x
    aVertex3Data[i+5 ] = y+yscale
    aVertex3Data[i+6 ] = x+xscale
    aVertex3Data[i+7 ] = y
    aVertex3Data[i+8 ] = x+xscale
    aVertex3Data[i+9 ] = y
    aVertex3Data[i+10] = x+xscale
    aVertex3Data[i+11] = y
  }

  function createAttribute(data) {
    return {
      buffer: createBuffer(gl, data)
      , type: gl.FLOAT
      , size: 2
      , offset: 0
      , stride: 0
      , normalized: false
    }
  }

  var attributes
  var vao = createVAO(gl, null, attributes = [
      createAttribute(aPositionData)
    , createAttribute(aVertex1Data)
    , createAttribute(aVertex2Data)
    , createAttribute(aVertex3Data)
  ])

  return { vao: vao, length: size / 2 }
}
<|endoftext|>


<commit_before>/* lib/CORS.js
 Inspired by se7ensky-restify-preflight
 Source: https://github.com/Se7enSky/se7ensky-restify-preflight
 License: MIT
 Permalink: https://github.com/Se7enSky/se7ensky-restify-preflight/blob/70de209f64d7624f46cd54eadfffec1aae14e403/index.js
*/
module.exports = function(server, opts) {
	// Access-Control-Allow-Headers
	var defaultHeaders = [
		'Accept',
		'Access-Control-Allow-Credentials',
		'Origin',
		'Content-Type',
		'Request-Id',
		'Server',
		'X-Api-Version',
		'X-Request-Id',
		'X-Requested-With'
	]
	var enabledHeaders = defaultHeaders.concat(opts.headers ? opts.headers : [])
	var headers = enabledHeaders.join(', ')

	// Access-Control-Expose-Headers
	var defaultExposeHeaders = [
		'Content-Type',
		'Request-Id',
		'Server',
		'X-Api-Version',
		'X-Request-Id',
		'X-Requested-With'
	]
	var enabledExposeHeaders = defaultExposeHeaders.concat(opts.exposeHeaders ? opts.exposeHeaders : [])
	var exposeHeaders = enabledExposeHeaders.join(', ')

	// Default middleware to enable CORS
	server.use(function(req, res, next) {
		console.log(req.headers.origin, opts.origins)
		if(req.headers['origin']) {
			if(!opts.origins ||
				(opts.origins instanceof Array && opts.origins.length < 1) ||
				(opts.origins && opts.origins.indexOf(req.headers['origin']) > -1) ||
				(opts.origins && opts.origins[0] == '*')
				) {
				res.header('Access-Control-Allow-Origin', req.headers['origin'])
			}
		}
		if(opts.allowCredentials) res.header('Access-Control-Allow-Credentials', 'true')
		res.header('Access-Control-Allow-Headers', headers)
		res.header('Access-Control-Expose-Headers', exposeHeaders)
		return next()
	})

	// Support for OPTIONS requests (for preflighted CORS requests)
	server.opts('.*', function(req, res, next) {
		if (req.headers.origin && req.headers['access-control-request-method']) {
			if(!opts.origins ||
				(opts.origins instanceof Array && opts.origins.length < 1) ||
				(opts.origins && opts.origins.indexOf(req.headers['origin']) > -1) ||
				(opts.origins && opts.origins[0] == '*')
				) {
				res.header('Access-Control-Allow-Origin', req.headers['origin'])
			}
			if(opts.allowCredentials) res.header('Access-Control-Allow-Credentials', 'true')
			res.header('Access-Control-Allow-Headers', headers)
			res.header('Access-Control-Expose-Headers', exposeHeaders)
			res.header('Allow', req.headers['access-control-request-method'])
			res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method'])
			if (req.log) {
				req.log.info({
					url: req.url,
					method: req.headers['access-control-request-method']
				}, 'Preflight')
			}
			res.send(204)
			return next()
		} else {
			res.send(404)
			return next()
		}
	})
}<commit_msg>Removed debug code<commit_after>/* lib/CORS.js
 Inspired by se7ensky-restify-preflight
 Source: https://github.com/Se7enSky/se7ensky-restify-preflight
 License: MIT
 Permalink: https://github.com/Se7enSky/se7ensky-restify-preflight/blob/70de209f64d7624f46cd54eadfffec1aae14e403/index.js
*/
module.exports = function(server, opts) {
	// Access-Control-Allow-Headers
	var defaultHeaders = [
		'Accept',
		'Access-Control-Allow-Credentials',
		'Origin',
		'Content-Type',
		'Request-Id',
		'Server',
		'X-Api-Version',
		'X-Request-Id',
		'X-Requested-With'
	]
	var enabledHeaders = defaultHeaders.concat(opts.headers ? opts.headers : [])
	var headers = enabledHeaders.join(', ')

	// Access-Control-Expose-Headers
	var defaultExposeHeaders = [
		'Content-Type',
		'Request-Id',
		'Server',
		'X-Api-Version',
		'X-Request-Id',
		'X-Requested-With'
	]
	var enabledExposeHeaders = defaultExposeHeaders.concat(opts.exposeHeaders ? opts.exposeHeaders : [])
	var exposeHeaders = enabledExposeHeaders.join(', ')

	// Default middleware to enable CORS
	server.use(function(req, res, next) {
		if(req.headers['origin']) {
			if(!opts.origins ||
				(opts.origins instanceof Array && opts.origins.length < 1) ||
				(opts.origins && opts.origins.indexOf(req.headers['origin']) > -1) ||
				(opts.origins && opts.origins[0] == '*')
				) {
				res.header('Access-Control-Allow-Origin', req.headers['origin'])
			}
		}
		if(opts.allowCredentials) res.header('Access-Control-Allow-Credentials', 'true')
		res.header('Access-Control-Allow-Headers', headers)
		res.header('Access-Control-Expose-Headers', exposeHeaders)
		return next()
	})

	// Support for OPTIONS requests (for preflighted CORS requests)
	server.opts('.*', function(req, res, next) {
		if (req.headers.origin && req.headers['access-control-request-method']) {
			if(!opts.origins ||
				(opts.origins instanceof Array && opts.origins.length < 1) ||
				(opts.origins && opts.origins.indexOf(req.headers['origin']) > -1) ||
				(opts.origins && opts.origins[0] == '*')
				) {
				res.header('Access-Control-Allow-Origin', req.headers['origin'])
			}
			if(opts.allowCredentials) res.header('Access-Control-Allow-Credentials', 'true')
			res.header('Access-Control-Allow-Headers', headers)
			res.header('Access-Control-Expose-Headers', exposeHeaders)
			res.header('Allow', req.headers['access-control-request-method'])
			res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method'])
			if (req.log) {
				req.log.info({
					url: req.url,
					method: req.headers['access-control-request-method']
				}, 'Preflight')
			}
			res.send(204)
			return next()
		} else {
			res.send(404)
			return next()
		}
	})
}<|endoftext|>


<commit_before>var app = angular.module("myApp",[]);
app.controller('ChartsController', ChartsController);

function ChartsController($scope) {
  $scope.headers = [];
  $scope.model = [];
  $scope.examples = Object.keys(examples).sort(function(a,b) {
	  return examples[b].headers.length - examples[a].headers.length;
      });

  $scope.setData = function(example) {
    $scope.charts = [];
    $scope.headers = examples[example].headers;
    var data = examples[example];
    $scope.model = Autoencoder.deserialize(data);
  };
}

app.directive("renderChart",function(){
  return function($scope, element, attrs){
    var j = $scope.$index;
    var getUpdateFn = function(index) {
      return function(update, newValue) { redraw($scope.model, $scope.charts, update, index, newValue); };
    }
    var chart = new Chart(element, getUpdateFn(j));

    $scope.charts.push(chart);

    if ($scope.charts.length == $scope.headers.length) {
      redraw($scope.model, $scope.charts, true);
    }
  }
});

function redraw(model, charts, update, index, newValue) {
  if (update && newValue != undefined)
    charts[index].fixedValue = newValue;

  var row = [];
  for (var j = 0; j < charts.length; j++)
    row.push(charts[j].fixedValue);

  if (newValue != undefined)
    row[index] = newValue;

  var curves = model.getPdfs(row);

  for (var j = 0; j < row.length; j++) {
    if (update) {
      charts[j].update(curves[j]);
      charts[j].render(null);
    } else {
      charts[j].render(curves[j]);
    }
  }
}

function Chart(element, redraw) {
  this.margin = {top: 10, right: 30, bottom: 30, left: 30};
  this.width = element[0].offsetWidth,
  this.height = element[0].offsetHeight,
  this.nBins = 30;
  this.fixedValue = undefined;
  this.redraw = redraw;

  var barWidth = Math.floor(this.width/this.nBins);
  this.width = barWidth * this.nBins;

  var svg = d3.select(element[0])
      .append('svg')
      .attr("width", this.width) // + this.margin.left + this.margin.right)
      .attr("height", this.height) // - this.margin.top - this.margin.bottom)
      .append("g");

  this.axis = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (this.height - this.margin.bottom) + ")");

  this.path = svg.append('path')
    .attr('stroke', 'black')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPath = svg.append('path')
    .attr('stroke', 'green')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPathQuartiles = svg.append('path')
    .attr('fill', 'green')
    .attr('fill-opacity', '0.1');

  var focus = svg.append("g")
      .attr("class", "focus")
      .style("display", "none");

  focus.append("circle")
    .attr("r", 4.5);

  focus.append("text")
    .attr("x", 9)
    .attr("dy", ".35em");

  svg.append("rect")
    .attr("fill", "none")
    .attr("pointer-events", "all")
    .attr("width", this.width)
    .attr("height", this.height)
    .on("mouseover", move)
    .on("mouseout", out)
    .on("mousemove", move)
    .on("click", click)

  var bisectData = d3.bisector(function(d) { return d.x; }).left;

  var chart = this;

  function click() {
    focus.locked = true;

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(true, x0);
  }

  function move() {
    if (!chart.data)
      return;

    if (focus.locked)
      return;

    focus.style("display", null);

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(false, x0);
  }

  function out() {
    if (!focus.locked)
      focus.style("display", 'none');

    chart.redraw(true, null);
  }
}

Chart.prototype.update = function(data) {
  this.data = data;
}

Chart.prototype.render = function(hypoData) {
  this.x = d3.scale.linear()
    .domain(d3.extent(this.data.xy, function(d) { return d.x; }))
    .range([0, this.width]);

  var getY = function(d) { return d.y };
  var max = d3.max(this.data.xy, getY);
  if (hypoData)
      max = Math.max(max, d3.max(hypoData.xy, getY));

  this.y = d3.scale.linear()
    .domain([0, max])
    .range([this.height - this.margin.bottom, 0]);

  var xAxis = d3.svg.axis()
      .scale(this.x)
      .orient("bottom");

  this.axis.call(xAxis);

  var chart = this;
  var lineFunction = d3.svg.line()
      .x(function(d) { return chart.x(d.x); })
      .y(function(d) { return chart.y(d.y); });

  this.path.attr('d', lineFunction(this.data.xy));

  if (hypoData == null) {
    this.hypoPath.attr('display', 'none');
    this.hypoPathQuartiles.attr('display', 'none');

  } else {
    this.hypoPath.attr('d', lineFunction(hypoData.xy));
    this.hypoPath.attr('display', null);

    if (hypoData.xyQuartile && hypoData.xyQuartile.length > 0) {
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[hypoData.xyQuartile.length-1].x, 'y': 0});
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[0].x, 'y': 0});

      this.hypoPathQuartiles.attr('d', lineFunction(hypoData.xyQuartile));
      this.hypoPathQuartiles.attr('display', null);
    }
  }
}
<commit_msg>fewer x axis ticks<commit_after>var app = angular.module("myApp",[]);
app.controller('ChartsController', ChartsController);

function ChartsController($scope) {
  $scope.headers = [];
  $scope.model = [];
  $scope.examples = Object.keys(examples).sort(function(a,b) {
	  return examples[b].headers.length - examples[a].headers.length;
      });

  $scope.setData = function(example) {
    $scope.charts = [];
    $scope.headers = examples[example].headers;
    var data = examples[example];
    $scope.model = Autoencoder.deserialize(data);
  };
}

app.directive("renderChart",function(){
  return function($scope, element, attrs){
    var j = $scope.$index;
    var getUpdateFn = function(index) {
      return function(update, newValue) { redraw($scope.model, $scope.charts, update, index, newValue); };
    }
    var chart = new Chart(element, getUpdateFn(j));

    $scope.charts.push(chart);

    if ($scope.charts.length == $scope.headers.length) {
      redraw($scope.model, $scope.charts, true);
    }
  }
});

function redraw(model, charts, update, index, newValue) {
  if (update && newValue != undefined)
    charts[index].fixedValue = newValue;

  var row = [];
  for (var j = 0; j < charts.length; j++)
    row.push(charts[j].fixedValue);

  if (newValue != undefined)
    row[index] = newValue;

  var curves = model.getPdfs(row);

  for (var j = 0; j < row.length; j++) {
    if (update) {
      charts[j].update(curves[j]);
      charts[j].render(null);
    } else {
      charts[j].render(curves[j]);
    }
  }
}

function Chart(element, redraw) {
  this.margin = {top: 10, right: 30, bottom: 30, left: 30};
  this.width = element[0].offsetWidth,
  this.height = element[0].offsetHeight,
  this.nBins = 30;
  this.fixedValue = undefined;
  this.redraw = redraw;

  var barWidth = Math.floor(this.width/this.nBins);
  this.width = barWidth * this.nBins;

  var svg = d3.select(element[0])
      .append('svg')
      .attr("width", this.width) // + this.margin.left + this.margin.right)
      .attr("height", this.height) // - this.margin.top - this.margin.bottom)
      .append("g");

  this.axis = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (this.height - this.margin.bottom) + ")");

  this.path = svg.append('path')
    .attr('stroke', 'black')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPath = svg.append('path')
    .attr('stroke', 'green')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPathQuartiles = svg.append('path')
    .attr('fill', 'green')
    .attr('fill-opacity', '0.1');

  var focus = svg.append("g")
      .attr("class", "focus")
      .style("display", "none");

  focus.append("circle")
    .attr("r", 4.5);

  focus.append("text")
    .attr("x", 9)
    .attr("dy", ".35em");

  svg.append("rect")
    .attr("fill", "none")
    .attr("pointer-events", "all")
    .attr("width", this.width)
    .attr("height", this.height)
    .on("mouseover", move)
    .on("mouseout", out)
    .on("mousemove", move)
    .on("click", click)

  var bisectData = d3.bisector(function(d) { return d.x; }).left;

  var chart = this;

  function click() {
    focus.locked = true;

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(true, x0);
  }

  function move() {
    if (!chart.data)
      return;

    if (focus.locked)
      return;

    focus.style("display", null);

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(false, x0);
  }

  function out() {
    if (!focus.locked)
      focus.style("display", 'none');

    chart.redraw(true, null);
  }
}

Chart.prototype.update = function(data) {
  this.data = data;
}

Chart.prototype.render = function(hypoData) {
  this.x = d3.scale.linear()
    .domain(d3.extent(this.data.xy, function(d) { return d.x; }))
    .range([0, this.width]);

  var getY = function(d) { return d.y };
  var max = d3.max(this.data.xy, getY);
  if (hypoData)
      max = Math.max(max, d3.max(hypoData.xy, getY));

  this.y = d3.scale.linear()
    .domain([0, max])
    .range([this.height - this.margin.bottom, 0]);

  var xAxis = d3.svg.axis()
      .scale(this.x)
      .ticks(5)
      .orient("bottom");

  this.axis.call(xAxis);

  var chart = this;
  var lineFunction = d3.svg.line()
      .x(function(d) { return chart.x(d.x); })
      .y(function(d) { return chart.y(d.y); });

  this.path.attr('d', lineFunction(this.data.xy));

  if (hypoData == null) {
    this.hypoPath.attr('display', 'none');
    this.hypoPathQuartiles.attr('display', 'none');

  } else {
    this.hypoPath.attr('d', lineFunction(hypoData.xy));
    this.hypoPath.attr('display', null);

    if (hypoData.xyQuartile && hypoData.xyQuartile.length > 0) {
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[hypoData.xyQuartile.length-1].x, 'y': 0});
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[0].x, 'y': 0});

      this.hypoPathQuartiles.attr('d', lineFunction(hypoData.xyQuartile));
      this.hypoPathQuartiles.attr('display', null);
    }
  }
}
<|endoftext|>


<commit_before>var
	inherits = require('util').inherits,

	addrs = require('./Misc/addresses'),
	msgs = require('./Misc/messages'),
	Client = require('./Agents/Client'),
	Server = require('./Agents/Server');

// ----------------
// Chat component
// ----------------
// This component adds a layer of abstraction
// over the Client and Server components. It essentially adds
// message history

function ChatMessage(sender, time, message) {
	this.sender = sender;
	this.time = time;
	this.message = message;
}

Chat = {};

// ----------------
// Client
// ----------------

Chat.Client = function() {
	Client.call(this, addrs.channels.everyone);

	var self = this;
	this.message_history = {};

	this.on('client-message', function(data) {
		if (!message_history[data.sender.uuid]) message_history[data.sender.uuid] = [];
		message_history[sender.uuid].push(new ChatMessage(data.sender, data.time, data.extras));
		self.emit('chat-message', sender.uuid);
	});

	this.on('group-message', function(data) {
		if (!message_history[data.extras.group.uuid]) message_history[data.extras.group.uuid] = [];
		message_history[data.extras.group.uuid].push(new ChatMessage(data.sender, data.time, data.extras.message));
		self.emit('chat-message', data.extras.group.uuid);
	});
}
inherits(Chat.Client, Client);

Chat.Cient.prototype.sendMessage = function(uuid, message) {
	var m = new msgs.Message(
		msgs.types.SINGLE_MESSAGE,
		this.getProfile(),
		message
	);

	this.sendUDP(this.getClientCache()[uuid].channel, m.toString());
}

// function getMessages
// @param group_uuid uuid of the person or group
// @returns an array of messages, sorted by time
Chat.Client.prototype.getMessages = function(group_uuid) {

	// Sorts the messages in ascending order
	function compare(a, b) {
		return a.time - b.time;
	}

	this.message_history[group_uuid].sort(compare);
}

// ----------------
// Server
// ----------------

Chat.Server = function() {
	Server.call(this, addrs.channels.server);
}
inherits(Chat.Server, Server);

// ----------------
// Exports
// ----------------

module.exports = Chat;<commit_msg>Fixed typo<commit_after>var
	inherits = require('util').inherits,

	addrs = require('./Misc/addresses'),
	msgs = require('./Misc/messages'),
	Client = require('./Agents/Client'),
	Server = require('./Agents/Server');

// ----------------
// Chat component
// ----------------
// This component adds a layer of abstraction
// over the Client and Server components. It essentially adds
// message history

function ChatMessage(sender, time, message) {
	this.sender = sender;
	this.time = time;
	this.message = message;
}

Chat = {};

// ----------------
// Client
// ----------------

Chat.Client = function() {
	Client.call(this, addrs.channels.everyone);

	var self = this;
	this.message_history = {};

	this.on('client-message', function(data) {
		if (!message_history[data.sender.uuid]) message_history[data.sender.uuid] = [];
		message_history[sender.uuid].push(new ChatMessage(data.sender, data.time, data.extras));
		self.emit('chat-message', sender.uuid);
	});

	this.on('group-message', function(data) {
		if (!message_history[data.extras.group.uuid]) message_history[data.extras.group.uuid] = [];
		message_history[data.extras.group.uuid].push(new ChatMessage(data.sender, data.time, data.extras.message));
		self.emit('chat-message', data.extras.group.uuid);
	});
}
inherits(Chat.Client, Client);

Chat.Client.prototype.sendMessage = function(uuid, message) {
	var m = new msgs.Message(
		msgs.types.SINGLE_MESSAGE,
		this.getProfile(),
		message
	);

	this.sendUDP(this.getClientCache()[uuid].channel, m.toString());
}

// function getMessages
// @param group_uuid uuid of the person or group
// @returns an array of messages, sorted by time
Chat.Client.prototype.getMessages = function(group_uuid) {

	// Sorts the messages in ascending order
	function compare(a, b) {
		return a.time - b.time;
	}

	this.message_history[group_uuid].sort(compare);
}

// ----------------
// Server
// ----------------

Chat.Server = function() {
	Server.call(this, addrs.channels.server);
}
inherits(Chat.Server, Server);

// ----------------
// Exports
// ----------------

module.exports = Chat;<|endoftext|>


<commit_before>var app = angular.module("myApp",[]);
app.controller('ChartsController', ChartsController);

var examples = {};

function ChartsController($scope) {
  $scope.headers = [];
  $scope.model = [];
  $scope.examples = ['stocks', 'countries', 'wine', 'car'];

  $scope.setData = function(key) {
    if (window.location.prototcol == 'file:')
      // We can't load a JS dynamically from local disk, so if it's local then load it from Github
      var url = 'https://rawgit.com/bettermg/crossfader/master/examples/models/' + key + '.js';
    else
      var url = window.location.href.split('demo.html')[0] + 'examples/models/' + key + '.js';
    console.log('url: ' + url);

    if (examples[key])
      $scope._setData(examples[key]);
    else
      $.getScript(url, function() {
	      $scope._setData(examples[key]);
	      $scope.$apply();
	  });
  }

  $scope._setData = function(example) {
    $scope.charts = [];
    $scope.model = Autoencoder.deserialize(example);
    $scope.headers = example.headers;
  };

  $scope.init = function() {
    var key = window.location.hash.substring(1);
    if (key) {
      $scope.setData(key);
    }
  }
}

app.directive("renderChart",function(){
  return function($scope, element, attrs){
    var j = $scope.$index;
    var getUpdateFn = function(index) {
      return function(update, newValue) { redraw($scope.model, $scope.charts, update, index, newValue); };
    }
    var chart = new Chart(element, getUpdateFn(j));

    $scope.charts.push(chart);

    if ($scope.charts.length == $scope.headers.length) {
      redraw($scope.model, $scope.charts, true);
    }
  }
});

function redraw(model, charts, update, index, newValue) {
  if (update && newValue != undefined)
    charts[index].fixedValue = newValue;

  var row = [];
  for (var j = 0; j < charts.length; j++)
    row.push(charts[j].fixedValue);

  if (newValue != undefined)
    row[index] = newValue;

  var curves = model.getPdfs(row);

  for (var j = 0; j < row.length; j++) {
    if (update) {
      charts[j].update(curves[j]);
      charts[j].render(null);
    } else {
      charts[j].render(curves[j]);
    }
  }
}

function Chart(element, redraw) {
  this.margin = {top: 10, right: 30, bottom: 30, left: 30};
  this.width = element[0].offsetWidth,
  this.height = element[0].offsetHeight,
  this.nBins = 30;
  this.fixedValue = undefined;
  this.redraw = redraw;

  var barWidth = Math.floor(this.width/this.nBins);
  this.width = barWidth * this.nBins;

  var svg = d3.select(element[0])
      .append('svg')
      .attr("width", this.width) // + this.margin.left + this.margin.right)
      .attr("height", this.height) // - this.margin.top - this.margin.bottom)
      .append("g");

  this.axis = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (this.height - this.margin.bottom) + ")");

  this.path = svg.append('path')
    .attr('stroke', 'black')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPath = svg.append('path')
    .attr('stroke', 'green')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPathQuartiles = svg.append('path')
    .attr('fill', 'green')
    .attr('fill-opacity', '0.1');

  var focus = svg.append("g")
      .attr("class", "focus")
      .style("display", "none");

  focus.append("circle")
    .attr("r", 4.5);

  focus.append("text")
    .attr("x", 9)
    .attr("dy", ".35em");

  svg.append("rect")
    .attr("fill", "none")
    .attr("pointer-events", "all")
    .attr("width", this.width)
    .attr("height", this.height)
    .on("mouseover", move)
    .on("mouseout", out)
    .on("mousemove", move)
    .on("click", click)

  var bisectData = d3.bisector(function(d) { return d.x; }).left;

  var chart = this;

  function click() {
    focus.locked = true;

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(true, x0);
  }

  function move() {
    if (!chart.data)
      return;

    if (focus.locked)
      return;

    focus.style("display", null);

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(false, x0);
  }

  function out() {
    if (!focus.locked)
      focus.style("display", 'none');

    chart.redraw(true, null);
  }
}

Chart.prototype.update = function(data) {
  this.data = data;
}

Chart.prototype.render = function(hypoData) {
  this.x = d3.scale.linear()
    .domain(d3.extent(this.data.xy, function(d) { return d.x; }))
    .range([0, this.width]);

  var getY = function(d) { return d.y };
  var max = d3.max(this.data.xy, getY);
  if (hypoData)
      max = Math.max(max, d3.max(hypoData.xy, getY));

  this.y = d3.scale.linear()
    .domain([0, max])
    .range([this.height - this.margin.bottom, 0]);

  var xAxis = d3.svg.axis()
      .scale(this.x)
      .ticks(5)
      .orient("bottom");

  this.axis.call(xAxis);

  var chart = this;
  var lineFunction = d3.svg.line()
      .x(function(d) { return chart.x(d.x); })
      .y(function(d) { return chart.y(d.y); });

  this.path.attr('d', lineFunction(this.data.xy));

  if (hypoData == null) {
    this.hypoPath.attr('display', 'none');
    this.hypoPathQuartiles.attr('display', 'none');

  } else {
    this.hypoPath.attr('d', lineFunction(hypoData.xy));
    this.hypoPath.attr('display', null);

    if (hypoData.xyQuartile && hypoData.xyQuartile.length > 0) {
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[hypoData.xyQuartile.length-1].x, 'y': 0});
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[0].x, 'y': 0});

      this.hypoPathQuartiles.attr('d', lineFunction(hypoData.xyQuartile));
      this.hypoPathQuartiles.attr('display', null);
    }
  }
}
<commit_msg>prototcol -> protocol typo<commit_after>var app = angular.module("myApp",[]);
app.controller('ChartsController', ChartsController);

var examples = {};

function ChartsController($scope) {
  $scope.headers = [];
  $scope.model = [];
  $scope.examples = ['stocks', 'countries', 'wine', 'car'];

  $scope.setData = function(key) {
    if (window.location.protocol == 'file:')
      // We can't load a JS dynamically from local disk, so if it's local then load it from Github
      var url = 'https://rawgit.com/bettermg/crossfader/master/examples/models/' + key + '.js';
    else
      var url = window.location.href.split('demo.html')[0] + 'examples/models/' + key + '.js';
    console.log('url: ' + url);

    if (examples[key])
      $scope._setData(examples[key]);
    else
      $.getScript(url, function() {
	      $scope._setData(examples[key]);
	      $scope.$apply();
	  });
  }

  $scope._setData = function(example) {
    $scope.charts = [];
    $scope.model = Autoencoder.deserialize(example);
    $scope.headers = example.headers;
  };

  $scope.init = function() {
    var key = window.location.hash.substring(1);
    if (key) {
      $scope.setData(key);
    }
  }
}

app.directive("renderChart",function(){
  return function($scope, element, attrs){
    var j = $scope.$index;
    var getUpdateFn = function(index) {
      return function(update, newValue) { redraw($scope.model, $scope.charts, update, index, newValue); };
    }
    var chart = new Chart(element, getUpdateFn(j));

    $scope.charts.push(chart);

    if ($scope.charts.length == $scope.headers.length) {
      redraw($scope.model, $scope.charts, true);
    }
  }
});

function redraw(model, charts, update, index, newValue) {
  if (update && newValue != undefined)
    charts[index].fixedValue = newValue;

  var row = [];
  for (var j = 0; j < charts.length; j++)
    row.push(charts[j].fixedValue);

  if (newValue != undefined)
    row[index] = newValue;

  var curves = model.getPdfs(row);

  for (var j = 0; j < row.length; j++) {
    if (update) {
      charts[j].update(curves[j]);
      charts[j].render(null);
    } else {
      charts[j].render(curves[j]);
    }
  }
}

function Chart(element, redraw) {
  this.margin = {top: 10, right: 30, bottom: 30, left: 30};
  this.width = element[0].offsetWidth,
  this.height = element[0].offsetHeight,
  this.nBins = 30;
  this.fixedValue = undefined;
  this.redraw = redraw;

  var barWidth = Math.floor(this.width/this.nBins);
  this.width = barWidth * this.nBins;

  var svg = d3.select(element[0])
      .append('svg')
      .attr("width", this.width) // + this.margin.left + this.margin.right)
      .attr("height", this.height) // - this.margin.top - this.margin.bottom)
      .append("g");

  this.axis = svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (this.height - this.margin.bottom) + ")");

  this.path = svg.append('path')
    .attr('stroke', 'black')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPath = svg.append('path')
    .attr('stroke', 'green')
    .attr('stroke-weight', '5')
    .attr('fill', 'none');

  this.hypoPathQuartiles = svg.append('path')
    .attr('fill', 'green')
    .attr('fill-opacity', '0.1');

  var focus = svg.append("g")
      .attr("class", "focus")
      .style("display", "none");

  focus.append("circle")
    .attr("r", 4.5);

  focus.append("text")
    .attr("x", 9)
    .attr("dy", ".35em");

  svg.append("rect")
    .attr("fill", "none")
    .attr("pointer-events", "all")
    .attr("width", this.width)
    .attr("height", this.height)
    .on("mouseover", move)
    .on("mouseout", out)
    .on("mousemove", move)
    .on("click", click)

  var bisectData = d3.bisector(function(d) { return d.x; }).left;

  var chart = this;

  function click() {
    focus.locked = true;

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(true, x0);
  }

  function move() {
    if (!chart.data)
      return;

    if (focus.locked)
      return;

    focus.style("display", null);

    var x0 = chart.x.invert(d3.mouse(this)[0]);

    focus.attr("transform", "translate(" + chart.x(x0) + "," + chart.y(0) + ")");
    focus.select("text").text(x0.toPrecision(4));

    chart.redraw(false, x0);
  }

  function out() {
    if (!focus.locked)
      focus.style("display", 'none');

    chart.redraw(true, null);
  }
}

Chart.prototype.update = function(data) {
  this.data = data;
}

Chart.prototype.render = function(hypoData) {
  this.x = d3.scale.linear()
    .domain(d3.extent(this.data.xy, function(d) { return d.x; }))
    .range([0, this.width]);

  var getY = function(d) { return d.y };
  var max = d3.max(this.data.xy, getY);
  if (hypoData)
      max = Math.max(max, d3.max(hypoData.xy, getY));

  this.y = d3.scale.linear()
    .domain([0, max])
    .range([this.height - this.margin.bottom, 0]);

  var xAxis = d3.svg.axis()
      .scale(this.x)
      .ticks(5)
      .orient("bottom");

  this.axis.call(xAxis);

  var chart = this;
  var lineFunction = d3.svg.line()
      .x(function(d) { return chart.x(d.x); })
      .y(function(d) { return chart.y(d.y); });

  this.path.attr('d', lineFunction(this.data.xy));

  if (hypoData == null) {
    this.hypoPath.attr('display', 'none');
    this.hypoPathQuartiles.attr('display', 'none');

  } else {
    this.hypoPath.attr('d', lineFunction(hypoData.xy));
    this.hypoPath.attr('display', null);

    if (hypoData.xyQuartile && hypoData.xyQuartile.length > 0) {
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[hypoData.xyQuartile.length-1].x, 'y': 0});
      hypoData.xyQuartile.push({'x': hypoData.xyQuartile[0].x, 'y': 0});

      this.hypoPathQuartiles.attr('d', lineFunction(hypoData.xyQuartile));
      this.hypoPathQuartiles.attr('display', null);
    }
  }
}
<|endoftext|>


<commit_before>var debug = require('debug')(require('../package.json').name);
var async = require('async');
var _ = require('lodash');
var S = require('string');
var fs = require('fs-extra');
var path = require('path');
var url = require('url');
var shortId = require('shortid');
var util = require('any2api-util');
var Registry = require('./Registry');

var specFile = 'apispec.json';

var nodeBinDir = path.resolve(process.execPath, '..'); // '/usr/local/opt/nvm/v0.10.33/bin'
if (nodeBinDir) process.env.PATH = nodeBinDir + path.delimiter + process.env.PATH;

module.exports = function() {
  var obj = {};

  var basePath = null;
  var log = debug;

  var scannersReg = null;
  var invokersReg = null;
  var generatorsReg = null;

  obj.scanners = function() {
    scannersReg = scannersReg || Registry({ path: path.join(basePath, 'scanners') });

    return scannersReg;
  };

  obj.invokers = function() {
    invokersReg = invokersReg || Registry({ path: path.join(basePath, 'invokers') });

    return invokersReg;
  };

  obj.generators = function() {
    generatorsReg = generatorsReg || Registry({ path: path.join(basePath, 'generators') });

    return generatorsReg;
  };

  obj.init = function(args) {
    if (basePath) throw new Error('core initialized already');

    args = args || {};

    basePath = args.path || __dirname;
    log = args.log || debug;

    debug('core initialized', args, basePath);
  };

  /*
   * Scan executable
   */
  obj.scan = function(args, done) {
    args = args || {};

    if (!args.outputPath) {
      return done(new Error('output directory must be specified'));
    } else if (!args.executables) {
      return done(new Error('executables must be specified'));
    }

    if (_.isString(args.executables)) args.executables = [ args.executables ];

    var scanners = obj.scanners();

    if (args.scanner && !scanners.existsSync(args.scanner)) {
      args.scanner = scannerPrefix + args.scanner;

      if (!scanners.existsSync(args.scanner)) {
        return done(new Error('scanner ' + args.scanner + ' missing'));
      }
    }

    var outputPath = path.resolve(args.outputPath);
    fs.mkdirsSync(outputPath);

    var apiSpec = { executables: {} };

    var specPath = path.join(outputPath, specFile);

    // Scan all executables
    async.eachSeries(args.executables, function(exec, done) {
      var retrieve = args.retrieve;
      var execId = shortId.generate();
      var execPath = path.join(outputPath, execId);
      var execSpec = null;
      var execStored = false;

      //var execPath = outputPath;
      //if (args.subdir) execPath = path.join(outputPath, args.subdir);

      async.series([
        function(callback) {
          // Called after trying to store executable
          var execStoredCallback = function(err) {
            if (err) return callback(err);

            execStored = true;

            log('Executable stored: ' + execPath);

            callback();
          };

          // Auto-detect URLs
          if (!retrieve &&
              (S(exec).startsWith('http://') || S(exec).startsWith('https://'))) {
            retrieve = 'http';
          } else if (!retrieve && S(exec).startsWith('lp:')) { // launchpad.net repository
            retrieve = 'bzr';
          }

          // Remotely hosted executable
          if (retrieve) {
            log('Retrieving executable: ' + exec);

            var execUrl = exec;
            //exec = _.last(url.parse(execUrl).pathname.replace(/\/$/, '').split('/'));

            if (retrieve === 'http' || retrieve === 'https') {
              util.download({ url: execUrl, dir: execPath }, execStoredCallback);
            } else if (retrieve === 'git') {
              util.checkoutGit({ url: execUrl, dir: execPath }, execStoredCallback);
            } else if (retrieve === 'bzr' || retrieve === 'bazaar') {
              util.checkoutBzr({ url: execUrl, dir: execPath }, execStoredCallback);
            } else {
              return callback(new Error('retrieve mode ' + retrieve + ' not supported'));
            }
          // Executable does not exist
          } else if (!fs.existsSync(exec)) {
            return callback(new Error('executable ' + exec + ' missing'));
          // Executable is a file
          } else if (fs.statSync(exec).isFile()) {
            log('Extracting executable: ' + exec);

            util.extract({ file: exec, dir: execPath }, execStoredCallback);
          // Executable is a directory
          } else if (fs.statSync(exec).isDirectory()) {
            if (path.resolve(exec) !== path.resolve(execPath) && args.copyExecutable) {
              log('Copying executable: ' + exec);

              fs.mkdirsSync(execPath);
              fs.copy(exec, execPath, execStoredCallback);
            //} else if (path.resolve(outputPath) === path.resolve(defaultOutput)) {
            //  outputPath = exec;

            //  specPath = path.join(outputPath, specFile);
            } else {
              execPath = exec;

              callback();
            }
          }
        },
        function(callback) {
          log('Scanning executable:', execPath);

          //var basename = path.basename(exec, path.extname(exec));

          if (args.scanner) {
            scanners.get(args.scanner, function(err, Scanner) {
              if (err) return callback(err);

              Scanner().scan(execPath, function(err, result) {
                if (err) return callback(err);

                execSpec = result;

                callback();
              });
            });
          } else {
            async.eachSeries(obj.scanners().listSync(), function(name, callback) {
              if (!_.isEmpty(execSpec)) {
                return callback();
              } else {
                var Scanner = obj.scanners().loadModuleSync(name);

                Scanner().scan(execPath, function(err, result) {
                  if (err) return callback(err);

                  if (!_.isEmpty(result)) execSpec = result;

                  callback();
                });
              }
            }, callback);
          }
        },
        function(callback) {
          if (_.isEmpty(execSpec)) {
            log('Warning: executable spec is empty, most probably no scanner available.');

            return callback();
          } else {
            log('Executable scanned.');
          }

          if (execStored && execSpec.name) {
            var betterExecPath = path.join(outputPath, execSpec.name);

            if (!fs.existsSync(betterExecPath)) {
              fs.renameSync(execPath, betterExecPath);

              execPath = betterExecPath;

              log('Executable moved: ' + execPath);
            }
          }

          execSpec.name = execSpec.name || execId;

          execSpec.path = path.relative(outputPath, execPath);
          if (S(execSpec.path).startsWith('..')) execSpec.path = execPath;
          else if (_.isEmpty(execSpec.path)) execSpec.path = '.';

          apiSpec.executables[execSpec.name] = execSpec;
          delete execSpec.name;

          callback();
        }
      ], done);
    }, function(err) {
      if (err) {
        return done(err);
      } else if (_.isEmpty(apiSpec) || _.isEmpty(apiSpec.executables)) {
        return done(new Error('API spec is empty'));
      }

      log('Writing API spec: ' + specPath);

      util.writeSpec({ specPath: specPath, apiSpec: apiSpec }, function(err, updApiSpec) {
        if (err) return done(err);

        log('API spec written.');

        done(null, updApiSpec);
      });
    });
  };

  /*
   * Generate API spec
   */
  obj.gen = function(args, done) {
    args = args || {};

    if (!args.specPath) {
      return done(new Error('API spec path must be specified'));
    } else if (!args.outputPath) {
      return done(new Error('output directory must be specified'));
    } else if (fs.existsSync(args.outputPath)) {
      return done(new Error('output directory must not exist'));
    }

    args.outputPath = path.resolve(args.outputPath);

    var apiSpec;

    var updateSpecCallback = function(callback) {
      return function(err, updApiSpec) {
        if (err) return callback(err);

        if (updApiSpec) apiSpec = updApiSpec;

        callback();
      };
    };

    async.series([
      function(callback) {
        util.readInput({ specPath: args.specPath }, updateSpecCallback(callback));
      },
      function(callback) {
        util.updateInvokers({ apiSpec: apiSpec, invokers: obj.invokers() }, callback);
      },
      function(callback) {
        _.each(apiSpec.executables, function(executable, name) {
          delete apiSpec.executables[name];

          name = S(name).dasherize().s;

          if (executable.invoker_name) {
            executable.invoker_name = S(executable.invoker_name).dasherize().s;
          }

          apiSpec.executables[name] = executable;
        });

        _.each(apiSpec.invokers, function(invoker, name) {
          delete apiSpec.invokers[name];

          name = S(name).dasherize().s;

          apiSpec.invokers[name] = invoker;
        });

        callback();
      },
      function(callback) {
        apiSpec.implementation.path = args.outputPath;

        if (args.implTitle) apiSpec.implementation.title = args.implTitle;
        if (args.implType) apiSpec.implementation.type = args.implType;
        if (args.interface) apiSpec.implementation.interface = args.interface;

        var generatorNames = [];

        if (args.generator) {
          generatorNames.push(args.generator);
        } else if (apiSpec.implementation.generator_name) {
          generatorNames.push(apiSpec.implementation.generator_name);
        } else {
          generatorNames = obj.generators().listSync();
        }

        async.eachSeries(generatorNames, function(name, callback) {
          if (apiSpec.generated) {
            return callback();
          } else {
            var Generator = obj.generators().loadModuleSync(name);

            var g = Generator();

            if (g.supports(apiSpec)) {
              apiSpec.implementation.generator_name = name;

              g.generate(apiSpec, function(err) {
                if (err) return callback(err);

                var implPath = apiSpec.implementation.path;

                apiSpec.implementation.path = '.';

                var title = apiSpec.implementation.title || 'untitled';
                var description = apiSpec.implementation.description || '';
                var ports = apiSpec.implementation.ports || [ '8080' ];

                var dockerBaseImg = process.env.DOCKER_BASE_IMAGE || 'node:0.10';
                var dockerBaseRun = process.env.DOCKER_BASE_RUN || 'apt-get -y update && apt-get -y install sudo';

                var vagrantBaseBox = process.env.VAGRANT_BASE_BOX || 'ubuntu/trusty64';

                async.parallel([
                  function(callback) {
                    fs.readFile(path.join(__dirname, '..', 'tpl', 'Dockerfile.tpl'), 'utf8', function(err, content) {
                      if (err) return callback(err);

                      fs.writeFile(path.join(implPath, 'Dockerfile'),
                        _.template(content, { ports: ports, baseImage: dockerBaseImg, baseRun: dockerBaseRun }), callback);
                    });
                  },
                  function(callback) {
                    fs.readFile(path.join(__dirname, '..', 'tpl', 'Vagrantfile.tpl'), 'utf8', function(err, content) {
                      if (err) return callback(err);

                      fs.writeFile(path.join(implPath, 'Vagrantfile'),
                        _.template(content, { ports: ports, baseBox: vagrantBaseBox }), callback);
                    });
                  },
                  function(callback) {
                    if (fs.existsSync(path.join(implPath, 'README.md'))) return callback();

                    fs.readFile(path.join(__dirname, '..', 'tpl', 'README.tpl'), 'utf8', function(err, content) {
                      if (err) return callback(err);

                      fs.writeFile(path.join(implPath, 'README.md'),
                        _.template(content, { ports: ports, title: title,
                                              description: description,
                                              name: S(title.toLowerCase()).camelize().s }), callback);
                    });
                  },
                  async.apply(util.writeSpec, { specPath: path.join(implPath, specFile), apiSpec: apiSpec })
                ], function(err) {
                  apiSpec.generated = true;

                  callback(err);
                });
              });
            } else {
              callback();
            }
          }
        }, function(err) {
          if (err) return callback(err);
          else if (!apiSpec.generated) return callback(new Error('no generator found'));

          delete apiSpec.generated;

          callback();
        });
      },
      function(callback) {
        if (args.skipPrepare) return callback();

        var preparedInvokers = {};

        async.eachSeries(_.keys(apiSpec.executables), function(name, callback) {
          log('Preparing buildtime environment for preparing executable ' + name);

          util.prepareBuildtime({ apiSpec: apiSpec, preparedInvokers: preparedInvokers, executable_name: name }, callback);
        }, callback);
      },
      function(callback) {
        if (args.skipPrepare) return callback();

        async.eachSeries(_.keys(apiSpec.executables), function(name, callback) {
          log('Preparing executable ' + name);

          util.prepareExecutable({ apiSpec: apiSpec, executable_name: name }, updateSpecCallback(callback));
        }, callback);
      }
    ], function(err) {
      if (err) return done(err);

      util.writeSpec({ apiSpec: apiSpec }, function(err, updApiSpec) {
        if (err) return done(err);

        log('API implementation generated with API spec: ' + apiSpec.apispec_path);

        done(null, updApiSpec);
      });
    });
  };

  return obj;
};
<commit_msg>deprecated variable removed<commit_after>var debug = require('debug')(require('../package.json').name);
var async = require('async');
var _ = require('lodash');
var S = require('string');
var fs = require('fs-extra');
var path = require('path');
var url = require('url');
var shortId = require('shortid');
var util = require('any2api-util');
var Registry = require('./Registry');

var specFile = 'apispec.json';

module.exports = function() {
  var obj = {};

  var basePath = null;
  var log = debug;

  var scannersReg = null;
  var invokersReg = null;
  var generatorsReg = null;

  obj.scanners = function() {
    scannersReg = scannersReg || Registry({ path: path.join(basePath, 'scanners') });

    return scannersReg;
  };

  obj.invokers = function() {
    invokersReg = invokersReg || Registry({ path: path.join(basePath, 'invokers') });

    return invokersReg;
  };

  obj.generators = function() {
    generatorsReg = generatorsReg || Registry({ path: path.join(basePath, 'generators') });

    return generatorsReg;
  };

  obj.init = function(args) {
    if (basePath) throw new Error('core initialized already');

    args = args || {};

    basePath = args.path || __dirname;
    log = args.log || debug;

    debug('core initialized', args, basePath);
  };

  /*
   * Scan executable
   */
  obj.scan = function(args, done) {
    args = args || {};

    if (!args.outputPath) {
      return done(new Error('output directory must be specified'));
    } else if (!args.executables) {
      return done(new Error('executables must be specified'));
    }

    if (_.isString(args.executables)) args.executables = [ args.executables ];

    var scanners = obj.scanners();

    if (args.scanner && !scanners.existsSync(args.scanner)) {
      args.scanner = scannerPrefix + args.scanner;

      if (!scanners.existsSync(args.scanner)) {
        return done(new Error('scanner ' + args.scanner + ' missing'));
      }
    }

    var outputPath = path.resolve(args.outputPath);
    fs.mkdirsSync(outputPath);

    var apiSpec = { executables: {} };

    var specPath = path.join(outputPath, specFile);

    // Scan all executables
    async.eachSeries(args.executables, function(exec, done) {
      var retrieve = args.retrieve;
      var execId = shortId.generate();
      var execPath = path.join(outputPath, execId);
      var execSpec = null;
      var execStored = false;

      //var execPath = outputPath;
      //if (args.subdir) execPath = path.join(outputPath, args.subdir);

      async.series([
        function(callback) {
          // Called after trying to store executable
          var execStoredCallback = function(err) {
            if (err) return callback(err);

            execStored = true;

            log('Executable stored: ' + execPath);

            callback();
          };

          // Auto-detect URLs
          if (!retrieve &&
              (S(exec).startsWith('http://') || S(exec).startsWith('https://'))) {
            retrieve = 'http';
          } else if (!retrieve && S(exec).startsWith('lp:')) { // launchpad.net repository
            retrieve = 'bzr';
          }

          // Remotely hosted executable
          if (retrieve) {
            log('Retrieving executable: ' + exec);

            var execUrl = exec;
            //exec = _.last(url.parse(execUrl).pathname.replace(/\/$/, '').split('/'));

            if (retrieve === 'http' || retrieve === 'https') {
              util.download({ url: execUrl, dir: execPath }, execStoredCallback);
            } else if (retrieve === 'git') {
              util.checkoutGit({ url: execUrl, dir: execPath }, execStoredCallback);
            } else if (retrieve === 'bzr' || retrieve === 'bazaar') {
              util.checkoutBzr({ url: execUrl, dir: execPath }, execStoredCallback);
            } else {
              return callback(new Error('retrieve mode ' + retrieve + ' not supported'));
            }
          // Executable does not exist
          } else if (!fs.existsSync(exec)) {
            return callback(new Error('executable ' + exec + ' missing'));
          // Executable is a file
          } else if (fs.statSync(exec).isFile()) {
            log('Extracting executable: ' + exec);

            util.extract({ file: exec, dir: execPath }, execStoredCallback);
          // Executable is a directory
          } else if (fs.statSync(exec).isDirectory()) {
            if (path.resolve(exec) !== path.resolve(execPath) && args.copyExecutable) {
              log('Copying executable: ' + exec);

              fs.mkdirsSync(execPath);
              fs.copy(exec, execPath, execStoredCallback);
            //} else if (path.resolve(outputPath) === path.resolve(defaultOutput)) {
            //  outputPath = exec;

            //  specPath = path.join(outputPath, specFile);
            } else {
              execPath = exec;

              callback();
            }
          }
        },
        function(callback) {
          log('Scanning executable:', execPath);

          //var basename = path.basename(exec, path.extname(exec));

          if (args.scanner) {
            scanners.get(args.scanner, function(err, Scanner) {
              if (err) return callback(err);

              Scanner().scan(execPath, function(err, result) {
                if (err) return callback(err);

                execSpec = result;

                callback();
              });
            });
          } else {
            async.eachSeries(obj.scanners().listSync(), function(name, callback) {
              if (!_.isEmpty(execSpec)) {
                return callback();
              } else {
                var Scanner = obj.scanners().loadModuleSync(name);

                Scanner().scan(execPath, function(err, result) {
                  if (err) return callback(err);

                  if (!_.isEmpty(result)) execSpec = result;

                  callback();
                });
              }
            }, callback);
          }
        },
        function(callback) {
          if (_.isEmpty(execSpec)) {
            log('Warning: executable spec is empty, most probably no scanner available.');

            return callback();
          } else {
            log('Executable scanned.');
          }

          if (execStored && execSpec.name) {
            var betterExecPath = path.join(outputPath, execSpec.name);

            if (!fs.existsSync(betterExecPath)) {
              fs.renameSync(execPath, betterExecPath);

              execPath = betterExecPath;

              log('Executable moved: ' + execPath);
            }
          }

          execSpec.name = execSpec.name || execId;

          execSpec.path = path.relative(outputPath, execPath);
          if (S(execSpec.path).startsWith('..')) execSpec.path = execPath;
          else if (_.isEmpty(execSpec.path)) execSpec.path = '.';

          apiSpec.executables[execSpec.name] = execSpec;
          delete execSpec.name;

          callback();
        }
      ], done);
    }, function(err) {
      if (err) {
        return done(err);
      } else if (_.isEmpty(apiSpec) || _.isEmpty(apiSpec.executables)) {
        return done(new Error('API spec is empty'));
      }

      log('Writing API spec: ' + specPath);

      util.writeSpec({ specPath: specPath, apiSpec: apiSpec }, function(err, updApiSpec) {
        if (err) return done(err);

        log('API spec written.');

        done(null, updApiSpec);
      });
    });
  };

  /*
   * Generate API spec
   */
  obj.gen = function(args, done) {
    args = args || {};

    if (!args.specPath) {
      return done(new Error('API spec path must be specified'));
    } else if (!args.outputPath) {
      return done(new Error('output directory must be specified'));
    } else if (fs.existsSync(args.outputPath)) {
      return done(new Error('output directory must not exist'));
    }

    args.outputPath = path.resolve(args.outputPath);

    var apiSpec;

    var updateSpecCallback = function(callback) {
      return function(err, updApiSpec) {
        if (err) return callback(err);

        if (updApiSpec) apiSpec = updApiSpec;

        callback();
      };
    };

    async.series([
      function(callback) {
        util.readInput({ specPath: args.specPath }, updateSpecCallback(callback));
      },
      function(callback) {
        util.updateInvokers({ apiSpec: apiSpec, invokers: obj.invokers() }, callback);
      },
      function(callback) {
        _.each(apiSpec.executables, function(executable, name) {
          delete apiSpec.executables[name];

          name = S(name).dasherize().s;

          if (executable.invoker_name) {
            executable.invoker_name = S(executable.invoker_name).dasherize().s;
          }

          apiSpec.executables[name] = executable;
        });

        _.each(apiSpec.invokers, function(invoker, name) {
          delete apiSpec.invokers[name];

          name = S(name).dasherize().s;

          apiSpec.invokers[name] = invoker;
        });

        callback();
      },
      function(callback) {
        apiSpec.implementation.path = args.outputPath;

        if (args.implTitle) apiSpec.implementation.title = args.implTitle;
        if (args.implType) apiSpec.implementation.type = args.implType;
        if (args.interface) apiSpec.implementation.interface = args.interface;

        var generatorNames = [];

        if (args.generator) {
          generatorNames.push(args.generator);
        } else if (apiSpec.implementation.generator_name) {
          generatorNames.push(apiSpec.implementation.generator_name);
        } else {
          generatorNames = obj.generators().listSync();
        }

        async.eachSeries(generatorNames, function(name, callback) {
          if (apiSpec.generated) {
            return callback();
          } else {
            var Generator = obj.generators().loadModuleSync(name);

            var g = Generator();

            if (g.supports(apiSpec)) {
              apiSpec.implementation.generator_name = name;

              g.generate(apiSpec, function(err) {
                if (err) return callback(err);

                var implPath = apiSpec.implementation.path;

                apiSpec.implementation.path = '.';

                var title = apiSpec.implementation.title || 'untitled';
                var description = apiSpec.implementation.description || '';
                var ports = apiSpec.implementation.ports || [ '8080' ];

                var dockerBaseImg = process.env.DOCKER_BASE_IMAGE || 'node:0.10';
                var dockerBaseRun = process.env.DOCKER_BASE_RUN || 'apt-get -y update && apt-get -y install sudo';

                var vagrantBaseBox = process.env.VAGRANT_BASE_BOX || 'ubuntu/trusty64';

                async.parallel([
                  function(callback) {
                    fs.readFile(path.join(__dirname, '..', 'tpl', 'Dockerfile.tpl'), 'utf8', function(err, content) {
                      if (err) return callback(err);

                      fs.writeFile(path.join(implPath, 'Dockerfile'),
                        _.template(content, { ports: ports, baseImage: dockerBaseImg, baseRun: dockerBaseRun }), callback);
                    });
                  },
                  function(callback) {
                    fs.readFile(path.join(__dirname, '..', 'tpl', 'Vagrantfile.tpl'), 'utf8', function(err, content) {
                      if (err) return callback(err);

                      fs.writeFile(path.join(implPath, 'Vagrantfile'),
                        _.template(content, { ports: ports, baseBox: vagrantBaseBox }), callback);
                    });
                  },
                  function(callback) {
                    if (fs.existsSync(path.join(implPath, 'README.md'))) return callback();

                    fs.readFile(path.join(__dirname, '..', 'tpl', 'README.tpl'), 'utf8', function(err, content) {
                      if (err) return callback(err);

                      fs.writeFile(path.join(implPath, 'README.md'),
                        _.template(content, { ports: ports, title: title,
                                              description: description,
                                              name: S(title.toLowerCase()).camelize().s }), callback);
                    });
                  },
                  async.apply(util.writeSpec, { specPath: path.join(implPath, specFile), apiSpec: apiSpec })
                ], function(err) {
                  apiSpec.generated = true;

                  callback(err);
                });
              });
            } else {
              callback();
            }
          }
        }, function(err) {
          if (err) return callback(err);
          else if (!apiSpec.generated) return callback(new Error('no generator found'));

          delete apiSpec.generated;

          callback();
        });
      },
      function(callback) {
        if (args.skipPrepare) return callback();

        var preparedInvokers = {};

        async.eachSeries(_.keys(apiSpec.executables), function(name, callback) {
          log('Preparing buildtime environment for preparing executable ' + name);

          util.prepareBuildtime({ apiSpec: apiSpec, preparedInvokers: preparedInvokers, executable_name: name }, callback);
        }, callback);
      },
      function(callback) {
        if (args.skipPrepare) return callback();

        async.eachSeries(_.keys(apiSpec.executables), function(name, callback) {
          log('Preparing executable ' + name);

          util.prepareExecutable({ apiSpec: apiSpec, executable_name: name }, updateSpecCallback(callback));
        }, callback);
      }
    ], function(err) {
      if (err) return done(err);

      util.writeSpec({ apiSpec: apiSpec }, function(err, updApiSpec) {
        if (err) return done(err);

        log('API implementation generated with API spec: ' + apiSpec.apispec_path);

        done(null, updApiSpec);
      });
    });
  };

  return obj;
};
<|endoftext|>