<commit_before>// Load modules

var Stream = require('stream');
var Zlib = require('zlib');
var Boom = require('boom');
var Shot = require('shot');
var Negotiator = require('negotiator');
var Plain = require('./plain');
var Payload = require('./payload');
var Headers = require('./headers');
var Utils = require('../utils');

// Declare internals

var internals = {};

exports.Plain = Plain;
exports.Payload = Payload;

exports.wrap = function (result, request) {

    var response = (result instanceof Error ? Boom.wrap(result)
                                            : (result instanceof Plain ? result : new Plain(result, request)));
    return response;
};

internals.setup = function (request, next) {

    request.response._marshall(request, function (err) {

        if (err) {
            return next(err.isBoom ? err : Boom.wrap(err));
        }

        return internals.headers(request, next);
    });
};

internals.headers = function (request, next) {

    var response = request.response;

    if (request.jsonp &&
        response._payload.jsonp) {

        response.type('text/javascript');
        response._payload.jsonp(request.jsonp);
    }

    Headers.apply(request, function (err) {

        if (err) {
            return next(err);
        }

        // Apply pass through headers

        if (response._payload.headers &&
            response.settings.passThrough) {

            var localCookies = Utils.clone(response.headers['set-cookie']);
            var localHeaders = response.headers;
            response.headers = Utils.clone(response._payload.headers);
            Utils.merge(response.headers, localHeaders);

            if (localCookies) {
                var headerKeys = Object.keys(response._payload.headers);
                for (var i = 0, il = headerKeys.length; i < il; ++i) {

                    if (headerKeys[i].toLowerCase() === 'set-cookie') {
                        delete response.headers[headerKeys[i]];
                        response._header('set-cookie', [].concat(response._payload.headers[headerKeys[i]]).concat(localCookies));
                        break;
                    }
                }
            }
        }

        return next();
    });
};

exports.send = function (request, callback) {

    var prepare = function () {

        var response = request.response;
        if (response.isBoom) {
            return fail(response);
        }

        internals.setup(request, function (err) {

            if (err) {
                request._setResponse(err);
                return fail(err);
            }

            return etag(response);
        });
    };

    var fail = function (boom) {

        var error = boom.output;
        var response = new Plain(error.payload, request);
        response.code(error.statusCode);
        Utils.merge(response.headers, error.headers);
        request.response = response;                            // Not using request._setResponse() to avoid double log

        internals.setup(request, function (err) {

            // Return the original error (which is partially prepared) instead of having to prepare the result error
            return internals.transmit(response, request, callback);
        });
    };

    var etag = function (response) {

        if (request.method !== 'get' &&
            request.method !== 'head') {

            return internals.transmit(response, request, callback);
        }

        if (response.headers.etag &&
            request.headers['if-none-match'] === response.headers.etag) {

            response.statusCode = 304;
        }
        else {
            var ifModifiedSinceHeader = request.headers['if-modified-since'];
            var lastModifiedHeader = response.headers && response.headers['last-modified'];

            if (ifModifiedSinceHeader &&
                lastModifiedHeader) {

                var ifModifiedSince = Date.parse(ifModifiedSinceHeader);
                var lastModified = Date.parse(lastModifiedHeader);

                if (ifModifiedSince &&
                    lastModified &&
                    ifModifiedSince >= lastModified) {

                    response.statusCode = 304;
                }
            }
        }

        return internals.transmit(response, request, callback);
    };

    prepare();
};

internals.transmit = function (response, request, callback) {

    // Injection

    if (response.variety === 'plain' &&
        Shot.isInjection(request.raw.req)) {

        request.raw.res._hapi = { result: response.source };
    }

    // Setup source

    var source = response._payload;

    if (request.method !== 'head' &&
        response.statusCode !== 304) {

        // Content encoding

        var encoder = null;
        if (!response.headers['content-encoding']) {
            var negotiator = new Negotiator(request.raw.req);
            var encoding = negotiator.preferredEncoding(['gzip', 'deflate', 'identity']);
            if (encoding === 'deflate' || encoding === 'gzip') {
                var keys = Object.keys(response.headers);
                for (var i = 0, il = keys.length; i < il; ++i) {
                    var key = keys[i];
                    if (/content\-length/i.test(key)) {                 // Can be lowercase when coming from proxy
                        delete response.headers[key];
                    }
                }

                response._header('content-encoding', encoding);
                response.vary('accept-encoding');

                if (source._hapi &&
                    source._hapi.gzipped &&
                    encoding === 'gzip') {

                    source = source._hapi.gzipped;
                }
                else {
                    encoder = (encoding === 'gzip' ? Zlib.createGzip() : Zlib.createDeflate());
                }
            }
        }
    }
    else {
        source = new internals.Empty();
    }

    // Close unused file streams

    if (source !== response._payload) {
        if (response._payload.close) {
            response._payload.close();          // Close file
        }
        else if (response._payload.destroy) {
            response._payload.destroy();        // Close upstream
        }
    }

    if (source._hapi &&
        source._hapi.gzipped &&
        source !== source._hapi.gzipped &&
        source._hapi.gzipped.close) {

        source._hapi.gzipped.close();           // Close file
    }

    // Write headers

    var headers = Object.keys(response.headers);
    for (var h = 0, hl = headers.length; h < hl; ++h) {
        var header = headers[h];
        request.raw.res.setHeader(header, response.headers[header]);
    }

    request.raw.res.writeHead(response.statusCode);

    // Generate tap stream

    var tap = response._tap();

    // Write payload

    var hasEnded = false;
    var end = function (err, event) {

        if (!hasEnded) {
            hasEnded = true;

            if (event !== 'aborted') {
                request.raw.res.end();
            }

            source.removeListener('error', end);

            request.raw.req.removeListener('aborted', onAborted);
            request.raw.req.removeListener('close', onClose);

            request.raw.res.removeListener('close', onClose);
            request.raw.res.removeListener('error', end);
            request.raw.res.removeListener('finish', end);

            response.removeAllListeners();

            var tags = (err ? ['hapi', 'response', 'error']
                            : (event ? ['hapi', 'response', 'error', event]
                                     : ['hapi', 'response']));

            if (event || err) {
                request.emit('disconnect');
            }

            request.log(tags, err);
            callback();
        }
    };

    source.once('error', end);

    var onAborted = function () {

        end(null, 'aborted');
    };

    var onClose = function () {

        end(null, 'close');
    };

    request.raw.req.once('aborted', onAborted);
    request.raw.req.once('close', onClose);

    request.raw.res.once('close', onClose);
    request.raw.res.once('error', end);
    request.raw.res.once('finish', end);

    var preview = (tap ? source.pipe(tap) : source);
    var encoded = (encoder ? preview.pipe(encoder) : preview);
    encoded.pipe(request.raw.res);
};

internals.Empty = function () {

    Stream.Readable.call(this);
};

Utils.inherits(internals.Empty, Stream.Readable);

internals.Empty.prototype._read = function (size) {

    this.push(null);
};
<commit_msg>remove headers in status 304 response<commit_after>// Load modules

var Stream = require('stream');
var Zlib = require('zlib');
var Boom = require('boom');
var Shot = require('shot');
var Negotiator = require('negotiator');
var Plain = require('./plain');
var Payload = require('./payload');
var Headers = require('./headers');
var Utils = require('../utils');

// Declare internals

var internals = {};

exports.Plain = Plain;
exports.Payload = Payload;

exports.wrap = function (result, request) {

    var response = (result instanceof Error ? Boom.wrap(result)
                                            : (result instanceof Plain ? result : new Plain(result, request)));
    return response;
};

internals.setup = function (request, next) {

    request.response._marshall(request, function (err) {

        if (err) {
            return next(err.isBoom ? err : Boom.wrap(err));
        }

        return internals.headers(request, next);
    });
};

internals.headers = function (request, next) {

    var response = request.response;

    if (request.jsonp &&
        response._payload.jsonp) {

        response.type('text/javascript');
        response._payload.jsonp(request.jsonp);
    }

    Headers.apply(request, function (err) {

        if (err) {
            return next(err);
        }

        // Apply pass through headers

        if (response._payload.headers &&
            response.settings.passThrough) {

            var localCookies = Utils.clone(response.headers['set-cookie']);
            var localHeaders = response.headers;
            response.headers = Utils.clone(response._payload.headers);
            Utils.merge(response.headers, localHeaders);

            if (localCookies) {
                var headerKeys = Object.keys(response._payload.headers);
                for (var i = 0, il = headerKeys.length; i < il; ++i) {

                    if (headerKeys[i].toLowerCase() === 'set-cookie') {
                        delete response.headers[headerKeys[i]];
                        response._header('set-cookie', [].concat(response._payload.headers[headerKeys[i]]).concat(localCookies));
                        break;
                    }
                }
            }
        }

        return next();
    });
};

exports.send = function (request, callback) {

    var prepare = function () {

        var response = request.response;
        if (response.isBoom) {
            return fail(response);
        }

        internals.setup(request, function (err) {

            if (err) {
                request._setResponse(err);
                return fail(err);
            }

            return etag(response);
        });
    };

    var fail = function (boom) {

        var error = boom.output;
        var response = new Plain(error.payload, request);
        response.code(error.statusCode);
        Utils.merge(response.headers, error.headers);
        request.response = response;                            // Not using request._setResponse() to avoid double log

        internals.setup(request, function (err) {

            // Return the original error (which is partially prepared) instead of having to prepare the result error
            return internals.transmit(response, request, callback);
        });
    };

    var etag = function (response) {

        if (request.method !== 'get' &&
            request.method !== 'head') {

            return internals.transmit(response, request, callback);
        }

        if (response.headers.etag &&
            request.headers['if-none-match'] === response.headers.etag) {

            var removeKeys = ['content-length', 'etag', 'last-modified'];
            Utils.removeKeys(response.headers, removeKeys);
            response.statusCode = 304;
        }
        else {
            var ifModifiedSinceHeader = request.headers['if-modified-since'];
            var lastModifiedHeader = response.headers && response.headers['last-modified'];

            if (ifModifiedSinceHeader &&
                lastModifiedHeader) {

                var ifModifiedSince = Date.parse(ifModifiedSinceHeader);
                var lastModified = Date.parse(lastModifiedHeader);

                if (ifModifiedSince &&
                    lastModified &&
                    ifModifiedSince >= lastModified) {

                    var removeKeys = ['content-length', 'etag', 'last-modified'];
                    Utils.removeKeys(response.headers, removeKeys);
                    response.statusCode = 304;
                }
            }
        }

        return internals.transmit(response, request, callback);
    };

    prepare();
};

internals.transmit = function (response, request, callback) {

    // Injection

    if (response.variety === 'plain' &&
        Shot.isInjection(request.raw.req)) {

        request.raw.res._hapi = { result: response.source };
    }

    // Setup source

    var source = response._payload;

    if (request.method !== 'head' &&
        response.statusCode !== 304) {

        // Content encoding

        var encoder = null;
        if (!response.headers['content-encoding']) {
            var negotiator = new Negotiator(request.raw.req);
            var encoding = negotiator.preferredEncoding(['gzip', 'deflate', 'identity']);
            if (encoding === 'deflate' || encoding === 'gzip') {
                var keys = Object.keys(response.headers);
                for (var i = 0, il = keys.length; i < il; ++i) {
                    var key = keys[i];
                    if (/content\-length/i.test(key)) {                 // Can be lowercase when coming from proxy
                        delete response.headers[key];
                    }
                }

                response._header('content-encoding', encoding);
                response.vary('accept-encoding');

                if (source._hapi &&
                    source._hapi.gzipped &&
                    encoding === 'gzip') {

                    source = source._hapi.gzipped;
                }
                else {
                    encoder = (encoding === 'gzip' ? Zlib.createGzip() : Zlib.createDeflate());
                }
            }
        }
    }
    else {
        source = new internals.Empty();
    }

    // Close unused file streams

    if (source !== response._payload) {
        if (response._payload.close) {
            response._payload.close();          // Close file
        }
        else if (response._payload.destroy) {
            response._payload.destroy();        // Close upstream
        }
    }

    if (source._hapi &&
        source._hapi.gzipped &&
        source !== source._hapi.gzipped &&
        source._hapi.gzipped.close) {

        source._hapi.gzipped.close();           // Close file
    }

    // Write headers

    var headers = Object.keys(response.headers);
    for (var h = 0, hl = headers.length; h < hl; ++h) {
        var header = headers[h];
        request.raw.res.setHeader(header, response.headers[header]);
    }

    request.raw.res.writeHead(response.statusCode);

    // Generate tap stream

    var tap = response._tap();

    // Write payload

    var hasEnded = false;
    var end = function (err, event) {

        if (!hasEnded) {
            hasEnded = true;

            if (event !== 'aborted') {
                request.raw.res.end();
            }

            source.removeListener('error', end);

            request.raw.req.removeListener('aborted', onAborted);
            request.raw.req.removeListener('close', onClose);

            request.raw.res.removeListener('close', onClose);
            request.raw.res.removeListener('error', end);
            request.raw.res.removeListener('finish', end);

            response.removeAllListeners();

            var tags = (err ? ['hapi', 'response', 'error']
                            : (event ? ['hapi', 'response', 'error', event]
                                     : ['hapi', 'response']));

            if (event || err) {
                request.emit('disconnect');
            }

            request.log(tags, err);
            callback();
        }
    };

    source.once('error', end);

    var onAborted = function () {

        end(null, 'aborted');
    };

    var onClose = function () {

        end(null, 'close');
    };

    request.raw.req.once('aborted', onAborted);
    request.raw.req.once('close', onClose);

    request.raw.res.once('close', onClose);
    request.raw.res.once('error', end);
    request.raw.res.once('finish', end);

    var preview = (tap ? source.pipe(tap) : source);
    var encoded = (encoder ? preview.pipe(encoder) : preview);
    encoded.pipe(request.raw.res);
};

internals.Empty = function () {

    Stream.Readable.call(this);
};

Utils.inherits(internals.Empty, Stream.Readable);

internals.Empty.prototype._read = function (size) {

    this.push(null);
};
<|endoftext|>


<commit_before>
'use strict';

/*********** VARIABLE ***********/
var resetButton = document.getElementById('resetBalanceButton');

/*********** SETUP ***********/
function setup(){
  insertPastUsers();
  insertNewUser();
}
setup();

/*********** ADDITIONAL VARIABLES ***********/
var addNewUserButton = document.getElementById('addNewUser');
var showPastUsersButton = document.getElementById('showPastUsers');
var pastUsersForm = document.getElementById('pastUsers');
var newUserForm = document.getElementById('newUser');

/*********** FUNCTIONS ***********/
function insertNewUser() {
  var form = document.createElement('form');
  var label = document.createElement('label');
  var selectUser = document.getElementById('selectUser');
  var button = document.createElement('button');
  form.setAttribute('id', 'newUser');
  form.setAttribute('class', 'leftNewUser');
  var input = document.createElement('input');
  input.setAttribute('type', 'text');
  input.setAttribute('name', 'userNameSelected');
  input.setAttribute('placeholder', 'Enter your name');
  label.textContent = 'Create a User';
  form.appendChild(label);
  form.appendChild(input);
  button.setAttribute('id', 'addNewUser');
  button.textContent = 'Start Playing';
  form.appendChild(button);
  selectUser.appendChild(form);
}

function insertPastUsers() {
  var form = document.createElement('form');
  var label = document.createElement('label');
  var selectUser = document.getElementById('selectUser');
  var button = document.createElement('button');
  form.setAttribute('id', 'pastUsers');
  label.textContent = 'Select a User';
  var select = document.createElement('select');
  select.setAttribute('name', 'userNameSelected');
  select.setAttribute('id', 'selectedCurrentUser');
  var allusers = Data.getAllUsers();
  for(var i = 0; i < allusers.length; i++){
    var each = allusers[i];
    var option = document.createElement('option');
    option.setAttribute('value', each.userName);
    option.textContent = each.userName;
    select.appendChild(option);
  }
  form.appendChild(label);
  form.appendChild(select);
  button.setAttribute('id', 'showPastUsers');
  button.textContent = 'Play';
  form.appendChild(button);
  selectUser.appendChild(form);
};

function checkIfValid(formInput) {
  var validUsername = formInput.value.match(/^[a-zA-Z]+$/);
  if (validUsername === null){
    alert('Your first name is not valid. Only characters A-Z and a-z are acceptable.');
    formInput.focus();
    return false;
  };
  return true;
};

/*********** EVENT LISTENERS ***********/
addNewUserButton.addEventListener('click', function(event) {
  event.preventDefault();
  if (checkIfValid(newUserForm.userNameSelected)){
    var newUser = new User(newUserForm.userNameSelected.value);
    Data.saveUser(newUser);
    console.log(newUserForm.userNameSelected.value);
    window.location.href = 'index.html';
  };
});

showPastUsersButton.addEventListener('click', function(event) {
  event.preventDefault();
  var userSelected = Data.loadUserName(pastUsersForm.userNameSelected.value);
  if (userSelected !== null ) {
    Data.saveUser(userSelected);
    window.location.href = 'index.html';
  } else {
    console.warn('Was not able to load selected user');
  }
});

resetButton.addEventListener('click', function(){
  var currentUser = Data.loadCurrentUser();
  currentUser.resetStats();
  Data.saveUser(currentUser);
  alert('Your balance has been reset.');
  window.location.href = 'index.html';
});

//Startup setting
if (Data.loadCurrentUser() === null) {
  pastUsersForm.hidden = true;
  currentUserSettings.hidden = true;
  newUser.className = 'centerNewUserDefault';
} else {
  pastUsers.userNameSelected.value = Data.loadCurrentUser().userName;
}

selectedCurrentUser.onchange = function() {
  var elem = (typeof this.selectedIndex === 'undefined' ? window.event.srcElement : this);
  var value = elem.value || elem.options[elem.selectedIndex].value;
  resetBalanceButton.textContent = 'Reset Balance of $' + Data.loadUserName(value).moneyBalance();
  difficultyLevel.difficultySelected.value = Data.loadCurrentUser().difficulty;
  console.log(Data.loadCurrentUser().difficulty);
};

difficultySelection.onchange = function () {
  var elem = (typeof this.selectedIndex === 'undefined' ? window.event.srcElement : this);
  var value = elem.value || elem.options[elem.selectedIndex].value;
  var currentUser = Data.loadCurrentUser();
  if ('easy' === value ) {
    currentUser.slots = ['wildcard.gif','wildcard.gif','dancer.png','dog.png','poop.png','unicorn.png'];
    currentUser.difficulty = 'easy';
  } if ('medium' === value) {
    currentUser.slots = ['wildcard.gif','cat.png','dancer.png','dog.png','poop.png','unicorn.png'];
    currentUser.difficulty = 'medium';
  } if ('hard' === value) {
    currentUser.slots = ['alien.png','cat.png','dancer.png','dog.png','poop.png','unicorn.png'];
    currentUser.difficulty = 'hard';
  }
  Data.saveUser(currentUser);
  window.location.href = 'index.html';
};
<commit_msg>refined saving user difficulty state to user object<commit_after>
'use strict';

/*********** VARIABLE ***********/
var resetButton = document.getElementById('resetBalanceButton');

/*********** SETUP ***********/
function setup(){
  insertPastUsers();
  insertNewUser();
}
setup();

/*********** ADDITIONAL VARIABLES ***********/
var addNewUserButton = document.getElementById('addNewUser');
var showPastUsersButton = document.getElementById('showPastUsers');
var pastUsersForm = document.getElementById('pastUsers');
var newUserForm = document.getElementById('newUser');

/*********** FUNCTIONS ***********/
function insertNewUser() {
  var form = document.createElement('form');
  var label = document.createElement('label');
  var selectUser = document.getElementById('selectUser');
  var button = document.createElement('button');
  form.setAttribute('id', 'newUser');
  form.setAttribute('class', 'leftNewUser');
  var input = document.createElement('input');
  input.setAttribute('type', 'text');
  input.setAttribute('name', 'userNameSelected');
  input.setAttribute('placeholder', 'Enter your name');
  label.textContent = 'Create a User';
  form.appendChild(label);
  form.appendChild(input);
  button.setAttribute('id', 'addNewUser');
  button.textContent = 'Start Playing';
  form.appendChild(button);
  selectUser.appendChild(form);
}

function insertPastUsers() {
  var form = document.createElement('form');
  var label = document.createElement('label');
  var selectUser = document.getElementById('selectUser');
  var button = document.createElement('button');
  form.setAttribute('id', 'pastUsers');
  label.textContent = 'Select a User';
  var select = document.createElement('select');
  select.setAttribute('name', 'userNameSelected');
  select.setAttribute('id', 'selectedCurrentUser');
  var allusers = Data.getAllUsers();
  for(var i = 0; i < allusers.length; i++){
    var each = allusers[i];
    var option = document.createElement('option');
    option.setAttribute('value', each.userName);
    option.textContent = each.userName;
    select.appendChild(option);
  }
  form.appendChild(label);
  form.appendChild(select);
  button.setAttribute('id', 'showPastUsers');
  button.textContent = 'Play';
  form.appendChild(button);
  selectUser.appendChild(form);
};

function checkIfValid(formInput) {
  var validUsername = formInput.value.match(/^[a-zA-Z]+$/);
  if (validUsername === null){
    alert('Your first name is not valid. Only characters A-Z and a-z are acceptable.');
    formInput.focus();
    return false;
  };
  return true;
};

/*********** EVENT LISTENERS ***********/
addNewUserButton.addEventListener('click', function(event) {
  event.preventDefault();
  if (checkIfValid(newUserForm.userNameSelected)){
    var newUser = new User(newUserForm.userNameSelected.value);
    Data.saveUser(newUser);
    console.log(newUserForm.userNameSelected.value);
    window.location.href = 'index.html';
  };
});

showPastUsersButton.addEventListener('click', function(event) {
  event.preventDefault();
  var userSelected = Data.loadUserName(pastUsersForm.userNameSelected.value);
  if (userSelected !== null ) {
    Data.saveUser(userSelected);
    window.location.href = 'index.html';
  } else {
    console.warn('Was not able to load selected user');
  }
});

resetButton.addEventListener('click', function(){
  var currentUser = Data.loadCurrentUser();
  currentUser.resetStats();
  Data.saveUser(currentUser);
  alert('Your balance has been reset.');
  window.location.href = 'index.html';
});

//Startup setting
if (Data.loadCurrentUser() === null) {
  pastUsersForm.hidden = true;
  currentUserSettings.hidden = true;
  newUser.className = 'centerNewUserDefault';
} else {
  pastUsers.userNameSelected.value = Data.loadCurrentUser().userName;
  difficultyLevel.difficultySelected.value = Data.loadCurrentUser().difficulty;
}

selectedCurrentUser.onchange = function() {
  var elem = (typeof this.selectedIndex === 'undefined' ? window.event.srcElement : this);
  var value = elem.value || elem.options[elem.selectedIndex].value;
  resetBalanceButton.textContent = 'Reset Balance of $' + Data.loadUserName(value).moneyBalance();
  difficultyLevel.difficultySelected.value = Data.loadCurrentUser().difficulty;
};

difficultySelection.onchange = function () {
  var elem = (typeof this.selectedIndex === 'undefined' ? window.event.srcElement : this);
  var value = elem.value || elem.options[elem.selectedIndex].value;
  var currentUser = Data.loadCurrentUser();
  if ('easy' === value ) {
    currentUser.slots = ['wildcard.gif','wildcard.gif','dancer.png','dog.png','poop.png','unicorn.png'];
    currentUser.difficulty = 'easy';
  } if ('medium' === value) {
    currentUser.slots = ['wildcard.gif','cat.png','dancer.png','dog.png','poop.png','unicorn.png'];
    currentUser.difficulty = 'medium';
  } if ('hard' === value) {
    currentUser.slots = ['alien.png','cat.png','dancer.png','dog.png','poop.png','unicorn.png'];
    currentUser.difficulty = 'hard';
  }
  Data.saveUser(currentUser);
  window.location.href = 'index.html';
};
<|endoftext|>


<commit_before>var rstats_obj = {
    values: {
        frame: {
            caption: 'Total frame time (ms)',
            over: 16.67
        },
        raf: {
            caption: 'since last rAF (ms)'
        },
        fps: {
            caption: 'Framerate (FPS)',
            below: 30
        }
    }
}

/* vars */

var canvas, engine, scene, assets, material, mesh, light, light2, camera, assets, light3, mesh, angle = 0,

    tx_box, tx_gold, tx_mat, tx_n, tx_sp,

    base_url = "https://dl.dropboxusercontent.com/u/1358781/lab/webgl/skull";

/* functions */

function render() {
    stats('frame').start();
    stats('rAF').tick();
    stats('FPS').frame();

    scene.render();

    stats('frame').end();
    stats().update();

    TWEEN.update();
}

function resize() {

    var aspect = 4 / 3;

    var c = document.getElementById("webgl-demo");
    var h = (3 / 4) * c.clientWidth;

    c.style.height = h + "px";
    //c.style.width = (aspect * h) + "px"

    engine.resize();
}

function before_render(camera) {

    mesh.rotation.y -= 0.015;

    camera.parent = light; //light.position = new BABYLON.Vector3(60 * Math.sin(angle), 0, 60 * Math.cos(angle));

    light3.position = new BABYLON.Vector3(20 * Math.sin(angle), 20 * Math.cos(angle), 0);
    //light.position = camera.position;

    angle += 0.025;
    /*scene.lights.forEach(function(l) {
    });*/
}

function on_progress_scene(progress) {

}

function on_init_scene() {

    camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 0, BABYLON.Vector3.Zero(), scene);
    scene.activeCamera = camera;
    camera.attachControl(canvas, true);

    mesh = scene.meshes[0];

    camera.target = mesh;
    camera.minZ = 10;
    //camera.maxZ = 200;
    camera.setPosition(new BABYLON.Vector3(0, 0, 100));
    camera.radius = 100;

    assets = new BABYLON.AssetsManager(scene);

    // Fog
    scene.fogMode = BABYLON.Scene.FOGMODE_LINEAR;
    scene.fogColor = new BABYLON.Color3(0, 0, 0);
    scene.fogStart = 20.0;
    scene.fogEnd = 1000.0;

    mesh.position.x = 0;
    mesh.position.y = 0;
    mesh.position.z = 0;
    //mesh.rotation.y = 2.0;

    mesh.optimizeIndices(function() {
        mesh.simplify([
                { quality: 0.15, distance: 200 },
                { quality: 0.25, distance: 100 },
                { quality: 0.25, distance: 50 },
                { quality: 0.25, distance: 10 }
            ],
            false,
            BABYLON.SimplificationType.QUADRATIC);
    });

    tx_box = new BABYLON.CubeTexture(base_url + "/textures/obsidian/ob", scene);

    var tx_gold_task = assets.addTextureTask("tx-gold", base_url + "/textures/gold/gold_texture_1024.jpg");
    tx_gold_task.onSuccess = function(task) {
        tx_gold = task.texture;
    }

    var tx_sp_task = assets.addTextureTask("tx-gold-sp", base_url + "/textures/gold/gold_sp.png")
    tx_sp_task.onSuccess = function(task) {
        tx_sp = task.texture;
    }

    var tx_n_task = assets.addTextureTask("tx-gold-n", base_url + "/textures/gold/gold_n.png")
    tx_n_task.onSuccess = function(task) {
        tx_n = task.texture;
    }

    assets.onFinish = function(tasks) {
        start_scene();
    };

    assets.load();
}

function start_scene() {

    var box = BABYLON.Mesh.CreateBox("sky-box", 800.0, scene);

    var box_mat = new BABYLON.PBRMaterial("skull-box-mat", scene);

    box_mat.reflectionTexture = tx_box;
    box_mat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
    box_mat.microSurface = 1.0;
    box_mat.cameraExposure = 1;
    box_mat.cameraContrast = 3.0;
    box_mat.diffuseColor = new BABYLON.Color3(0, 0, 0);
    box_mat.specularColor = new BABYLON.Color3(1, 1, 1);
    box_mat.disableLighting = true;
    box_mat.infiniteDistance = true;
    box_mat.backFaceCulling = false;
    box.material = box_mat;

    /*** https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/src/Shaders/pbr.fragment.fx
    *
    *
    * #ifdef BUMP# extension GL_OES_standard_derivatives: enable# endif
    # ifdef LODBASEDMICROSFURACE# extension GL_EXT_shader_texture_lod: enable# endif
    # ifdef LOGARITHMICDEPTH# extension GL_EXT_frag_depth: enable# endif
    */

    var use_pbr = true;
    var ext_a =  getWebGLExtensions(canvas) ;
    var pbr_a = ["GL_EXT_shader_texture_lod","GL_EXT_frag_depth","GL_OES_standard_derivatives"];
    var i = 0;
    while( i <= pbr_a.length-1 ){
        if ( ext_a.indexOf(pbr_a[i]) !== -1 ){
            use_pbr = false;
            break;
        }
        else{
            console.log(pbr_a[i]," ok");

        }
        i++;
    }

    //ext_a.every(function( el ){ return item.length > 0 });
    // true

    /**var shader_mat = new BABYLON.ShaderMaterial("amiga", scene, "./shaders",{
            attributes: ["position", "normal", "uv"],
            uniforms: ["world", "worldView", "worldViewProjection"]
        });
    shader_mat.setTexture("textureSampler", tx_gold);*/

    /**var standardPipeline = new BABYLON.PostProcessRenderPipeline(engine, "standardPipeline");
    var blackAndWhiteEffect = new BABYLON.PostProcessRenderEffect(engine, "blackAndWhiteEffect",  function() {return new BABYLON.BlackAndWhitePostProcess("bw", 1.0, null, null, engine, true)});

    standardPipeline.addEffect(blackAndWhiteEffect);
    scene.postProcessRenderPipelineManager.addPipeline(standardPipeline);*/

    //shader_mat.setTexture("refSampler", refTexture);
    //shader_mat.setFloat("time", 0);
    //shader_mat.setVector3("cameraPosition", BABYLON.Vector3.Zero());

    //  post fx
    // BlackAndWhitePostProcess(name, ratio, camera, samplingMode, engine, reusable)
    //var postProcess = new BlackAndWhitePostProcess("wb", 1.0, true, engine, true)

    // attach post fx
    //camera.attachPostProcess(postProcess);

    if (use_pbr === true) {

        //skull pbr material

        mat = new BABYLON.PBRMaterial("skull-mat", scene);

        mat.microSurface = .76;
        mat.albedoColor = new BABYLON.Color3(0.05, 0.03, 0.01);
        mat.albedoTexture = tx_n;

        mat.reflectivityColor = new BABYLON.Color3(0.9, 0.8, 0.1);
        mat.reflectivityTexture = tx_gold;

        mat.environmentIntensity = .5;
        mat.directIntensity = 1.25;

        mat.cameraExposure = 5.0;
        mat.cameraContrast = 2.25;

        mat.emissiveColor = new BABYLON.Color3(0.05, 0.03, 0.01);

        //reflection
        mat.reflectionTexture = tx_box;
        mat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
        mat.reflectionFresnelParameters = new BABYLON.FresnelParameters();
        mat.reflectionFresnelParameters.power = .10;
        mat.reflectionFresnelParameters.bias = .15;
        mat.reflectionFresnelParameters.leftColor = BABYLON.Color3.White();
        mat.reflectionFresnelParameters.rightColor = BABYLON.Color3.Black()

        //refraction
        mat.refractionTexture = tx_box;
        mat.refractionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
        mat.refractionFresnelParameters = new BABYLON.FresnelParameters();
        mat.refractionFresnelParameters.leftColor = BABYLON.Color3.White();
        mat.refractionFresnelParameters.rightColor = BABYLON.Color3.Black();
        mat.refractionFresnelParameters.bias = .15;
        mat.refractionFresnelParameters.power = .10;

    } else     {

           //skull standard material
           mat = new BABYLON.StandardMaterial("skull-mat", scene);

           mat.diffuseColor = new BABYLON.Color3(0.9, 0.8, 0.1);
           mat.diffuseTexture = tx_gold;

           mat.specularColor = new BABYLON.Color3(0.9, 0.8, 0.1);
           mat.specularTexture =  tx_sp;

           mat.ambientColor = new BABYLON.Color3(0.0, 0.0, 0.0);
           mat.emissiveColor = new BABYLON.Color3(0.0, 0.0, 0.0);
           mat.specularPower = 30;
           mat.alpha = 1.0;

           //emissive
           mat.emissiveTexture =  tx_gold;
           mat.emissiveFresnelParameters = new BABYLON.FresnelParameters();
           mat.emissiveFresnelParameters.bias = 0.25;
           mat.emissiveFresnelParameters.power = .25;
           mat.emissiveFresnelParameters.leftColor = BABYLON.Color3.White();
           mat.emissiveFresnelParameters.rightColor = BABYLON.Color3.Black();

           //reflection
           /*mat.reflectionTexture = tx_box;
           mat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
           mat.reflectionFresnelParameters = new BABYLON.FresnelParameters();
           mat.reflectionFresnelParameters.power = .25;
           mat.reflectionFresnelParameters.bias = .25;
           mat.reflectionFresnelParameters.leftColor = BABYLON.Color3.White();
           mat.reflectionFresnelParameters.rightColor = BABYLON.Color3.Black()

           //refraction
           mat.refractionTexture = tx_box;
           mat.refractionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
           mat.refractionFresnelParameters = new BABYLON.FresnelParameters();
           mat.refractionFresnelParameters.leftColor = BABYLON.Color3.White();
           mat.refractionFresnelParameters.rightColor = BABYLON.Color3.Black();
           mat.refractionFresnelParameters.bias = .25;
           mat.refractionFresnelParameters.power = .25;*/

    }

    mesh.material = mat;

    light = scene.lights[0];
    light.diffuseColor = new BABYLON.Color3(1, 1, 1);
    light.specularColor = new BABYLON.Color3(1, 1, 1);
    light.intensity = .95;
    light.position = new BABYLON.Vector3(0, 0, 0);

    light2 = new BABYLON.HemisphericLight("hemi-2", new BABYLON.Vector3(0, 0, 30), scene);
    light2.diffuse = new BABYLON.Color3(1, 1, 1);
    light2.specular = new BABYLON.Color3(1, 1, 1);
    light2.groundColor = new BABYLON.Color3(0.05, 0.03, 0.01);
    light2.intensity = .75;

    light3 = new BABYLON.PointLight("point-3", new BABYLON.Vector3(0, 0, -100), scene);
    light3.diffuse = new BABYLON.Color3(1, 1, 1);
    light3.specular = new BABYLON.Color3(1, 1, 1);
    light3.intensity = .75;

    angle = 0;
    scene.beforeRender = before_render;
    engine.runRenderLoop(render);

    //scene.debugLayer.show();

    window.addEventListener('resize', resize, false);
    resize();

    var t1 = new TWEEN.Tween({ z: 150 })
        .to({ z: 200 }, 4000)
        .easing(TWEEN.Easing.Exponential.InOut)
        .onUpdate(function() {
            camera.setPosition(new BABYLON.Vector3(0, 0, this.z));
        });

    t1.start();
}

function getWebGLExtensions(canvas) {
    var gl ;
    try {
        gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
        return gl != null && !!window.WebGLRenderingContext ? gl.getSupportedExtensions() : [];
    } catch (e) {
        return []
    }
}

function init() {
    if (Detector.webgl) {
        if (BABYLON.Engine.isSupported()) {

            document.onselectstart = function() {
                return false;
            }

            stats = new rStats(rstats_obj);
            canvas = document.getElementById("webgl-canvas");
            engine = new BABYLON.Engine(canvas, false, null, true);
            engine.enableOfflineSupport = true;

            BABYLON.SceneLoader.Load("", base_url + "/skull/skull-ok.babylon", engine, function(loaded_scene) {
                scene = loaded_scene;
                scene.executeWhenReady(on_init_scene);
            }, on_progress_scene);

        }
    } else {
        Detector.addGetWebGLMessage();
    }
}
//   /init

onDomReady(init);
<commit_msg>switch webgl extension<commit_after>var rstats_obj = {
    values: {
        frame: {
            caption: 'Total frame time (ms)',
            over: 16.67
        },
        raf: {
            caption: 'since last rAF (ms)'
        },
        fps: {
            caption: 'Framerate (FPS)',
            below: 30
        }
    }
}

/* vars */

var canvas, engine, scene, assets, material, mesh, light, light2, camera, assets, light3, mesh, angle = 0,

    tx_box, tx_gold, tx_mat, tx_n, tx_sp,

    base_url = "https://dl.dropboxusercontent.com/u/1358781/lab/webgl/skull";

/* functions */

function render() {
    stats('frame').start();
    stats('rAF').tick();
    stats('FPS').frame();

    scene.render();

    stats('frame').end();
    stats().update();

    TWEEN.update();
}

function resize() {

    var aspect = 4 / 3;

    var c = document.getElementById("webgl-demo");
    var h = (3 / 4) * c.clientWidth;

    c.style.height = h + "px";
    //c.style.width = (aspect * h) + "px"

    engine.resize();
}

function before_render(camera) {

    mesh.rotation.y -= 0.015;

    camera.parent = light; //light.position = new BABYLON.Vector3(60 * Math.sin(angle), 0, 60 * Math.cos(angle));

    light3.position = new BABYLON.Vector3(20 * Math.sin(angle), 20 * Math.cos(angle), 0);
    //light.position = camera.position;

    angle += 0.025;
    /*scene.lights.forEach(function(l) {
    });*/
}

function on_progress_scene(progress) {

}

function on_init_scene() {

    camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 0, BABYLON.Vector3.Zero(), scene);
    scene.activeCamera = camera;
    camera.attachControl(canvas, true);

    mesh = scene.meshes[0];

    camera.target = mesh;
    camera.minZ = 10;
    //camera.maxZ = 200;
    camera.setPosition(new BABYLON.Vector3(0, 0, 100));
    camera.radius = 100;

    assets = new BABYLON.AssetsManager(scene);

    // Fog
    scene.fogMode = BABYLON.Scene.FOGMODE_LINEAR;
    scene.fogColor = new BABYLON.Color3(0, 0, 0);
    scene.fogStart = 20.0;
    scene.fogEnd = 1000.0;

    mesh.position.x = 0;
    mesh.position.y = 0;
    mesh.position.z = 0;
    //mesh.rotation.y = 2.0;

    mesh.optimizeIndices(function() {
        mesh.simplify([
                { quality: 0.15, distance: 200 },
                { quality: 0.25, distance: 100 },
                { quality: 0.25, distance: 50 },
                { quality: 0.25, distance: 10 }
            ],
            false,
            BABYLON.SimplificationType.QUADRATIC);
    });

    tx_box = new BABYLON.CubeTexture(base_url + "/textures/obsidian/ob", scene);

    var tx_gold_task = assets.addTextureTask("tx-gold", base_url + "/textures/gold/gold_texture_1024.jpg");
    tx_gold_task.onSuccess = function(task) {
        tx_gold = task.texture;
    }

    var tx_sp_task = assets.addTextureTask("tx-gold-sp", base_url + "/textures/gold/gold_sp.png")
    tx_sp_task.onSuccess = function(task) {
        tx_sp = task.texture;
    }

    var tx_n_task = assets.addTextureTask("tx-gold-n", base_url + "/textures/gold/gold_n.png")
    tx_n_task.onSuccess = function(task) {
        tx_n = task.texture;
    }

    assets.onFinish = function(tasks) {
        start_scene();
    };

    assets.load();
}

function start_scene() {

    var box = BABYLON.Mesh.CreateBox("sky-box", 800.0, scene);

    var box_mat = new BABYLON.PBRMaterial("skull-box-mat", scene);

    box_mat.reflectionTexture = tx_box;
    box_mat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
    box_mat.microSurface = 1.0;
    box_mat.cameraExposure = 1;
    box_mat.cameraContrast = 3.0;
    box_mat.diffuseColor = new BABYLON.Color3(0, 0, 0);
    box_mat.specularColor = new BABYLON.Color3(1, 1, 1);
    box_mat.disableLighting = true;
    box_mat.infiniteDistance = true;
    box_mat.backFaceCulling = false;
    box.material = box_mat;

    /*** https://raw.githubusercontent.com/BabylonJS/Babylon.js/master/src/Shaders/pbr.fragment.fx
    *
    *
    * #ifdef BUMP# extension GL_OES_standard_derivatives: enable# endif
    # ifdef LODBASEDMICROSFURACE# extension GL_EXT_shader_texture_lod: enable# endif
    # ifdef LOGARITHMICDEPTH# extension GL_EXT_frag_depth: enable# endif
    */

    var use_pbr = true;
    var ext_a = getWebGLExtensions(canvas);
    var pbr_a = ["GL_EXT_shader_texture_lod", "GL_EXT_frag_depth", "GL_OES_standard_derivatives"];
    var i = 0;
    while (i <= pbr_a.length - 1) {
        if (ext_a.indexOf(pbr_a[i]) !== -1) {
            use_pbr = false;
            break;
        }
        /*else{
            console.log(pbr_a[i]," ok");

        }*/
        i++;
    }

    //ext_a.every(function( el ){ return item.length > 0 });
    // true

    /**var shader_mat = new BABYLON.ShaderMaterial("amiga", scene, "./shaders",{
            attributes: ["position", "normal", "uv"],
            uniforms: ["world", "worldView", "worldViewProjection"]
        });
    shader_mat.setTexture("textureSampler", tx_gold);*/

    /**var standardPipeline = new BABYLON.PostProcessRenderPipeline(engine, "standardPipeline");
    var blackAndWhiteEffect = new BABYLON.PostProcessRenderEffect(engine, "blackAndWhiteEffect",  function() {return new BABYLON.BlackAndWhitePostProcess("bw", 1.0, null, null, engine, true)});

    standardPipeline.addEffect(blackAndWhiteEffect);
    scene.postProcessRenderPipelineManager.addPipeline(standardPipeline);*/

    //shader_mat.setTexture("refSampler", refTexture);
    //shader_mat.setFloat("time", 0);
    //shader_mat.setVector3("cameraPosition", BABYLON.Vector3.Zero());

    //  post fx
    // BlackAndWhitePostProcess(name, ratio, camera, samplingMode, engine, reusable)
    //var postProcess = new BlackAndWhitePostProcess("wb", 1.0, true, engine, true)

    // attach post fx
    //camera.attachPostProcess(postProcess);

    if (use_pbr === true) {

        //skull pbr material

        mat = new BABYLON.PBRMaterial("skull-mat", scene);

        mat.microSurface = .76;
        mat.albedoColor = new BABYLON.Color3(0.05, 0.03, 0.01);
        mat.albedoTexture = tx_n;

        mat.reflectivityColor = new BABYLON.Color3(0.9, 0.8, 0.1);
        mat.reflectivityTexture = tx_gold;

        mat.environmentIntensity = .5;
        mat.directIntensity = 1.25;

        mat.cameraExposure = 5.0;
        mat.cameraContrast = 2.25;

        mat.emissiveColor = new BABYLON.Color3(0.05, 0.03, 0.01);

        //reflection
        mat.reflectionTexture = tx_box;
        mat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
        mat.reflectionFresnelParameters = new BABYLON.FresnelParameters();
        mat.reflectionFresnelParameters.power = .10;
        mat.reflectionFresnelParameters.bias = .15;
        mat.reflectionFresnelParameters.leftColor = BABYLON.Color3.White();
        mat.reflectionFresnelParameters.rightColor = BABYLON.Color3.Black()

        //refraction
        mat.refractionTexture = tx_box;
        mat.refractionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
        mat.refractionFresnelParameters = new BABYLON.FresnelParameters();
        mat.refractionFresnelParameters.leftColor = BABYLON.Color3.White();
        mat.refractionFresnelParameters.rightColor = BABYLON.Color3.Black();
        mat.refractionFresnelParameters.bias = .15;
        mat.refractionFresnelParameters.power = .10;

    } else {

        //skull standard material
        mat = new BABYLON.StandardMaterial("skull-mat", scene);
        mat.diffuseColor = new BABYLON.Color3(0.9, 0.8, 0.1);

        /*mat.diffuseTexture = tx_gold;

        mat.specularColor = new BABYLON.Color3(1, 1, 1);
        mat.specularTexture = tx_sp;

        mat.ambientColor = new BABYLON.Color3(0.05, 0.03, 0.01);

        mat.specularPower = 30;
        mat.alpha = 1.0;

        //reflection
        mat.reflectionTexture = tx_box;
        mat.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
        mat.reflectionFresnelParameters = new BABYLON.FresnelParameters();
        mat.reflectionFresnelParameters.power = .10;
        mat.reflectionFresnelParameters.bias = .15;
        mat.reflectionFresnelParameters.leftColor = BABYLON.Color3.White();
        mat.reflectionFresnelParameters.rightColor = BABYLON.Color3.Black()

        //refraction
        mat.refractionTexture = tx_box;
        mat.refractionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
        mat.refractionFresnelParameters = new BABYLON.FresnelParameters();
        mat.refractionFresnelParameters.leftColor = BABYLON.Color3.White();
        mat.refractionFresnelParameters.rightColor = BABYLON.Color3.Black();
        mat.refractionFresnelParameters.bias = .15;
        mat.refractionFresnelParameters.power = .10*/

    }

    mesh.material = mat;

    light = scene.lights[0];
    light.diffuseColor = new BABYLON.Color3(1, 1, 1);
    light.specularColor = new BABYLON.Color3(1, 1, 1);
    light.intensity = .95;
    light.position = new BABYLON.Vector3(0, 0, 0);

    light2 = new BABYLON.HemisphericLight("hemi-2", new BABYLON.Vector3(0, 0, 30), scene);
    light2.diffuse = new BABYLON.Color3(1, 1, 1);
    light2.specular = new BABYLON.Color3(1, 1, 1);
    light2.groundColor = new BABYLON.Color3(0.05, 0.03, 0.01);
    light2.intensity = .75;

    light3 = new BABYLON.PointLight("point-3", new BABYLON.Vector3(0, 0, -100), scene);
    light3.diffuse = new BABYLON.Color3(1, 1, 1);
    light3.specular = new BABYLON.Color3(1, 1, 1);
    light3.intensity = .75;

    angle = 0;
    scene.beforeRender = before_render;
    engine.runRenderLoop(render);

    //scene.debugLayer.show();

    window.addEventListener('resize', resize, false);
    resize();

    var t1 = new TWEEN.Tween({ z: 150 })
        .to({ z: 200 }, 4000)
        .easing(TWEEN.Easing.Exponential.InOut)
        .onUpdate(function() {
            camera.setPosition(new BABYLON.Vector3(0, 0, this.z));
        });

    t1.start();
}

function getWebGLExtensions(canvas) {
    var gl;
    try {
        gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
        return gl != null && !!window.WebGLRenderingContext ? gl.getSupportedExtensions() : [];
    } catch (e) {
        return []
    }
}

function init() {
    if (Detector.webgl) {
        if (BABYLON.Engine.isSupported()) {

            document.onselectstart = function() {
                return false;
            }

            stats = new rStats(rstats_obj);
            canvas = document.getElementById("webgl-canvas");
            engine = new BABYLON.Engine(canvas, false, null, true);
            engine.enableOfflineSupport = true;

            BABYLON.SceneLoader.Load("", base_url + "/skull/skull-ok.babylon", engine, function(loaded_scene) {
                scene = loaded_scene;
                scene.executeWhenReady(on_init_scene);
            }, on_progress_scene);

        }
    } else {
        Detector.addGetWebGLMessage();
    }
}
//   /init

onDomReady(init);
<|endoftext|>


<commit_before>var tern = require('tern');
var path = require("path");
var fs = require("fs");
var walk = require("acorn/dist/walk");

require('tern/plugin/doc_comment');
require('tern/plugin/commonjs');
require('tern/plugin/modules');
require('tern/plugin/node');
require('tern/plugin/node_resolve');
//require('tern/plugin/requirejs');

var localDir = process.cwd();
var ternServer = null;

var localFiles = null;

var out = {
    Defs: [],
    Refs: [],
    Docs: []
}

module.exports.initTernServer = function(files) {
    localFiles = files;
    var defsPath = path.join(__dirname, "../node_modules/tern/defs/ecma5.json");
    var defs = JSON.parse(fs.readFileSync(defsPath, "utf8"));
    var ternOptions = {
        projectDir: localDir,
        defs: [defs],
        async: false,
        getFile: function(file) {
            return fs.readFileSync(path.resolve(localDir, file), "utf8");
        },
        plugins: {
            node: true,
            requirejs: true,
            modules: true,
            es_modules: true,
            commonjs: true,
            doc_comment: true
        }
    };

    ternServer = new tern.Server(ternOptions);

    files.forEach(function(file) {
        ternServer.addFile(file);
    });

    var data = null;
    ternServer.flush(function(err) {
        if (err) throw err;
        data = analyse_all();
    });

    //console.error("TERN = ", ternServer);
    return data;
}

function getQueryInfo(file, offset, type, start) {
    var query = {
        type: type,
        start: start,
        end: offset,
        file: file,
        docFormat: "full"
    }

    var res = null;
    ternServer.request({
        query: query,
        offset: offset
    }, function(error, data) {
        if (error) {
            console.error("Error returned from Tern 'definition' request: " + error);
            return;
        }
        res = data;
    });
    return res;
}

function getType(file, offset, start) {
    return getQueryInfo(file, offset, "type", start);
}

function getDefinition(file, offset, start) {
    return getQueryInfo(file, offset, "definition", start);
}

function getCompletions(file, offset, start) {
    return getQueryInfo(file, offset, "completions", start);
}

function getDocumentation(file, offset, start) {
    return getQueryInfo(file, offset, "documentation", start);
}

function formPathFromId(id) {
    return id.sourceFile.name + "_" + id.start + "_" + id.end;
}

function formPathFromData(data, externalRepo) {
    if (data === null) {
        return null;
    }
    if (externalRepo === null) {
        if (data.origin === undefined || data.start === undefined || data.end === undefined) {
            return null;
        } else {
            return data.origin + "_" + data.start + "_" + data.end;
        }
    } else {
        return externalRepo.filePath + "_" + data.start + "_" + data.end;
    }
}

//TODO refactor this method, bad approach for finding package.json
function getExternalRepoInfo(data) {
    if (data === null || data.origin === undefined) {
        return null;
    }

    if (localFiles.indexOf(data.origin) > -1 || data.origin.indexOf("node_modules") == -1) {
        return null;
    }

    if (data.origin === "node" || data.origin === "commonjs" || data.origin === "ecma5") {
        return null;
    }

    var filePath = path.normalize(data.origin);
    var pathRes = filePath.split("/");
    var json = fs.readFileSync(localDir + "/" + pathRes[0] + "/" + pathRes[1] + '/package.json');
    var packageJson = JSON.parse(json.toString());

    if (packageJson.repository === undefined) {
        console.error("PACKAGE json does not define repository ", packageJson);
        return null;
    }

    //var repo = packageJson.repository.url;
    //var repoInfo = repo.slice(repo.indexOf("://") + 3).replace(".git", "").replace(".js", "");

    return {
        repo: packageJson.repository.url,
        unit: pathRes[1],
        filePath: pathRes.slice(2).join("/")
    };
}

function analyse_all() {

    var searchVisitor = walk.make({
        Function: function(node, kind, c) {
            if (node.id) {
                c(node.id, "function");
            }

            for (var i = 0; i < node.params.length; ++i)
                c(node.params[i], "param");
            c(node.body, "");
        },

        // TryStatement: function(node, st, c) {
        //     if (node.handler)
        //         c(node.handler.param, st);
        //     walk.base.TryStatement(node, st, c);

        // },

        VariableDeclaration: function(node, kind, c) {
            for (var i = 0; i < node.declarations.length; ++i) {
                var decl = node.declarations[i];

                c(decl.id, "var");
                if (decl.init) c(decl.init, "");
            }
        },
        MemberExpression: function(node, kind, c) {
            c(node.object, kind);
            c(node.property, "property");
        },
        ObjectExpression: function(node, kind, c) {
            for (var i = 0; i < node.properties.length; ++i) {
                c(node.properties[i].value, kind);
                c(node.properties[i].key, kind);
            }
        },
        Identifier: function(node, kind, c) {

            var pathForId = formPathFromId(node);
            var data = getDefinition(node.sourceFile.name, node.end, node.start);
            var externalRepo = getExternalRepoInfo(data);

            var typeInfo = getType(node.sourceFile.name, node.end, node.start);
            var documentation = getDocumentation(node.sourceFile.name, node.end, node.start);
            var pathForDef = formPathFromData(data, externalRepo);

            //emmission of Docs
            if (documentation !== null && documentation.doc !== undefined) {
                var docData = {
                    Path: pathForId,
                    Format: "",
                    Data: documentation.doc
                }

                out.Docs.push(docData);
            }

            if (data === null || pathForDef === null && data.url === undefined) {
                console.error("EMPTY data for Identifier = ", node.name);
                //console.error("DATA = ", data);
                return;
            }

            if (pathForDef === null && data.url !== undefined && kind !== "var") {
                //emmission of refs for environment vars
                var envRef = {
                    DefPath: data.url,
                    //DefURL: data.url,
                    Def: false,
                    File: node.sourceFile.name,
                    Start: node.start,
                    End: node.end
                }
                out.Refs.push(envRef);
                return;
            }

            if (pathForDef === pathForId || ((kind === "var") && (pathForDef !== pathForId))) {
                //emit def here
                var defData = {
                    Type: typeInfo.type,
                    Keyword: kind,
                    Kind: kind,
                    Separator: " "
                };
                var def = {
                    Path: pathForId,
                    Name: node.name,
                    Kind: kind,
                    File: node.sourceFile.name,
                    DefStart: node.start,
                    DefEnd: node.end,
                    TreePath: pathForId,
                    Data: defData
                };
                out.Defs.push(def);

                //emit fake ref here
                var ref = {
                    DefPath: pathForId,
                    Def: true,
                    File: node.sourceFile.name,
                    Start: node.start,
                    End: node.end
                }
                out.Refs.push(ref);
            } else {
                //emit simple ref here
                var ref = {
                    DefPath: pathForDef,
                    Def: false,
                    File: node.sourceFile.name,
                    Start: node.start,
                    End: node.end
                }
                if (externalRepo != null) {
                    ref.DefRepo = externalRepo.repo;
                    ref.DefUnit = externalRepo.unit;
                }
                out.Refs.push(ref);
            }

            // console.error("Identifier = ", node.name, "IN file = ", node.sourceFile.name);
            // console.error(data);
            // console.error("Here inside identifier = ", formPathFromId(node));
            // console.error("Here inside id data = ", formPathFromData(data, externalRepo));
            // console.error("TYPE = ", getType(node.sourceFile.name, node.end, node.start));
            // console.error("DOC = ", getDocumentation(node.sourceFile.name, node.end));
            // console.error("\n ========================== \n");
        }
    });

    ternServer.files.forEach(function(file) {
        if (file.name.indexOf('node_modules') == -1) {
            walk.recursive(file.ast, "ast", null, searchVisitor);
        }
        //console.error("FILE = ", file);
        //console.error("AST = ", file.ast);
    });

    //console.error("DEFS = ", out.Defs);
    // console.error("REFS = ", out.Refs);
    // console.error("DOCS = ", out.Docs);
    return out;
}
<commit_msg>Add some statistics data for undefined identifiers number<commit_after>var tern = require('tern');
var path = require("path");
var fs = require("fs");
var walk = require("acorn/dist/walk");

require('tern/plugin/doc_comment');
require('tern/plugin/commonjs');
require('tern/plugin/modules');
require('tern/plugin/node');
require('tern/plugin/node_resolve');
//require('tern/plugin/requirejs');

var localDir = process.cwd();
var ternServer = null;

var localFiles = null;

var allIdents = 0;
var undefinedIdents = 0;

var out = {
    Defs: [],
    Refs: [],
    Docs: []
}

module.exports.initTernServer = function(files) {
    localFiles = files;
    var defsPath = path.join(__dirname, "../node_modules/tern/defs/ecma5.json");
    var defs = JSON.parse(fs.readFileSync(defsPath, "utf8"));
    var ternOptions = {
        projectDir: localDir,
        defs: [defs],
        async: false,
        getFile: function(file) {
            return fs.readFileSync(path.resolve(localDir, file), "utf8");
        },
        plugins: {
            node: true,
            requirejs: true,
            modules: true,
            es_modules: true,
            commonjs: true,
            doc_comment: true
        }
    };

    ternServer = new tern.Server(ternOptions);

    files.forEach(function(file) {
        ternServer.addFile(file);
    });

    var data = null;
    ternServer.flush(function(err) {
        if (err) throw err;
        data = analyse_all();
    });

    console.error("All ids = ", allIdents, " Undefined ids = ", undefinedIdents);
    console.error("percentage of undefined ids = ", (undefinedIdents / allIdents) * 100, "%");
    return data;
}

function getQueryInfo(file, offset, type, start) {
    var query = {
        type: type,
        start: start,
        end: offset,
        file: file,
        docFormat: "full"
    }

    var res = null;
    ternServer.request({
        query: query,
        offset: offset
    }, function(error, data) {
        if (error) {
            console.error("Error returned from Tern 'definition' request: " + error);
            return;
        }
        res = data;
    });
    return res;
}

function getType(file, offset, start) {
    return getQueryInfo(file, offset, "type", start);
}

function getDefinition(file, offset, start) {
    return getQueryInfo(file, offset, "definition", start);
}

function getCompletions(file, offset, start) {
    return getQueryInfo(file, offset, "completions", start);
}

function getDocumentation(file, offset, start) {
    return getQueryInfo(file, offset, "documentation", start);
}

function formPathFromId(id) {
    return id.sourceFile.name + "_" + id.start + "_" + id.end;
}

function formPathFromData(data, externalRepo) {
    if (data === null) {
        return null;
    }
    if (externalRepo === null) {
        if (data.origin === undefined || data.start === undefined || data.end === undefined) {
            return null;
        } else {
            return data.origin + "_" + data.start + "_" + data.end;
        }
    } else {
        return externalRepo.filePath + "_" + data.start + "_" + data.end;
    }
}

//TODO refactor this method, bad approach for finding package.json
function getExternalRepoInfo(data) {
    if (data === null || data.origin === undefined) {
        return null;
    }

    if (localFiles.indexOf(data.origin) > -1 || data.origin.indexOf("node_modules") == -1) {
        return null;
    }

    if (data.origin === "node" || data.origin === "commonjs" || data.origin === "ecma5") {
        return null;
    }

    var filePath = path.normalize(data.origin);
    var pathRes = filePath.split("/");
    var json = fs.readFileSync(localDir + "/" + pathRes[0] + "/" + pathRes[1] + '/package.json');
    var packageJson = JSON.parse(json.toString());

    if (packageJson.repository === undefined) {
        console.error("PACKAGE json does not define repository ", packageJson);
        return null;
    }

    //var repo = packageJson.repository.url;
    //var repoInfo = repo.slice(repo.indexOf("://") + 3).replace(".git", "").replace(".js", "");

    return {
        repo: packageJson.repository.url,
        unit: pathRes[1],
        filePath: pathRes.slice(2).join("/")
    };
}

function analyse_all() {

    var searchVisitor = walk.make({
        Function: function(node, kind, c) {
            if (node.id) {
                c(node.id, "function");
            }

            for (var i = 0; i < node.params.length; ++i)
                c(node.params[i], "param");
            c(node.body, "");
        },

        // TryStatement: function(node, st, c) {
        //     if (node.handler)
        //         c(node.handler.param, st);
        //     walk.base.TryStatement(node, st, c);

        // },

        VariableDeclaration: function(node, kind, c) {
            for (var i = 0; i < node.declarations.length; ++i) {
                var decl = node.declarations[i];

                c(decl.id, "var");
                if (decl.init) c(decl.init, "");
            }
        },
        MemberExpression: function(node, kind, c) {
            c(node.object, kind);
            c(node.property, "property");
        },
        ObjectExpression: function(node, kind, c) {
            for (var i = 0; i < node.properties.length; ++i) {
                c(node.properties[i].value, kind);
                c(node.properties[i].key, kind);
            }
        },
        Identifier: function(node, kind, c) {
            allIdents = allIdents + 1;
            var pathForId = formPathFromId(node);
            var data = getDefinition(node.sourceFile.name, node.end, node.start);
            var externalRepo = getExternalRepoInfo(data);

            var typeInfo = getType(node.sourceFile.name, node.end, node.start);
            var documentation = getDocumentation(node.sourceFile.name, node.end, node.start);
            var pathForDef = formPathFromData(data, externalRepo);

            //emmission of Docs
            if (documentation !== null && documentation.doc !== undefined) {
                var docData = {
                    Path: pathForId,
                    Format: "",
                    Data: documentation.doc
                }

                out.Docs.push(docData);
            }

            if (data === null || pathForDef === null && data.url === undefined) {
                undefinedIdents = undefinedIdents + 1;
                console.error("EMPTY data for Identifier = ", node.name);
                //console.error("DATA = ", data);
                return;
            }

            if (pathForDef === null && data.url !== undefined && kind !== "var") {
                //emmission of refs for environment vars
                var envRef = {
                    DefPath: data.url,
                    //DefURL: data.url,
                    Def: false,
                    File: node.sourceFile.name,
                    Start: node.start,
                    End: node.end
                }
                out.Refs.push(envRef);
                return;
            }

            if (pathForDef === pathForId || ((kind === "var") && (pathForDef !== pathForId))) {
                //emit def here
                var defData = {
                    Type: typeInfo.type,
                    Keyword: kind,
                    Kind: kind,
                    Separator: " "
                };
                var def = {
                    Path: pathForId,
                    Name: node.name,
                    Kind: kind,
                    File: node.sourceFile.name,
                    DefStart: node.start,
                    DefEnd: node.end,
                    TreePath: pathForId,
                    Data: defData
                };
                out.Defs.push(def);

                //emit fake ref here
                var ref = {
                    DefPath: pathForId,
                    Def: true,
                    File: node.sourceFile.name,
                    Start: node.start,
                    End: node.end
                }
                out.Refs.push(ref);
            } else {
                //emit simple ref here
                var ref = {
                    DefPath: pathForDef,
                    Def: false,
                    File: node.sourceFile.name,
                    Start: node.start,
                    End: node.end
                }
                if (externalRepo != null) {
                    ref.DefRepo = externalRepo.repo;
                    ref.DefUnit = externalRepo.unit;
                }
                out.Refs.push(ref);
            }

            // console.error("Identifier = ", node.name, "IN file = ", node.sourceFile.name);
            // console.error(data);
            // console.error("Here inside identifier = ", formPathFromId(node));
            // console.error("Here inside id data = ", formPathFromData(data, externalRepo));
            // console.error("TYPE = ", getType(node.sourceFile.name, node.end, node.start));
            // console.error("DOC = ", getDocumentation(node.sourceFile.name, node.end));
            // console.error("\n ========================== \n");
        }
    });

    ternServer.files.forEach(function(file) {
        if (file.name.indexOf('node_modules') == -1) {
            walk.recursive(file.ast, "ast", null, searchVisitor);
        }
        //console.error("FILE = ", file);
        //console.error("AST = ", file.ast);
    });

    //console.error("DEFS = ", out.Defs);
    // console.error("REFS = ", out.Refs);
    // console.error("DOCS = ", out.Docs);
    return out;
}
<|endoftext|>


<commit_before>"use strict";
var responseHelper = module.exports = { };

var _ = require("underscore");
var async = require("async");
var Joi = require("joi");

responseHelper.setBaseUrl = function(baseUrl) {
  responseHelper._baseUrl = baseUrl;
};
responseHelper.setMetadata = function(meta) {
  responseHelper._metadata = meta;
};

responseHelper._enforceSchemaOnArray = function(items, schema, callback) {
  if (!(items instanceof Array)) {
    items = [ items ];
  }
  async.map(items, function(item, done) {
    return responseHelper._enforceSchemaOnObject(item, schema, done);
  }, function(err, results) {
    if (err) return callback(err);

    results = results.filter(function(result) {
      return !!result;
    });
    return callback(null, results);
  });
};

responseHelper._enforceSchemaOnObject = function(item, schema, callback) {
  Joi.validate(item, schema, function (err) {
    if (err) {
      console.log("Failed to validate internal object?!", JSON.stringify(arguments));
      return callback(null);
    }

    var dataItem = responseHelper._generateDataItem(item, schema);
    return callback(null, dataItem);
  });
};

responseHelper._generateDataItem = function(item, schema) {

  var isSpecialProperty = function(value) {
    if (!(value instanceof Object)) return false;
    if (value._settings) return true;
    return false;
  };
  var linkProperties = Object.keys(schema).filter(function(someProperty) {
    return isSpecialProperty(schema[someProperty]);
  });
  var attributeProperties = Object.keys(schema).filter(function(someProperty) {
    if ((someProperty === "id") || (someProperty === "type")) return false;
    return !isSpecialProperty(schema[someProperty]);
  });

  var result = {
    type: item.type,
    id: item.id,
    attributes: _.pick(item, attributeProperties),
    links: responseHelper._generateLinks(item, schema, linkProperties),
    relationships: responseHelper._generateRelationships(item, schema, linkProperties)
  };

  return result;
};

responseHelper._generateLinks = function(item) {
  return {
    self: responseHelper._baseUrl + item.type + "/" + item.id
  };
};

responseHelper._generateRelationships = function(item, schema, linkProperties) {
  if (linkProperties.length === 0) return undefined;

  var links = { };

  linkProperties.forEach(function(linkProperty) {
    links[linkProperty] = responseHelper._generateLink(item, schema[linkProperty], linkProperty);
  });

  return links;
};

responseHelper._generateLink = function(item, schemaProperty, linkProperty) {
  var link = {
    meta: {
      relation: "primary",
      // type: schemaProperty._settings.__many || schemaProperty._settings.__,
      readOnly: false
    },
    links: {
      self: responseHelper._baseUrl + item.type + "/" + item.id + "/relationships/" + linkProperty,
      related: responseHelper._baseUrl + item.type + "/" + item.id + "/" + linkProperty
    },
    data: null
  };

  if (schemaProperty._settings.__many) {
    link.data = [ ];
    var linkItems = item[linkProperty];
    if (linkItems) {
      if (!(linkItems instanceof Array)) linkItems = [ linkItems ];
      linkItems.forEach(function(linkItem) {
        link.data.push({
          type: linkItem.type,
          id: linkItem.id
        });
      });
    }
  }

  if (schemaProperty._settings.__one) {
    var linkItem = item[linkProperty];
    if (linkItem) {
      link.data = {
        type: linkItem.type,
        id: linkItem.id
      };
    }
  }

  if (schemaProperty._settings.__as) {
    var relatedResource = schemaProperty._settings.__one || schemaProperty._settings.__many;
    // get information about the linkage - list of ids and types
    // /rest/bookings/relationships/?customer=26aa8a92-2845-4e40-999f-1fa006ec8c63
    link.links.self = responseHelper._baseUrl + relatedResource + "/relationships/?" + schemaProperty._settings.__as + "=" + item.id;
    // get full details of all linked resources
    // /rest/bookings/?relationships[customer]=26aa8a92-2845-4e40-999f-1fa006ec8c63
    link.links.related = responseHelper._baseUrl + relatedResource + "/?relationships[" + schemaProperty._settings.__as + "]=" + item.id;
    if (!item[linkProperty]) {
      link.data = undefined;
    }
    link.meta = {
      relation: "foreign",
      belongsTo: relatedResource,
      as: schemaProperty._settings.__as,
      many: !!schemaProperty._settings.__many,
      readOnly: true
    };
  }

  return link;
};

responseHelper.generateError = function(request, err) {

  if (!(err instanceof Array)) err = [ err ];

  var errorResponse = {
    meta: responseHelper._generateMeta(request),
    links: {
      self: request.route.path
    },
    errors: err.map(function(error) {
      return {
        status: error.status,
        code: error.code,
        title: error.title,
        detail: error.detail
      };
    })
  };

  return errorResponse;
};

responseHelper._generateResponse = function(request, resourceConfig, sanitisedData) {
  return {
    meta: responseHelper._generateMeta(request),
    links: {
      self: request.route.path + (request.route.query ? ("?" + request.route.query) : "")
    },
    data: sanitisedData
  };
};

responseHelper._generateMeta = function() {
  return responseHelper._metadata;
};
<commit_msg>Added additional info to relation metadata<commit_after>"use strict";
var responseHelper = module.exports = { };

var _ = require("underscore");
var async = require("async");
var Joi = require("joi");

responseHelper.setBaseUrl = function(baseUrl) {
  responseHelper._baseUrl = baseUrl;
};
responseHelper.setMetadata = function(meta) {
  responseHelper._metadata = meta;
};

responseHelper._enforceSchemaOnArray = function(items, schema, callback) {
  if (!(items instanceof Array)) {
    items = [ items ];
  }
  async.map(items, function(item, done) {
    return responseHelper._enforceSchemaOnObject(item, schema, done);
  }, function(err, results) {
    if (err) return callback(err);

    results = results.filter(function(result) {
      return !!result;
    });
    return callback(null, results);
  });
};

responseHelper._enforceSchemaOnObject = function(item, schema, callback) {
  Joi.validate(item, schema, function (err) {
    if (err) {
      console.log("Failed to validate internal object?!", JSON.stringify(arguments));
      return callback(null);
    }

    var dataItem = responseHelper._generateDataItem(item, schema);
    return callback(null, dataItem);
  });
};

responseHelper._generateDataItem = function(item, schema) {

  var isSpecialProperty = function(value) {
    if (!(value instanceof Object)) return false;
    if (value._settings) return true;
    return false;
  };
  var linkProperties = Object.keys(schema).filter(function(someProperty) {
    return isSpecialProperty(schema[someProperty]);
  });
  var attributeProperties = Object.keys(schema).filter(function(someProperty) {
    if ((someProperty === "id") || (someProperty === "type")) return false;
    return !isSpecialProperty(schema[someProperty]);
  });

  var result = {
    type: item.type,
    id: item.id,
    attributes: _.pick(item, attributeProperties),
    links: responseHelper._generateLinks(item, schema, linkProperties),
    relationships: responseHelper._generateRelationships(item, schema, linkProperties)
  };

  return result;
};

responseHelper._generateLinks = function(item) {
  return {
    self: responseHelper._baseUrl + item.type + "/" + item.id
  };
};

responseHelper._generateRelationships = function(item, schema, linkProperties) {
  if (linkProperties.length === 0) return undefined;

  var links = { };

  linkProperties.forEach(function(linkProperty) {
    links[linkProperty] = responseHelper._generateLink(item, schema[linkProperty], linkProperty);
  });

  return links;
};

responseHelper._generateLink = function(item, schemaProperty, linkProperty) {
  var link = {
    meta: {
      relation: "primary",
      // type: schemaProperty._settings.__many || schemaProperty._settings.__one,
      readOnly: false
    },
    links: {
      self: responseHelper._baseUrl + item.type + "/" + item.id + "/relationships/" + linkProperty,
      related: responseHelper._baseUrl + item.type + "/" + item.id + "/" + linkProperty
    },
    data: null
  };

  if (schemaProperty._settings.__many) {
    link.data = [ ];
    var linkItems = item[linkProperty];
    if (linkItems) {
      if (!(linkItems instanceof Array)) linkItems = [ linkItems ];
      linkItems.forEach(function(linkItem) {
        link.data.push({
          type: linkItem.type,
          id: linkItem.id
        });
      });
    }
  }

  if (schemaProperty._settings.__one) {
    var linkItem = item[linkProperty];
    if (linkItem) {
      link.data = {
        type: linkItem.type,
        id: linkItem.id
      };
    }
  }

  if (schemaProperty._settings.__as) {
    var relatedResource = schemaProperty._settings.__one || schemaProperty._settings.__many;
    // get information about the linkage - list of ids and types
    // /rest/bookings/relationships/?customer=26aa8a92-2845-4e40-999f-1fa006ec8c63
    link.links.self = responseHelper._baseUrl + relatedResource + "/relationships/?" + schemaProperty._settings.__as + "=" + item.id;
    // get full details of all linked resources
    // /rest/bookings/?relationships[customer]=26aa8a92-2845-4e40-999f-1fa006ec8c63
    link.links.related = responseHelper._baseUrl + relatedResource + "/?relationships[" + schemaProperty._settings.__as + "]=" + item.id;
    if (!item[linkProperty]) {
      link.data = undefined;
    }
    link.meta = {
      relation: "foreign",
      belongsTo: relatedResource,
      as: schemaProperty._settings.__as,
      many: !!schemaProperty._settings.__many,
      readOnly: true
    };
  }

  return link;
};

responseHelper.generateError = function(request, err) {

  if (!(err instanceof Array)) err = [ err ];

  var errorResponse = {
    meta: responseHelper._generateMeta(request),
    links: {
      self: request.route.path
    },
    errors: err.map(function(error) {
      return {
        status: error.status,
        code: error.code,
        title: error.title,
        detail: error.detail
      };
    })
  };

  return errorResponse;
};

responseHelper._generateResponse = function(request, resourceConfig, sanitisedData) {
  return {
    meta: responseHelper._generateMeta(request),
    links: {
      self: request.route.path + (request.route.query ? ("?" + request.route.query) : "")
    },
    data: sanitisedData
  };
};

responseHelper._generateMeta = function() {
  return responseHelper._metadata;
};
<|endoftext|>


<commit_before>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2016, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function(DefaultApplication, DefaultApplicationWindow, Application, Window, Utils, API, VFS, GUI) {
  'use strict';
  // TODO: Playlist
  // TODO: Server seek support: https://gist.github.com/codler/3906826

  function formatTime(secs) {
    var hr  = Math.floor(secs / 3600);
    var min = Math.floor((secs - (hr * 3600)) / 60);
    var sec = Math.floor(secs - (hr * 3600) -  (min * 60));

    if (min < 10) {
      min = '0' + min;
    }
    if (sec < 10) {
      sec  = '0' + sec;
    }

    return min + ':' + sec;
  }

  /////////////////////////////////////////////////////////////////////////////
  // WINDOWS
  /////////////////////////////////////////////////////////////////////////////

  function ApplicationMusicPlayerWindow(app, metadata, scheme, file) {
    DefaultApplicationWindow.apply(this, ['ApplicationMusicPlayerWindow', {
      icon: metadata.icon,
      title: metadata.name,
      allow_drop: true,
      allow_resize: false,
      allow_maximize: false,
      width: 370,
      height: 260
    }, app, scheme, file]);

    this.updated = false;
  }

  ApplicationMusicPlayerWindow.prototype = Object.create(DefaultApplicationWindow.prototype);
  ApplicationMusicPlayerWindow.constructor = DefaultApplicationWindow.prototype;

  ApplicationMusicPlayerWindow.prototype.init = function(wm, app, scheme) {
    var root = DefaultApplicationWindow.prototype.init.apply(this, arguments);
    var self = this;

    // Load and set up scheme (GUI) here
    scheme.render(this, 'MusicPlayerWindow', root, null, null, {
      _: OSjs.Applications.ApplicationMusicPlayer._
    });

    var label = this._scheme.find(this, 'LabelTime');
    var seeker = this._scheme.find(this, 'Seek');

    var player = scheme.find(this, 'Player');
    var audio = player.$element.firstChild;

    var buttonStart = scheme.find(this, 'ButtonStart').set('disabled', true);
    var buttonRew = scheme.find(this, 'ButtonRew').set('disabled', true);
    var buttonPlay = scheme.find(this, 'ButtonPlay').set('disabled', true).on('click', function() {
      audio.play();
    });
    var buttonPause = scheme.find(this, 'ButtonPause').set('disabled', true).on('click', function() {
      audio.pause();
    });
    var buttonFwd = scheme.find(this, 'ButtonFwd').set('disabled', true);
    var buttonEnd = scheme.find(this, 'ButtonEnd').set('disabled', true);

    seeker.on('change', function(ev) {
      audio.pause();
      audio.currentTime = ev.detail;
      audio.play();
    });

    player.on('play', function(ev) {
      buttonPause.set('disabled', false);
      buttonPlay.set('disabled', true);
    });
    player.on('ended', function(ev) {
      buttonPause.set('disabled', true);
    });
    player.on('pause', function(ev) {
      buttonPause.set('disabled', false);
      buttonPlay.set('disabled', false);
    });
    player.on('loadeddata', function(ev) {
    });
    player.on('timeupdate', function(ev) {
      self.updateTime(label, seeker);
    });
    player.on('error', function(ev) {
      if ( !player.$element.src ) {
        return;
      }
      var msg = null;
      try {
        switch ( ev.target.error.code ) {
          case ev.target.error.MEDIA_ERR_ABORTED:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Playback aborted');
            break;
          case ev.target.error.MEDIA_ERR_NETWORK:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Network or communication error');
            break;
          case ev.target.error.MEDIA_ERR_DECODE:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Decoding failed. Corruption or unsupported media');
            break;
          case ev.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Media source not supported');
            break;
          default:
            msg = OSjs.API._('ERR_APP_UNKNOWN_ERROR');
            break;
        }
      } catch ( e ) {
        msg = OSjs.API._('ERR_GENERIC_APP_FATAL_FMT', e);
      }

      if ( msg ) {
        API.createDialog('Alert', {title: self._title, message: msg}, null, self);
      }
    });

    return root;
  };

  ApplicationMusicPlayerWindow.prototype.showFile = function(file, content) {
    if ( !file || !content ) { return; }

    var self = this;
    var scheme = this._scheme;
    var player = scheme.find(this, 'Player');
    var seeker = this._scheme.find(this, 'Seek');
    var audio = player.$element.firstChild;

    var artist = file ? file.filename : '';
    var album = file ? Utils.dirname(file.path) : '';

    var labelArtist = this._scheme.find(this, 'LabelArtist').set('value', '');
    var labelTitle  = this._scheme.find(this, 'LabelTitle').set('value', artist);
    var labelAlbum  = this._scheme.find(this, 'LabelAlbum').set('value', album);
    this._scheme.find(this, 'LabelTime').set('value', '');
    seeker.set('min', 0);
    seeker.set('max', 0);
    seeker.set('value', 0);

    this.updated = false;

    function getInfo() {
      self._app._call('info', {filename: file.path}, function(res) {
        var info = (res && res.result) ? res.result : null;
        if ( info ) {
          if ( info.Artist ) { labelArtist.set('value', info.Artist); }
          if ( info.Album ) { labelAlbum.set('value', info.Album); }
          if ( info.Title ) { labelTitle.set('value', info.Track); }
        }
      });
    }

    audio.src = content || '';
    audio.play();
    getInfo();
  };

  ApplicationMusicPlayerWindow.prototype.updateTime = function(label, seeker) {
    if ( this._destroyed ) { return; } // Important because async

    var player = this._scheme.find(this, 'Player');
    var audio = player.$element.firstChild;

    var total   = audio.duration;
    var current = audio.currentTime;
    var unknown = false;

    if ( isNaN(current) || !isFinite(current) ) {
      current = 0.0;
    }

    if ( isNaN(total) || !isFinite(total) ) {
      total = current;
      unknown = true;
    }

    var time = Utils.format('{0} / {1}', formatTime(current), unknown ? '<unknown>' : formatTime(total));

    if ( !this.updated ) {
      seeker.set('min', 0);
      seeker.set('max', total);
    }

    label.set('value', time);
    seeker.set('value', current);

    this.updated = true;
  };

  /////////////////////////////////////////////////////////////////////////////
  // APPLICATION
  /////////////////////////////////////////////////////////////////////////////

  var ApplicationMusicPlayer = function(args, metadata) {
    DefaultApplication.apply(this, ['ApplicationMusicPlayer', args, metadata, {
      readData: false
    }]);
  };

  ApplicationMusicPlayer.prototype = Object.create(DefaultApplication.prototype);
  ApplicationMusicPlayer.constructor = DefaultApplication;

  ApplicationMusicPlayer.prototype.destroy = function() {
    return DefaultApplication.prototype.destroy.apply(this, arguments);
  };

  ApplicationMusicPlayer.prototype.init = function(settings, metadata, onInited) {
    var self = this;
    DefaultApplication.prototype.init.call(this, settings, metadata, onInited, function(scheme, file) {
      self._addWindow(new ApplicationMusicPlayerWindow(self, metadata, scheme, file));
    });
  };

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.ApplicationMusicPlayer = OSjs.Applications.ApplicationMusicPlayer || {};
  OSjs.Applications.ApplicationMusicPlayer.Class = ApplicationMusicPlayer;

})(OSjs.Helpers.DefaultApplication, OSjs.Helpers.DefaultApplicationWindow, OSjs.Core.Application, OSjs.Core.Window, OSjs.Utils, OSjs.API, OSjs.VFS, OSjs.GUI);
<commit_msg>MusicPlayer: Prevent error in seeker when no audio attached (Fixes #251)<commit_after>/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2016, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function(DefaultApplication, DefaultApplicationWindow, Application, Window, Utils, API, VFS, GUI) {
  'use strict';
  // TODO: Playlist
  // TODO: Server seek support: https://gist.github.com/codler/3906826

  function formatTime(secs) {
    var hr  = Math.floor(secs / 3600);
    var min = Math.floor((secs - (hr * 3600)) / 60);
    var sec = Math.floor(secs - (hr * 3600) -  (min * 60));

    if (min < 10) {
      min = '0' + min;
    }
    if (sec < 10) {
      sec  = '0' + sec;
    }

    return min + ':' + sec;
  }

  /////////////////////////////////////////////////////////////////////////////
  // WINDOWS
  /////////////////////////////////////////////////////////////////////////////

  function ApplicationMusicPlayerWindow(app, metadata, scheme, file) {
    DefaultApplicationWindow.apply(this, ['ApplicationMusicPlayerWindow', {
      icon: metadata.icon,
      title: metadata.name,
      allow_drop: true,
      allow_resize: false,
      allow_maximize: false,
      width: 370,
      height: 260
    }, app, scheme, file]);

    this.updated = false;
  }

  ApplicationMusicPlayerWindow.prototype = Object.create(DefaultApplicationWindow.prototype);
  ApplicationMusicPlayerWindow.constructor = DefaultApplicationWindow.prototype;

  ApplicationMusicPlayerWindow.prototype.init = function(wm, app, scheme) {
    var root = DefaultApplicationWindow.prototype.init.apply(this, arguments);
    var self = this;

    // Load and set up scheme (GUI) here
    scheme.render(this, 'MusicPlayerWindow', root, null, null, {
      _: OSjs.Applications.ApplicationMusicPlayer._
    });

    var label = this._scheme.find(this, 'LabelTime');
    var seeker = this._scheme.find(this, 'Seek');

    var player = scheme.find(this, 'Player');
    var audio = player.$element.firstChild;

    var buttonStart = scheme.find(this, 'ButtonStart').set('disabled', true);
    var buttonRew = scheme.find(this, 'ButtonRew').set('disabled', true);
    var buttonPlay = scheme.find(this, 'ButtonPlay').set('disabled', true).on('click', function() {
      audio.play();
    });
    var buttonPause = scheme.find(this, 'ButtonPause').set('disabled', true).on('click', function() {
      audio.pause();
    });
    var buttonFwd = scheme.find(this, 'ButtonFwd').set('disabled', true);
    var buttonEnd = scheme.find(this, 'ButtonEnd').set('disabled', true);

    seeker.on('change', function(ev) {
      if ( audio ) {
        audio.pause();
        if ( ev ) {
          audio.currentTime = ev.detail || 0;
        }
        audio.play();
      }
    });

    player.on('play', function(ev) {
      buttonPause.set('disabled', false);
      buttonPlay.set('disabled', true);
    });
    player.on('ended', function(ev) {
      buttonPause.set('disabled', true);
    });
    player.on('pause', function(ev) {
      buttonPause.set('disabled', false);
      buttonPlay.set('disabled', false);
    });
    player.on('loadeddata', function(ev) {
    });
    player.on('timeupdate', function(ev) {
      self.updateTime(label, seeker);
    });
    player.on('error', function(ev) {
      if ( !player.$element.src ) {
        return;
      }
      var msg = null;
      try {
        switch ( ev.target.error.code ) {
          case ev.target.error.MEDIA_ERR_ABORTED:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Playback aborted');
            break;
          case ev.target.error.MEDIA_ERR_NETWORK:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Network or communication error');
            break;
          case ev.target.error.MEDIA_ERR_DECODE:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Decoding failed. Corruption or unsupported media');
            break;
          case ev.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED:
            msg = OSjs.Applications.ApplicationMusicPlayer._('Media source not supported');
            break;
          default:
            msg = OSjs.API._('ERR_APP_UNKNOWN_ERROR');
            break;
        }
      } catch ( e ) {
        msg = OSjs.API._('ERR_GENERIC_APP_FATAL_FMT', e);
      }

      if ( msg ) {
        API.createDialog('Alert', {title: self._title, message: msg}, null, self);
      }
    });

    return root;
  };

  ApplicationMusicPlayerWindow.prototype.showFile = function(file, content) {
    if ( !file || !content ) { return; }

    var self = this;
    var scheme = this._scheme;
    var player = scheme.find(this, 'Player');
    var seeker = this._scheme.find(this, 'Seek');
    var audio = player.$element.firstChild;

    var artist = file ? file.filename : '';
    var album = file ? Utils.dirname(file.path) : '';

    var labelArtist = this._scheme.find(this, 'LabelArtist').set('value', '');
    var labelTitle  = this._scheme.find(this, 'LabelTitle').set('value', artist);
    var labelAlbum  = this._scheme.find(this, 'LabelAlbum').set('value', album);
    this._scheme.find(this, 'LabelTime').set('value', '');
    seeker.set('min', 0);
    seeker.set('max', 0);
    seeker.set('value', 0);

    this.updated = false;

    function getInfo() {
      self._app._call('info', {filename: file.path}, function(res) {
        var info = (res && res.result) ? res.result : null;
        if ( info ) {
          if ( info.Artist ) { labelArtist.set('value', info.Artist); }
          if ( info.Album ) { labelAlbum.set('value', info.Album); }
          if ( info.Title ) { labelTitle.set('value', info.Track); }
        }
      });
    }

    audio.src = content || '';
    audio.play();
    getInfo();
  };

  ApplicationMusicPlayerWindow.prototype.updateTime = function(label, seeker) {
    if ( this._destroyed ) { return; } // Important because async

    var player = this._scheme.find(this, 'Player');
    var audio = player.$element.firstChild;

    var total   = audio.duration;
    var current = audio.currentTime;
    var unknown = false;

    if ( isNaN(current) || !isFinite(current) ) {
      current = 0.0;
    }

    if ( isNaN(total) || !isFinite(total) ) {
      total = current;
      unknown = true;
    }

    var time = Utils.format('{0} / {1}', formatTime(current), unknown ? '<unknown>' : formatTime(total));

    if ( !this.updated ) {
      seeker.set('min', 0);
      seeker.set('max', total);
    }

    label.set('value', time);
    seeker.set('value', current);

    this.updated = true;
  };

  /////////////////////////////////////////////////////////////////////////////
  // APPLICATION
  /////////////////////////////////////////////////////////////////////////////

  var ApplicationMusicPlayer = function(args, metadata) {
    DefaultApplication.apply(this, ['ApplicationMusicPlayer', args, metadata, {
      readData: false
    }]);
  };

  ApplicationMusicPlayer.prototype = Object.create(DefaultApplication.prototype);
  ApplicationMusicPlayer.constructor = DefaultApplication;

  ApplicationMusicPlayer.prototype.destroy = function() {
    return DefaultApplication.prototype.destroy.apply(this, arguments);
  };

  ApplicationMusicPlayer.prototype.init = function(settings, metadata, onInited) {
    var self = this;
    DefaultApplication.prototype.init.call(this, settings, metadata, onInited, function(scheme, file) {
      self._addWindow(new ApplicationMusicPlayerWindow(self, metadata, scheme, file));
    });
  };

  /////////////////////////////////////////////////////////////////////////////
  // EXPORTS
  /////////////////////////////////////////////////////////////////////////////

  OSjs.Applications = OSjs.Applications || {};
  OSjs.Applications.ApplicationMusicPlayer = OSjs.Applications.ApplicationMusicPlayer || {};
  OSjs.Applications.ApplicationMusicPlayer.Class = ApplicationMusicPlayer;

})(OSjs.Helpers.DefaultApplication, OSjs.Helpers.DefaultApplicationWindow, OSjs.Core.Application, OSjs.Core.Window, OSjs.Utils, OSjs.API, OSjs.VFS, OSjs.GUI);
<|endoftext|>