<commit_before>#!/usr/bin/env node

// maintainer note - x.y.z-ab version in package.json -> x.y.z
var version = require('./package').version.replace(/-.*/, '')

var fs = require('fs')
var os = require('os')
var path = require('path')
var extract = require('extract-zip')
var download = require('electron-download')

var installedVersion = null
try {
  installedVersion = fs.readFileSync(path.join(__dirname, 'dist', 'version'), 'utf-8').replace(/^v/, '')
} catch (err) {
  // do nothing
}

var platform = process.env.npm_config_platform || os.platform()

function onerror (err) {
  throw err
}

var paths = {
  darwin: 'dist/Electron.app/Contents/MacOS/Electron',
  freebsd: 'dist/electron',
  linux: 'dist/electron',
  win32: 'dist/electron.exe'
}

if (!paths[platform]) throw new Error('Electron builds are not available on platform: ' + platform)

if (installedVersion === version && fs.existsSync(path.join(__dirname, paths[platform]))) {
  process.exit(0)
}

// downloads if not cached
download({
  version: version,
  platform: process.env.npm_config_platform,
  arch: process.env.npm_config_arch,
  strictSSL: process.env.npm_config_strict_ssl === 'true',
  quiet: ['info', 'verbose', 'silly', 'http'].indexOf(process.env.npm_config_loglevel) === -1
}, extractFile)

// unzips and makes path.txt point at the correct executable
function extractFile (err, zipPath) {
  if (err) return onerror(err)
  fs.writeFile(path.join(__dirname, 'path.txt'), paths[platform], function (err) {
    if (err) return onerror(err)
    extract(zipPath, {dir: path.join(__dirname, 'dist')}, function (err) {
      if (err) return onerror(err)
    })
  })
}
<commit_msg>Write path.txt after extraction<commit_after>#!/usr/bin/env node

// maintainer note - x.y.z-ab version in package.json -> x.y.z
var version = require('./package').version.replace(/-.*/, '')

var fs = require('fs')
var os = require('os')
var path = require('path')
var extract = require('extract-zip')
var download = require('electron-download')

var installedVersion = null
try {
  installedVersion = fs.readFileSync(path.join(__dirname, 'dist', 'version'), 'utf-8').replace(/^v/, '')
} catch (err) {
  // do nothing
}

var platform = process.env.npm_config_platform || os.platform()

function onerror (err) {
  throw err
}

var paths = {
  darwin: 'dist/Electron.app/Contents/MacOS/Electron',
  freebsd: 'dist/electron',
  linux: 'dist/electron',
  win32: 'dist/electron.exe'
}

if (!paths[platform]) throw new Error('Electron builds are not available on platform: ' + platform)

if (installedVersion === version && fs.existsSync(path.join(__dirname, paths[platform]))) {
  process.exit(0)
}

// downloads if not cached
download({
  version: version,
  platform: process.env.npm_config_platform,
  arch: process.env.npm_config_arch,
  strictSSL: process.env.npm_config_strict_ssl === 'true',
  quiet: ['info', 'verbose', 'silly', 'http'].indexOf(process.env.npm_config_loglevel) === -1
}, extractFile)

// unzips and makes path.txt point at the correct executable
function extractFile (err, zipPath) {
  if (err) return onerror(err)
  extract(zipPath, {dir: path.join(__dirname, 'dist')}, function (err) {
    if (err) return onerror(err)
    fs.writeFile(path.join(__dirname, 'path.txt'), paths[platform], function (err) {
      if (err) return onerror(err)
    })
  })
}
<|endoftext|>


<commit_before>/**
 * JavaScript based speech recognizer.
 *
 * Copyright 2016, Dominic Winkelman
 * Free to use under the Apache 2.0 License
 *
 * https://github.com/dreamdom/JsSpeechRecognizer
 *
 * Requires the WebRTC adapter.js file.
 */

function JsSpeechRecognizer() {

    // Variables for recording data
    this.recordingBufferArray = [];
    this.currentRecordingBuffer = [];
    this.wordBuffer = [];
    this.modelBuffer = [];
    this.deleteMap = {};

    // TODO: rename this
    this.dominateBins = [];

    // The speech recognition model
    var model = {};

    // We are not recording yet
    this.isRecording = false;
    this.doRecognition = false;

    // Get an audio context
    this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();

    // Create an analyser
    this.analyser = this.audioCtx.createAnalyser();
    this.analyser.minDecibels = -80;
    this.analyser.maxDecibels = -10;
    this.analyser.smoothingTimeConstant = 0;
    this.analyser.fftSize = 1024;

    // Create the scriptNode
    this.scriptNode = this.audioCtx.createScriptProcessor(this.analyser.fftSize, 1, 1);

    // Function for script node to process
    var _this = this;
    this.scriptNode.onaudioprocess = function(audioProcessingEvent) {

        // Looping var
        var i = 0;

        // If we aren't recording, don't do anything
        if (!_this.isRecording) {
            return;
        }

        // get the fft data
        var dataArray = new Uint8Array(_this.analyser.fftSize);
        _this.analyser.getByteFrequencyData(dataArray);

        // Loop through the array and print out the max
        var max = -1;
        var bin = -1;
        for (i = 0; i < dataArray.length; i++) {
            if (dataArray[i] > max) {
                max = dataArray[i];
                bin = i;
            }
        }

        // If the max is zero ignore it.
        if (max === 0) {
            return;
        }

        // Save the data for playback
        var inputBuffer = audioProcessingEvent.inputBuffer;
        var leftChannel = inputBuffer.getChannelData(0);
        Array.prototype.push.apply(_this.currentRecordingBuffer, new Float32Array(leftChannel));

        // TODO: Rename addIt
        var groups = [];
        for (i = 0; i < 25; i++) {
            var addIt = 0;
            for (var j = 0; j < 10; j++) {
                var curPos = (10 * i) + j;

                // normalize the value
                var tempCalc = Math.floor((dataArray[curPos] / max) * 100);

                // Keep the peak normalized value for this group
                if (tempCalc > addIt) {
                    addIt = tempCalc;
                }

            }
            groups.push(addIt);
        }
        _this.dominateBins.push(groups);
    };

}

JsSpeechRecognizer.prototype.openMic = function() {
    // Request access to the microphone
    var constraints = {
        "audio": true
    };

    navigator.getUserMedia(constraints, successCallback, errorCallback);

    var _this = this;
    // Acess to the microphone was granted
    function successCallback(stream) {
        console.log('getUserMedia() got stream: ', stream);

        _this.stream = stream;
        _this.source = _this.audioCtx.createMediaStreamSource(stream);

        _this.source.connect(_this.analyser);
        _this.analyser.connect(_this.scriptNode);

        // This is needed due to a chrome bug!
        _this.scriptNode.connect(_this.audioCtx.destination);
    }

    function errorCallback(error) {
        console.log('navigator.getUserMedia error: ', error);
    }
};

JsSpeechRecognizer.prototype.startTrainingRecording = function(curWord) {

    this.doRecognition = false;
    this.isRecording = true;

    // Create a new current buffer
    this.currentRecordingBuffer = [];

    // Create a new recognition buffer
    this.dominateBins = [];
    this.wordBuffer.push(curWord);

};

JsSpeechRecognizer.prototype.startRecognitionRecording = function() {

    this.doRecognition = true;
    this.isRecording = true;

    // Create a new current buffer
    this.currentRecordingBuffer = [];

    // Create a new recognition buffer
    this.dominateBins = [];
};

JsSpeechRecognizer.prototype.stopRecording = function() {

    this.isRecording = false;
    this.dominateBins = [].concat.apply([], this.dominateBins);

    if (this.doRecognition) {
        console.log("doing recognition");
        return;
    }

    // This is training
    this.recordingBufferArray.push(this.currentRecordingBuffer.slice(0));
    // Save the recognition model
    this.modelBuffer.push(this.dominateBins.slice(0));

    return this.recordingBufferArray.length;
};

/**
 * Function will play back the recorded audio for a specific index that is part of the training data.
 */
JsSpeechRecognizer.prototype.playTrainingBuffer = function(index) {

    // Mono
    var channels = 1;
    var playBuffer = this.recordingBufferArray[index];
    var frameCount = playBuffer.length;
    var myArrayBuffer = this.audioCtx.createBuffer(channels, frameCount, this.audioCtx.sampleRate);

    for (var channel = 0; channel < channels; channel++) {
        var nowBuffering = myArrayBuffer.getChannelData(channel);
        for (var i = 0; i < frameCount; i++) {
            nowBuffering[i] = playBuffer[i];
        }
    }

    var source2 = this.audioCtx.createBufferSource();
    source2.buffer = myArrayBuffer;
    source2.connect(this.audioCtx.destination);
    source2.start();

};

JsSpeechRecognizer.prototype.deleteTrainingBuffer = function(input) {
    this.deleteMap[input] = true;
};

/**
 * Method to generate the new speech recognition model from the  training data.
 */
JsSpeechRecognizer.prototype.generateModel = function() {

    // Local vars
    var i = 0;
    var key = "";

    // Reset the model
    this.model = {};

    for (i = 0; i < this.wordBuffer.length; i++) {
        key = this.wordBuffer[i];
        this.model[key] = [];
    }

    for (i = 0; i < this.modelBuffer.length; i++) {
        if (!this.deleteMap[i]) {
            key = this.wordBuffer[i];
            console.log("key: " + key);
            this.model[key].push(this.modelBuffer[i]);
        }
    }
};

JsSpeechRecognizer.prototype.getTopRecognitionHypothesis = function() {
    return this.findClosestMatch(this.dominateBins.slice(0));
};

// Calculation functions

JsSpeechRecognizer.prototype.findClosestMatch = function(input) {

    var i = 0;
    var key = "";

    var confidences = {};

    for (key in this.model) {

        confidences[key] = [];
        for (i = 0; i < this.model[key].length; i++) {

            var curDistance = this.findDistance(input, this.model[key][i]);
            var curConfidence = this.calcConfidence(curDistance, this.model[key][i]);

            // console.log("cur confidence " + curConfidence);
            confidences[key].push(curConfidence);
        }

    }

    var max = -1;
    var maxKey = "";
    var maxKeyIndex = -1;
    for (key in confidences) {

        for (i = 0; i < confidences[key].length; i++) {
            if (max == -1 || confidences[key][i] > max) {
                max = confidences[key][i];
                maxKey = key;
                maxKeyIndex = i;
            }
        }
    }

    // Print out
    console.log(maxKey + " - " + max);

    var result = {};
    result[maxKey] = max;

    return result;
};

JsSpeechRecognizer.prototype.findDistance = function(input, check) {
    var i = 0;
    var distance = 0;

    if (check.length < input.length) {
        for (i = 0; i < check.length; i++) {
            distance += Math.abs(check[i] - input[i]);
        }
        for (i = check.length; i < input.length; i++) {
            distance += input[i];
        }
    } else {
        for (i = 0; i < input.length; i++) {
            distance += Math.abs(check[i] - input[i]);
        }
        for (i = input.length; i < check.length; i++) {
            distance += check[i];
        }
    }

    return distance;
};

JsSpeechRecognizer.prototype.calcConfidence = function(distance, matchArray) {
    var sum = 0;
    var i = 0;

    for (i = 0; i < matchArray.length; i++) {
        sum += matchArray[i];
    }

    // console.log("distance: " + distance + " sum: " + sum);
    return (1 - (distance / sum));
};

<commit_msg>small amount of code cleanup<commit_after>/**
 * JavaScript based speech recognizer.
 *
 * Copyright 2016, Dominic Winkelman
 * Free to use under the Apache 2.0 License
 *
 * https://github.com/dreamdom/JsSpeechRecognizer
 *
 * Requires the WebRTC adapter.js file.
 */

function JsSpeechRecognizer() {

    // Variables for recording data
    this.recordingBufferArray = [];
    this.currentRecordingBuffer = [];
    this.wordBuffer = [];
    this.modelBuffer = [];
    this.deleteMap = {};
    this.groupedValues = [];

    // The speech recognition model
    var model = {};

    // State variables. Initialize to not recording and not doing recognition
    this.isRecording = false;
    this.doRecognition = false;

    // Get an audio context
    this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();

    // Create an analyser
    this.analyser = this.audioCtx.createAnalyser();
    this.analyser.minDecibels = -80;
    this.analyser.maxDecibels = -10;
    this.analyser.smoothingTimeConstant = 0;
    this.analyser.fftSize = 1024;

    // Create the scriptNode
    this.scriptNode = this.audioCtx.createScriptProcessor(this.analyser.fftSize, 1, 1);

    // Function for script node to process
    var _this = this;
    this.scriptNode.onaudioprocess = function(audioProcessingEvent) {

        // Looping var
        var i = 0;

        // If we aren't recording, don't do anything
        if (!_this.isRecording) {
            return;
        }

        // get the fft data
        var dataArray = new Uint8Array(_this.analyser.fftSize);
        _this.analyser.getByteFrequencyData(dataArray);

        // Loop through the array and find the max
        var max = -1;
        for (i = 0; i < dataArray.length; i++) {
            if (dataArray[i] > max) {
                max = dataArray[i];
            }
        }

        // If the max is zero ignore it.
        if (max === 0) {
            return;
        }

        // Save the data for playback. For simplicity just take one channel
        var inputBuffer = audioProcessingEvent.inputBuffer;
        var leftChannel = inputBuffer.getChannelData(0);
        Array.prototype.push.apply(_this.currentRecordingBuffer, new Float32Array(leftChannel));

        var numGroups = 25;
        var groupSize = 10;
        var groups = [];

        for (i = 0; i < numGroups; i++) {
            var peakGroupValue = 0;
            for (var j = 0; j < groupSize; j++) {
                var curPos = (10 * i) + j;

                // normalize the value
                var tempCalc = Math.floor((dataArray[curPos] / max) * 100);

                // Keep the peak normalized value for this group
                if (tempCalc > peakGroupValue) {
                    peakGroupValue = tempCalc;
                }

            }
            groups.push(peakGroupValue);
        }
        _this.groupedValues.push(groups);
    };

}

JsSpeechRecognizer.prototype.openMic = function() {
    // Request access to the microphone
    var constraints = {
        "audio": true
    };

    navigator.getUserMedia(constraints, successCallback, errorCallback);

    var _this = this;
    // Acess to the microphone was granted
    function successCallback(stream) {
        _this.stream = stream;
        _this.source = _this.audioCtx.createMediaStreamSource(stream);

        _this.source.connect(_this.analyser);
        _this.analyser.connect(_this.scriptNode);

        // This is needed for chrome
        _this.scriptNode.connect(_this.audioCtx.destination);
    }

    function errorCallback(error) {
        console.error('navigator.getUserMedia error: ', error);
    }
};

JsSpeechRecognizer.prototype.startTrainingRecording = function(curWord) {

    this.doRecognition = false;
    this.isRecording = true;

    // Create a new current recording buffer
    this.currentRecordingBuffer = [];

    // Create a new groupedValues buffer
    this.groupedValues = [];
    this.wordBuffer.push(curWord);
};

JsSpeechRecognizer.prototype.startRecognitionRecording = function() {

    this.doRecognition = true;
    this.isRecording = true;

    // Create a new current recording buffer
    this.currentRecordingBuffer = [];

    // Create a new groupedValues buffer
    this.groupedValues = [];
};

JsSpeechRecognizer.prototype.stopRecording = function() {

    this.isRecording = false;
    this.groupedValues = [].concat.apply([], this.groupedValues);

    // If we are doing recognition we don't want to save to the model
    if (this.doRecognition) {
        return;
    }

    // This is training
    this.recordingBufferArray.push(this.currentRecordingBuffer.slice(0));
    // Save the recognition model
    this.modelBuffer.push(this.groupedValues.slice(0));

    return this.recordingBufferArray.length;
};

/**
 * Function will play back the recorded audio for a specific index that is part of the training data.
 */
JsSpeechRecognizer.prototype.playTrainingBuffer = function(index) {

    // Mono
    var channels = 1;
    var playBuffer = this.recordingBufferArray[index];
    var frameCount = playBuffer.length;
    var myArrayBuffer = this.audioCtx.createBuffer(channels, frameCount, this.audioCtx.sampleRate);

    for (var channel = 0; channel < channels; channel++) {
        var nowBuffering = myArrayBuffer.getChannelData(channel);
        for (var i = 0; i < frameCount; i++) {
            nowBuffering[i] = playBuffer[i];
        }
    }

    var source2 = this.audioCtx.createBufferSource();
    source2.buffer = myArrayBuffer;
    source2.connect(this.audioCtx.destination);
    source2.start();

};

JsSpeechRecognizer.prototype.deleteTrainingBuffer = function(input) {
    this.deleteMap[input] = true;
};

/**
 * Method to generate the new speech recognition model from the  training data.
 */
JsSpeechRecognizer.prototype.generateModel = function() {

    // Local vars
    var i = 0;
    var key = "";

    // Reset the model
    this.model = {};

    for (i = 0; i < this.wordBuffer.length; i++) {
        key = this.wordBuffer[i];
        this.model[key] = [];
    }

    for (i = 0; i < this.modelBuffer.length; i++) {
        if (!this.deleteMap[i]) {
            key = this.wordBuffer[i];
            this.model[key].push(this.modelBuffer[i]);
        }
    }
};

JsSpeechRecognizer.prototype.getTopRecognitionHypothesis = function() {
    return this.findClosestMatch(this.groupedValues);
};

// Calculation functions

JsSpeechRecognizer.prototype.findClosestMatch = function(input) {

    var i = 0;
    var key = "";

    var confidences = {};

    // Loop through all the keys in the model
    for (key in this.model) {
        confidences[key] = [];
        // Loop through all entries for that key
        for (i = 0; i < this.model[key].length; i++) {

            var curDistance = this.findDistance(input, this.model[key][i]);
            var curConfidence = this.calcConfidence(curDistance, this.model[key][i]);

            confidences[key].push(curConfidence);
        }

    }

    var max = -1;
    var maxKey = "";
    var maxKeyIndex = -1;
    for (key in confidences) {

        for (i = 0; i < confidences[key].length; i++) {
            if (max == -1 || confidences[key][i] > max) {
                max = confidences[key][i];
                maxKey = key;
                maxKeyIndex = i;
            }
        }
    }

    var result = {};
    result[maxKey] = max;

    return result;
};

JsSpeechRecognizer.prototype.findDistance = function(input, check) {
    var i = 0;
    var distance = 0;

    if (check.length < input.length) {
        for (i = 0; i < check.length; i++) {
            distance += Math.abs(check[i] - input[i]);
        }
        for (i = check.length; i < input.length; i++) {
            distance += input[i];
        }
    } else {
        for (i = 0; i < input.length; i++) {
            distance += Math.abs(check[i] - input[i]);
        }
        for (i = input.length; i < check.length; i++) {
            distance += check[i];
        }
    }

    return distance;
};

JsSpeechRecognizer.prototype.calcConfidence = function(distance, matchArray) {
    var sum = 0;
    var i = 0;

    for (i = 0; i < matchArray.length; i++) {
        sum += matchArray[i];
    }

    return (1 - (distance / sum));
};

<|endoftext|>


<commit_before>"use strict";

class Advertisement {

  constructor(title, link){
    this.title = title;
    this.link = link;
  }

  _buildContent(){
    return `
${this.title}

      ${this._linkText()}`;
  }

  _linkText(){
    return "Click Here";
  }

  render(){
    return this._buildContent();
  }
}

// Here's an example of how this class is used:
/*
  let ad = new Advertisement("CodeSchool", "http://codeschool.com");
  _appendToPage( targetElement, ad.render() );
*/<commit_msg>Export Advertisement class using named exports<commit_after>"use strict";

class Advertisement {

  constructor(title, link){
    this.title = title;
    this.link = link;
  }

  _buildContent(){
    return `
${this.title}

      ${this._linkText()}`;
  }

  _linkText(){
    return "Click Here";
  }

  render(){
    return this._buildContent();
  }
}

// Here's an example of how this class is used:
/*
  let ad = new Advertisement("CodeSchool", "http://codeschool.com");
  _appendToPage( targetElement, ad.render() );
*/

export { Advertisement };<|endoftext|>


<commit_before>'use strict';
//noinspection JSUnresolvedVariable
var path = require('path'),
    baboon = require('../../lib/baboon')(path.join(__dirname, '../')),
    auth = baboon.middleware.auth,
    server = baboon.server,
    io = server.io,
    config = server.config;

io.sockets.on('connection', function (client) {
    'use strict';

    client.on('message', function(message) {
        console.log(message);
    });

    client.on('disconnect', function() {
        console.log('client: ' + client.id + ' disconnected');
    });

    client.emit('send:name', {
        name: 'Bob'
    });

    setInterval(function () {
        client.emit('send:time', {
            time: (new Date()).toString()
        });
    }, 1000);
});

server.start();<commit_msg>106 Baboon Server Lib, 100 Socket Routing Client Service Ebene<commit_after>'use strict';
//noinspection JSUnresolvedVariable
var path = require('path'),
    baboon = require('../../lib/baboon')(path.join(__dirname, '../')),
    auth = baboon.middleware.auth,
    server = baboon.server,
    io = server.io,
    config = server.config;

io.sockets.on('connection', function (client) {
    'use strict';

    client.on('message', function(message) {
        console.log(message);
    });

    client.on('disconnect', function() {
        console.log('client: ' + client.id + ' disconnected');
    });

    client.emit('send:name', {
        name: 'Bob'
    });

    setInterval(function () {
        client.emit('send:time', {
            time: (new Date()).toString()
        });
    }, 5000);
});

server.start();<|endoftext|>


<commit_before>/*

This example implements a blocky, dissolve transition effect, that transitions between two 3D models. It
  uses the stencil buffer to achieve this.

*/

const c = document.createElement('canvas')
const webglCanvas = document.body.appendChild(c)
var gl = c.getContext('webgl', {
  antialias: true,
  stencil: true
})

const fit = require('canvas-fit')
const regl = require('../regl')({gl: gl})
const mat4 = require('gl-mat4')
window.addEventListener('resize', fit(webglCanvas), false)
const bunny = require('bunny')
const normals = require('angle-normals')
var boundingBox = require('vertices-bounding-box')
var tform = require('geo-3d-transform-mat4')
var seedrandom = require('seedrandom')

// center the rabbit mesh to the origin.
function centerMesh (mesh) {
  var bb = boundingBox(mesh.positions)

  var _translate = [
    -0.5 * (bb[0][0] + bb[1][0]),
    -0.5 * (bb[0][1] + bb[1][1]),
    -0.5 * (bb[0][2] + bb[1][2])
  ]
  var translate = mat4.create()
  mat4.translate(translate, translate, _translate)
  mesh.positions = tform(mesh.positions, translate)
}
centerMesh(bunny)

var boxPosition = [
  // side faces
  [-0.5, +0.5, +0.5], [+0.5, +0.5, +0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5], // positive z face.
  [+0.5, +0.5, +0.5], [+0.5, +0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], // positive x face
  [+0.5, +0.5, -0.5], [-0.5, +0.5, -0.5], [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], // negative z face
  [-0.5, +0.5, -0.5], [-0.5, +0.5, +0.5], [-0.5, -0.5, +0.5], [-0.5, -0.5, -0.5], // negative x face.
  [-0.5, +0.5, -0.5], [+0.5, +0.5, -0.5], [+0.5, +0.5, +0.5], [-0.5, +0.5, +0.5],  // top face
  [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5]  // bottom face
]

const boxElements = [
  [2, 1, 0], [2, 0, 3],
  [6, 5, 4], [6, 4, 7],
  [10, 9, 8], [10, 8, 11],
  [14, 13, 12], [14, 12, 15],
  [18, 17, 16], [18, 16, 19],
  [20, 21, 22], [23, 20, 22]
]

// all the normals of a single block.
var boxNormal = [
  // side faces
  [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0],
  [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0],
  [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0],
  [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0],
  // top
  [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0],
  // bottom
  [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0]
]

var rng = seedrandom('seed.')

var textures = [] // transition textures.
var TEX_W = 64 // width of a transition texture
var TEX_H = 64 // height of a transition texture
var N_TEX = 20 // how many transition textures we use.

/*
  To implement the transition effect, we have a bunch of textures that we cycle through, and
  render to the stencul buffer.

  The texture returned by makeTexture(0) is all white, and makeTexture(1.0) is all black.
  But makeTexture(0.5) will be random noise, where about in average, half the pixels are white, and
  the other half are black.
 */
function makeTexture (f) {
  var texData = []

  for (var y = 0; y < TEX_W; y++) {
    var r = []
    for (var x = 0; x < TEX_H; x++) {
      var rand = rng()
      var g = rand > f ? 255 : 0

      r.push([g, g, g, 255])
    }
    texData.push(r)
  }

  return regl.texture({
    mag: 'nearest',
    wrap: 'repeat',
    data: texData
  })
}

// create all transition textures.
for (var i = 0; i <= N_TEX; i++) {
  textures[i] = makeTexture(i / N_TEX)
}

const globalScope = regl({
  cull: {
    enable: true
  }
})

function Mesh (elements, position, normal) {
  this.elements = elements
  this.position = position
  this.normal = normal
}

Mesh.prototype.draw = regl({
  uniforms: {
    model: (_, props, batchId) => {
      var m = mat4.identity([])

      var s = props.scale
      mat4.scale(m, m, [s, s, s])
      return m
    },
    ambientLightAmount: 0.3,
    diffuseLightAmount: 0.7,
    color: regl.prop('color'),
    lightDir: [0.39, 0.87, 0.29],
    view: () => { return mat4.lookAt([], [0.0, 10.0, 20.0], [0, 0, 0], [0, 1, 0]) },
    projection: ({viewportWidth, viewportHeight}) =>
      mat4.perspective([],
                       Math.PI / 4,
                       viewportWidth / viewportHeight,
                       0.01,
                       1000)
  },
  attributes: {
    position: regl.this('position'),
    normal: regl.this('normal')
  },
  elements: regl.this('elements'),
  frag: `
  precision mediump float;

  varying vec3 vNormal;
  varying vec3 vPosition;

  uniform float ambientLightAmount;
  uniform float diffuseLightAmount;
  uniform vec3 lightDir;

  uniform vec3 color;

  void main () {
    vec3 ambient = ambientLightAmount * color;
    float cosTheta = dot(vNormal, lightDir);
    vec3 diffuse = diffuseLightAmount * color * clamp(cosTheta , 0.0, 1.0 );

    gl_FragColor = vec4((ambient + diffuse), 1.0);
  }`,
  vert: `
  precision mediump float;

  attribute vec3 position;
  attribute vec3 normal;

  varying vec3 vPosition;
  varying vec3 vNormal;

  uniform mat4 projection, view, model;

  void main() {
    vec4 worldSpacePosition = model * vec4(position, 1);

    vPosition = worldSpacePosition.xyz;
    vNormal = normal;

    gl_Position = projection * view * worldSpacePosition;
  }`
})

/*
  Draw a texture onto the entire screen.
 */
var drawFullscreenTexture = regl({
  frag: `
  precision mediump float;

  varying vec2 uv;

  uniform float viewportWidth, viewportHeight;

  uniform sampler2D tex;
  uniform vec2 scale;

  void main () {
    /*
      We basically tile the transition texture over the entire screen.

      The factor 0.05 makes the blocks in the effect very big.
      You can make them smaller by increasing this factor.
     */
    float x = texture2D(tex, uv * scale * 0.05).x;

    /*
      If white, do not draw to stencil buffer, but discard the fragment.
      But if black, draw to stencil buffer.
     */
    if(x > 0.5)
      discard;

    gl_FragColor = vec4(1.0);
  }`,

  vert: `
  precision mediump float;
  attribute vec2 position;

  uniform float t;

  varying vec2 uv;

  void main () {
    uv = position * 0.5 + 0.5;
    gl_Position = vec4(position, 0, 1);
  }`,

  attributes: {
    position: [
      [-1, -1], [1, -1], [1, 1],
      [-1, -1], [1, 1], [-1, 1]
    ]
  },

  uniforms: {
    viewportWidth: ({viewportWidth}) => viewportWidth,
    viewportHeight: ({viewportHeight}) => viewportHeight,

    // cycle through the transition textures, as t goes from 0.0 to 1.0
    tex: (_, props) => { return textures[Math.floor(props.t * N_TEX)] },

    scale: ({viewportWidth, viewportHeight}) => {
      return [Math.ceil(viewportWidth / TEX_W), Math.ceil(viewportHeight / TEX_H)]
    }
  },

  count: 6,
  depth: {
    enable: false
  }
})

/*
  Setup rendering to stencil buffer.
 */
const createMask = regl({
  stencil: {
    enable: true,
    mask: 0xff,
    // if a fragment is covered, set that fragment to 1 in the stencil buffer.
    func: {
      cmp: 'always',
      ref: 1,
      mask: 0xff
    },
    opFront: {
      fail: 'replace',
      zfail: 'replace',
      pass: 'replace'
    }
  },
  // we want to write only to the stencil buffer,
  // so disable these masks.
  colorMask: [false, false, false, false],
  depth: {
    enable: true,
    mask: false
  }
})

// pass stencil test only if value in stencil buffer is 0.
const filterMask0 = regl({
  stencil: {
    enable: true,
    mask: 0xff,
    func: {
      cmp: 'equal',
      ref: 0,
      mask: 0xff
    }
  }
})

// pass stencil test only if value in stencil buffer is 1.
const filterMask1 = regl({
  stencil: {
    enable: true,
    mask: 0xff,
    func: {
      cmp: 'equal',
      ref: 1,
      mask: 0xff
    }
  }
})

var bunnyMesh = new Mesh(bunny.cells, bunny.positions, normals(bunny.cells, bunny.positions))
var boxMesh = new Mesh(boxElements, boxPosition, boxNormal)

var f0 = filterMask0
var f1 = filterMask1

regl.frame(({tick}) => {
  regl.clear({
    color: [0, 0, 0, 255],
    depth: 1,
    stencil: 0
  })

  // These are the scenes we will be transitioning between.
  var scene0 = () => {
    boxMesh.draw({scale: 10.2, color: [0.0, 0.5, 0.0]})
  }
  var scene1 = () => {
    bunnyMesh.draw({scale: 1.0, color: [0.6, 0.0, 0.0]})
  }

  // Takes this many frames to transition from one scene to the other.
  var CYCLE_LENGTH = 60

  var normTick = tick % CYCLE_LENGTH  // normalize tick to be in range [0,CYCLE_LENGTH-1]
  var t = normTick * normTick * 0.001
  if (t > 1.0) {
    t = 1.0
  }

  if ((tick % CYCLE_LENGTH) === 0) {
    // One cycle is over. So swap filters.
    var temp = f0
    f0 = f1
    f1 = temp
  }

  globalScope(() => {
    // first, render to stencil buffer.
    createMask(() => {
      drawFullscreenTexture({t: t})
    })

    // then actually render the scenes.
    // and we are using the stencil buffer to mask the scenes.
    f0(scene0)
    f1(scene1)
  })
})
<commit_msg>upgrade stencil-transition example<commit_after>/*

This example implements a blocky, dissolve transition effect, that transitions between two 3D models. It
  uses the stencil buffer to achieve this.

*/

const c = document.createElement('canvas')
const webglCanvas = document.body.appendChild(c)
var gl = c.getContext('webgl', {
  antialias: true,
  stencil: true
})

const fit = require('canvas-fit')
const regl = require('../regl')({gl: gl})
const mat4 = require('gl-mat4')
window.addEventListener('resize', fit(webglCanvas), false)
const bunny = require('bunny')
const normals = require('angle-normals')
var boundingBox = require('vertices-bounding-box')
var tform = require('geo-3d-transform-mat4')
var seedrandom = require('seedrandom')

// center the rabbit mesh to the origin.
function centerMesh (mesh) {
  var bb = boundingBox(mesh.positions)

  var _translate = [
    -0.5 * (bb[0][0] + bb[1][0]),
    -0.5 * (bb[0][1] + bb[1][1]),
    -0.5 * (bb[0][2] + bb[1][2])
  ]
  var translate = mat4.create()
  mat4.translate(translate, translate, _translate)
  mesh.positions = tform(mesh.positions, translate)
}
centerMesh(bunny)

var boxPosition = [
  // side faces
  [-0.5, +0.5, +0.5], [+0.5, +0.5, +0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5], // positive z face.
  [+0.5, +0.5, +0.5], [+0.5, +0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], // positive x face
  [+0.5, +0.5, -0.5], [-0.5, +0.5, -0.5], [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], // negative z face
  [-0.5, +0.5, -0.5], [-0.5, +0.5, +0.5], [-0.5, -0.5, +0.5], [-0.5, -0.5, -0.5], // negative x face.
  [-0.5, +0.5, -0.5], [+0.5, +0.5, -0.5], [+0.5, +0.5, +0.5], [-0.5, +0.5, +0.5],  // top face
  [-0.5, -0.5, -0.5], [+0.5, -0.5, -0.5], [+0.5, -0.5, +0.5], [-0.5, -0.5, +0.5]  // bottom face
]

const boxElements = [
  [2, 1, 0], [2, 0, 3],
  [6, 5, 4], [6, 4, 7],
  [10, 9, 8], [10, 8, 11],
  [14, 13, 12], [14, 12, 15],
  [18, 17, 16], [18, 16, 19],
  [20, 21, 22], [23, 20, 22]
]

// all the normals of a single block.
var boxNormal = [
  // side faces
  [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0], [0.0, 0.0, +1.0],
  [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0], [+1.0, 0.0, 0.0],
  [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0], [0.0, 0.0, -1.0],
  [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0], [-1.0, 0.0, 0.0],
  // top
  [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0], [0.0, +1.0, 0.0],
  // bottom
  [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0], [0.0, -1.0, 0.0]
]

var rng = seedrandom('seed.')

var textures = [] // transition textures.
var TEX_W = 64 // width of a transition texture
var TEX_H = 64 // height of a transition texture
var N_TEX = 20 // how many transition textures we use.

/*
  To implement the transition effect, we have a bunch of textures that we cycle through, and
  render to the stencul buffer.

  The texture returned by makeTexture(0) is all white, and makeTexture(1.0) is all black.
  But makeTexture(0.5) will be random noise, where about in average, half the pixels are white, and
  the other half are black.
 */
function makeTexture (f) {
  var texData = []

  for (var y = 0; y < TEX_W; y++) {
    var r = []
    for (var x = 0; x < TEX_H; x++) {
      var rand = rng()
      var g = rand > f ? 255 : 0

      r.push([g, g, g, 255])
    }
    texData.push(r)
  }

  return regl.texture({
    mag: 'nearest',
    wrap: 'repeat',
    data: texData
  })
}

// create all transition textures.
for (var i = 0; i <= N_TEX; i++) {
  textures[i] = makeTexture(i / N_TEX)
}

const globalScope = regl({
  cull: {
    enable: true
  }
})

function Mesh (elements, position, normal) {
  this.elements = elements
  this.position = position
  this.normal = normal
}

Mesh.prototype.draw = regl({
  uniforms: {
    model: (_, props, batchId) => {
      var m = mat4.identity([])

      var s = props.scale
      mat4.scale(m, m, [s, s, s])
      return m
    },
    ambientLightAmount: 0.3,
    diffuseLightAmount: 0.7,
    color: regl.prop('color'),
    lightDir: [0.39, 0.87, 0.29],
    view: () => { return mat4.lookAt([], [0.0, 10.0, 20.0], [0, 0, 0], [0, 1, 0]) },
    projection: ({viewportWidth, viewportHeight}) =>
      mat4.perspective([],
                       Math.PI / 4,
                       viewportWidth / viewportHeight,
                       0.01,
                       1000)
  },
  attributes: {
    position: regl.this('position'),
    normal: regl.this('normal')
  },
  elements: regl.this('elements'),
  frag: `
  precision mediump float;

  varying vec3 vNormal;
  varying vec3 vPosition;

  uniform float ambientLightAmount;
  uniform float diffuseLightAmount;
  uniform vec3 lightDir;

  uniform vec3 color;

  void main () {
    vec3 ambient = ambientLightAmount * color;
    float cosTheta = dot(vNormal, lightDir);
    vec3 diffuse = diffuseLightAmount * color * clamp(cosTheta , 0.0, 1.0 );

    gl_FragColor = vec4((ambient + diffuse), 1.0);
  }`,
  vert: `
  precision mediump float;

  attribute vec3 position;
  attribute vec3 normal;

  varying vec3 vPosition;
  varying vec3 vNormal;

  uniform mat4 projection, view, model;

  void main() {
    vec4 worldSpacePosition = model * vec4(position, 1);

    vPosition = worldSpacePosition.xyz;
    vNormal = normal;

    gl_Position = projection * view * worldSpacePosition;
  }`
})

/*
  Draw a texture onto the entire screen.
 */
var drawFullscreenTexture = regl({
  frag: `
  precision mediump float;

  varying vec2 uv;

  uniform float viewportWidth, viewportHeight;

  uniform sampler2D tex;
  uniform vec2 scale;

  void main () {
    /*
      We basically tile the transition texture over the entire screen.

      The factor 0.05 makes the blocks in the effect very big.
      You can make them smaller by increasing this factor.
     */
    float x = texture2D(tex, uv * scale * 0.05).x;

    /*
      If white, do not draw to stencil buffer, but discard the fragment.
      But if black, draw to stencil buffer.
     */
    if(x > 0.5)
      discard;

    gl_FragColor = vec4(1.0);
  }`,

  vert: `
  precision mediump float;
  attribute vec2 position;

  uniform float t;

  varying vec2 uv;

  void main () {
    uv = position * 0.5 + 0.5;
    gl_Position = vec4(position, 0, 1);
  }`,

  attributes: {
    position: [
      [-1, -1], [1, -1], [1, 1],
      [-1, -1], [1, 1], [-1, 1]
    ]
  },

  uniforms: {
    viewportWidth: ({viewportWidth}) => viewportWidth,
    viewportHeight: ({viewportHeight}) => viewportHeight,

    // cycle through the transition textures, as t goes from 0.0 to 1.0
    tex: (_, props) => { return textures[Math.floor(props.t * N_TEX)] },

    scale: ({viewportWidth, viewportHeight}) => {
      return [Math.ceil(viewportWidth / TEX_W), Math.ceil(viewportHeight / TEX_H)]
    }
  },

  count: 6,
  depth: {
    enable: false
  }
})

/*
  Setup rendering to stencil buffer.
 */
const createMask = regl({
  stencil: {
    enable: true,
    mask: 0xff,
    // if a fragment is covered, set that fragment to 1 in the stencil buffer.
    func: {
      cmp: 'always',
      ref: 1,
      mask: 0xff
    },
    opFront: {
      fail: 'replace',
      zfail: 'replace',
      zpass: 'replace'
    }
  },
  // we want to write only to the stencil buffer,
  // so disable these masks.
  colorMask: [false, false, false, false],
  depth: {
    enable: true,
    mask: false
  }
})

// pass stencil test only if value in stencil buffer is 0.
const filterMask0 = regl({
  stencil: {
    enable: true,
    mask: 0xff,
    func: {
      cmp: 'equal',
      ref: 0,
      mask: 0xff
    }
  }
})

// pass stencil test only if value in stencil buffer is 1.
const filterMask1 = regl({
  stencil: {
    enable: true,
    mask: 0xff,
    func: {
      cmp: 'equal',
      ref: 1,
      mask: 0xff
    }
  }
})

var bunnyMesh = new Mesh(bunny.cells, bunny.positions, normals(bunny.cells, bunny.positions))
var boxMesh = new Mesh(boxElements, boxPosition, boxNormal)

var f0 = filterMask0
var f1 = filterMask1

regl.frame(({tick}) => {
  regl.clear({
    color: [0, 0, 0, 255],
    depth: 1,
    stencil: 0
  })

  // These are the scenes we will be transitioning between.
  var scene0 = () => {
    boxMesh.draw({scale: 10.2, color: [0.0, 0.5, 0.0]})
  }
  var scene1 = () => {
    bunnyMesh.draw({scale: 1.0, color: [0.6, 0.0, 0.0]})
  }

  // Takes this many frames to transition from one scene to the other.
  var CYCLE_LENGTH = 60

  var normTick = tick % CYCLE_LENGTH  // normalize tick to be in range [0,CYCLE_LENGTH-1]
  var t = normTick * normTick * 0.001
  if (t > 1.0) {
    t = 1.0
  }

  if ((tick % CYCLE_LENGTH) === 0) {
    // One cycle is over. So swap filters.
    var temp = f0
    f0 = f1
    f1 = temp
  }

  globalScope(() => {
    // first, render to stencil buffer.
    createMask(() => {
      drawFullscreenTexture({t: t})
    })

    // then actually render the scenes.
    // and we are using the stencil buffer to mask the scenes.
    f0(scene0)
    f1(scene1)
  })
})
<|endoftext|>


<commit_before>module.exports = Renderer;

var EntityManager   = require('tiny-ecs').EntityManager;
var Vec2            = require('tiny-ecs').Vec2;
var Style           = require('../../lib/renderer/Style.js');
var Canvas          = require('../../lib/renderer/Canvas.js');
var Position        = require('../components/Position.js');
var Spatial         = require('../components/Spatial.js');
var LevelObject     = require('../components/LevelObject.js');
var ColorSpirit     = require('../components/ColorSpirit.js');
var Finish          = require('../components/Finish.js');
var Color           = require('../../lib/renderer/Color.js');
var Avatar          = require('../components/Avatar.js');
var Text            = require('../components/Text.js');
var colors          = require('../maps/colors.js');
var CollisionSystem = require('./CollisionSystem.js');

/**
 * @constructor
 * @param {EntityManager} entities
 * @param {Canvas} screen
 */
function Renderer(messanger, screen, entities, maps, inputs)
{
  this.screen     = screen;
  this.entities   = entities;
  this.maps       = maps;
  this.inputs     = inputs;
  global.renderer = this;

  this.fade = 0;

  messanger.listenTo(CollisionSystem.WALL, [], this.onShake.bind(this));
  messanger.listenTo('shake', [], this.onShake.bind(this));
}

var COLOR_FILTER = [Position, Spatial, ColorSpirit];
var LEVEL_FILTER = [Position, LevelObject];
var FINISH_FILTER = [Finish];
var TEXT_FILTER = [Position, Text];

// All avatars have to have a color spirit
var AVATAR_FILTER = [Position, Spatial, Avatar, ColorSpirit];

/**
 * @param {Number} dt
 * @param {Number} time
 */
Renderer.prototype.update = function(dt, time)
{
  if (this.isFinishing())
    this.fade = Math.min(1, this.fade + (dt/1000));
  else
    this.fade = Math.max(0, this.fade - (dt/1000));

  global.renderer = this;

  this.screen.save();
  this.screen.fill('#202020');
  this.cameraTransform();
  this.drawBg();
  this.drawWalls();
  this.drawGems(dt, time);
  this.drawLevelObjects(dt, time);
  this.drawAvatars();
  // this.drawTexts();
  this.screen.restore();
  this.drawFade();
};

Renderer.prototype.drawFade = function()
{
  this.screen
    .save()
    .setAlpha(this.fade)
    .fill('black')
    .restore();
};

var bV = new Vec2();

var borderStyle = new Style();
borderStyle.color = '#333';

var datStyle = new Style();
datStyle.color = '#222';

Renderer.prototype.drawBg = function()
{
  var player = this.entities.queryTag('player')[0];
  var pad = 30;
  bV.assign(this.maps.size);
  bV.x += pad*2;
  bV.y += pad*2;
  this.screen.save();
  this.screen.save();
  this.screen.translate(-pad, -pad);
  this.screen.drawRectangle(bV, borderStyle);
  this.screen.restore();
  this.screen.drawRectangle(this.maps.size, datStyle);
  this.screen.restore();
};

Renderer.prototype.isFinishing = function()
{
  return !!this.entities.queryComponents(FINISH_FILTER)[0].finish.timeOut;
};

var ct = new Vec2();
Renderer.prototype.cameraTransform = function()
{
  var player = this.entities.queryTag('player')[0];
  var inputs = this.inputs;
  var plusKey = inputs.button_k_107 || inputs.button_k_43 || inputs.button_k_187;
  var minusKey = inputs.button_k_109 || inputs.button_k_45 || inputs.button_k_189;

  // cacl zoom
  var zoom = this.zoom || 1;
  var per = player.newtonian.velocity.magnitude() / player.newtonian.maxSpeed;

  // do zoom
  if(per > 0.001){
    if(this.isFinishing())
      zoom = Math.min(20, Math.pow(zoom, 1.15));
    else
      zoom = 1 - this.fade/3;

    var p = 0.995;
    var newZoom = 1.2 - 0.2 * per;
    zoom = zoom * p + (1-p) * newZoom;
  }
  if(plusKey){
    zoom += (zoom+0.01 > 1) ? 0 : 0.01;
  }
  if(minusKey){
    zoom -= (zoom-0.01 < 0.15) ? 0 : 0.01;
  }
  this.screen.scale(zoom, zoom);
  this.zoom = zoom;

  // Translate to account for player
  ct.assign(this.screen.getSize()).smult(0.5 * (1/zoom));
  this.screen.vtranslate(ct);
  ct.assign(player.position.location).smult(-1);
  this.screen.vtranslate(ct);

  var shake = this.shake;

  this.screen.translate(
    Math.random()*shake - shake/2,
    Math.random()*shake - shake/2
  );

  this.shake = this.shake * 0.7;

};

Renderer.prototype.onShake = function()
{
  this.shake = 40;
};

Renderer.prototype.drawTexts = function()
{
  var entities = this.entities.queryComponents(TEXT_FILTER);

  for (var n = 0; n < entities.length; n++) {
    this.drawText(entities[n]);
  }
};

Renderer.prototype.drawWalls = function()
{
  var entities = this.entities.queryTag('wall');
  var pColor = this.entities.queryTag('player')[0].colorSpirit.toColor();

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    var wColor = entity.colorSpirit.toColor();
    if (Color.equals(pColor, wColor)) {
      this.screen.save().setAlpha(0.1);
      this.drawWall(entities[n]);
      this.screen.restore();
    }
  }

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    var wColor = entity.colorSpirit.toColor();
    if (!Color.equals(pColor, wColor))
      this.drawWall(entities[n]);
  }
};

Renderer.prototype.drawWall = function(entity)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawHwRect(entity.spatial.hwidth, entity.colorSpirit.style)
    .restore();
};

Renderer.prototype.drawGems = function(dt, time)
{
  var entities = this.entities.queryTag('gem');
  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    this.drawGem(entity, dt, time);
  }
};

var disabledGemStyle = new Style();
disabledGemStyle.color = '#555';
Renderer.prototype.drawGem = function(entity, dt, time)
{
  var disabled = !!entity.colorSpirit.cooldown;
  var gemSize = entity.spatial.hwidth.x;
  var mult = gemSize / 4;
  var wiggle = Math.sin(5*time/1000) * mult + mult;

  var player = this.entities.queryTag('player')[0];

  var alpha = Color.equals(
    entity.colorSpirit.toColor(),
    player.colorSpirit.toColor()) ? 0.1 : 1;

  if (disabled) {
    wiggle = wiggle*0.5 + -5 + 5 * (1 - entity.colorSpirit.cooldown/1500);
  }

  var style = disabled ? disabledGemStyle : entity.colorSpirit.style;

  this.screen
    .save()
    .vtranslate(entity.position.location)
    .setAlpha(alpha)
    .drawCircle(entity.spatial.hwidth.x + wiggle, style)
    .restore();
};

Renderer.prototype.drawAvatars = function()
{
  var entities = this.entities.queryComponents(AVATAR_FILTER);

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    this.drawAvatar(entity);
  }
};

var vh = new Vec2();
var playerStyle = new Style();
playerStyle.color = '#fff';
var shipsize = 15;
//playerStyle.fillStyle = '#EEE';
Renderer.prototype.drawAvatar = function(entity)
{
  var h = Vec2.aquire();
  var pos = Vec2.aquire();

  var player = this.entities.queryTag(['player'])[0];

  h.assign(entity.spatial.hwidth);
  h.y *= 0.5;
  pos.set(entity.spatial.hwidth.x/2.2, 0);

  this.screen
    .save()
    .vtranslate(entity.position.location)
    .rotate(entity.position.rotation)
    //.drawHwRect(entity.spatial.hwidth, playerStyle)
    .drawShape(
      [ {x:-shipsize, y:shipsize}, {x:shipsize,y:0}, {x:-shipsize,y:-shipsize}]
      , player.colorSpirit.style)
    /*
    .save()
    .scale(0.5, 0.5)
    .drawShape(
      [ {x:-shipsize, y:shipsize}, {x:shipsize,y:0}, {x:-shipsize,y:-shipsize}]
      , player.colorSpirit.style)
    .restore()
    */

    //.vtranslate(pos)
    //.drawHwRect(h, playerStyle)
    .restore();

  Vec2.release(h);
  Vec2.release(pos);
};

Renderer.prototype.drawLevelObjects = function(dt, time)
{
  var entities = this.entities.queryComponents(LEVEL_FILTER);
  var screen = this.screen;

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];

    if (entity.levelObject.type === LevelObject.types.LEVEL_FINISH)
      this.drawFinish(entity, dt, time);
  }
};

var textStyle = new Style();
textStyle.color = '#fff';
Renderer.prototype.drawText = function(entity)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawText(entity.text.value, textStyle)
    .restore();
}

var startSize = new Vec2(25, 25);
var startStyle = new Style()
startStyle.stroke = Color.tohtml(colors.green);
startStyle.strokeWidth = 5;
Renderer.prototype.drawFinish = function(entity, dt, time)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawCircle(entity.spatial.hwidth.x, startStyle)
    .restore();
};

<commit_msg>zoom refix<commit_after>module.exports = Renderer;

var EntityManager   = require('tiny-ecs').EntityManager;
var Vec2            = require('tiny-ecs').Vec2;
var Style           = require('../../lib/renderer/Style.js');
var Canvas          = require('../../lib/renderer/Canvas.js');
var Position        = require('../components/Position.js');
var Spatial         = require('../components/Spatial.js');
var LevelObject     = require('../components/LevelObject.js');
var ColorSpirit     = require('../components/ColorSpirit.js');
var Finish          = require('../components/Finish.js');
var Color           = require('../../lib/renderer/Color.js');
var Avatar          = require('../components/Avatar.js');
var Text            = require('../components/Text.js');
var colors          = require('../maps/colors.js');
var CollisionSystem = require('./CollisionSystem.js');

/**
 * @constructor
 * @param {EntityManager} entities
 * @param {Canvas} screen
 */
function Renderer(messanger, screen, entities, maps, inputs)
{
  this.screen     = screen;
  this.entities   = entities;
  this.maps       = maps;
  this.inputs     = inputs;
  global.renderer = this;

  this.fade = 0;

  messanger.listenTo(CollisionSystem.WALL, [], this.onShake.bind(this));
  messanger.listenTo('shake', [], this.onShake.bind(this));
}

var COLOR_FILTER = [Position, Spatial, ColorSpirit];
var LEVEL_FILTER = [Position, LevelObject];
var FINISH_FILTER = [Finish];
var TEXT_FILTER = [Position, Text];

// All avatars have to have a color spirit
var AVATAR_FILTER = [Position, Spatial, Avatar, ColorSpirit];

/**
 * @param {Number} dt
 * @param {Number} time
 */
Renderer.prototype.update = function(dt, time)
{
  if (this.isFinishing())
    this.fade = Math.min(1, this.fade + (dt/1000));
  else
    this.fade = Math.max(0, this.fade - (dt/1000));

  global.renderer = this;

  this.screen.save();
  this.screen.fill('#202020');
  this.cameraTransform();
  this.drawBg();
  this.drawWalls();
  this.drawGems(dt, time);
  this.drawLevelObjects(dt, time);
  this.drawAvatars();
  // this.drawTexts();
  this.screen.restore();
  this.drawFade();
};

Renderer.prototype.drawFade = function()
{
  this.screen
    .save()
    .setAlpha(this.fade)
    .fill('black')
    .restore();
};

var bV = new Vec2();

var borderStyle = new Style();
borderStyle.color = '#333';

var datStyle = new Style();
datStyle.color = '#222';

Renderer.prototype.drawBg = function()
{
  var player = this.entities.queryTag('player')[0];
  var pad = 30;
  bV.assign(this.maps.size);
  bV.x += pad*2;
  bV.y += pad*2;
  this.screen.save();
  this.screen.save();
  this.screen.translate(-pad, -pad);
  this.screen.drawRectangle(bV, borderStyle);
  this.screen.restore();
  this.screen.drawRectangle(this.maps.size, datStyle);
  this.screen.restore();
};

Renderer.prototype.isFinishing = function()
{
  return !!this.entities.queryComponents(FINISH_FILTER)[0].finish.timeOut;
};

var ct = new Vec2();
Renderer.prototype.cameraTransform = function()
{
  var player = this.entities.queryTag('player')[0];
  var inputs = this.inputs;
  var plusKey = inputs.button_k_107 || inputs.button_k_43 || inputs.button_k_187;
  var minusKey = inputs.button_k_109 || inputs.button_k_45 || inputs.button_k_189;

  // cacl zoom
  var zoom = this.zoom || 1;
  var per = player.newtonian.velocity.magnitude() / player.newtonian.maxSpeed;

  if(this.isFinishing())
    zoom = Math.min(20, Math.pow(zoom, 1.15));
  else
    zoom = 1 - this.fade/3;

  // do zoom
  if(per > 0.001){
    var p = 0.995;
    var newZoom = 1.2 - 0.2 * per;
    zoom = zoom * p + (1-p) * newZoom;
  }
  if(plusKey){
    zoom += (zoom+0.01 > 1) ? 0 : 0.01;
  }
  if(minusKey){
    zoom -= (zoom-0.01 < 0.15) ? 0 : 0.01;
  }
  this.screen.scale(zoom, zoom);
  this.zoom = zoom;

  // Translate to account for player
  ct.assign(this.screen.getSize()).smult(0.5 * (1/zoom));
  this.screen.vtranslate(ct);
  ct.assign(player.position.location).smult(-1);
  this.screen.vtranslate(ct);

  var shake = this.shake;

  this.screen.translate(
    Math.random()*shake - shake/2,
    Math.random()*shake - shake/2
  );

  this.shake = this.shake * 0.7;

};

Renderer.prototype.onShake = function()
{
  this.shake = 40;
};

Renderer.prototype.drawTexts = function()
{
  var entities = this.entities.queryComponents(TEXT_FILTER);

  for (var n = 0; n < entities.length; n++) {
    this.drawText(entities[n]);
  }
};

Renderer.prototype.drawWalls = function()
{
  var entities = this.entities.queryTag('wall');
  var pColor = this.entities.queryTag('player')[0].colorSpirit.toColor();

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    var wColor = entity.colorSpirit.toColor();
    if (Color.equals(pColor, wColor)) {
      this.screen.save().setAlpha(0.1);
      this.drawWall(entities[n]);
      this.screen.restore();
    }
  }

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    var wColor = entity.colorSpirit.toColor();
    if (!Color.equals(pColor, wColor))
      this.drawWall(entities[n]);
  }
};

Renderer.prototype.drawWall = function(entity)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawHwRect(entity.spatial.hwidth, entity.colorSpirit.style)
    .restore();
};

Renderer.prototype.drawGems = function(dt, time)
{
  var entities = this.entities.queryTag('gem');
  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    this.drawGem(entity, dt, time);
  }
};

var disabledGemStyle = new Style();
disabledGemStyle.color = '#555';
Renderer.prototype.drawGem = function(entity, dt, time)
{
  var disabled = !!entity.colorSpirit.cooldown;
  var gemSize = entity.spatial.hwidth.x;
  var mult = gemSize / 4;
  var wiggle = Math.sin(5*time/1000) * mult + mult;

  var player = this.entities.queryTag('player')[0];

  var alpha = Color.equals(
    entity.colorSpirit.toColor(),
    player.colorSpirit.toColor()) ? 0.1 : 1;

  if (disabled) {
    wiggle = wiggle*0.5 + -5 + 5 * (1 - entity.colorSpirit.cooldown/1500);
  }

  var style = disabled ? disabledGemStyle : entity.colorSpirit.style;

  this.screen
    .save()
    .vtranslate(entity.position.location)
    .setAlpha(alpha)
    .drawCircle(entity.spatial.hwidth.x + wiggle, style)
    .restore();
};

Renderer.prototype.drawAvatars = function()
{
  var entities = this.entities.queryComponents(AVATAR_FILTER);

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];
    this.drawAvatar(entity);
  }
};

var vh = new Vec2();
var playerStyle = new Style();
playerStyle.color = '#fff';
var shipsize = 15;
//playerStyle.fillStyle = '#EEE';
Renderer.prototype.drawAvatar = function(entity)
{
  var h = Vec2.aquire();
  var pos = Vec2.aquire();

  var player = this.entities.queryTag(['player'])[0];

  h.assign(entity.spatial.hwidth);
  h.y *= 0.5;
  pos.set(entity.spatial.hwidth.x/2.2, 0);

  this.screen
    .save()
    .vtranslate(entity.position.location)
    .rotate(entity.position.rotation)
    //.drawHwRect(entity.spatial.hwidth, playerStyle)
    .drawShape(
      [ {x:-shipsize, y:shipsize}, {x:shipsize,y:0}, {x:-shipsize,y:-shipsize}]
      , player.colorSpirit.style)
    /*
    .save()
    .scale(0.5, 0.5)
    .drawShape(
      [ {x:-shipsize, y:shipsize}, {x:shipsize,y:0}, {x:-shipsize,y:-shipsize}]
      , player.colorSpirit.style)
    .restore()
    */

    //.vtranslate(pos)
    //.drawHwRect(h, playerStyle)
    .restore();

  Vec2.release(h);
  Vec2.release(pos);
};

Renderer.prototype.drawLevelObjects = function(dt, time)
{
  var entities = this.entities.queryComponents(LEVEL_FILTER);
  var screen = this.screen;

  for (var n = 0; n < entities.length; n++) {
    var entity = entities[n];

    if (entity.levelObject.type === LevelObject.types.LEVEL_FINISH)
      this.drawFinish(entity, dt, time);
  }
};

var textStyle = new Style();
textStyle.color = '#fff';
Renderer.prototype.drawText = function(entity)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawText(entity.text.value, textStyle)
    .restore();
}

var startSize = new Vec2(25, 25);
var startStyle = new Style()
startStyle.stroke = Color.tohtml(colors.green);
startStyle.strokeWidth = 5;
Renderer.prototype.drawFinish = function(entity, dt, time)
{
  this.screen
    .save()
    .vtranslate(entity.position.location)
    .drawCircle(entity.spatial.hwidth.x, startStyle)
    .restore();
};

<|endoftext|>


<commit_before>module.exports = function (context, input) {

    const RxHttpRequest = require("@akanass/rx-http-request").RxHR;

    const url = process.env['POST_URL'];

    const options = {
        auth: {
            user: process.env['POST_USERNAME'],
            pass: process.env['POST_PASSWORD']
        },
        headers: {
            'User-Agent': process.env['POST_USER_AGENT']
        },
        qs: {
            code: process.env['POST_CODE']
        },
        body: {
            some: 'payload'
        },
        timeout: 2000,
        json: true // Automatically stringifies the body to JSON
    };

    context.log('JavaScript manually triggered function called with input:', input);

    RxHttpRequest.post(url, options).subscribe(
        result => context.log('body: %s, code: %s', result.body, result.response.statusCode),
        error => context.log('onError: %s', error),
        () => context.done()
    );

    context.log('Synchronous part done');

};<commit_msg>logging<commit_after>module.exports = function (context, input) {

    const RxHttpRequest = require("@akanass/rx-http-request").RxHR;

    const url = process.env['POST_URL'];

    const options = {
        auth: {
            user: process.env['POST_USERNAME'],
            pass: process.env['POST_PASSWORD']
        },
        headers: {
            'User-Agent': process.env['POST_USER_AGENT']
        },
        qs: {
            code: process.env['POST_CODE']
        },
        body: {
            some: 'payload'
        },
        timeout: 2000,
        json: true // Automatically stringifies the body to JSON
    };

    context.log('JavaScript manually triggered function called with input:', input);

    RxHttpRequest.post(url, options).subscribe(
        result => context.log('body: %s, code: %s', JSON.stringify(result.body), result.response.statusCode),
        error => context.log('onError: %s', error),
        () => context.done()
    );

    context.log('Synchronous part done');

};<|endoftext|>


<commit_before><commit_msg>Update olddeals.js<commit_after><|endoftext|>


<commit_before>var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var request = require("request");
var redis = require("redis");
var scale = require("./scale.js");

//Setup Redis
client = redis.createClient();
client.on("error", function (err) {
    console.log("Error " + err);
});

//var connectedServers = {}
var serverQueue = []

http.listen(3000, function(){
    console.log('listening on *:3000');
});

//Returns the IP of the next server in the round-robin
function nextServer(){
    var ip = serverQueue.shift();
    serverQueue.push(ip);
    return ip;
}

var cpuUsages = []
var time = 0;
var recordingInterval = 1000 * 10;
var endtime = 7440000;
var training = false;
var recording = false;
var ended = false;
var keyPrefix = training ? "training:" : "testing:";

//Clear data from previous runs
client.keys(keyPrefix + "*", function(err, keys){
    keys.forEach(function(key){
        client.del(key);
    });
    console.log("Flushed Keys");
});

var requests = 0;
var serverResponses = {};

function startRecordingUsage() {
    scale.emitTrainingData(client, io);
    scale.scale(client, 1000 * 10, io);
    var recordUsage = setInterval(function(){
        if(!ended){
            var count = cpuUsages.length;
            if(count == 0){
                return;
            }

            var sum = 0;
            while(cpuUsages.length > 0){
                sum += cpuUsages.pop();
            }

            var average = sum / count;

            console.log(JSON.stringify({ip: "Average",
            usage: average.toString()}));

            io.emit('cpu-ip', JSON.stringify({ip: "Average",
            usage: average.toString()}));

            time += recordingInterval;

            client.set(keyPrefix + time, average, redis.print);
            client.set(keyPrefix + "requests:" + time, requests);
            scale.scale(client, time + (1000 * 10), io);

            for (var server in serverResponses) {
                if (serverResponses.hasOwnProperty(server)) {
                    client.set(keyPrefix + "responses:" + server + ":" + time, serverResponses[server])
                }
            }

            scale.emitTestData(client, time, io);

            requests = 0;
            serverResponses = {};

            if(time > endtime){
                ended = true;
            }

        }

    }, recordingInterval);
}

function removeFromServerList(ip){
    var index = serverQueue.indexOf(ip);
    if(index > -1){
        serverQueue.splice(index, 1);
    }
}

io.on('connection', function(socket){
    console.log(socket.request.connection._peername.address);
    var ip = socket.request.connection._peername.address;

    socket.on('cpu-usage', function(msg){
        if(serverQueue.indexOf(ip) === -1){
            serverQueue.push(ip);
        }

        if(recording){
            cpuUsages.push(msg);
        }
    });

    socket.on('shutdown', function(){
        console.log('Shutdown Request Received');
        removeFromServerList(ip);
        socket.emit('shutdown-complete', "");
    });

    socket.on('disconnect', function(){
        //Call again incase of unexpected shutdown
        removeFromServerList(ip);
    });
});

app.get('/', function(req, res){
    if(!recording){
        recording = true;
        startRecordingUsage();
    }

    requests++;

    var server = nextServer();
    request("http://" + server + ":3005" , function(error, response, body) {
        res.write("You were served by " + server + "\n")
        res.end(body);

        if(serverResponses[server] === undefined){
            serverResponses[server] = 1;
        }
        else {
            serverResponses[server]++;
        }
    });
});
<commit_msg>Add prediction emit<commit_after>var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var request = require("request");
var redis = require("redis");
var scale = require("./scale.js");

//Setup Redis
client = redis.createClient();
client.on("error", function (err) {
    console.log("Error " + err);
});

//var connectedServers = {}
var serverQueue = []

http.listen(3000, function(){
    console.log('listening on *:3000');
});

//Returns the IP of the next server in the round-robin
function nextServer(){
    var ip = serverQueue.shift();
    if(ip !== undefined){
        serverQueue.push(ip);
    }

    return ip;
}

var cpuUsages = []
var time = 0;
var recordingInterval = 1000 * 10;
var endtime = 7440000;
var training = false;
var recording = false;
var ended = false;
var keyPrefix = training ? "training:" : "testing:";

//Clear data from previous runs
client.keys(keyPrefix + "*", function(err, keys){
    keys.forEach(function(key){
        client.del(key);
    });
    console.log("Flushed Keys");
});

var requests = 0;
var serverResponses = {};

function startRecordingUsage() {
    scale.emitTrainingData(client, io);
    scale.scale(client, 1000 * 10, io);
    var recordUsage = setInterval(function(){
        if(!ended){
            var count = cpuUsages.length;
            if(count == 0){
                return;
            }

            var sum = 0;
            while(cpuUsages.length > 0){
                sum += cpuUsages.pop();
            }

            var average = sum / count;

            console.log(JSON.stringify({ip: "Average",
            usage: average.toString()}));

            io.emit('cpu-ip', JSON.stringify({ip: "Average",
            usage: average.toString()}));

            time += recordingInterval;

            client.set(keyPrefix + time, average, redis.print);
            client.set(keyPrefix + "requests:" + time, requests);
            scale.scale(client, time + (1000 * 10), io);

            for (var server in serverResponses) {
                if (serverResponses.hasOwnProperty(server)) {
                    client.set(keyPrefix + "responses:" + server + ":" + time, serverResponses[server])
                }
            }

            scale.emitTestData(client, time, io);

            requests = 0;
            serverResponses = {};

            if(time > endtime){
                ended = true;
            }

        }

    }, recordingInterval);
}

function removeFromServerList(ip){
    var index = serverQueue.indexOf(ip);
    if(index > -1){
        serverQueue.splice(index, 1);
    }
}

io.on('connection', function(socket){
    console.log(socket.request.connection._peername.address);
    var ip = socket.request.connection._peername.address;

    socket.on('cpu-usage', function(msg){
        if(serverQueue.indexOf(ip) === -1){
            serverQueue.push(ip);
        }

        if(recording){
            cpuUsages.push(msg);
        }
    });

    socket.on('shutdown', function(){
        console.log('Shutdown Request Received');
        removeFromServerList(ip);
        socket.emit('shutdown-complete', "");
    });

    socket.on('disconnect', function(){
        //Call again incase of unexpected shutdown
        removeFromServerList(ip);
    });
});

app.get('/', function(req, res){
    if(!recording){
        recording = true;
        startRecordingUsage();
    }

    requests++;

    var server = nextServer();
    request("http://" + server + ":3005" , function(error, response, body) {
        res.write("You were served by " + server + "\n")
        res.end(body);

        if(serverResponses[server] === undefined){
            serverResponses[server] = 1;
        }
        else {
            serverResponses[server]++;
        }
    });
});
<|endoftext|>


<commit_before>var utils = {

    "extend": function(base, child) {
        if (child == undefined) return base;
        var current = {"blocks": {}};
        for (var key in base.blocks) {
            if (!child.blocks[key]) {
                current.blocks[key] = base.blocks[key];
            } else {
                current.blocks[key] = child.blocks[key];
            }
        }
        return current;
    },

    "slice": function(val, start, stop) {
        if (typeof(val) == "string") {
            return val.substring(start, stop);
        } else if (val instanceof Array) {
            return val.slice(start, stop);
        }
    },

    "loop": function(iter) {
        function LoopObject() {
            this.iter = iter;
            this.l = iter.length;
            this.i = 0;
            this.update = function() {
            	this.index = this.i + 1;
            	this.index0 = this.i;
            	this.revindex = this.l - this.i;
            	this.revindex0 = this.l - this.i - 1;
            	this.first = !this.i;
            	this.last = this.i == this.l - 1;
            }
            this.cycle = function() {
            	return arguments[this.index0 % arguments.length];
            };
    	}
    	return new LoopObject();
    },

    "contains": function(n, hs) {
        if (hs instanceof Array) {
            for (var i = 0; i < hs.length; i++) {
                if (hs[i] == n) return true;
            }
            return false;
        } else if (typeof(hs) == "string") {
            return !!hs.match(RegExp(n));
        } else if (typeof(hs) == "object") {
            return hs[n] !== undefined;
        } else {
            throw new TypeError("containment is undefined");
        }
    },

    "strjoin": function() {
        var buf = [];
        for (var i = 0; i < arguments.length; i++) {
            buf.push(arguments[i].toString());
        }
        return buf.join("");
    },

    "strmul": function(s, n) {
    	var buf = [];
    	for (var i = 0; i < n; i++) {
    		buf.push(s);
    	}
    	return buf.join('');
    },

};

var filters = {

    "attr": function(obj, name) {
        return obj[name];
    },

    "abs": function(n) {
        return Math.abs(n);
    },

    "capitalize": function(s) {
        s = s.toLowerCase();
        return s.charAt(0).toUpperCase() + s.substring(1);
    },

    "center": function(s, width) {
    	width = arguments[1] ? width : 80;
        var pre = Math.floor((width - s.length) / 2);
        var post = Math.ceil((width - s.length) / 2);
        var buf = [];
        for (var i = 0; i < pre; i++) {
            buf.push(' ');
        }
        buf.push(s);
        for (var i = 0; i < post; i++) {
            buf.push(' ');
        }
        return buf.join('');
    },

    "count": function(val) {
        return filters.length(val);
    },

    "d": function(val, alt) {
        return filters.default(val, alt);
    },

    "default": function(val, alt) {
        return val ? val : alt;
    },

    "dictsort": function(val) {
        var keys = filters.list(val);
        keys.sort();
        var ls = [];
        for (var i = 0; i < keys.length; i++) {
            ls.push([keys[i], val[keys[i]]]);
        }
        return ls;
    },

    "e": function(s) {
        return this.escape(s);
    },

    "escape": function(s) {
        s = s.replace('&', '&');
        s = s.replace('<', '<');
        s = s.replace('>', '>');
        s = s.replace('"', '"');
        s = s.replace("'", ''');
        return s;
    },

    "filesizeformat": function(val, binary) {
    	binary = arguments[1] ? binary : false;
    	var bytes = parseFloat(val);
    	var base = binary ? 1024 : 1000;
    	var middle = binary ? 'i' : '';
    	if (bytes < base) {
    		var multi = bytes == 1 ? '' : 's';
    	    return filters.format("%i Byte%s", bytes, multi);
    	} else if (bytes < base * base) {
    	    return filters.format("%.1f K%sB", bytes / base, middle);
    	} else if (bytes < base * base * base) {
    	    return filters.format("%.1f M%sB", bytes / (base * base), middle);
    	}
    	return filters.format("%.1f G%sB", bytes / (base * base * base), middle);
    },

    "first": function(val) {
        if (typeof(val) == "string") {
            return val.charAt(0);
        } else if (val instanceof Array) {
            return val[0];
        }
    },

    "float": function(val) {
        return parseFloat(val) || 0.0;
    },

    "format": function(fmt) {
        var vals = Array.prototype.slice.call(arguments, 1);
        var regex = new RegExp('\%([0 ]?)((?:[0-9]+)?)(\.[0-9]+)?([fis%])');
        while (regex.test(fmt)) {

        	var parts = regex.exec(fmt);
	        var ext = parts[1] ? parts[1] : ' ';
        	var wantlen = parseInt(parts[2]);
	        var type = parts[0].substring(parts[0].length - 1);
        	var val = vals.shift();

	        if (type == "f") {

	        	val = parseFloat(val);
	        	if (parts[3]) {
	        		val = val.toFixed(parseInt(parts[3].substring(1)));
	        	} else {
	        		val = val.toString();
	        	}
	        	if (val.length < wantlen) {
	        		val = utils.strmul(ext, wantlen - val.length) + val;
	        	}
	        	fmt = fmt.replace(parts[0], val);

	        } else if (type == "i") {

	            val = parseInt(val).toString();
	            if (val.length < wantlen) {
	            	val = utils.strmul(ext, wantlen - val.length) + val;
	            }
	            fmt = fmt.replace(parts[0], val);

	        } else if (type == "s") {

	        	if (val.length < wantlen) {
	        		val = utils.strmul(ext, wantlen - val.length) + val;
	        	}
	        	fmt = fmt.replace(parts[0], val.toString());

	        } else if (type == "%") {
	        	fmt = fmt.replace("%%", "%");
	        }

        }
        return fmt;
    },

    "int": function(val) {
        return Math.floor(val) || 0;
    },

    "last": function(val) {
        if (typeof(val) == "string") {
            return val.charAt(val.length - 1);
        } else if (val instanceof Array) {
            return val[val.length - 1];
        }
    },

    "length": function(val) {
        return val.length;
    },

    "list": function(val) {
        if (val instanceof Array) {
            return val;
        } else if (typeof(val) == "string") {
            var ls = [];
            for (var i = 0; i < val.length; i++) {
                ls.push(val.charAt(i));
            }
            return ls;
        } else if (typeof(val) == "object") {
            var ls = [];
            for (var key in val) {
                ls.push(key);
            }
            return ls;
        } else {
            throw new TypeError("containment is undefined");
        }
    },

    "join": function(val, d) {
        return val.join(d);
    },

    "reverse": function(r) {
    	var c = r.slice(0);
    	c.reverse();
    	return c;
    },

    "round": function(val) {
        var num = arguments[1] ? arguments[1] : 0;
        var mul = num ? num * 10 : 1;
        return Math.round(val * mul) / mul;
    },

    "sort": function(val) {
        var c = val.slice(0);
        c.sort();
        return c;
    },

    "string": function(val) {
        return val.toString();
    },

    "title": function(s) {
        return s.replace(/[a-zA-Z]+/g, filters.capitalize);
    }

};

var tests = {
    "callable": function(val) {
        return typeof(val) == "function";
    },
    "defined": function(val) {
        return val !== undefined;
    },
    "divisibleby": function(val, num) {
        return !(val % num);
    },
    "even": function(val) {
        return tests.divisibleby(val, 2);
    },
    "lower": function(val) {
        return val.toLowerCase() == val;
    },
    "none": function(val) {
        return val === null;
    },
    "number": function(val) {
        return typeof(val) == "number";
    },
    "odd": function(val) {
        return !tests.divisibleby(val, 2);
    },
    "undefined": function(val) {
        return val === undefined;
    },
    "upper": function(val) {
        return val.toUpperCase() == val;
    },
    "string": function(val) {
        return typeof(val) == "string";
    }
}

var templates = {
[DATA]

};
<commit_msg>Add optional convenience argument to LoopObject.update().<commit_after>var utils = {

    "extend": function(base, child) {
        if (child == undefined) return base;
        var current = {"blocks": {}};
        for (var key in base.blocks) {
            if (!child.blocks[key]) {
                current.blocks[key] = base.blocks[key];
            } else {
                current.blocks[key] = child.blocks[key];
            }
        }
        return current;
    },

    "slice": function(val, start, stop) {
        if (typeof(val) == "string") {
            return val.substring(start, stop);
        } else if (val instanceof Array) {
            return val.slice(start, stop);
        }
    },

    "loop": function(iter) {
        function LoopObject() {
            this.iter = iter;
            this.l = iter.length;
            this.i = 0;
            this.update = function() {
            	if (arguments.length) this.i = arguments[0];
            	this.index = this.i + 1;
            	this.index0 = this.i;
            	this.revindex = this.l - this.i;
            	this.revindex0 = this.l - this.i - 1;
            	this.first = !this.i;
            	this.last = this.i == this.l - 1;
            }
            this.cycle = function() {
            	return arguments[this.index0 % arguments.length];
            };
    	}
    	return new LoopObject();
    },

    "contains": function(n, hs) {
        if (hs instanceof Array) {
            for (var i = 0; i < hs.length; i++) {
                if (hs[i] == n) return true;
            }
            return false;
        } else if (typeof(hs) == "string") {
            return !!hs.match(RegExp(n));
        } else if (typeof(hs) == "object") {
            return hs[n] !== undefined;
        } else {
            throw new TypeError("containment is undefined");
        }
    },

    "strjoin": function() {
        var buf = [];
        for (var i = 0; i < arguments.length; i++) {
            buf.push(arguments[i].toString());
        }
        return buf.join("");
    },

    "strmul": function(s, n) {
    	var buf = [];
    	for (var i = 0; i < n; i++) {
    		buf.push(s);
    	}
    	return buf.join('');
    },

};

var filters = {

    "attr": function(obj, name) {
        return obj[name];
    },

    "abs": function(n) {
        return Math.abs(n);
    },

    "capitalize": function(s) {
        s = s.toLowerCase();
        return s.charAt(0).toUpperCase() + s.substring(1);
    },

    "center": function(s, width) {
    	width = arguments[1] ? width : 80;
        var pre = Math.floor((width - s.length) / 2);
        var post = Math.ceil((width - s.length) / 2);
        var buf = [];
        for (var i = 0; i < pre; i++) {
            buf.push(' ');
        }
        buf.push(s);
        for (var i = 0; i < post; i++) {
            buf.push(' ');
        }
        return buf.join('');
    },

    "count": function(val) {
        return filters.length(val);
    },

    "d": function(val, alt) {
        return filters.default(val, alt);
    },

    "default": function(val, alt) {
        return val ? val : alt;
    },

    "dictsort": function(val) {
        var keys = filters.list(val);
        keys.sort();
        var ls = [];
        for (var i = 0; i < keys.length; i++) {
            ls.push([keys[i], val[keys[i]]]);
        }
        return ls;
    },

    "e": function(s) {
        return this.escape(s);
    },

    "escape": function(s) {
        s = s.replace('&', '&');
        s = s.replace('<', '<');
        s = s.replace('>', '>');
        s = s.replace('"', '"');
        s = s.replace("'", ''');
        return s;
    },

    "filesizeformat": function(val, binary) {
    	binary = arguments[1] ? binary : false;
    	var bytes = parseFloat(val);
    	var base = binary ? 1024 : 1000;
    	var middle = binary ? 'i' : '';
    	if (bytes < base) {
    		var multi = bytes == 1 ? '' : 's';
    	    return filters.format("%i Byte%s", bytes, multi);
    	} else if (bytes < base * base) {
    	    return filters.format("%.1f K%sB", bytes / base, middle);
    	} else if (bytes < base * base * base) {
    	    return filters.format("%.1f M%sB", bytes / (base * base), middle);
    	}
    	return filters.format("%.1f G%sB", bytes / (base * base * base), middle);
    },

    "first": function(val) {
        if (typeof(val) == "string") {
            return val.charAt(0);
        } else if (val instanceof Array) {
            return val[0];
        }
    },

    "float": function(val) {
        return parseFloat(val) || 0.0;
    },

    "format": function(fmt) {
        var vals = Array.prototype.slice.call(arguments, 1);
        var regex = new RegExp('\%([0 ]?)((?:[0-9]+)?)(\.[0-9]+)?([fis%])');
        while (regex.test(fmt)) {

        	var parts = regex.exec(fmt);
	        var ext = parts[1] ? parts[1] : ' ';
        	var wantlen = parseInt(parts[2]);
	        var type = parts[0].substring(parts[0].length - 1);
        	var val = vals.shift();

	        if (type == "f") {

	        	val = parseFloat(val);
	        	if (parts[3]) {
	        		val = val.toFixed(parseInt(parts[3].substring(1)));
	        	} else {
	        		val = val.toString();
	        	}
	        	if (val.length < wantlen) {
	        		val = utils.strmul(ext, wantlen - val.length) + val;
	        	}
	        	fmt = fmt.replace(parts[0], val);

	        } else if (type == "i") {

	            val = parseInt(val).toString();
	            if (val.length < wantlen) {
	            	val = utils.strmul(ext, wantlen - val.length) + val;
	            }
	            fmt = fmt.replace(parts[0], val);

	        } else if (type == "s") {

	        	if (val.length < wantlen) {
	        		val = utils.strmul(ext, wantlen - val.length) + val;
	        	}
	        	fmt = fmt.replace(parts[0], val.toString());

	        } else if (type == "%") {
	        	fmt = fmt.replace("%%", "%");
	        }

        }
        return fmt;
    },

    "int": function(val) {
        return Math.floor(val) || 0;
    },

    "last": function(val) {
        if (typeof(val) == "string") {
            return val.charAt(val.length - 1);
        } else if (val instanceof Array) {
            return val[val.length - 1];
        }
    },

    "length": function(val) {
        return val.length;
    },

    "list": function(val) {
        if (val instanceof Array) {
            return val;
        } else if (typeof(val) == "string") {
            var ls = [];
            for (var i = 0; i < val.length; i++) {
                ls.push(val.charAt(i));
            }
            return ls;
        } else if (typeof(val) == "object") {
            var ls = [];
            for (var key in val) {
                ls.push(key);
            }
            return ls;
        } else {
            throw new TypeError("containment is undefined");
        }
    },

    "join": function(val, d) {
        return val.join(d);
    },

    "reverse": function(r) {
    	var c = r.slice(0);
    	c.reverse();
    	return c;
    },

    "round": function(val) {
        var num = arguments[1] ? arguments[1] : 0;
        var mul = num ? num * 10 : 1;
        return Math.round(val * mul) / mul;
    },

    "sort": function(val) {
        var c = val.slice(0);
        c.sort();
        return c;
    },

    "string": function(val) {
        return val.toString();
    },

    "title": function(s) {
        return s.replace(/[a-zA-Z]+/g, filters.capitalize);
    }

};

var tests = {
    "callable": function(val) {
        return typeof(val) == "function";
    },
    "defined": function(val) {
        return val !== undefined;
    },
    "divisibleby": function(val, num) {
        return !(val % num);
    },
    "even": function(val) {
        return tests.divisibleby(val, 2);
    },
    "lower": function(val) {
        return val.toLowerCase() == val;
    },
    "none": function(val) {
        return val === null;
    },
    "number": function(val) {
        return typeof(val) == "number";
    },
    "odd": function(val) {
        return !tests.divisibleby(val, 2);
    },
    "undefined": function(val) {
        return val === undefined;
    },
    "upper": function(val) {
        return val.toUpperCase() == val;
    },
    "string": function(val) {
        return typeof(val) == "string";
    }
}

var templates = {
[DATA]

};
<|endoftext|>


<commit_before>/**
 * Doranis GEO
 * Doranis.Geo | Tuesday, June 3, 2014
 * @author Pezhvak IMV (pezhvakimv@gmail.com)
 * @package doranis
 * @version 1.0
 **/
(function($){
    $.doranis.geo = {}
    $.doranis.geo.isSupported = function(){
        return navigator.geolocation ? true : false;
    }

    /**
     * Locate user by getting latitude and longitude
     * @param opts Callbacks
     */
    $.doranis.geo.locate = function(opts){
        opts = $.extend({process: function(data){}, decline: function(error){}}, opts);
        if(!$.doranis.geo.isSupported()) $opts.decline('geolocation is not supported by your browser, please update your browser now!');
        else
            navigator.geolocation.getCurrentPosition(opts.process, opts.decline);
    }

    /**
     * Convert Latitude and longitude into address detail
     * @param lat Latitude (or locate result)
     * @param lng Longitude (omit if locate result set for lat)
     * @param success callback(detail)
     */
    $.doranis.geo.latlng2detail = function(lat, lng, success){
        // Convert $.doranis.geo.locate result into lat, lng
        if(isNaN(success) && lat.coords){
            success = lng;
            lng = lat.coords.longitude;
            lat = lat.coords.latitude;
        }

        $.getJSON('http://maps.google.com/maps/api/geocode/json?latlng='+lat+','+lng+'&sensor=false', function(detail){
            success(detail);
        });
    }

    /**
     * Detect user location and return simplified address object
     * @param opts Callbacks
     */
    $.doranis.geo.detect = function(opts){
        opts = $.extend({success: function(data){}, decline: function(error){}}, opts);

        $.doranis.geo.locate({process: function(data){
            $.doranis.geo.latlng2detail(data, function(info){
                var geo = {}
                for(result in info.results){
                    console.log(result);
                    var t = result.types[0];
                    geo[t] = {}
                    geo[t]['address'] = result.formatted_address;
                    for(ac in result.address_components){
                        geo[ac.types[0]] = ac.long_name;
                    }
                }

                opts.success(geo);
            });
        }, decline: opts.decline});
    }
})(jQuery);<commit_msg>geo debug<commit_after>/**
 * Doranis GEO
 * Doranis.Geo | Tuesday, June 3, 2014
 * @author Pezhvak IMV (pezhvakimv@gmail.com)
 * @package doranis
 * @version 1.0
 **/
(function($){
    $.doranis.geo = {}
    $.doranis.geo.isSupported = function(){
        return navigator.geolocation ? true : false;
    }

    /**
     * Locate user by getting latitude and longitude
     * @param opts Callbacks
     */
    $.doranis.geo.locate = function(opts){
        opts = $.extend({process: function(data){}, decline: function(error){}}, opts);
        if(!$.doranis.geo.isSupported()) $opts.decline('geolocation is not supported by your browser, please update your browser now!');
        else
            navigator.geolocation.getCurrentPosition(opts.process, opts.decline);
    }

    /**
     * Convert Latitude and longitude into address detail
     * @param lat Latitude (or locate result)
     * @param lng Longitude (omit if locate result set for lat)
     * @param success callback(detail)
     */
    $.doranis.geo.latlng2detail = function(lat, lng, success){
        // Convert $.doranis.geo.locate result into lat, lng
        if(isNaN(success) && lat.coords){
            success = lng;
            lng = lat.coords.longitude;
            lat = lat.coords.latitude;
        }

        $.getJSON('http://maps.google.com/maps/api/geocode/json?latlng='+lat+','+lng+'&sensor=false', function(detail){
            success(detail);
        });
    }

    /**
     * Detect user location and return simplified address object
     * @param opts Callbacks
     */
    $.doranis.geo.detect = function(opts){
        opts = $.extend({success: function(data){}, decline: function(error){}}, opts);

        $.doranis.geo.locate({process: function(data){
            $.doranis.geo.latlng2detail(data, function(info){
                var geo = {}
                for(result in info.results){

                    console.log(result);
                    var t = result.types[0];
                    geo[t] = {}
                    geo[t]['address'] = result.formatted_address;
                    for(ac in result.address_components){
                        geo[ac.types[0]] = ac.long_name;
                    }
                }

                opts.success(geo);
            });
        }, decline: opts.decline});
    }
})(jQuery);<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var Job = require('./models/job');
var Company = require('./models/company');

var test = false;

if (!test) mongoose.connect('mongodb://127.0.0.1/bikeindustryjobs');

// request tracker so i know when it's safe to exit

/*
^--- seem good to go

https://chc.tbe.taleo.net/chc01/ats/careers/searchResults.jsp?org=SHIMANO&cws=1
^--- maybe multiple pages? also has fish

http://wheelsmfg.com/employment-opportunities
https://www.eastoncycling.com/about-us/careers/
https://www.pinkbike.com/about/jobs/
^--- all on one page

^--- json but easy looking to scrape

https://www.giant-bicycles.com/us/job-openings

http://www.finishlineusa.com/resources/careers.php
https://www.brompton.com/About-Us/Careers
^--- weird pdfs

https://recruiting.ultipro.com/QUA1003QBP/JobBoard/4b01c3ed-7e54-43da-954f-c74c4b3945a6/OpportunityDetail?opportunityId=19b344bd-5891-40ec-9fa0-46d4393c3b98
https://www.fitzii.com/careers/cervelo/
https://www.trekbikes.com/us/en_US/current_openings?p=jobs&nl=1
https://www.specialized.com/us/en/careers
https://www.santacruzbicycles.com/en-US/current-job-openings
^--- donezo

*/

var companyComplete = [];

var started = (company) => {
	companyComplete[company] = false;
}

var completed = (company) => {
	companyComplete[company] = true;
}

var companyCompleted = () => Object.keys(companyComplete).every(e=>companyComplete[e]==true);

class jobsaver {
	constructor() {
		this.jobQueue = [];
		this.done = true;
	}

	next() {
		return this.jobQueue.shift();
	}

	add(...job) {
		if (job == undefined) {
			console.log("undefined job");
			return;
		}
		this.jobQueue.push(...job);
		if (this.done) this.start();
	}

	start() {
		this.done = false;
		this.saveJob();
	}

	stop() {
		this.done = true;
		// have all companies been scraped?
		if (companyCompleted()) {
			console.log('all done, exiting');
			process.exit();
		}

	}

	saveJob() {
		var job = this.next();

		if (job == undefined) { this.stop(); return; }

		Job.findOneAndUpdate({'url':job.url}, {$set:job,$setOnInsert: {
			first_seen: new Date()
		}}, {upsert:true}, (err,doc) => {
			if (err) {
				console.log(err);
			}
			else {
				if (doc == null) {
					console.log("new job added: "+job.title);
				} else {
					console.log("job updated: "+job.title);
				}
			}
			this.saveJob();

		});

	}

}

/* pull companies from db with hasScraper */

Company.find({'hasScraper': true},(err,res)=>{
	if (res) {
		var js = new jobsaver();

		res.forEach((company) => {
			var scraper = require(`./scrapers/${company.company}`)
			var s = new scraper(company);
			started(company.company);

			//s.process(saveJobs);
			s.process(js.add.bind(js),()=>{completed(company.company)})

			console.log('scraping '+company.company);

		})
	}
})
<commit_msg>cleanup<commit_after>var mongoose = require('mongoose');
var Job = require('./models/job');
var Company = require('./models/company');

var test = false;

if (!test) mongoose.connect('mongodb://127.0.0.1/bikeindustryjobs');

/*
^--- seem good to go

https://chc.tbe.taleo.net/chc01/ats/careers/searchResults.jsp?org=SHIMANO&cws=1
^--- maybe multiple pages? also has fish

http://wheelsmfg.com/employment-opportunities
https://www.eastoncycling.com/about-us/careers/
https://www.pinkbike.com/about/jobs/
^--- all on one page

^--- json but easy looking to scrape

https://www.giant-bicycles.com/us/job-openings

http://www.finishlineusa.com/resources/careers.php
https://www.brompton.com/About-Us/Careers
^--- weird pdfs

https://recruiting.ultipro.com/QUA1003QBP/JobBoard/4b01c3ed-7e54-43da-954f-c74c4b3945a6/OpportunityDetail?opportunityId=19b344bd-5891-40ec-9fa0-46d4393c3b98
https://www.fitzii.com/careers/cervelo/
https://www.trekbikes.com/us/en_US/current_openings?p=jobs&nl=1
https://www.specialized.com/us/en/careers
https://www.santacruzbicycles.com/en-US/current-job-openings
^--- donezo

*/

var companyComplete = [];

var started = (company) => {
	companyComplete[company] = false;
}

var completed = (company) => {
	companyComplete[company] = true;
}

var companyCompleted = () => Object.keys(companyComplete).every(e=>companyComplete[e]==true);

class jobsaver {
	constructor() {
		this.jobQueue = [];
		this.done = true;
	}

	next() {
		return this.jobQueue.shift();
	}

	add(...job) {
		if (job == undefined) {
			console.log("undefined job");
			return;
		}
		this.jobQueue.push(...job);
		if (this.done) this.start();
	}

	start() {
		this.done = false;
		this.saveJob();
	}

	stop() {
		this.done = true;
		// have all companies been scraped?
		if (companyCompleted()) {
			console.log('all done, exiting');
			process.exit();
		}

	}

	saveJob() {
		var job = this.next();

		if (job == undefined) { this.stop(); return; }

		Job.findOneAndUpdate({'url':job.url}, {$set:job,$setOnInsert: {
			first_seen: new Date()
		}}, {upsert:true}, (err,doc) => {
			if (err) {
				console.log(err);
			}
			else {
				if (doc == null) {
					console.log("new job added: "+job.title);
				} else {
					console.log("job updated: "+job.title);
				}
			}
			this.saveJob();

		});

	}

}

/* pull companies from db with hasScraper */

Company.find({'hasScraper': true},(err,res)=>{
	if (res) {
		var js = new jobsaver();

		res.forEach((company) => {
			var scraper = require(`./scrapers/${company.company}`);
			console.log('scraping '+company.company);
			started(company.company);

			var s = new scraper(company);
			s.process(
				js.add.bind(js),
				()=>{completed(company.company)}
			)

		})
	}
})
<|endoftext|>