<commit_before>const ScratchRender = require('../RenderWebGL');
const getMousePosition = require('./getMousePosition');

var canvas = document.getElementById('scratch-stage');
var fudge = 90;
var renderer = new ScratchRender(canvas);
renderer.setLayerGroupOrdering(['group1']);

var drawableID = renderer.createDrawable('group1');
renderer.updateDrawableProperties(drawableID, {
    position: [0, 0],
    scale: [100, 100],
    direction: 90
});

var drawableID2 = renderer.createDrawable('group1');
var wantBitmapSkin = false;

// Bitmap (squirrel)
var image = new Image();
image.addEventListener('load', () => {
    var bitmapSkinId = renderer.createBitmapSkin(image);
    if (wantBitmapSkin) {
        renderer.updateDrawableProperties(drawableID2, {
            skinId: bitmapSkinId
        });
    }
});
image.crossOrigin = 'anonymous';
image.src = 'https://cdn.assets.scratch.mit.edu/internalapi/asset/7e24c99c1b853e52f8e7f9004416fa34.png/get/';

// SVG (cat 1-a)
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function () {
    var skinId = renderer.createSVGSkin(xhr.responseText);
    if (!wantBitmapSkin) {
        renderer.updateDrawableProperties(drawableID2, {
            skinId: skinId
        });
    }
});
xhr.open('GET', 'https://cdn.assets.scratch.mit.edu/internalapi/asset/b7853f557e4426412e64bb3da6531a99.svg/get/');
xhr.send();

var posX = 0;
var posY = 0;
var scaleX = 100;
var scaleY = 100;
var fudgeProperty = 'posx';

const fudgePropertyInput = document.getElementById('fudgeproperty');
fudgePropertyInput.addEventListener('change', updateFudgeProperty);
fudgePropertyInput.addEventListener('init', updateFudgeProperty);

const fudgeInput = document.getElementById('fudge');

const fudgeMinInput = document.getElementById('fudgeMin');
fudgeMinInput.addEventListener('change', updateFudgeMin);
fudgeMinInput.addEventListener('init', updateFudgeMin);

const fudgeMaxInput = document.getElementById('fudgeMax');
fudgeMaxInput.addEventListener('change', updateFudgeMax);
fudgeMaxInput.addEventListener('init', updateFudgeMax);

function updateFudgeProperty(event) {
    fudgeProperty = event.target.value;
}

function updateFudgeMin(event) {
    fudgeInput.min = event.target.valueAsNumber;
}

function updateFudgeMax(event) {
    fudgeInput.max = event.target.valueAsNumber;
}

// Ugly hack to properly set the values of the inputs on page load,
// since they persist across reloads, at least in Firefox.
// The best ugly hacks are the ones that reduce code duplication!
fudgePropertyInput.dispatchEvent(new CustomEvent("init"));
fudgeMinInput.dispatchEvent(new CustomEvent("init"));
fudgeMaxInput.dispatchEvent(new CustomEvent("init"));

const handleFudgeChanged = function (event) {
    fudge = event.target.valueAsNumber;
    var props = {};
    switch (fudgeProperty) {
    case 'posx':
        props.position = [fudge, posY];
        posX = fudge;
        break;
    case 'posy':
        props.position = [posX, fudge];
        posY = fudge;
        break;
    case 'direction':
        props.direction = fudge;
        break;
    case 'scalex':
        props.scale = [fudge, scaleY];
        scaleX = fudge;
        break;
    case 'scaley':
        props.scale = [scaleX, fudge];
        scaleY = fudge;
        break;
    case 'color':
        props.color = fudge;
        break;
    case 'whirl':
        props.whirl = fudge;
        break;
    case 'fisheye':
        props.fisheye = fudge;
        break;
    case 'pixelate':
        props.pixelate = fudge;
        break;
    case 'mosaic':
        props.mosaic = fudge;
        break;
    case 'brightness':
        props.brightness = fudge;
        break;
    case 'ghost':
        props.ghost = fudge;
        break;
    }
    renderer.updateDrawableProperties(drawableID2, props);
};
fudgeInput.addEventListener('input', handleFudgeChanged);
fudgeInput.addEventListener('change', handleFudgeChanged);
fudgeInput.addEventListener('load', handleFudgeChanged);

canvas.addEventListener('mousemove', event => {
    var mousePos = getMousePosition(event, canvas);
    renderer.extractColor(mousePos.x, mousePos.y, 30);
});

canvas.addEventListener('click', event => {
    var mousePos = getMousePosition(event, canvas);
    var pickID = renderer.pick(mousePos.x, mousePos.y);
    console.log('You clicked on ' + (pickID < 0 ? 'nothing' : 'ID# ' + pickID));
    if (pickID >= 0) {
        console.dir(renderer.extractDrawable(pickID, mousePos.x, mousePos.y));
    }
});

const drawStep = function () {
    renderer.draw();
    // renderer.getBounds(drawableID2);
    // renderer.isTouchingColor(drawableID2, [255,255,255]);
    requestAnimationFrame(drawStep);
};
drawStep();

var debugCanvas = /** @type {canvas} */ document.getElementById('debug-canvas');
renderer.setDebugCanvas(debugCanvas);
<commit_msg>More fixes for loading in playground<commit_after>const ScratchRender = require('../RenderWebGL');
const getMousePosition = require('./getMousePosition');

var canvas = document.getElementById('scratch-stage');
var fudge = 90;
var renderer = new ScratchRender(canvas);
renderer.setLayerGroupOrdering(['group1']);

var drawableID = renderer.createDrawable('group1');
renderer.updateDrawableProperties(drawableID, {
    position: [0, 0],
    scale: [100, 100],
    direction: 90
});

var drawableID2 = renderer.createDrawable('group1');
var wantBitmapSkin = false;

// Bitmap (squirrel)
var image = new Image();
image.addEventListener('load', () => {
    var bitmapSkinId = renderer.createBitmapSkin(image);
    if (wantBitmapSkin) {
        renderer.updateDrawableProperties(drawableID2, {
            skinId: bitmapSkinId
        });
    }
});
image.crossOrigin = 'anonymous';
image.src = 'https://cdn.assets.scratch.mit.edu/internalapi/asset/7e24c99c1b853e52f8e7f9004416fa34.png/get/';

// SVG (cat 1-a)
var xhr = new XMLHttpRequest();
xhr.addEventListener('load', function () {
    var skinId = renderer.createSVGSkin(xhr.responseText);
    if (!wantBitmapSkin) {
        renderer.updateDrawableProperties(drawableID2, {
            skinId: skinId
        });
    }
});
xhr.open('GET', 'https://cdn.assets.scratch.mit.edu/internalapi/asset/b7853f557e4426412e64bb3da6531a99.svg/get/');
xhr.send();

var posX = 0;
var posY = 0;
var scaleX = 100;
var scaleY = 100;
var fudgeProperty = 'posx';

const fudgePropertyInput = document.getElementById('fudgeproperty');
fudgePropertyInput.addEventListener('change', updateFudgeProperty);
fudgePropertyInput.addEventListener('init', updateFudgeProperty);

const fudgeInput = document.getElementById('fudge');

const fudgeMinInput = document.getElementById('fudgeMin');
fudgeMinInput.addEventListener('change', updateFudgeMin);
fudgeMinInput.addEventListener('init', updateFudgeMin);

const fudgeMaxInput = document.getElementById('fudgeMax');
fudgeMaxInput.addEventListener('change', updateFudgeMax);
fudgeMaxInput.addEventListener('init', updateFudgeMax);

function updateFudgeProperty(event) {
    fudgeProperty = event.target.value;
}

function updateFudgeMin(event) {
    fudgeInput.min = event.target.valueAsNumber;
}

function updateFudgeMax(event) {
    fudgeInput.max = event.target.valueAsNumber;
}

// Ugly hack to properly set the values of the inputs on page load,
// since they persist across reloads, at least in Firefox.
// The best ugly hacks are the ones that reduce code duplication!
fudgePropertyInput.dispatchEvent(new CustomEvent("init"));
fudgeMinInput.dispatchEvent(new CustomEvent("init"));
fudgeMaxInput.dispatchEvent(new CustomEvent("init"));
fudgeInput.dispatchEvent(new CustomEvent("init"));

const handleFudgeChanged = function (event) {
    fudge = event.target.valueAsNumber;
    var props = {};
    switch (fudgeProperty) {
    case 'posx':
        props.position = [fudge, posY];
        posX = fudge;
        break;
    case 'posy':
        props.position = [posX, fudge];
        posY = fudge;
        break;
    case 'direction':
        props.direction = fudge;
        break;
    case 'scalex':
        props.scale = [fudge, scaleY];
        scaleX = fudge;
        break;
    case 'scaley':
        props.scale = [scaleX, fudge];
        scaleY = fudge;
        break;
    case 'color':
        props.color = fudge;
        break;
    case 'whirl':
        props.whirl = fudge;
        break;
    case 'fisheye':
        props.fisheye = fudge;
        break;
    case 'pixelate':
        props.pixelate = fudge;
        break;
    case 'mosaic':
        props.mosaic = fudge;
        break;
    case 'brightness':
        props.brightness = fudge;
        break;
    case 'ghost':
        props.ghost = fudge;
        break;
    }
    renderer.updateDrawableProperties(drawableID2, props);
};

fudgeInput.addEventListener('input', handleFudgeChanged);
fudgeInput.addEventListener('change', handleFudgeChanged);
fudgeInput.addEventListener('init', handleFudgeChanged);

canvas.addEventListener('mousemove', event => {
    var mousePos = getMousePosition(event, canvas);
    renderer.extractColor(mousePos.x, mousePos.y, 30);
});

canvas.addEventListener('click', event => {
    var mousePos = getMousePosition(event, canvas);
    var pickID = renderer.pick(mousePos.x, mousePos.y);
    console.log('You clicked on ' + (pickID < 0 ? 'nothing' : 'ID# ' + pickID));
    if (pickID >= 0) {
        console.dir(renderer.extractDrawable(pickID, mousePos.x, mousePos.y));
    }
});

const drawStep = function () {
    renderer.draw();
    // renderer.getBounds(drawableID2);
    // renderer.isTouchingColor(drawableID2, [255,255,255]);
    requestAnimationFrame(drawStep);
};
drawStep();

var debugCanvas = /** @type {canvas} */ document.getElementById('debug-canvas');
renderer.setDebugCanvas(debugCanvas);
<|endoftext|>


<commit_before>const assert = require('assert');

const BinaryReversal = str => {
  const val = Number(str).toString(2);

  return parseInt(
    val
      .padStart(Math.ceil(val.length / 8) * 8, '0')
      .split('')
      .reverse()
      .join(''),
    2
  );

  // console.log('err here');
};

console.log(BinaryReversal);

const in1 = '213'; // input
const expect1 = '171'; // output
const test1 = BinaryReversal(in1);
assert.strictEqual(test1, expect1);
<commit_msg>wip-update function to debug test<commit_after>const assert = require('assert');

const BinaryReversal = str => {

  // first, convert int to binary
  let num = Number(str).toString(2).toString();

    // add 0 at beginning to create blocks of 8 bits
    while (num.length % 8 !== 0) {
      num = '0' + num;
    }

    // reverse binary number
    rev = num.split('').reverse().join('');

    // now, convert binary to int
    int = parseInt(rev, 2);

    return int;
};

// console.log(int);

const in1 = '213'; // input
const expect1 = '171'; // output
const test1 = BinaryReversal(in1);
assert.strictEqual(test1, expect1);
<|endoftext|>


<commit_before>/*
 * gstorage
 * https://github.com/goliatone/gstorage
 * Created with gbase.
 * Copyright (c) 2014 goliatone
 * Licensed under the MIT license.
 */
/* jshint strict: false, plusplus: true */
/*global define: false, require: false, module: false, exports: false */
(function(root, name, deps, factory) {
    "use strict";
    // Node
    if (typeof deps === 'function') {
        factory = deps;
        deps = [];
    }

    if (typeof exports === 'object') {
        module.exports = factory.apply(root, deps.map(require));
    } else if (typeof define === 'function' && 'amd' in define) {
        //require js, here we assume the file is named as the lower
        //case module name.
        define(name.toLowerCase(), deps, factory);
    } else {
        // Browser
        var d, i = 0,
            global = root,
            old = global[name],
            mod;
        while ((d = deps[i]) !== undefined) deps[i++] = root[d];
        global[name] = mod = factory.apply(global, deps);
        //Export no 'conflict module', aliases the module.
        mod.noConflict = function() {
            global[name] = old;
            return mod;
        };
    }
}(this, 'gstorage', ['extend'], function(extend) {

    /**
     * Extend method.
     * @param  {Object} target Source object
     * @return {Object}        Resulting object from
     *                         meging target to params.
     */
    var _extend = extend;

    /**
     * Shim console, make sure that if no console
     * available calls do not generate errors.
     * @return {Object} Console shim.
     */
    var _shimConsole = function(con) {

        if (con) return con;

        con = {};
        var empty = {},
            noop = function() {},
            properties = 'memory'.split(','),
            methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
                'groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,' +
                'table,time,timeEnd,timeStamp,trace,warn').split(','),
            prop,
            method;

        while (method = methods.pop()) con[method] = noop;
        while (prop = properties.pop()) con[prop] = empty;

        return con;
    };

    ///////////////////////////////////////////////////
    // CONSTRUCTOR
    ///////////////////////////////////////////////////

    var OPTIONS = {
        hashLength: 32,
        storeKey: '_GST_',
        storeID: '_gstore_default_',
        autoinitialize: true,
        buildDefaultStore: function() {
            //Use NullStore
            return new WebSQLStore();
        },
        makeStoreId: function() {
            return this.storeKey + window.location.hostname;
        }
    };

    /**
     * GStorage constructor
     *
     * @param  {object} config Configuration object.
     */
    var GStorage = function(config) {
        config = config || {};

        config = _extend({}, this.constructor.DEFAULTS, config);

        if (config.autoinitialize) this.init(config);
    };

    GStorage.name = GStorage.prototype.name = 'GStorage';

    GStorage.VERSION = '0.0.0';

    /**
     * Make default options available so we
     * can override.
     */
    GStorage.DEFAULTS = OPTIONS;

    GStorage.use = function(ext) {
        _extend(GStorage.prototype, ext);
    };

    ///////////////////////////////////////////////////
    // PRIVATE METHODS
    ///////////////////////////////////////////////////

    GStorage.prototype.init = function(config) {
        if (this.initialized) return this.logger.warn('Already initialized');
        this.initialized = true;

        console.log('GStorage: Init!');
        _extend(this, config);

        //TODO: Use promises!!!!!!
        this.store = this.buildDefaultStore();
        this.store.onError = this.onError.bind(this);
        this.store.onSuccess = this.onSuccess.bind(this);
        this.store.onConnected = this.onConnected.bind(this);

        return this;
    };

    GStorage.prototype.onError = function(e) {
        this.logger.error(e);
    };

    GStorage.prototype.onConnected = function(e) {
        this.logger.info('On connected', e, this);
        this.emit('connected');
    };

    GStorage.prototype.onSuccess = function(e) {
        this.logger.info('On success', e, this);
        this.emit('success', e);
    };

    ////////////////////////////////////////////
    /// DATA ACCESSSOR MEHTODS
    ///
    ////////////////////////////////////////////
    GStorage.prototype.get = function(key, def) {
        return this.store.get(key, def);
    };

    GStorage.prototype.set = function(key, value) {
        return this.store.set(key, value).then(function() {
            this.emit('change', {
                key: key,
                value: value
            });
        }.bind(this));
    };

    GStorage.prototype.del = function(key) {
        return this.store.del(key).then('success', function(result) {
            this.emit('change', {
                key: key,
                action: 'delete',
                value: result
            });
        }.bind(this));
    };

    GStorage.prototype.key = function(key) {
        //TODO: Do we want to transform key?
        return key;
    };

    ////////////////////////////////////////////
    /// STORE DELEGATE METHODS
    ///
    ////////////////////////////////////////////

    //TODO: This might now make sense
    GStorage.prototype.clear = function() {
        return this.store.clear();
        return this;
    };
    //TODO: This might now make sense
    GStorage.prototype.purge = function() {
        var args = Array.prototype.slice.call(arguments);
        this.store.purge(args);
        return this;
    };
    //TODO: This might now make sense
    GStorage.prototype.setTTL = function(key, time) {
        throw new Error('TODO: This needs to be implemented!!!');
    };

    ////////////////////////////////////////////
    /// UTILITY METHODS
    ///
    ////////////////////////////////////////////
    GStorage.prototype.now = function() {
        //Unix timestamp
        return new Date().getTime() / 1000 | 0;
    };

    /**
     * Get Date from timestamp
     * @param  {int} t  Unit timestamp.
     * @return {Date}   Date
     */
    GStorage.prototype.dateFromTimestamp = function(t) {
        //From unit timestamp to date.
        return new Date(parseInt(t) * 1000);
    };

    GStorage.prototype.hash = function(key) {
        var hash2 =
            hash1 = (5381 << 16) + 5381,
            pos = 0;
        while (pos < key.length) {
            hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ key.charCodeAt(pos);
            if (pos == key.length - 1) break;
            hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ key.charCodeAt(pos + 1);
            pos += 2;
        }

        return (hash1 + (hash2 * 1566083941)).toString();
    };

    /**
     * Logger method, meant to be implemented by
     * mixin. As a placeholder, we use console if available
     * or a shim if not present.
     */
    GStorage.prototype.logger = _shimConsole(console);

    /**
     * PubSub emit method stub.
     */
    GStorage.prototype.emit = function() {
        this.logger.warn(GStorage, 'emit method is not implemented', arguments);
    };

    return GStorage;
}));<commit_msg>GStorage: Refactoring how stores are constructed.<commit_after>/*
 * gstorage
 * https://github.com/goliatone/gstorage
 * Created with gbase.
 * Copyright (c) 2014 goliatone
 * Licensed under the MIT license.
 */
/* jshint strict: false, plusplus: true */
/*global define: false, require: false, module: false, exports: false */
(function(root, name, deps, factory) {
    "use strict";
    // Node
    if (typeof deps === 'function') {
        factory = deps;
        deps = [];
    }

    if (typeof exports === 'object') {
        module.exports = factory.apply(root, deps.map(require));
    } else if (typeof define === 'function' && 'amd' in define) {
        //require js, here we assume the file is named as the lower
        //case module name.
        define(name.toLowerCase(), deps, factory);
    } else {
        // Browser
        var d, i = 0,
            global = root,
            old = global[name],
            mod;
        while ((d = deps[i]) !== undefined) deps[i++] = root[d];
        global[name] = mod = factory.apply(global, deps);
        //Export no 'conflict module', aliases the module.
        mod.noConflict = function() {
            global[name] = old;
            return mod;
        };
    }
}(this, 'gstorage', ['extend'], function(extend) {

    /**
     * Extend method.
     * @param  {Object} target Source object
     * @return {Object}        Resulting object from
     *                         meging target to params.
     */
    var _extend = extend;

    /**
     * Shim console, make sure that if no console
     * available calls do not generate errors.
     * @return {Object} Console shim.
     */
    var _shimConsole = function(con) {

        if (con) return con;

        con = {};
        var empty = {},
            noop = function() {},
            properties = 'memory'.split(','),
            methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' +
                'groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,' +
                'table,time,timeEnd,timeStamp,trace,warn').split(','),
            prop,
            method;

        while (method = methods.pop()) con[method] = noop;
        while (prop = properties.pop()) con[prop] = empty;

        return con;
    };

    ///////////////////////////////////////////////////
    // CONSTRUCTOR
    ///////////////////////////////////////////////////

    var OPTIONS = {
        hashLength: 32,
        storeKey: '_GST_',
        storeID: '_gstore_default_',
        autoinitialize: true,
        buildDefaultStore: function() {
            //Use NullStore
            return new WebSQLStore();
        },
        storeConfig: {
            storeID: '_gstore_default_'
        },
        makeStoreId: function() {
            return this.storeKey + window.location.hostname;
        }
    };

    /**
     * GStorage constructor
     *
     * @param  {object} config Configuration object.
     */
    var GStorage = function(config) {
        config = config || {};

        config = _extend({}, this.constructor.DEFAULTS, config);

        if (config.autoinitialize) this.init(config);
    };

    GStorage.name = GStorage.prototype.name = 'GStorage';

    GStorage.VERSION = '0.0.0';

    /**
     * Make default options available so we
     * can override.
     */
    GStorage.DEFAULTS = OPTIONS;

    GStorage.use = function(ext) {
        _extend(GStorage.prototype, ext);
    };

    ///////////////////////////////////////////////////
    // PRIVATE METHODS
    ///////////////////////////////////////////////////

    GStorage.prototype.init = function(config) {
        if (this.initialized) return this.logger.warn('Already initialized');
        this.initialized = true;

        console.log('GStorage: Init!');
        _extend(this, config);

        this.store = this.buildStore();

        return this;
    };

    GStorage.prototype.buildStore = function() {
        var config = this.storeConfig;

        var store = this.storeFactory(config);

        if (typeof store.setOwner === 'function') store.setOwner(this);

        store.onError = this.onError.bind(this);
        store.onSuccess = this.onSuccess.bind(this);
        store.onConnected = this.onConnected.bind(this);

        return store;
    };

    GStorage.prototype.onError = function(e) {
        this.logger.error(e);
    };

    GStorage.prototype.onConnected = function(e) {
        this.logger.info('On connected', e, this);
        this.emit('connected');
    };

    GStorage.prototype.onSuccess = function(e) {
        this.logger.info('On success', e, this);
        this.emit('success', e);
    };

    ////////////////////////////////////////////
    /// DATA ACCESSSOR MEHTODS
    ///
    ////////////////////////////////////////////
    GStorage.prototype.get = function(key, def) {
        return this.store.get(key, def);
    };

    GStorage.prototype.set = function(key, value) {
        return this.store.set(key, value).then(function() {
            this.emit('change', {
                key: key,
                value: value
            });
        }.bind(this));
    };

    GStorage.prototype.del = function(key) {
        return this.store.del(key).then('success', function(result) {
            this.emit('change', {
                key: key,
                action: 'delete',
                value: result
            });
        }.bind(this));
    };

    GStorage.prototype.key = function(key) {
        //TODO: Do we want to transform key?
        return key;
    };

    ////////////////////////////////////////////
    /// STORE DELEGATE METHODS
    ///
    ////////////////////////////////////////////

    //TODO: This might now make sense
    GStorage.prototype.clear = function() {
        return this.store.clear();
        return this;
    };
    //TODO: This might now make sense
    GStorage.prototype.purge = function() {
        var args = Array.prototype.slice.call(arguments);
        this.store.purge(args);
        return this;
    };
    //TODO: This might now make sense
    GStorage.prototype.setTTL = function(key, time) {
        throw new Error('TODO: This needs to be implemented!!!');
    };

    ////////////////////////////////////////////
    /// UTILITY METHODS
    ///
    ////////////////////////////////////////////
    GStorage.prototype.now = function() {
        //Unix timestamp
        return new Date().getTime() / 1000 | 0;
    };

    /**
     * Get Date from timestamp
     * @param  {int} t  Unit timestamp.
     * @return {Date}   Date
     */
    GStorage.prototype.dateFromTimestamp = function(t) {
        //From unit timestamp to date.
        return new Date(parseInt(t) * 1000);
    };

    GStorage.prototype.hash = function(key) {
        var hash2 =
            hash1 = (5381 << 16) + 5381,
            pos = 0;
        while (pos < key.length) {
            hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ key.charCodeAt(pos);
            if (pos == key.length - 1) break;
            hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ key.charCodeAt(pos + 1);
            pos += 2;
        }

        return (hash1 + (hash2 * 1566083941)).toString();
    };

    /**
     * Logger method, meant to be implemented by
     * mixin. As a placeholder, we use console if available
     * or a shim if not present.
     */
    GStorage.prototype.logger = _shimConsole(console);

    /**
     * PubSub emit method stub.
     */
    GStorage.prototype.emit = function() {
        this.logger.warn(GStorage, 'emit method is not implemented', arguments);
    };

    return GStorage;
}));<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var del = require('del');
var concat = require('gulp-concat');
var gulpInject = require('gulp-inject');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var nodemon = require('gulp-nodemon');
var livereload = require('gulp-livereload');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var Server = require('karma').Server;
var svgSprite = require('gulp-svg-sprite');
var svgmin = require('gulp-svgmin');
var autoprefixer = require('gulp-autoprefixer');
var templateCache = require('gulp-angular-templatecache');
var RevAll = require('gulp-rev-all');
var path = require('path');
var child_process = require('child_process');

var paths = {
  root: '.',
  build: 'build',
  server: 'server',
  app: 'wwwroot',
  lib: 'wwwroot/lib',
  styles: 'wwwroot/styles',
  tmp: 'tmp',
  tmpStyles: 'wwwroot/tmp', // Where SASS result is stored. By the moment it is useful for development environment and also as an auxiliar on build
  tmpPrebuild: 'tmp/prebuild', // Temporary place of built files before add revision to filename
  fonts: 'wwwroot/icons/',
  testsE2E: [
    'spec/**/*_spec.js'
  ]
};

/**
 * Cleans build directory before creating a new build.
 * Relies on: "del".
 */
gulp.task('clean', function (callback) {
  del([
    paths.build,
    paths.tmp,
    paths.tmpStyles
  ], callback);
});

/**
 * Ensures the code is beautiful.
 * Relies on "gulp-jshint".
 */
gulp.task('lint', function () {
  return gulp.src([
    paths.app + '/**/*.js',
    '!' + paths.lib + '/**/*.js'
  ])
  .pipe(jshint())
  .pipe(jshint.reporter('default'));
});

/**
 * Concatenates lib scripts and generates a ready-for-production bundle.
 * Relies on: "gulp-concat".
 */
gulp.task('build-scripts-lib', function () {
  // When you update it, please remember to edit karma.conf.js and index.html
  // TODO: remove this duplicated code
  return gulp.src([
    paths.lib + '/angular/angular.min.js',
    paths.lib + '/angular-route/angular-route.min.js',
    paths.lib + '/angular-sanitize/angular-sanitize.min.js',
    paths.lib + '/angular-translate/angular-translate.min.js',
    paths.lib + '/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js',
    paths.lib + '/c3/c3.min.js',
    paths.lib + '/d3/d3.min.js',
    paths.lib + '/angular-animate/angular-animate.min.js',
    paths.lib + '/angular-jwt/dist/angular-jwt.js',
    paths.lib + '/svgxuse/svgxuse.js',
    paths.lib + '/autofill-directive/autofill-directive.js',
    paths.lib + '/angular-modal-service/dst/angular-modal-service.min.js',
    paths.lib + '/angular-click-outside/clickoutside.directive.js',
    paths.lib + '/angular-scroll/angular-scroll.min.js',
    paths.lib + '/jquery/dist/jquery.min.js',
    paths.lib + '/moment/min/moment.min.js',
    paths.lib + '/angular-moment/angular-moment.js',
    paths.lib + '/bootstrap-daterangepicker/daterangepicker.js',
    paths.lib + '/angular-daterangepicker/js/angular-daterangepicker.min.js',
    paths.lib + '/angular-ui-select/dist/select.min.js',
    paths.lib + '/angular-ui-mask/dist/mask.min.js',
    paths.lib + '/angular-slugify/angular-slugify.js',
    paths.lib + '/angular-tooltips/dist/angular-tooltips.min.js',
    paths.lib + '/clipboard/dist/clipboard.min.js',
    paths.lib + '/angularjs-slider/dist/rzslider.min.js',
    paths.lib + '/angular-recaptcha/release/angular-recaptcha.min.js'
  ])
  .pipe(concat('lib.min.js'))
  .pipe(gulp.dest(paths.tmpPrebuild + '/scripts'));
});

/**
 * Uglify and concatenates app scripts.
 * Relies on: "gulp-uglify", "gulp-concat".
 */
gulp.task('build-scripts-app', function () {
  // When you update it, please remember to edit karma.conf.js and index.html
  // TODO: remove this duplicated code
  return gulp.src([
    '!' + paths.app + '/**/*.spec.js',
    paths.app + '/polyfills/**/*.js',
    paths.app + '/app.js',
    paths.app + '/controllers/**/*.js',
    paths.app + '/interceptors/*.js',
    paths.app + '/directives/*.js',
    paths.app + '/filters/*.js',
    paths.app + '/services/**/*.js',
    paths.app + '/lists/*.js',
    paths.app + '/*.js',
    paths.app + '/env/' + process.env.NODE_ENV + '.js'
  ])
  .pipe(concat('app.min.js'))
  .pipe(uglify({
    mangle: false
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/scripts'));
});

/**
 * Uglify and concatenates scripts in building process.
 */
gulp.task('build-scripts', [
  'build-scripts-lib',
  'build-scripts-app'
]);
/**
 * Creates a svg sprite using the .svg files.
 * Relies on: "gulp-svg-sprite" and "gulp-rename".
 */
gulp.task('svg-sprite', function () {
  return gulp.src(paths.app + '/images/svg/*.svg')
    .pipe(svgmin())
    .pipe(svgSprite({
      shape: {
        id: {
          generator: 'doppler-icon-%s'
        },
        dimension: {
          maxWidth: 24,
          maxHeight: 24,
          attributes: true
        }
      },
      mode: {
        symbol: true
      }
    }).on('error', function (error) {
      console.log(error);
    }))
    .pipe(rename('sprite.svg'))
    .pipe(gulp.dest(paths.tmpPrebuild + '/images'));
});

gulp.task('svg-sprite-development', function () {
  return gulp.src(paths.app + '/images/svg/*.svg')
    .pipe(svgmin())
    .pipe(svgSprite({
      shape: {
        id: {
          generator: 'doppler-icon-%s'
        },
        dimension: {
          maxWidth: 24,
          maxHeight: 24,
          attributes: true
        }
      },
      mode: {
        symbol: true
      }
    }).on('error', function (error) {
      console.log(error);
    }))
    .pipe(rename('sprite.svg'))
    .pipe(gulp.dest(paths.app + '/images'));
});

/**
 * Compile sass files to css.
 * Relies on: "gulp-sass".
 */
gulp.task('styles', function () {
  return gulp.src([
    paths.styles + '/styles.scss',
  ])
  .pipe(sass().on('error', sass.logError))
  .pipe(autoprefixer({
    browsers: ['last 2 versions'],
    cascade: false
  }))
  // TODO: add sourcemaps
  .pipe(gulp.dest(paths.tmpStyles));
});

/**
 * Minify, rename and move compiled css to build path.
 * Relies on: "gulp-minify-css" and "gulp-rename".
 */
gulp.task('build-styles', ['styles'], function () {
  return gulp.src([
    paths.tmpStyles + '/styles.css',
    paths.lib + '/c3/c3.css',
    paths.lib + '/angular-ui-select/dist/select.min.css',
    paths.lib + '/selectize/dist/css/selectize.default.css',
    paths.lib + '/angular-tooltips/dist/angular-tooltips.css',
    paths.lib + '/angularjs-slider/dist/rzslider.min.css'
  ])
  .pipe(minifyCss({ compatibility: 'ie8' }))
  .pipe(rename({
    suffix: '.min'
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/styles'));
});

/**
 * Builds the index.html injecting several dependencies.
 * Relies on: "gulp-inject".
 */
gulp.task('build-html', ['add-revision-numbers'], function () {
  // Note: wild-cards are there to keep the file order and also to support revision numbers
  var sources = gulp.src([
    paths.build + '/scripts/lib*.js',
    paths.build + '/locales/*.js',
    paths.build + '/scripts/app*.js',
    paths.build + '/scripts/templates*.js',
    paths.build + '/styles/styles*.css',
    paths.build + '/styles/c3*.css',
    paths.build + '/styles/select*.css',
    paths.build + '/styles/selectize*.css',
    paths.build + '/styles/angular-tooltips*.css',
    paths.build + '/styles/rzslider*.css',
  ], {
    read: false // It's not necessary to read the files (will speed up things), we're only after their paths.
  });

  return gulp.src([
    paths.app + '/index.html'
  ])
  .pipe(gulpInject(sources, {
    addRootSlash: false, // ensures proper relative paths
    ignorePath: paths.build + '/' // ensures proper relative paths
  }))
  .pipe(gulp.dest(paths.build));
});

gulp.task('build-mseditor', ['build-scripts-template-editor', 'add-revision-numbers'], function () {
  var sources = gulp.src([
    paths.build + '/scripts/relay-editor.*.js'
  ]);
  return gulp.src([
    paths.app + '/template-editor/index.html'
  ])
  .pipe(gulpInject(sources, {
    addRootSlash: false, // ensures proper relative paths removing the root slash
    ignorePath: paths.build // ensures proper relative paths removing the absolute path
  }))
  .pipe(gulp.dest(paths.build + '/template-editor'));
});

gulp.task('build-scripts-template-editor', function () {
  return gulp.src([
    paths.app + '/template-editor/*.js'
  ])
  .pipe(concat('relay-editor.js'))
  .pipe(uglify({
    mangle: false
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/scripts'));
});

gulp.task('build-partials', function () {
  // TODO: minify partials. It is important for cache/revision
  // TODO: take into account revision here
  return gulp.src([
    paths.app + '/partials/**/*.html'
  ])
  .pipe(templateCache({
    module: 'dopplerRelay',
    root: 'partials',
    filename: 'templates.js'
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/scripts'));
});

/**
 * Copy locales folder with json files into build/locales.
 */
gulp.task('locales', function () {
  return gulp.src([
      paths.app + '/locales/*.js'
  ])
  .pipe(gulp.dest(paths.tmpPrebuild + '/locales'));
});

/**
 * Copy web.config file into build.
 */
gulp.task('web.config', function () {
  return gulp.src([
    paths.app + '/web.config'
  ])
  .pipe(gulp.dest(paths.build));
});

/**
 * Copy hcheck.png file into build.
 */
gulp.task('hcheck.png', function () {
  return gulp.src([
    paths.app + '/hcheck.png'
  ])
  .pipe(gulp.dest(paths.build));
});

gulp.task('fonts', function () {
  return gulp.src([
      paths.app + '/fonts/*.otf',
      paths.app + '/fonts/*.ttf',
      paths.app + '/fonts/*.woff',
      paths.app + '/fonts/*.woff2',
      paths.app + '/fonts/*.eot'
  ])
  .pipe(gulp.dest(paths.build + '/fonts'));
});

gulp.task('add-revision-numbers', ['build-scripts-template-editor', 'build-scripts', 'build-styles', 'locales', 'svg-sprite', 'build-partials', 'fonts'], function () {
  var revAll = new RevAll();
  return gulp.src([
    paths.tmpPrebuild + '/**'
  ])
  .pipe(revAll.revision())
  .pipe(gulp.dest(paths.build));
});

/**
 * Ensures the code is tested, valid & beautiful.
 */
gulp.task('validate', [
  //'lint',
  //'test'
]);

/**
 * Starts Karma server and runs the unit tests.
 * Relies on: "karma".
 */
gulp.task('test:unit', function (done) {
  new Server({
    configFile: __dirname + '/karma.conf.js', // Using __dirname because doesn't seems to work without it
    singleRun: true
  }, done).start();
});

/**
 * Starts our node server.
 * Relies on: "gulp-nodemon".
 */
gulp.task('server', function () {
  nodemon({
    script: 'server.js',
    watch: [
      '*.js',
      'server/**/*.js'
    ]
  });
});

/**
 * Reloads the browser's tab.
 * You need a browser extension to got it working (http://livereload.com/extensions).
 * Relies on: "gulp-livereload".
 */
gulp.task('reload', function () {
  livereload.reload();
});

/**
 * Watches for files changes.
 * Watch is a Gulp built-in feature, but not livereload.
 * Relies on: "gulp-livereload".
 */
gulp.task('watch', ['server'], function () {
  // Start livereload in order to refresh the browser
  livereload.listen();

  gulp.watch([
    paths.root + '/*.js',
    paths.server + '/**/*.js',
    paths.app + '/polyfills/**/*.js',
    paths.app + '/*.js',
    paths.app + '/controllers/**/*.js',
    paths.app + '/services/**/*.js'
  ], ['reload', 'validate']);

  gulp.watch([
    paths.app + '/**/*.html',
    paths.tmpStyles + '/*.css'
  ], ['reload']);

  gulp.watch([
    paths.styles + '/**/*.scss'
  ], ['styles']);
});

function getNodeBinary() {
  return /^win/.test(process.platform) ? 'node.exe' : 'node';
}

function getProtractorBinary() {
  var pkgPath = require.resolve('protractor');
  var protractorDir = path.resolve(path.join(path.dirname(pkgPath), '..', 'bin'));
  return path.join(protractorDir, '/' + 'protractor');
}

gulp.task('test:component', function () {
  // TODO: fix it:
  // If the server is already running, it show ugly errors (but works anyway),
  // maybe we should use another port, or do not try to start the server again.
  gulp.start('default');

  var argv = [getProtractorBinary(), 'protractor-conf.js'].concat(process.argv.slice(3));

  child_process
    .spawn(getNodeBinary(), argv, { stdio: 'inherit' })
    .on('error', function (e) {
      throw e;
    })
    .on('close', function (e) {
      process.exit(e);
    });
});
/**
 * Default task, used for development.
 * Starts a server and watches for changes in order to validate it.
 */
gulp.task('default', [
  'server',
  'watch',
  'styles',
  'validate',
  'svg-sprite-development'
]);

gulp.task('test', [
  'test:unit',
  'test:component'
]);

/**
 * Builds the entire application and generates a bundle in "deploy" folder.
 */
gulp.task('build', ['clean'], function () {
  gulp.start(
    'build-mseditor',
    'build-html',
    'web.config',
    'hcheck.png'
  );
});

<commit_msg>Move template editor script bundle along with the html<commit_after>'use strict';

var gulp = require('gulp');
var del = require('del');
var concat = require('gulp-concat');
var gulpInject = require('gulp-inject');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var nodemon = require('gulp-nodemon');
var livereload = require('gulp-livereload');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var Server = require('karma').Server;
var svgSprite = require('gulp-svg-sprite');
var svgmin = require('gulp-svgmin');
var autoprefixer = require('gulp-autoprefixer');
var templateCache = require('gulp-angular-templatecache');
var RevAll = require('gulp-rev-all');
var path = require('path');
var child_process = require('child_process');

var paths = {
  root: '.',
  build: 'build',
  server: 'server',
  app: 'wwwroot',
  lib: 'wwwroot/lib',
  styles: 'wwwroot/styles',
  tmp: 'tmp',
  tmpStyles: 'wwwroot/tmp', // Where SASS result is stored. By the moment it is useful for development environment and also as an auxiliar on build
  tmpPrebuild: 'tmp/prebuild', // Temporary place of built files before add revision to filename
  fonts: 'wwwroot/icons/',
  testsE2E: [
    'spec/**/*_spec.js'
  ]
};

/**
 * Cleans build directory before creating a new build.
 * Relies on: "del".
 */
gulp.task('clean', function (callback) {
  del([
    paths.build,
    paths.tmp,
    paths.tmpStyles
  ], callback);
});

/**
 * Ensures the code is beautiful.
 * Relies on "gulp-jshint".
 */
gulp.task('lint', function () {
  return gulp.src([
    paths.app + '/**/*.js',
    '!' + paths.lib + '/**/*.js'
  ])
  .pipe(jshint())
  .pipe(jshint.reporter('default'));
});

/**
 * Concatenates lib scripts and generates a ready-for-production bundle.
 * Relies on: "gulp-concat".
 */
gulp.task('build-scripts-lib', function () {
  // When you update it, please remember to edit karma.conf.js and index.html
  // TODO: remove this duplicated code
  return gulp.src([
    paths.lib + '/angular/angular.min.js',
    paths.lib + '/angular-route/angular-route.min.js',
    paths.lib + '/angular-sanitize/angular-sanitize.min.js',
    paths.lib + '/angular-translate/angular-translate.min.js',
    paths.lib + '/angular-translate-loader-static-files/angular-translate-loader-static-files.min.js',
    paths.lib + '/c3/c3.min.js',
    paths.lib + '/d3/d3.min.js',
    paths.lib + '/angular-animate/angular-animate.min.js',
    paths.lib + '/angular-jwt/dist/angular-jwt.js',
    paths.lib + '/svgxuse/svgxuse.js',
    paths.lib + '/autofill-directive/autofill-directive.js',
    paths.lib + '/angular-modal-service/dst/angular-modal-service.min.js',
    paths.lib + '/angular-click-outside/clickoutside.directive.js',
    paths.lib + '/angular-scroll/angular-scroll.min.js',
    paths.lib + '/jquery/dist/jquery.min.js',
    paths.lib + '/moment/min/moment.min.js',
    paths.lib + '/angular-moment/angular-moment.js',
    paths.lib + '/bootstrap-daterangepicker/daterangepicker.js',
    paths.lib + '/angular-daterangepicker/js/angular-daterangepicker.min.js',
    paths.lib + '/angular-ui-select/dist/select.min.js',
    paths.lib + '/angular-ui-mask/dist/mask.min.js',
    paths.lib + '/angular-slugify/angular-slugify.js',
    paths.lib + '/angular-tooltips/dist/angular-tooltips.min.js',
    paths.lib + '/clipboard/dist/clipboard.min.js',
    paths.lib + '/angularjs-slider/dist/rzslider.min.js',
    paths.lib + '/angular-recaptcha/release/angular-recaptcha.min.js'
  ])
  .pipe(concat('lib.min.js'))
  .pipe(gulp.dest(paths.tmpPrebuild + '/scripts'));
});

/**
 * Uglify and concatenates app scripts.
 * Relies on: "gulp-uglify", "gulp-concat".
 */
gulp.task('build-scripts-app', function () {
  // When you update it, please remember to edit karma.conf.js and index.html
  // TODO: remove this duplicated code
  return gulp.src([
    '!' + paths.app + '/**/*.spec.js',
    paths.app + '/polyfills/**/*.js',
    paths.app + '/app.js',
    paths.app + '/controllers/**/*.js',
    paths.app + '/interceptors/*.js',
    paths.app + '/directives/*.js',
    paths.app + '/filters/*.js',
    paths.app + '/services/**/*.js',
    paths.app + '/lists/*.js',
    paths.app + '/*.js',
    paths.app + '/env/' + process.env.NODE_ENV + '.js'
  ])
  .pipe(concat('app.min.js'))
  .pipe(uglify({
    mangle: false
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/scripts'));
});

/**
 * Uglify and concatenates scripts in building process.
 */
gulp.task('build-scripts', [
  'build-scripts-lib',
  'build-scripts-app'
]);
/**
 * Creates a svg sprite using the .svg files.
 * Relies on: "gulp-svg-sprite" and "gulp-rename".
 */
gulp.task('svg-sprite', function () {
  return gulp.src(paths.app + '/images/svg/*.svg')
    .pipe(svgmin())
    .pipe(svgSprite({
      shape: {
        id: {
          generator: 'doppler-icon-%s'
        },
        dimension: {
          maxWidth: 24,
          maxHeight: 24,
          attributes: true
        }
      },
      mode: {
        symbol: true
      }
    }).on('error', function (error) {
      console.log(error);
    }))
    .pipe(rename('sprite.svg'))
    .pipe(gulp.dest(paths.tmpPrebuild + '/images'));
});

gulp.task('svg-sprite-development', function () {
  return gulp.src(paths.app + '/images/svg/*.svg')
    .pipe(svgmin())
    .pipe(svgSprite({
      shape: {
        id: {
          generator: 'doppler-icon-%s'
        },
        dimension: {
          maxWidth: 24,
          maxHeight: 24,
          attributes: true
        }
      },
      mode: {
        symbol: true
      }
    }).on('error', function (error) {
      console.log(error);
    }))
    .pipe(rename('sprite.svg'))
    .pipe(gulp.dest(paths.app + '/images'));
});

/**
 * Compile sass files to css.
 * Relies on: "gulp-sass".
 */
gulp.task('styles', function () {
  return gulp.src([
    paths.styles + '/styles.scss',
  ])
  .pipe(sass().on('error', sass.logError))
  .pipe(autoprefixer({
    browsers: ['last 2 versions'],
    cascade: false
  }))
  // TODO: add sourcemaps
  .pipe(gulp.dest(paths.tmpStyles));
});

/**
 * Minify, rename and move compiled css to build path.
 * Relies on: "gulp-minify-css" and "gulp-rename".
 */
gulp.task('build-styles', ['styles'], function () {
  return gulp.src([
    paths.tmpStyles + '/styles.css',
    paths.lib + '/c3/c3.css',
    paths.lib + '/angular-ui-select/dist/select.min.css',
    paths.lib + '/selectize/dist/css/selectize.default.css',
    paths.lib + '/angular-tooltips/dist/angular-tooltips.css',
    paths.lib + '/angularjs-slider/dist/rzslider.min.css'
  ])
  .pipe(minifyCss({ compatibility: 'ie8' }))
  .pipe(rename({
    suffix: '.min'
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/styles'));
});

/**
 * Builds the index.html injecting several dependencies.
 * Relies on: "gulp-inject".
 */
gulp.task('build-html', ['add-revision-numbers'], function () {
  // Note: wild-cards are there to keep the file order and also to support revision numbers
  var sources = gulp.src([
    paths.build + '/scripts/lib*.js',
    paths.build + '/locales/*.js',
    paths.build + '/scripts/app*.js',
    paths.build + '/scripts/templates*.js',
    paths.build + '/styles/styles*.css',
    paths.build + '/styles/c3*.css',
    paths.build + '/styles/select*.css',
    paths.build + '/styles/selectize*.css',
    paths.build + '/styles/angular-tooltips*.css',
    paths.build + '/styles/rzslider*.css',
  ], {
    read: false // It's not necessary to read the files (will speed up things), we're only after their paths.
  });

  return gulp.src([
    paths.app + '/index.html'
  ])
  .pipe(gulpInject(sources, {
    addRootSlash: false, // ensures proper relative paths
    ignorePath: paths.build + '/' // ensures proper relative paths
  }))
  .pipe(gulp.dest(paths.build));
});

gulp.task('build-mseditor', ['build-scripts-template-editor', 'add-revision-numbers'], function () {
  var sources = gulp.src([
    paths.build + '/template-editor/relay-editor.*.js'
  ]);
  return gulp.src([
    paths.app + '/template-editor/index.html'
  ])
  .pipe(gulpInject(sources, {
    addRootSlash: false, // ensures proper relative paths removing the root slash
    ignorePath: paths.build + '/template-editor' // ensures proper relative paths removing the absolute path
  }))
  .pipe(gulp.dest(paths.build + '/template-editor'));
});

gulp.task('build-scripts-template-editor', function () {
  return gulp.src([
    paths.app + '/template-editor/*.js'
  ])
  .pipe(concat('relay-editor.js'))
  .pipe(uglify({
    mangle: false
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/template-editor'));
});

gulp.task('build-partials', function () {
  // TODO: minify partials. It is important for cache/revision
  // TODO: take into account revision here
  return gulp.src([
    paths.app + '/partials/**/*.html'
  ])
  .pipe(templateCache({
    module: 'dopplerRelay',
    root: 'partials',
    filename: 'templates.js'
  }))
  .pipe(gulp.dest(paths.tmpPrebuild + '/scripts'));
});

/**
 * Copy locales folder with json files into build/locales.
 */
gulp.task('locales', function () {
  return gulp.src([
      paths.app + '/locales/*.js'
  ])
  .pipe(gulp.dest(paths.tmpPrebuild + '/locales'));
});

/**
 * Copy web.config file into build.
 */
gulp.task('web.config', function () {
  return gulp.src([
    paths.app + '/web.config'
  ])
  .pipe(gulp.dest(paths.build));
});

/**
 * Copy hcheck.png file into build.
 */
gulp.task('hcheck.png', function () {
  return gulp.src([
    paths.app + '/hcheck.png'
  ])
  .pipe(gulp.dest(paths.build));
});

gulp.task('fonts', function () {
  return gulp.src([
      paths.app + '/fonts/*.otf',
      paths.app + '/fonts/*.ttf',
      paths.app + '/fonts/*.woff',
      paths.app + '/fonts/*.woff2',
      paths.app + '/fonts/*.eot'
  ])
  .pipe(gulp.dest(paths.build + '/fonts'));
});

gulp.task('add-revision-numbers', ['build-scripts-template-editor', 'build-scripts', 'build-styles', 'locales', 'svg-sprite', 'build-partials', 'fonts'], function () {
  var revAll = new RevAll();
  return gulp.src([
    paths.tmpPrebuild + '/**'
  ])
  .pipe(revAll.revision())
  .pipe(gulp.dest(paths.build));
});

/**
 * Ensures the code is tested, valid & beautiful.
 */
gulp.task('validate', [
  //'lint',
  //'test'
]);

/**
 * Starts Karma server and runs the unit tests.
 * Relies on: "karma".
 */
gulp.task('test:unit', function (done) {
  new Server({
    configFile: __dirname + '/karma.conf.js', // Using __dirname because doesn't seems to work without it
    singleRun: true
  }, done).start();
});

/**
 * Starts our node server.
 * Relies on: "gulp-nodemon".
 */
gulp.task('server', function () {
  nodemon({
    script: 'server.js',
    watch: [
      '*.js',
      'server/**/*.js'
    ]
  });
});

/**
 * Reloads the browser's tab.
 * You need a browser extension to got it working (http://livereload.com/extensions).
 * Relies on: "gulp-livereload".
 */
gulp.task('reload', function () {
  livereload.reload();
});

/**
 * Watches for files changes.
 * Watch is a Gulp built-in feature, but not livereload.
 * Relies on: "gulp-livereload".
 */
gulp.task('watch', ['server'], function () {
  // Start livereload in order to refresh the browser
  livereload.listen();

  gulp.watch([
    paths.root + '/*.js',
    paths.server + '/**/*.js',
    paths.app + '/polyfills/**/*.js',
    paths.app + '/*.js',
    paths.app + '/controllers/**/*.js',
    paths.app + '/services/**/*.js'
  ], ['reload', 'validate']);

  gulp.watch([
    paths.app + '/**/*.html',
    paths.tmpStyles + '/*.css'
  ], ['reload']);

  gulp.watch([
    paths.styles + '/**/*.scss'
  ], ['styles']);
});

function getNodeBinary() {
  return /^win/.test(process.platform) ? 'node.exe' : 'node';
}

function getProtractorBinary() {
  var pkgPath = require.resolve('protractor');
  var protractorDir = path.resolve(path.join(path.dirname(pkgPath), '..', 'bin'));
  return path.join(protractorDir, '/' + 'protractor');
}

gulp.task('test:component', function () {
  // TODO: fix it:
  // If the server is already running, it show ugly errors (but works anyway),
  // maybe we should use another port, or do not try to start the server again.
  gulp.start('default');

  var argv = [getProtractorBinary(), 'protractor-conf.js'].concat(process.argv.slice(3));

  child_process
    .spawn(getNodeBinary(), argv, { stdio: 'inherit' })
    .on('error', function (e) {
      throw e;
    })
    .on('close', function (e) {
      process.exit(e);
    });
});
/**
 * Default task, used for development.
 * Starts a server and watches for changes in order to validate it.
 */
gulp.task('default', [
  'server',
  'watch',
  'styles',
  'validate',
  'svg-sprite-development'
]);

gulp.task('test', [
  'test:unit',
  'test:component'
]);

/**
 * Builds the entire application and generates a bundle in "deploy" folder.
 */
gulp.task('build', ['clean'], function () {
  gulp.start(
    'build-mseditor',
    'build-html',
    'web.config',
    'hcheck.png'
  );
});

<|endoftext|>


<commit_before>var oauth = require('auth-server'),
    connect = require('connect'),
    util = require('util'),
    uuid = require('node-uuid'),
    model = require('./model'),
    config = require('./config');

var authCodes = {},
    accessTokens = {},
    clientService = {},
    tokenService = {},
    authorizationService = {},
    membershipService = {},
    supportedScopes = {},
    expiresIn = {},
    authServer = null,
    server = null;

var buildAuthServices = function () {

    model.ModelContainer.ClientModel.find({}, function (err, mongoClients) {

        //Building a consistent client structure
        var clients = {};

        mongoClients.forEach(function (client) {
            clients[client.id] = client;
        });

        authCodes = {},
            accessTokens = {},
            clientService = {
                getById: function (id, callback) {
                    return callback(clients[id]);
                },
                isValidRedirectUri: function (client, uri) {
                    return true;
                }
            },
            tokenService = {
                generateToken: function () {
                    return uuid.v4();
                },
                generateDeviceCode: function () {
                    return uuid.v4();
                }
            },
            authorizationService = {
                saveAuthorizationCode: function (codeData, callback) {
                    authCodes[codeData.code] = codeData;
                    return callback();
                },
                saveAccessToken: function (tokenData, callback) {
                    accessTokens[tokenData.access_token] = tokenData;
                    return callback();
                },
                getAuthorizationCode: function (code, callback) {
                    return callback(authCodes[code]);
                },
                getAccessToken: function (token, callback) {
                    return callback(accessTokens[token]);
                }
            },
            membershipService = {
                areUserCredentialsValid: function (userName, password, scope, callback) {
                    return callback(true);
                }
            },
            supportedScopes = ['profile', 'status', 'avatar'],
            expiresIn = 3600,
            authServer = new oauth(clientService, tokenService, authorizationService, membershipService, expiresIn, supportedScopes);

            if(!server) {
                startAuthServer();
            }

    });

};

exports.buildAuthServices = buildAuthServices;

var startAuthServer = function () {

    var authorize = function (req, res) {
            authServer.authorizeRequest(req, 'userid', function (response) {
                res.write(util.inspect(response));
                res.end();
            });
        },
        grantToken = function (req, res) {
            authServer.grantAccessToken(req, 'userid', function (token) {
                res.write(util.inspect(token));
                res.end();
            });
        },
        apiEndpoint = function (req, res) {
            authServer.validateAccessToken(req, function (validationResponse) {
                res.write(util.inspect(validationResponse));
                res.end();
            });
        };

    server = connect()
        .use(connect.query())
        .use(connect.bodyParser())
        .use('/oauth/authorize', authorize)
        .use('/oauth/token', grantToken)
        .use('/api/test', apiEndpoint).listen(config.values.auth_server_port);
};<commit_msg>/api/test is returning a json string<commit_after>var oauth = require('auth-server'),
    connect = require('connect'),
    util = require('util'),
    uuid = require('node-uuid'),
    model = require('./model'),
    config = require('./config');

var authCodes = {},
    accessTokens = {},
    clientService = {},
    tokenService = {},
    authorizationService = {},
    membershipService = {},
    supportedScopes = {},
    expiresIn = {},
    authServer = null,
    server = null;

var buildAuthServices = function () {

    model.ModelContainer.ClientModel.find({}, function (err, mongoClients) {

        //Building a consistent client structure
        var clients = {};

        mongoClients.forEach(function (client) {
            clients[client.id] = client;
        });

        authCodes = {},
            accessTokens = {},
            clientService = {
                getById: function (id, callback) {
                    return callback(clients[id]);
                },
                isValidRedirectUri: function (client, uri) {
                    return true;
                }
            },
            tokenService = {
                generateToken: function () {
                    return uuid.v4();
                },
                generateDeviceCode: function () {
                    return uuid.v4();
                }
            },
            authorizationService = {
                saveAuthorizationCode: function (codeData, callback) {
                    authCodes[codeData.code] = codeData;
                    return callback();
                },
                saveAccessToken: function (tokenData, callback) {
                    accessTokens[tokenData.access_token] = tokenData;
                    return callback();
                },
                getAuthorizationCode: function (code, callback) {
                    return callback(authCodes[code]);
                },
                getAccessToken: function (token, callback) {
                    return callback(accessTokens[token]);
                }
            },
            membershipService = {
                areUserCredentialsValid: function (userName, password, scope, callback) {
                    return callback(true);
                }
            },
            supportedScopes = ['profile', 'status', 'avatar'],
            expiresIn = 3600,
            authServer = new oauth(clientService, tokenService, authorizationService, membershipService, expiresIn, supportedScopes);

            if(!server) {
                startAuthServer();
            }

    });

};

exports.buildAuthServices = buildAuthServices;

var startAuthServer = function () {

    var authorize = function (req, res) {
            authServer.authorizeRequest(req, 'userid', function (response) {
                res.write(util.inspect(response));
                res.end();
            });
        },
        grantToken = function (req, res) {
            authServer.grantAccessToken(req, 'userid', function (token) {
                res.write(util.inspect(token));
                res.end();
            });
        },
        apiEndpoint = function (req, res) {
            authServer.validateAccessToken(req, function (validationResponse) {
                res.write(JSON.stringify(validationResponse));
                res.end();
            });
        };

    server = connect()
        .use(connect.query())
        .use(connect.bodyParser())
        .use('/oauth/authorize', authorize)
        .use('/oauth/token', grantToken)
        .use('/api/test', apiEndpoint).listen(config.values.auth_server_port);
};<|endoftext|>


<commit_before>'use strict';

function World(numCreatures, canvas, synaptic) {
	var that = this;

	this.width = canvas.width;
	this.height = canvas.height;
	this.ctx = canvas.getContext('2d');

	// configuration (this should be externalized at some point...)
	this.maxCreatures = numCreatures;
	this.tickIntervalInMs = 10;
	this.generationLengthInSec = 5;

	// populate
	this.creatures = function (numCreatures, synaptic) {

		var squashingFunctions = [
			synaptic.Neuron.squash.LOGISTIC,
			synaptic.Neuron.squash.TANH,
			synaptic.Neuron.squash.HLIM,
			synaptic.Neuron.squash.IDENTITY
		];

		var creatures = [];

		for (var i = 0; i < numCreatures; i++) {

			var x = Math.random() * (that.width - 100) + 50;
			var y = Math.random() * (that.height - 100) + 50;

			var network = new synaptic.Architect.Perceptron(5, 3, 2);

			// randomize the activation functions
			network.neurons().forEach(function (neuron) {
				if (neuron.layer === 'output') {
					neuron.neuron.squash = synaptic.Neuron.squash.TANH;
				}
				else {
					neuron.neuron.squash = squashingFunctions[Math.floor(Math.random() * squashingFunctions.length)];
				}
			});

			creatures[i] = new Creature(network, that, x, y);
			creatures[i].velocity.random();
		}

		return creatures;

	}(numCreatures, synaptic);

	this.foodDensity = .001;
	this.food = [];
	for (var i = 0; i < (this.width * this.height * this.foodDensity); i++) {
		this.food.push(null);
	}

	this.generation = 1;
	this.era = 1;
	this.numSpecies = numCreatures;
	this.ticks = 1;
	this.ticksPerGeneration = this.generationLengthInSec * 1000 / this.tickIntervalInMs;

	this.overlay = new Overlay(this);

	var loop = function () {

		drawBackground();
		populateFood();
		updateCreatures();

		that.ticks++;
		if (that.ticks % that.ticksPerGeneration === 0) {
			newGeneration();
		}

		that.overlay.draw();
	}

	var drawBackground = function () {
		that.ctx.fillStyle = '#f4f4f4';
		that.ctx.fillRect(0, 0, that.width, that.height);
	}

	var populateFood = function () {
		for (var i = 0; i < that.food.length; i++) {
			if (that.food[i] === null) {
				that.food[i] = new Vector(null, null);
			}

			if (that.food[i].x === null || that.food[i].y === null) {
				that.food[i].x = Math.random() * (that.width - 100) + 50;
				that.food[i].y = Math.random() * (that.height - 100) + 50;
			}

			that.ctx.beginPath();
			that.ctx.fillStyle = '#DDDDDD';
			that.ctx.arc(that.food[i].x, that.food[i].y, 3, 0, 2 * Math.PI);
			that.ctx.fill();
		}
	}

	var updateCreatures = function () {
		that.creatures.forEach(function (creature) {
			creature.tick();
			creature.draw();
		});

		that.creatures[0].isAlive() && that.creatures[0].highlight();
	}

	var newGeneration = function () {
		console.log("new generation");
		that.generation++;

		// remove dead creatures and sort remaining by fitness
		var newCreatures = that.creatures.filter(function (creature) {
			return creature.isAlive();
		}).sort(function (a, b) {
			return b.fitness() - a.fitness();
		});
		console.log("Removed " + (that.creatures.length - newCreatures.length) + " dead creatures");

		// remove unfit
		var numUnfitRemoved = 0;
		while (newCreatures.length > that.maxCreatures / 2) {
			newCreatures.pop();
			++numUnfitRemoved;
		}
		console.log("Removed " + numUnfitRemoved + " unfit creatures");

		// reproduce
		var numToClone = newCreatures.length;
		for (var i = 0; i < numToClone; i++) {
			newCreatures.push(newCreatures[i].clone());
		}
		console.log(numToClone + " creatures reproduced");

		// collect stats
		var colors = {};
		for (var i = 0; i < newCreatures.length; i++) {
			colors[newCreatures[i].color] = colors[newCreatures[i].color] ? colors[newCreatures[i].color]++ : 1;
		}

		that.numSpecies = Object.keys(colors).length;
		if (that.numSpecies == 1) {
			that.era++;

			// randomize colors
			for (var i = 0; i < newCreatures.length; i++) {
				newCreatures[i].color = 'rgb(' +
					Math.floor(Math.random() * 255) + ',' +
					Math.floor(Math.random() * 255) + ',' +
					Math.floor(Math.random() * 255) + ')';
			}

			that.numSpecies = newCreatures.length;
		}

		// reset
		newCreatures.forEach(function (creature) {
			creature.reset();
		});

		that.creatures = newCreatures;
		that.ticks = 1;
	}

	this.start = function() {

		setInterval(loop, that.tickIntervalInMs);
	}
}
<commit_msg>Update network<commit_after>'use strict';

function World(numCreatures, canvas, synaptic) {
	var that = this;

	this.width = canvas.width;
	this.height = canvas.height;
	this.ctx = canvas.getContext('2d');

	// configuration (this should be externalized at some point...)
	this.maxCreatures = numCreatures;
	this.tickIntervalInMs = 10;
	this.generationLengthInSec = 5;

	// populate
	this.creatures = function (numCreatures, synaptic) {

		var squashingFunctions = [
			synaptic.Neuron.squash.LOGISTIC,
			synaptic.Neuron.squash.TANH,
			synaptic.Neuron.squash.HLIM,
			synaptic.Neuron.squash.IDENTITY
		];

		var creatures = [];

		for (var i = 0; i < numCreatures; i++) {

			var x = Math.random() * (that.width - 100) + 50;
			var y = Math.random() * (that.height - 100) + 50;

			var network = new synaptic.Architect.Perceptron(5, 4, 3, 2);

			// randomize the activation functions
			network.neurons().forEach(function (neuron) {
				if (neuron.layer === 'output') {
					neuron.neuron.squash = synaptic.Neuron.squash.TANH;
				}
				else {
					neuron.neuron.squash = squashingFunctions[Math.floor(Math.random() * squashingFunctions.length)];
				}
			});

			creatures[i] = new Creature(network, that, x, y);
			creatures[i].velocity.random();
		}

		return creatures;

	}(numCreatures, synaptic);

	this.foodDensity = .001;
	this.food = [];
	for (var i = 0; i < (this.width * this.height * this.foodDensity); i++) {
		this.food.push(null);
	}

	this.generation = 1;
	this.era = 1;
	this.numSpecies = numCreatures;
	this.ticks = 1;
	this.ticksPerGeneration = this.generationLengthInSec * 1000 / this.tickIntervalInMs;

	this.overlay = new Overlay(this);

	var loop = function () {

		drawBackground();
		populateFood();
		updateCreatures();

		that.ticks++;
		if (that.ticks % that.ticksPerGeneration === 0) {
			newGeneration();
		}

		that.overlay.draw();
	}

	var drawBackground = function () {
		that.ctx.fillStyle = '#f4f4f4';
		that.ctx.fillRect(0, 0, that.width, that.height);
	}

	var populateFood = function () {
		for (var i = 0; i < that.food.length; i++) {
			if (that.food[i] === null) {
				that.food[i] = new Vector(null, null);
			}

			if (that.food[i].x === null || that.food[i].y === null) {
				that.food[i].x = Math.random() * (that.width - 100) + 50;
				that.food[i].y = Math.random() * (that.height - 100) + 50;
			}

			that.ctx.beginPath();
			that.ctx.fillStyle = '#DDDDDD';
			that.ctx.arc(that.food[i].x, that.food[i].y, 3, 0, 2 * Math.PI);
			that.ctx.fill();
		}
	}

	var updateCreatures = function () {
		that.creatures.forEach(function (creature) {
			creature.tick();
			creature.draw();
		});

		that.creatures[0].isAlive() && that.creatures[0].highlight();
	}

	var newGeneration = function () {
		console.log("new generation");
		that.generation++;

		// remove dead creatures and sort remaining by fitness
		var newCreatures = that.creatures.filter(function (creature) {
			return creature.isAlive();
		}).sort(function (a, b) {
			return b.fitness() - a.fitness();
		});
		console.log("Removed " + (that.creatures.length - newCreatures.length) + " dead creatures");

		// remove unfit
		var numUnfitRemoved = 0;
		while (newCreatures.length > that.maxCreatures / 2) {
			newCreatures.pop();
			++numUnfitRemoved;
		}
		console.log("Removed " + numUnfitRemoved + " unfit creatures");

		// reproduce
		var numToClone = newCreatures.length;
		for (var i = 0; i < numToClone; i++) {
			newCreatures.push(newCreatures[i].clone());
		}
		console.log(numToClone + " creatures reproduced");

		// collect stats
		var colors = {};
		for (var i = 0; i < newCreatures.length; i++) {
			colors[newCreatures[i].color] = colors[newCreatures[i].color] ? colors[newCreatures[i].color]++ : 1;
		}

		that.numSpecies = Object.keys(colors).length;
		if (that.numSpecies == 1) {
			that.era++;

			// randomize colors
			for (var i = 0; i < newCreatures.length; i++) {
				newCreatures[i].color = 'rgb(' +
					Math.floor(Math.random() * 255) + ',' +
					Math.floor(Math.random() * 255) + ',' +
					Math.floor(Math.random() * 255) + ')';
			}

			that.numSpecies = newCreatures.length;
		}

		// reset
		newCreatures.forEach(function (creature) {
			creature.reset();
		});

		that.creatures = newCreatures;
		that.ticks = 1;
	}

	this.start = function() {

		setInterval(loop, that.tickIntervalInMs);
	}
}
<|endoftext|>


<commit_before>// creates the home page menu, used to access the phases

'use strict'

const designUI = require('./phasesUI/designUI.js')
const designStateUI = require('./phasesUI/designStateUI.js')
const implementationUI = require('./phasesUI/implementationUI.js')
const implementationStateUI = require('./phasesUI/implementationStateUI.js')

module.exports = function homeMenu () {
  // get the graph container
  const graph = document.getElementById('graph-container')

  // creater wrapper for the phase buttons
  const wrapper = document.createElement('wrapper')
  wrapper.id = 'wrapper-id'
  wrapper.className = 'wrapper'
  wrapper.textContent = 'select phase'

  // create the design phase button
  const buttonDgn = document.createElement('button')
  buttonDgn.id = 'dgn-id'
  buttonDgn.className = 'startButtons'
  buttonDgn.type = 'button'
  buttonDgn.textContent = 'design phase'

  // create the design state phase button
  const buttonDgnState = document.createElement('button')
  buttonDgnState.id = 'dgn-state-id'
  buttonDgnState.className = 'startButtons'
  buttonDgnState.type = 'button'
  buttonDgnState.textContent = 'design state phase'

  // create the implementation phase button
  const buttonImp = document.createElement('button')
  buttonImp.id = 'imp-id'
  buttonImp.className = 'startButtons'
  buttonImp.type = 'button'
  buttonImp.textContent = 'implementation phase'

  // create the implementation state button
  const buttonImpState = document.createElement('button')
  buttonImpState.id = 'imp-state-id'
  buttonImpState.className = 'startButtons'
  buttonImpState.type = 'button'
  buttonImpState.textContent = 'implementation state phase'

  // append buttons to the wrapper
  wrapper.appendChild(buttonDgn)
  wrapper.appendChild(buttonDgnState)
  wrapper.appendChild(buttonImp)
  wrapper.appendChild(buttonImpState)

  graph.appendChild(wrapper)

  // add events listeners to the buttons, each event listener loads a
  // specific UI and then removes the wrapper
  buttonDgn.addEventListener('click', () => {
    designUI()
    graph.removeChild(wrapper)
  })
  buttonDgnState.addEventListener('click', () => {
    designStateUI()
    graph.removeChild(wrapper)
  })
  buttonImp.addEventListener('click', () => {
    implementationUI()
    graph.removeChild(wrapper)
  })
  buttonImpState.addEventListener('click', () => {
    implementationStateUI()
    graph.removeChild(wrapper)
  })

  const ack = document.createElement('ack')
  ack.id = 'ack-id'
  ack.innerHTML =
    '❮❯ with ♥ by or3stis'
  graph.appendChild(ack)
}
<commit_msg>:bug: remove acknowledgement<commit_after>// creates the home page menu, used to access the phases

'use strict'

const designUI = require('./phasesUI/designUI.js')
const designStateUI = require('./phasesUI/designStateUI.js')
const implementationUI = require('./phasesUI/implementationUI.js')
const implementationStateUI = require('./phasesUI/implementationStateUI.js')

module.exports = function homeMenu () {
  // get the graph container
  const graph = document.getElementById('graph-container')

  // creater wrapper for the phase buttons
  const wrapper = document.createElement('wrapper')
  wrapper.id = 'wrapper-id'
  wrapper.className = 'wrapper'
  wrapper.textContent = 'select phase'

  // create the design phase button
  const buttonDgn = document.createElement('button')
  buttonDgn.id = 'dgn-id'
  buttonDgn.className = 'startButtons'
  buttonDgn.type = 'button'
  buttonDgn.textContent = 'design phase'

  // create the design state phase button
  const buttonDgnState = document.createElement('button')
  buttonDgnState.id = 'dgn-state-id'
  buttonDgnState.className = 'startButtons'
  buttonDgnState.type = 'button'
  buttonDgnState.textContent = 'design state phase'

  // create the implementation phase button
  const buttonImp = document.createElement('button')
  buttonImp.id = 'imp-id'
  buttonImp.className = 'startButtons'
  buttonImp.type = 'button'
  buttonImp.textContent = 'implementation phase'

  // create the implementation state button
  const buttonImpState = document.createElement('button')
  buttonImpState.id = 'imp-state-id'
  buttonImpState.className = 'startButtons'
  buttonImpState.type = 'button'
  buttonImpState.textContent = 'implementation state phase'

  // append buttons to the wrapper
  wrapper.appendChild(buttonDgn)
  wrapper.appendChild(buttonDgnState)
  wrapper.appendChild(buttonImp)
  wrapper.appendChild(buttonImpState)

  graph.appendChild(wrapper)

  // add events listeners to the buttons, each event listener loads a
  // specific UI and then removes the wrapper
  buttonDgn.addEventListener('click', () => {
    designUI()
    graph.removeChild(wrapper)
    graph.removeChild(ack)
  })
  buttonDgnState.addEventListener('click', () => {
    designStateUI()
    graph.removeChild(wrapper)
    graph.removeChild(ack)
  })
  buttonImp.addEventListener('click', () => {
    implementationUI()
    graph.removeChild(wrapper)
    graph.removeChild(ack)
  })
  buttonImpState.addEventListener('click', () => {
    implementationStateUI()
    graph.removeChild(wrapper)
    graph.removeChild(ack)
  })

  const ack = document.createElement('ack')
  ack.id = 'ack-id'
  ack.innerHTML =
    '❮❯ with ♥ by or3stis'
  graph.appendChild(ack)
}
<|endoftext|>


<commit_before>/*
	hotlinkr
	Version: 0.1
	Copyright 2009 Josh Bush (digitalbush.com)
	Licensed under the MIT license (http://github.com/digitalBush/hotlinkr/raw/master/LICENSE)

	If you are reading this because you were hotlinking to a script hoted on another site, then shame on you.
	Please go get the script you need and host it from your own server using you own bandwidth.

	If you're not sure why what you're doing is wrong, please visit http://altlab.com/hotlinking.html
*/

(function(type,url) {
	var body=null;

	function doTags(tag,fn){
		var elms=document.getElementsByTagName(tag);
		for (var i = -1, len = elms.length; ++i < len; )
			fn.call(elms[i]);
	}

	var isIE=(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent) );

	function chooseRandomly(obj,seed) {
		var index = -1, item = null;
		if( !seed ) {
			seed=[];
			for(var key in obj){
				if(obj.hasOwnProperty(key))
					seed.push(key);
			}
		}
		index=Math.floor(Math.random() * seed.length);
		if(console && console.log)console.log("hotlinkr >> type = " + seed[index]);
		return obj[seed[index]];
	}

	var types={
		alert:function(){alert("Hotlinking is bad.  Please stop hotlinking to "+url);},
		redirect: function(){window.location.href="http://"+url;},
		link:function(){doTags("a",function(){this.href="http://"+url;});},
		hide:function(){body.style.display="none";},
		banner:function(){
			var banner=document.createElement("div");
			banner.setAttribute("style","position:absolute;top:0;left:0;width:100%;height:100px;border:1px solid #f00;line-height:100px;text-align:center;color:#f00;background:#fff");
			banner.innerText="Script Hosting provided courtesy of "+url+"
To remove this message, please host scripts from "+url+" on your own server.";
			body.appendChild(banner);
			body.style.paddingTop="100px";
		},
		cornify:function(){
			var s=document.createElement('script');
			s.src='http://cornify.com/js/cornify.js';
			body.appendChild(s);

			setInterval(function(){cornify_add();},5000);
		},
		translate:function(){
			window.location.href="http://translate.google.com/translate?tl=sw&u="+window.location.href;
		},
		pad:function(){doTags("div",function(){this.style.padding="300px";});},
		title:function(){document.title=url+" is my daddy!"},
		hasselhoff:function(){doTags("img",function(){this.src="http://farm1.static.flickr.com/54/127503978_0c1a5a0f4b_t.jpg"})},
		overlay:function(){
			var banner=document.createElement("img");
			banner.setAttribute("style",'position:absolute;top:0;width:100%;height:' + window.outerHeight + 'px;right:0;z-index:1000;');
			body.appendChild(banner);
		},
		flip:function(){
			if( !isIE ) {
				body.setAttribute('style',body.getAttribute('style') + "; -moz-transform: scaleY(-1);-webkit-transform: scaleY(-1);transform: scaleY(-1);filter: FlipV;");
			} else {
				doTags("img",function() {
					this.setAttribute('style', this.getAttribute('style') + "; -moz-transform: scaleY(-1);-webkit-transform: scaleY(-1);transform: scaleY(-1);filter: FlipV;");
				});
			}
		},
		fail:function() {
			window.location.href = "http://farm4.static.flickr.com/3102/2780516431_28b7d23cfc.jpg";
		}

	};

	if( isIE ) {
		types.resize=function(x,y) {
			if(x && y) {
				window.resizeBy(x,y);
			}else {
				var local = types, v = new Date().getUTCMilliseconds()%2 == 0 ? -1 : 1;
				setInterval( function() { try{local.resize(v,v);}catch(e){} }, 10);
			}
		};
		types.spaz=function() {
			var local = types;
			setInterval( function() { var v = new Date().getUTCMilliseconds()%2 == 0 ? -1 : 1; try{local.resize(v,v);}catch(e){} }, 1);
		};
	}

	(window.addEventListener ? window.addEventListener : window.attachEvent)(isIE()?"onload":"load",function(){
		body=document.body?document.body:document.getElementsByTagName("body")[0];
		(chooseRandomly( types, type === "random" ? undefined : type.split(',') ))();
	}, false);
})("random","digitalbush.com");<commit_msg>forgot to change one ref for isIE<commit_after>/*
	hotlinkr
	Version: 0.1
	Copyright 2009 Josh Bush (digitalbush.com)
	Licensed under the MIT license (http://github.com/digitalBush/hotlinkr/raw/master/LICENSE)

	If you are reading this because you were hotlinking to a script hoted on another site, then shame on you.
	Please go get the script you need and host it from your own server using you own bandwidth.

	If you're not sure why what you're doing is wrong, please visit http://altlab.com/hotlinking.html
*/

(function(type,url) {
	var body=null;

	function doTags(tag,fn){
		var elms=document.getElementsByTagName(tag);
		for (var i = -1, len = elms.length; ++i < len; )
			fn.call(elms[i]);
	}

	var isIE=(/msie/i.test(navigator.userAgent) && !/opera/i.test(navigator.userAgent));

	function chooseRandomly(obj,seed) {
		var index = -1, item = null;
		if( !seed ) {
			seed=[];
			for(var key in obj){
				if(obj.hasOwnProperty(key))
					seed.push(key);
			}
		}
		index=Math.floor(Math.random() * seed.length);
		if(console && console.log)console.log("hotlinkr >> type = " + seed[index]);
		return obj[seed[index]];
	}

	var types={
		alert:function(){alert("Hotlinking is bad.  Please stop hotlinking to "+url);},
		redirect: function(){window.location.href="http://"+url;},
		link:function(){doTags("a",function(){this.href="http://"+url;});},
		hide:function(){body.style.display="none";},
		banner:function(){
			var banner=document.createElement("div");
			banner.setAttribute("style","position:absolute;top:0;left:0;width:100%;height:100px;border:1px solid #f00;line-height:100px;text-align:center;color:#f00;background:#fff");
			banner.innerText="Script Hosting provided courtesy of "+url+"
To remove this message, please host scripts from "+url+" on your own server.";
			body.appendChild(banner);
			body.style.paddingTop="100px";
		},
		cornify:function(){
			var s=document.createElement('script');
			s.src='http://cornify.com/js/cornify.js';
			body.appendChild(s);

			setInterval(function(){cornify_add();},5000);
		},
		translate:function(){
			window.location.href="http://translate.google.com/translate?tl=sw&u="+window.location.href;
		},
		pad:function(){doTags("div",function(){this.style.padding="300px";});},
		title:function(){document.title=url+" is my daddy!"},
		hasselhoff:function(){doTags("img",function(){this.src="http://farm1.static.flickr.com/54/127503978_0c1a5a0f4b_t.jpg"})},
		overlay:function(){
			var banner=document.createElement("img");
			banner.setAttribute("style",'position:absolute;top:0;width:100%;height:' + window.outerHeight + 'px;right:0;z-index:1000;');
			body.appendChild(banner);
		},
		flip:function(){
			if( !isIE ) {
				body.setAttribute('style',body.getAttribute('style') + "; -moz-transform: scaleY(-1);-webkit-transform: scaleY(-1);transform: scaleY(-1);filter: FlipV;");
			} else {
				doTags("img",function() {
					this.setAttribute('style', this.getAttribute('style') + "; -moz-transform: scaleY(-1);-webkit-transform: scaleY(-1);transform: scaleY(-1);filter: FlipV;");
				});
			}
		},
		fail:function() {
			window.location.href = "http://farm4.static.flickr.com/3102/2780516431_28b7d23cfc.jpg";
		}
	};

	if( isIE ) {
		types.resize=function(x,y) {
			if(x && y) {
				window.resizeBy(x,y);
			}else {
				var local = types, v = new Date().getUTCMilliseconds()%2 == 0 ? -1 : 1;
				setInterval( function() { try{local.resize(v,v);}catch(e){} }, 10);
			}
		};
		types.spaz=function() {
			var local = types;
			setInterval( function() { var v = new Date().getUTCMilliseconds()%2 == 0 ? -1 : 1; try{local.resize(v,v);}catch(e){} }, 1);
		};
	}

	(window.addEventListener ? window.addEventListener : window.attachEvent)(isIE?"onload":"load",function(){
		body=document.body?document.body:document.getElementsByTagName("body")[0];
		(chooseRandomly( types, type === "random" ? undefined : type.split(',') ))();
	}, false);
})("random","digitalbush.com");<|endoftext|>


<commit_before>function _debug(msg){
    DEBUG && console.log(msg);
}

function callBotAPI(newmsg,callback,sendto,jumpback) {
    //jsonp proxy
    var url = 'https://cuhk.me/wx/jsonp.php';
    $.ajax({
        'url': url,
        'data': {msg: encodeURIComponent(newmsg), s: session_id} ,
        'dataType': 'jsonp',
        'timeout': 60000,
        'success': function(response) {
            if (typeof(response)=='undefined') {
                _debug("no response error");
                setTimeout(function(){
                    ans = '太累了，我想休息一下，zzz～';
                    callback(ans,sendto,jumpback);
                },60*1000);
            } else {
                ans = response.text;
                callback(ans,sendto,jumpback);
            }
        },
        'error': function() {
            _debug("ajax error occured");
            setTimeout(function(){
                ans = '太累了，我想休息一下，zzz～';
                callback(ans,sendto,jumpback);
            },60*1000);
        }
    });
}

function sendmsg_callback(ans,sendto,jumpback){
    _debug("bot resp with: " + ans);
    sendto && $(sendto).click();
    $('#textInput')[0].value=ans;
    $('.chatSend')[0].click();
    $(jumpback).click();
    var name = $(sendto).find('.left.name').text();
    setTimeout(function(){
        $(sendto).find('.desc').removeClass('read'); //clear read mark
    },100); // dirty: prevent extreme timing case
    _debug('msg sent to: '+name);
}

function installbot(chats){
    //add bot notes
    for (i=0;i<chats.length;i++) {
        var bot = document.createElement('div');
        bot.className='bot';
        chats[i].appendChild(bot);
    }

    //listen on bot click event
    $(chats).children('.bot').click(function(e){
        e.stopPropagation();
        $(this).toggleClass('active');
        typeof(observer) !== 'undefined' && observer.disconnect();
    });

    //add drag drop event to bot div
    jQuery.event.props.push('dataTransfer');
    $(chats).on({
        dragenter: function(e) {
            $(this).addClass('over');
        },
        dragover: function(e) {
            e.preventDefault();
        },
        dragleave: function(e) {
            $(this).removeClass('over');
        },
        drop: function() {
            $(this).find('.bot').toggleClass('active');
        },
    });

    _debug("installed "+chats.length.toString()+" bots");
}

function buildbothome() {
    //add bot home
    $('#profile').append([
    '
',
        '',
        '',
            '
快把我拖到聊天列表上
',
            '
点击我可以 暂停/恢复
',
        '',
        '',
    '
'].join(''));

    //show tooltip for 10s
    $('img.botico').load(function(){
        $('#bot-wrapper span').show();
        setTimeout(function(){
            $('#bot-wrapper span').hide();
        },10*1000);
    });

    //clear tooltip on mousedown
    $('.bot-home').mousedown(function(){
        $('#bot-wrapper span').hide();
    });

    //listen on bot-home click event
    $('.bot-home').click(function(){
        $('.bot-home').toggleClass('paused');
    });

    //listen drag event
    jQuery.event.props.push('dataTransfer');
    $('.bot-home').on({
        dragstart: function() {
            $(this).css('opacity', '0.5');
            $('.chatListColumn *').css('pointer-events','none');
        },
        dragend: function() {
            $(this).css('opacity', '1');
            $('.chatListColumn *').css('pointer-events','');
            $('.chatListColumn').removeClass('over');
        },
    });
    _debug("bot home constructed");
}

function botinit(){
    $(document).ready(function(){
        //init bot-home
        buildbothome();
        //init bot divs
        var bots = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")'].join(''))
        installbot(bots);
        _debug(bots.length.toString()+" bots initiated");
        //set chat list update listener
        setupdater();
        //identify user by cookie
        C = function(k){return encodeURIComponent(document.cookie.match(k+'=([^;]*)')[1])};
        session_id = C('xsid');
        nm = encodeURIComponent($('.myProfile .nickName').text());
    });
}

function botstart(interval){
    interval = typeof interval !== 'undefined' ? interval : 30;
    setInterval(chatbot,interval*1000);
    _debug("started with interval: "+interval.toString()+"s");
}

function botupdate(){
    uninstalled = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")',
            ':not(:has(".bot"))'].join(''));
    uninstalled.length && installbot(uninstalled);
}

function setupdater() {
    updater = new MutationObserver(function(mutations) {
        botupdate();
    });
    updater.observe($('#conversationContainer')[0], { childList: true});
    _debug('updater set');
}

function chatbot() {
    //if paused
    if ( $('.bot-home').hasClass('paused') ) return;
    //if no bot-took-overed
    if ( $('.bot.active').length == 0 )  return;

    //record current chat
    var activechat = $('.activeColumn');

    //reply in current chat window
    if ( $('.activeColumn:has(".bot.active")').length ) {
        var lastchat = $('#chat_chatmsglist').children().last();
            if ($(lastchat).not('.read').hasClass('chatItem you')) {  //has read or self msg
                var name = $(activechat).find('.left.name').text();
                var newmsg = $(lastchat).find('pre').text();
                _debug("msg from: " + name);
                if (newmsg) {
                    _debug("msg content: " + newmsg);
                    $(lastchat).addClass('read'); //add read mark
                    callBotAPI(newmsg,sendmsg_callback,activechat);
                } else {
                    _debug("no msg found");
                }
            }
    }

    //reply for red dotted item
    $('.unreadDot:visible, .unreadDotS:visible').each(function()
    {
        var receiver = $(this).parent();
        is_active = $(receiver).find(".bot").hasClass("active");
        if (!is_active) return;
        if ($(receiver).find('.desc').hasClass('read')) return;  //has read, wait for response
        var name = $(receiver).find(".left.name").text();
        _debug("msg from: " + name);
        var newmsg = $(receiver).find('.desc').text();
        if (newmsg) {
            _debug("msg content: " + newmsg);
            $(receiver).find('.desc').addClass('read'); // add read mark
            callBotAPI(newmsg,sendmsg_callback,$(receiver),$(activechat));
        } else {
            _debug("no msg found");
        }
    });
}

DEBUG = true;
VERSION = "2.2.2";
botinit();
botstart(runtimeGlobal.interval);
botupdate();
<commit_msg>adjust err timeout<commit_after>function _debug(msg){
    DEBUG && console.log(msg);
}

function callBotAPI(newmsg,callback,sendto,jumpback) {
    //jsonp proxy
    var url = 'https://cuhk.me/wx/jsonp.php';
    $.ajax({
        'url': url,
        'data': {msg: encodeURIComponent(newmsg), s: session_id} ,
        'dataType': 'jsonp',
        'timeout': 60000,
        'success': function(response) {
            if (typeof(response)=='undefined') {
                _debug("no response error");
                ans = '太累了，我想休息一下，zzz～';
                callback(ans,sendto,jumpback,'err');
            } else {
                ans = response.text;
                callback(ans,sendto,jumpback,'err');
            }
        },
        'error': function() {
            _debug("ajax error occured");
            ans = '太累了，我想休息一下，zzz～';
            callback(ans,sendto,jumpback);
        }
    });
}

function sendmsg_callback(ans,sendto,jumpback,flag){
    _debug("bot resp with: " + ans);
    sendto && $(sendto).click();
    $('#textInput')[0].value=ans;
    $('.chatSend')[0].click();
    $(jumpback).click();
    var name = $(sendto).find('.left.name').text();
    setTimeout(function(){
        $(sendto).find('.desc').removeClass('read'); //clear read mark
    }, (typeof(flag)!=='undefined' && flag=='err') ? 60*1000 : 100 ); // dirty: prevent extreme timing case
    _debug('msg sent to: '+name);
}

function installbot(chats){
    //add bot notes
    for (i=0;i<chats.length;i++) {
        var bot = document.createElement('div');
        bot.className='bot';
        chats[i].appendChild(bot);
    }

    //listen on bot click event
    $(chats).children('.bot').click(function(e){
        e.stopPropagation();
        $(this).toggleClass('active');
        typeof(observer) !== 'undefined' && observer.disconnect();
    });

    //add drag drop event to bot div
    jQuery.event.props.push('dataTransfer');
    $(chats).on({
        dragenter: function(e) {
            $(this).addClass('over');
        },
        dragover: function(e) {
            e.preventDefault();
        },
        dragleave: function(e) {
            $(this).removeClass('over');
        },
        drop: function() {
            $(this).find('.bot').toggleClass('active');
        },
    });

    _debug("installed "+chats.length.toString()+" bots");
}

function buildbothome() {
    //add bot home
    $('#profile').append([
    '
',
        '',
        '',
            '
快把我拖到聊天列表上
',
            '
点击我可以 暂停/恢复
',
        '',
        '',
    '
'].join(''));

    //show tooltip for 10s
    $('img.botico').load(function(){
        $('#bot-wrapper span').show();
        setTimeout(function(){
            $('#bot-wrapper span').hide();
        },10*1000);
    });

    //clear tooltip on mousedown
    $('.bot-home').mousedown(function(){
        $('#bot-wrapper span').hide();
    });

    //listen on bot-home click event
    $('.bot-home').click(function(){
        $('.bot-home').toggleClass('paused');
    });

    //listen drag event
    jQuery.event.props.push('dataTransfer');
    $('.bot-home').on({
        dragstart: function() {
            $(this).css('opacity', '0.5');
            $('.chatListColumn *').css('pointer-events','none');
        },
        dragend: function() {
            $(this).css('opacity', '1');
            $('.chatListColumn *').css('pointer-events','');
            $('.chatListColumn').removeClass('over');
        },
    });
    _debug("bot home constructed");
}

function botinit(){
    $(document).ready(function(){
        //init bot-home
        buildbothome();
        //init bot divs
        var bots = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")'].join(''))
        installbot(bots);
        _debug(bots.length.toString()+" bots initiated");
        //set chat list update listener
        setupdater();
        //identify user by cookie
        C = function(k){return encodeURIComponent(document.cookie.match(k+'=([^;]*)')[1])};
        session_id = C('xsid');
        nm = encodeURIComponent($('.myProfile .nickName').text());
    });
}

function botstart(interval){
    interval = typeof interval !== 'undefined' ? interval : 30;
    setInterval(chatbot,interval*1000);
    _debug("started with interval: "+interval.toString()+"s");
}

function botupdate(){
    uninstalled = $(['.chatListColumn',
            ':not([un="newsapp"])',
            ':not([un="filehelper"])',
            ':not([un="fmessage"])',
            ':not(".loadMoreConv")',
            ':not(:has(".bot"))'].join(''));
    uninstalled.length && installbot(uninstalled);
}

function setupdater() {
    updater = new MutationObserver(function(mutations) {
        botupdate();
    });
    updater.observe($('#conversationContainer')[0], { childList: true});
    _debug('updater set');
}

function chatbot() {
    //if paused
    if ( $('.bot-home').hasClass('paused') ) return;
    //if no bot-took-overed
    if ( $('.bot.active').length == 0 )  return;

    //record current chat
    var activechat = $('.activeColumn');

    //reply in current chat window
    if ( $('.activeColumn:has(".bot.active")').length ) {
        var lastchat = $('#chat_chatmsglist').children().last();
            if ($(lastchat).not('.read').hasClass('chatItem you')) {  //has read or self msg
                var name = $(activechat).find('.left.name').text();
                var newmsg = $(lastchat).find('pre').text();
                _debug("msg from: " + name);
                if (newmsg) {
                    _debug("msg content: " + newmsg);
                    $(lastchat).addClass('read'); //add read mark
                    callBotAPI(newmsg,sendmsg_callback,activechat);
                } else {
                    _debug("no msg found");
                }
            }
    }

    //reply for red dotted item
    $('.unreadDot:visible, .unreadDotS:visible').each(function()
    {
        var receiver = $(this).parent();
        is_active = $(receiver).find(".bot").hasClass("active");
        if (!is_active) return;
        if ($(receiver).find('.desc').hasClass('read')) return;  //has read, wait for response
        var name = $(receiver).find(".left.name").text();
        _debug("msg from: " + name);
        var newmsg = $(receiver).find('.desc').text();
        if (newmsg) {
            _debug("msg content: " + newmsg);
            $(receiver).find('.desc').addClass('read'); // add read mark
            callBotAPI(newmsg,sendmsg_callback,$(receiver),$(activechat));
        } else {
            _debug("no msg found");
        }
    });
}

DEBUG = true;
VERSION = "2.2.2";
botinit();
botstart(runtimeGlobal.interval);
botupdate();
<|endoftext|>