<commit_before>import {
  defineHiddenPropertiesRW
  // defineHiddenPropertyRO,
  // StackedContext
} from 'picimo/utils'

import EntityElement from '../EntityElement'

import createWebGlRenderer from './createWebGlRenderer'
import resize from './resize'

export default class CanvasElement extends EntityElement {
  /** @ignore */
  constructor (_) {
    const self = super(_)

    self.now = 0
    self.frameNo = 0
    self.animationFrameRequestId = 0
    self.animationFrameRequestIsStopped = false

    defineHiddenPropertiesRW(self, {
      _webGlRenderer: null,
      _clearColor: undefined,
      _lastFrameTime: 0
    })
    // defineHiddenPropertyRO(self, 'renderFrameContext', new StackedContext())

    self.canvas = document.createElement('canvas')
    self.firstTimeConnected = true
    resize(self)

    return self
  }

  get webGlRenderer () {
    const renderer = this._webGlRenderer
    if (renderer) return renderer
    const { webGlRenderer, canvasContextAttributes } = createWebGlRenderer(this)
    this.canvasContextAttributes = canvasContextAttributes
    this._webGlRenderer = webGlRenderer
    return webGlRenderer
  }

  startAnimation () {
    if (this.animationFrameRequestId) return
    this.animationFrameRequestIsStopped = false
    this.animationFrameRequestId = window.requestAnimationFrame((now) => {
      this.animationFrameRequestId = 0
      if (!this.animationFrameRequestIsStopped) {
        this.startAnimation()

        ++this.frameNo
        this.now = now / 1000.0 // seconds
        this.timeFrameOffset = this.now - this._lastFrameTime
        this._lastFrameTime = this.now

        resize(this)
        const { webGlRenderer } = this
        webGlRenderer.setViewport(0, 0, this.width, this.height)
        webGlRenderer.renderFrame(() => {
          this.renderFrame(this, webGlRenderer)
        })
      }
    })
  }

  stopAnimation () {
    this.animationFrameRequestIsStopped = true
    if (this.animationFrameRequestId !== 0) {
      window.cancelAnimationFrame(this.animationFrameRequestId)
      this.animationFrameRequestId = 0
    }
  }

  /** @private */
  connectedCallback () {
    if (this.firstTimeConnected) {
      this.firstTimeConnected = false
      this.appendChild(this.canvas)
    }
    resize(this)
    this.startAnimation()
  }

  /** @private */
  disconnectedCallback () {
    this.stopAnimation()
  }
}
<commit_msg>cleanup code<commit_after>import { defineHiddenPropertiesRW } from 'picimo/utils'

import EntityElement from '../EntityElement'

import createWebGlRenderer from './createWebGlRenderer'
import resize from './resize'

export default class CanvasElement extends EntityElement {
  /** @ignore */
  constructor (_) {
    const self = super(_)

    self.now = 0
    self.frameNo = 0
    self.animationFrameRequestId = 0
    self.animationFrameRequestIsStopped = false

    defineHiddenPropertiesRW(self, {
      _webGlRenderer: null,
      _clearColor: undefined,
      _lastFrameTime: 0
    })

    self.canvas = document.createElement('canvas')
    self.firstTimeConnected = true
    resize(self)

    return self
  }

  get webGlRenderer () {
    const renderer = this._webGlRenderer
    if (renderer) return renderer
    const { webGlRenderer, canvasContextAttributes } = createWebGlRenderer(this)
    this.canvasContextAttributes = canvasContextAttributes
    this._webGlRenderer = webGlRenderer
    return webGlRenderer
  }

  startAnimation () {
    if (this.animationFrameRequestId) return
    this.animationFrameRequestIsStopped = false
    this.animationFrameRequestId = window.requestAnimationFrame((now) => {
      this.animationFrameRequestId = 0
      if (!this.animationFrameRequestIsStopped) {
        this.startAnimation()

        ++this.frameNo
        this.now = now / 1000.0 // seconds
        this.timeFrameOffset = this.now - this._lastFrameTime
        this._lastFrameTime = this.now

        resize(this)
        const { webGlRenderer } = this
        webGlRenderer.setViewport(0, 0, this.width, this.height)
        webGlRenderer.renderFrame(() => {
          this.renderFrame(this, webGlRenderer)
        })
      }
    })
  }

  stopAnimation () {
    this.animationFrameRequestIsStopped = true
    if (this.animationFrameRequestId !== 0) {
      window.cancelAnimationFrame(this.animationFrameRequestId)
      this.animationFrameRequestId = 0
    }
  }

  /** @private */
  connectedCallback () {
    if (this.firstTimeConnected) {
      this.firstTimeConnected = false
      this.appendChild(this.canvas)
    }
    resize(this)
    this.startAnimation()
  }

  /** @private */
  disconnectedCallback () {
    this.stopAnimation()
  }
}
<|endoftext|>


<commit_before>'use strict';

angular.module('firebase', []).value('Firebase', Firebase);

// Implicit syncing. angularFire binds a model to $scope and keeps the dat
// synchronized with a Firebase location both ways.
// TODO: Optimize to use child events instead of whole 'value'.
angular.module('firebase').factory('angularFire', function($q) {
  return function(url, scope, name) {
    var af = new AngularFire($q, url);
    return af.associate(scope, name);
  };
});

function AngularFire($q, url) {
  this._q = $q;
  this._initial = true;
  this._remoteValue = false;
  this._fRef = new Firebase(url);
}
AngularFire.prototype = {
  associate: function($scope, name, ret) {
    var self = this;
    if (!ret) {
      ret = [];
    }
    var deferred = this._q.defer();
    this._fRef.on('value', function(snap) {
      var resolve = false;
      if (deferred) {
        resolve = deferred;
        deferred = false;
      }
      self._remoteValue = ret;
      if (snap && snap.val()) {
        var val = snap.val();
        if (typeof val != typeof ret) {
          self._fRef.set(null);
          return;
        }
        // Also distinguish between objects and arrays.
        var check = Object.prototype.toString;
        if (check.call(ret) != check.call(val)) {
          self._fRef.set(null);
          return;
        }
        self._remoteValue = angular.copy(val);
        if (angular.equals(val, $scope[name])) {
          return;
        }
      }
      self._safeApply($scope,
        self._resolve.bind(self, $scope, name, resolve, self._remoteValue));
    });
    return deferred.promise;
  },
  _resolve: function($scope, name, deferred, val) {
    $scope[name] = angular.copy(val);
    this._remoteValue = angular.copy(val);
    if (deferred) {
      deferred.resolve(val);
      this._watch($scope, name);
    }
  },
  _watch: function($scope, name) {
    // Watch for local changes.
    var self = this;
    $scope.$watch(name, function() {
      if (self._initial) {
        self._initial = false;
        return;
      }
      var val = JSON.parse(angular.toJson($scope[name]));
      if (angular.equals(val, self._remoteValue)) {
        return;
      }
      self._fRef.set(val);
    }, true);
  },
  _safeApply: function($scope, fn) {
    var phase = $scope.$root.$$phase;
    if (phase == '$apply' || phase == '$digest') {
      fn();
    } else {
      $scope.$apply(fn);
    }
  }
};

// Explicit syncing. Provides a collection object you can modify.
// Original code by @petebacondarwin, from:
// https://github.com/petebacondarwin/angular-firebase/blob/master/ng-firebase-collection.js
angular.module('firebase').factory('angularFireCollection', function($timeout) {
  function angularFireItem(ref, index) {
    this.$ref = ref.ref();
    this.$id = ref.name();
    this.$index = index;
    angular.extend(this, ref.val());
  }

  return function(collectionUrl, initialCb) {
    var collection = [];
    var indexes = {};
    var collectionRef = new Firebase(collectionUrl);

    function getIndex(prevId) {
      return prevId ? indexes[prevId] + 1 : 0;
    }

    function addChild(index, item) {
      indexes[item.$id] = index;
      collection.splice(index, 0, item);
    }

    function removeChild(id) {
      var index = indexes[id];
      // Remove the item from the collection.
      collection.splice(index, 1);
      indexes[id] = undefined;
    }

    function updateChild (index, item) {
      collection[index] = item;
    }

    function moveChild (from, to, item) {
      collection.splice(from, 1);
      collection.splice(to, 0, item);
      updateIndexes(from, to);
    }

    function updateIndexes(from, to) {
      var length = collection.length;
      to = to || length;
      if (to > length) {
        to = length;
      }
      for (var index = from; index < to; index++) {
        var item = collection[index];
        item.$index = indexes[item.$id] = index;
      }
    }

    if (initialCb && typeof initialCb == 'function') {
      collectionRef.once('value', initialCb);
    }

    collectionRef.on('child_added', function(data, prevId) {
      $timeout(function() {
        var index = getIndex(prevId);
        addChild(index, new angularFireItem(data, index));
        updateIndexes(index);
      });
    });

    collectionRef.on('child_removed', function(data) {
      $timeout(function() {
        var id = data.name();
        removeChild(id);
        updateIndexes(indexes[id]);
      });
    });

    collectionRef.on('child_changed', function(data, prevId) {
      $timeout(function() {
        var index = indexes[data.name()];
        var newIndex = getIndex(prevId);
        var item = new angularFireItem(data, index);

        updateChild(index, item);
        if (newIndex !== index) {
          moveChild(index, newIndex, item);
        }
      });
    });

    collectionRef.on('child_moved', function(ref, prevId) {
      $timeout(function() {
        var oldIndex = indexes[ref.name()];
        var newIndex = getIndex(prevId);
        var item = collection[oldIndex];
        moveChild(oldIndex, newIndex, item);
      });
    });

    collection.add = function(item, cb) {
      collectionRef.push(item, cb ? cb : null);
    };
    collection.remove = function(itemOrId) {
      var item = angular.isString(itemOrId) ? collection[itemOrId] : itemOrId;
      item.$ref.remove();
    };

    collection.update = function(itemOrId) {
      var item = angular.isString(itemOrId) ? collection[itemOrId] : itemOrId;
      var copy = {};
      angular.forEach(item, function(value, key) {
        if (key.indexOf('$') !== 0) {
          copy[key] = value;
        }
      });
      item.$ref.set(copy);
    };

    return collection;
  };
});
<commit_msg>Account for the 4th argument of angularFire()<commit_after>'use strict';

angular.module('firebase', []).value('Firebase', Firebase);

// Implicit syncing. angularFire binds a model to $scope and keeps the dat
// synchronized with a Firebase location both ways.
// TODO: Optimize to use child events instead of whole 'value'.
angular.module('firebase').factory('angularFire', function($q) {
  return function(url, scope, name, ret) {
    var af = new AngularFire($q, url);
    return af.associate(scope, name, ret);
  };
});

function AngularFire($q, url) {
  this._q = $q;
  this._initial = true;
  this._remoteValue = false;
  this._fRef = new Firebase(url);
}
AngularFire.prototype = {
  associate: function($scope, name, ret) {
    var self = this;
    if (!ret) {
      ret = [];
    }
    var deferred = this._q.defer();
    this._fRef.on('value', function(snap) {
      var resolve = false;
      if (deferred) {
        resolve = deferred;
        deferred = false;
      }
      self._remoteValue = ret;
      if (snap && snap.val()) {
        var val = snap.val();
        if (typeof val != typeof ret) {
          self._fRef.set(null);
          return;
        }
        // Also distinguish between objects and arrays.
        var check = Object.prototype.toString;
        if (check.call(ret) != check.call(val)) {
          self._fRef.set(null);
          return;
        }
        self._remoteValue = angular.copy(val);
        if (angular.equals(val, $scope[name])) {
          return;
        }
      }
      self._safeApply($scope,
        self._resolve.bind(self, $scope, name, resolve, self._remoteValue));
    });
    return deferred.promise;
  },
  _resolve: function($scope, name, deferred, val) {
    $scope[name] = angular.copy(val);
    this._remoteValue = angular.copy(val);
    if (deferred) {
      deferred.resolve(val);
      this._watch($scope, name);
    }
  },
  _watch: function($scope, name) {
    // Watch for local changes.
    var self = this;
    $scope.$watch(name, function() {
      if (self._initial) {
        self._initial = false;
        return;
      }
      var val = JSON.parse(angular.toJson($scope[name]));
      if (angular.equals(val, self._remoteValue)) {
        return;
      }
      self._fRef.set(val);
    }, true);
  },
  _safeApply: function($scope, fn) {
    var phase = $scope.$root.$$phase;
    if (phase == '$apply' || phase == '$digest') {
      fn();
    } else {
      $scope.$apply(fn);
    }
  }
};

// Explicit syncing. Provides a collection object you can modify.
// Original code by @petebacondarwin, from:
// https://github.com/petebacondarwin/angular-firebase/blob/master/ng-firebase-collection.js
angular.module('firebase').factory('angularFireCollection', function($timeout) {
  function angularFireItem(ref, index) {
    this.$ref = ref.ref();
    this.$id = ref.name();
    this.$index = index;
    angular.extend(this, ref.val());
  }

  return function(collectionUrl, initialCb) {
    var collection = [];
    var indexes = {};
    var collectionRef = new Firebase(collectionUrl);

    function getIndex(prevId) {
      return prevId ? indexes[prevId] + 1 : 0;
    }

    function addChild(index, item) {
      indexes[item.$id] = index;
      collection.splice(index, 0, item);
    }

    function removeChild(id) {
      var index = indexes[id];
      // Remove the item from the collection.
      collection.splice(index, 1);
      indexes[id] = undefined;
    }

    function updateChild (index, item) {
      collection[index] = item;
    }

    function moveChild (from, to, item) {
      collection.splice(from, 1);
      collection.splice(to, 0, item);
      updateIndexes(from, to);
    }

    function updateIndexes(from, to) {
      var length = collection.length;
      to = to || length;
      if (to > length) {
        to = length;
      }
      for (var index = from; index < to; index++) {
        var item = collection[index];
        item.$index = indexes[item.$id] = index;
      }
    }

    if (initialCb && typeof initialCb == 'function') {
      collectionRef.once('value', initialCb);
    }

    collectionRef.on('child_added', function(data, prevId) {
      $timeout(function() {
        var index = getIndex(prevId);
        addChild(index, new angularFireItem(data, index));
        updateIndexes(index);
      });
    });

    collectionRef.on('child_removed', function(data) {
      $timeout(function() {
        var id = data.name();
        removeChild(id);
        updateIndexes(indexes[id]);
      });
    });

    collectionRef.on('child_changed', function(data, prevId) {
      $timeout(function() {
        var index = indexes[data.name()];
        var newIndex = getIndex(prevId);
        var item = new angularFireItem(data, index);

        updateChild(index, item);
        if (newIndex !== index) {
          moveChild(index, newIndex, item);
        }
      });
    });

    collectionRef.on('child_moved', function(ref, prevId) {
      $timeout(function() {
        var oldIndex = indexes[ref.name()];
        var newIndex = getIndex(prevId);
        var item = collection[oldIndex];
        moveChild(oldIndex, newIndex, item);
      });
    });

    collection.add = function(item, cb) {
      collectionRef.push(item, cb ? cb : null);
    };
    collection.remove = function(itemOrId) {
      var item = angular.isString(itemOrId) ? collection[itemOrId] : itemOrId;
      item.$ref.remove();
    };

    collection.update = function(itemOrId) {
      var item = angular.isString(itemOrId) ? collection[itemOrId] : itemOrId;
      var copy = {};
      angular.forEach(item, function(value, key) {
        if (key.indexOf('$') !== 0) {
          copy[key] = value;
        }
      });
      item.$ref.set(copy);
    };

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


<commit_before>'use strict';

var glob  = require('glob');
var grunt;

try {
    grunt = require('grunt');
} catch (e) {
    try {
        grunt = require(process.cwd() + '/node_modules/grunt/lib/grunt');
    } catch (e) {
        process.send({ msg: 'error', data: 'Unable to find grunt, please install it locally or globally' });
        process.exit(1);
    }
}

var npmTasks,
    keepAliveTimeout = Number(process.argv[2]),
    keepAliveTimeoutId,
    exit = process.exit,
    running = false;

// function to reset the keep alive timeout
// once a keep alive message from the parent is received
function resetKeepAlive() {
    if (keepAliveTimeoutId) {
        clearTimeout(keepAliveTimeoutId);
    }

    keepAliveTimeoutId = setTimeout(function () {
        exit.call(process, 1);
    }, keepAliveTimeout);
}

// auto-load npm tasks
npmTasks = glob.sync('./grunt-*', { cwd: 'node_modules', mark : true });
npmTasks.forEach(function (npmTask) {
    if (/[\/\\]$/.test(npmTask)) {
        grunt.loadNpmTasks(npmTask.slice(2, -1));
    }
});

// auto-load local tasks
grunt.loadTasks('./tasks');

// handle parent messages
process.on('message', function (data) {
    // run message arrived?
    if (data.msg === 'run') {
        if (running) {
            return process.send({ msg: 'error', data: 'Another task is already running' });
        }

        var task = data.task,
            initConfig = {},
            gruntConfig = task.config || {},
            taskDef;

        // prepare the config
        task.opts = task.opts || {};
        gruntConfig.config = __dirname + '/gruntfile';
        gruntConfig.base = gruntConfig.base || process.cwd();
        if (typeof gruntConfig.tasks === 'string') {  // attempt to fix bad usage of tasks option
            gruntConfig.tasks = [gruntConfig.tasks];
        }

        // force grunt to initialize and load tasks specified in the "tasks" config
        grunt.option.init(gruntConfig);
        grunt.task.init([]);

        // check if the task is loaded
        taskDef = grunt.task._tasks[task.name];
        if (!taskDef) {
            return process.send({ msg: 'end', error: 'Task "' + task.name + '" not loaded, specify its directory in the "tasks" grunt config' });
        }

        // set task options in the init config
        initConfig[task.name] = taskDef.multi ? { automaton: task.opts } : task.opts;

        // run the task using grunt
        running = true;
        grunt.initConfig(initConfig);
        grunt.tasks([task.name], gruntConfig, function () {
            running = false;
            process.send({ msg: 'end' });
        });
    // keep alive message arrive?
    } else if (data.msg === 'keep-alive') {
        resetKeepAlive();
    }
});

// do some monkey patching because grunt calls process.exit()
// as long as nodejs allows to monkey patch process.exit, the code bellow is valid
// otherwise we would need to monkey patch grunt.fail in order to prevent calls to process.exit()
process.stdout.write = function (str) {
    process.send({ msg: 'log', data: str });
};
process.exit = function (code) {
    var err;

    if (code) {
        running = false;
        // throw an error to kill the call stack
        // this is needed because code bellow `process.exit` cannot be run
        // note that this error will be uncaught bellow with process.on('uncaughtException')
        err = new Error('end');
        err.code = code;
        throw err;
    }

    exit.call(process);
};
process.on('uncaughtException', function (err) {
    var wasRunning = running;
    running = false;

    // caught self thrown exceptions and inform the parent
    if (err.message === 'end') {
        process.send({ msg: 'end', error: 'Failed to run grunt task' });
    // otherwise its some other exception
    } else {
        if (wasRunning) {
            process.send({ msg: 'end', error: 'Failed to run grunt task: ' + err.message });
        } else {
            process.send({ msg: 'error', data: err.message });
        }
    }
});

// inform that the worker is ready!
process.nextTick(function () {
    resetKeepAlive();
    process.send({ msg: 'inited' });
});<commit_msg>Fix small bug in the grunt worker.<commit_after>'use strict';

var glob  = require('glob');
var grunt;

try {
    grunt = require('grunt');
} catch (e) {
    try {
        grunt = require(process.cwd() + '/node_modules/grunt/lib/grunt');
    } catch (e) {
        process.send({ msg: 'error', data: 'Unable to find grunt, please install it locally or globally' });
        process.exit(1);
    }
}

var npmTasks,
    keepAliveTimeout = Number(process.argv[2]),
    keepAliveTimeoutId,
    exit = process.exit,
    running = false;

// function to reset the keep alive timeout
// once a keep alive message from the parent is received
function resetKeepAlive() {
    if (keepAliveTimeoutId) {
        clearTimeout(keepAliveTimeoutId);
    }

    keepAliveTimeoutId = setTimeout(function () {
        exit.call(process, 1);
    }, keepAliveTimeout);
}

// auto-load npm tasks
npmTasks = glob.sync('./grunt-*', { cwd: 'node_modules', mark : true });
npmTasks.forEach(function (npmTask) {
    if (/[\/\\]$/.test(npmTask)) {
        grunt.loadNpmTasks(npmTask.slice(2, -1));
    }
});

// auto-load local tasks
grunt.loadTasks('./tasks');

// handle parent messages
process.on('message', function (data) {
    // run message arrived?
    if (data.msg === 'run') {
        if (running) {
            return process.send({ msg: 'error', data: 'Another task is already running' });
        }

        var task = data.task,
            initConfig = {},
            gruntConfig = task.config || {},
            taskDef;

        // prepare the config
        task.opts = task.opts || {};
        gruntConfig.config = __dirname + '/gruntfile';
        gruntConfig.base = gruntConfig.base || process.cwd();
        if (typeof gruntConfig.tasks === 'string') {  // attempt to fix bad usage of tasks option
            gruntConfig.tasks = [gruntConfig.tasks];
        }

        // force grunt to initialize and load tasks specified in the "tasks" config
        grunt.option.init(gruntConfig);
        grunt.task.init([]);

        // check if the task is loaded
        taskDef = grunt.task._tasks[task.name];
        if (!taskDef) {
            return process.send({ msg: 'end', error: 'Task "' + task.name + '" not loaded, specify its directory in the "tasks" grunt config' });
        }

        // set task options in the init config
        initConfig[task.name] = taskDef.multi ? { automaton: task.opts } : task.opts;

        // run the task using grunt
        running = true;
        grunt.initConfig(initConfig);
        grunt.tasks([task.name], gruntConfig, function () {
            running = false;
            process.send({ msg: 'end' });
        });
    // keep alive message arrive?
    } else if (data.msg === 'keep-alive') {
        resetKeepAlive();
    }
});

// do some monkey patching because grunt calls process.exit()
// as long as nodejs allows to monkey patch process.exit, the code bellow is valid
// otherwise we would need to monkey patch grunt.fail in order to prevent calls to process.exit()
process.stdout.write = function (str) {
    process.send({ msg: 'log', data: str });
};
process.exit = function (code) {
    if (code) {
        running = false;
        // throw an error to kill the call stack
        // this is needed because code bellow `process.exit` cannot be run
        // note that this error will be uncaught bellow with process.on('uncaughtException')
        throw new Error('automaton_task_failed');
    }

    exit.call(process);
};
process.on('uncaughtException', function (err) {
    var wasRunning = running;
    running = false;

    // caught self thrown exceptions and inform the parent
    if (err.message === 'automaton_task_failed') {
        process.send({ msg: 'end', error: 'Failed to run grunt task' });
    // otherwise its some other exception
    } else {
        if (wasRunning) {
            process.send({ msg: 'end', error: 'Failed to run grunt task: ' + err.message });
        } else {
            process.send({ msg: 'error', data: err.message });
        }
    }
});

// inform that the worker is ready!
process.nextTick(function () {
    resetKeepAlive();
    process.send({ msg: 'inited' });
});<|endoftext|>


<commit_before>import Http from '../services/Http';

export const state = () => ({
    user: null,
    profile: null,
    stats: null,
    count: 0,
    activities: [],
    linkedAccounts: [],
});

export const getters = {
    userCount(state) {
        return state.count;
    },

    isCompetitor({ profile, linkedAccounts }) {
        if (!profile) return false;

        const { firstName, lastName, country, skills } = profile;
        if ((!firstName, !lastName, !country, !skills)) return false;

        if (linkedAccounts.length <= 0) return false;

        const discordAccount = linkedAccounts.find((account) => account.provider === 'DISCORD');
        if (!discordAccount) return false;

        return true;
    },

    getDiscord({ linkedAccounts }) {
        return linkedAccounts.find((account) => account.provider === 'DISCORD');
    },
};

export const mutations = {
    user(state, user) {
        state.user = user;
    },

    profile(state, profile) {
        state.profile = profile;
    },

    activities(state, activities) {
        state.activities = activities;
    },

    profileUpdate(state, { key, values }) {
        state.profile[key] = values;
    },

    stats(state, stats) {
        state.stats = stats;
    },

    count(state, count) {
        state.count = count;
    },

    linkedAccounts(state, accounts) {
        state.linkedAccounts = accounts;
    },

    removeLinkedAccount(state, provider) {
        state.linkedAccounts = state.linkedAccounts.filter((it) => it.provider !== provider);
    },
};

export const actions = {
    async refresh({ commit, dispatch }) {
        try {
            const user = await Http.for('auth/user').get();

            commit('user', user);

            await dispatch('profile');
            await dispatch('stats');
            await dispatch('linkedAccounts');
            await dispatch('activities');
        } catch (e) {
            commit('user', null);
        }
    },

    async activities({ commit }) {
        try {
            const activities = await Http.for('activities/mine').get();

            commit('activities', activities);
        } catch (e) {
            console.log(e);
            commit('user', null);
        }
    },

    async profile({ commit, state }) {
        try {
            const profile = await Http.for(`/users/${state.user.id}/profile`).get();
            commit('profile', profile);
        } catch (e) {
            commit('user', null);
        }
    },

    async stats({ commit, state }) {
        try {
            const stats = await Http.for(`/users/${state.user.id}/stats`).get();

            commit('stats', stats);
        } catch (e) {
            commit('user', null);
        }
    },

    async refreshUserCount({ commit }) {
        const data = await Http.for('leaderboards').get('users');

        commit('count', data.count);
    },

    async login({ commit, dispatch }, { username, password }) {
        try {
            await Http.for('auth').post('login', {
                identifier: username,
                password,
            });

            await dispatch('refresh');

            dispatch('toast/add', { type: 'success', message: 'Welcome back to DevWars!' }, { root: true });

            await dispatch('nuxtServerInit', null, { root: true });

            dispatch('navigate', '/dashboard', { root: true });
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });

            commit('user', null);
        }
    },

    async register({ dispatch }, registration) {
        try {
            await this.$axios.post('/auth/register', registration);

            await dispatch('refresh');

            dispatch('toast/add', { type: 'success', message: 'Welcome to DevWars!' }, { root: true });

            await dispatch('nuxtServerInit', null, { root: true });

            dispatch('navigate', '/dashboard', { root: true });
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async logout({ commit, dispatch }) {
        await Http.for('auth').post('logout');

        await dispatch('navigate', '/', { root: true });

        commit('user', null);
    },

    async settings({ commit, dispatch, state }) {
        try {
            const user = await this.$axios.patch(`users/${state.user.id}/profile`, state.profile);

            commit('user', user);
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async password({ dispatch }, data) {
        try {
            await Http.for(`auth/reset/password`).put(data);

            dispatch('toast/success', `We've updated your password!`, {
                root: true,
            });
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async email({ dispatch, commit }, data) {
        try {
            const user = await Http.for('auth/reset/email').post('email', data);

            commit('user', user);

            await dispatch('toast/success', `We've updated your email, please go verify your email.`, { root: true });
            await dispatch('navigate', '/pending', { root: true });
        } catch (e) {
            console.error(e);
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async forgot({ dispatch }, email) {
        try {
            await Http.for('auth/forgot/password').save({ username_or_email: email });

            dispatch('toast/success', `Check your email for a guide to reset your password.`, { root: true });

            return true;
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });

            return false;
        }
    },

    async resetByToken({ dispatch }, data) {
        await Http.for('auth/reset/password').post({}, data);

        dispatch('toast/success', `We've updated your password, give it a go!`, { root: true });
    },

    async avatar({ dispatch, state }, data) {
        const formData = new FormData();
        formData.append('avatar', data, 'avatar.jpg');

        await Http.axios({
            url: `/users/${state.user.id}/avatar`,
            method: 'PUT',
            data: formData,
            noTransform: true,
        });

        await dispatch('refresh');
    },

    async linkedAccounts({ commit }) {
        const req = await this.$axios.get(`/oauth`);
        const accounts = req.data;

        commit('linkedAccounts', accounts);

        return accounts;
    },

    async connectLinkedAccount({ dispatch, commit }, provider) {
        await this.$axios.get(`/oauth/${provider}`);

        commit('connectLinkedAccount', provider);

        await dispatch('refresh');
    },

    async disconnectLinkedAccount({ dispatch, commit }, provider) {
        await this.$axios.delete(`/oauth/${provider}`);

        commit('removeLinkedAccount', provider);

        await dispatch('refresh');
    },
};
<commit_msg>fix(profile): When saving, update the profile and not the user, ensuring that its the data object.<commit_after>import Http from '../services/Http';

export const state = () => ({
    user: null,
    profile: null,
    stats: null,
    count: 0,
    activities: [],
    linkedAccounts: [],
});

export const getters = {
    userCount(state) {
        return state.count;
    },

    isCompetitor({ profile, linkedAccounts }) {
        if (!profile) return false;

        const { firstName, lastName, country, skills } = profile;
        if ((!firstName, !lastName, !country, !skills)) return false;

        if (linkedAccounts.length <= 0) return false;

        const discordAccount = linkedAccounts.find((account) => account.provider === 'DISCORD');
        if (!discordAccount) return false;

        return true;
    },

    getDiscord({ linkedAccounts }) {
        return linkedAccounts.find((account) => account.provider === 'DISCORD');
    },
};

export const mutations = {
    user(state, user) {
        state.user = user;
    },

    profile(state, profile) {
        state.profile = profile;
    },

    activities(state, activities) {
        state.activities = activities;
    },

    profileUpdate(state, { key, values }) {
        state.profile[key] = values;
    },

    stats(state, stats) {
        state.stats = stats;
    },

    count(state, count) {
        state.count = count;
    },

    linkedAccounts(state, accounts) {
        state.linkedAccounts = accounts;
    },

    removeLinkedAccount(state, provider) {
        state.linkedAccounts = state.linkedAccounts.filter((it) => it.provider !== provider);
    },
};

export const actions = {
    async refresh({ commit, dispatch }) {
        try {
            const user = await Http.for('auth/user').get();

            commit('user', user);

            await dispatch('profile');
            await dispatch('stats');
            await dispatch('linkedAccounts');
            await dispatch('activities');
        } catch (e) {
            commit('user', null);
        }
    },

    async activities({ commit }) {
        try {
            const activities = await Http.for('activities/mine').get();

            commit('activities', activities);
        } catch (e) {
            console.log(e);
            commit('user', null);
        }
    },

    async profile({ commit, state }) {
        try {
            const profile = await Http.for(`/users/${state.user.id}/profile`).get();
            commit('profile', profile);
        } catch (e) {
            commit('user', null);
        }
    },

    async stats({ commit, state }) {
        try {
            const stats = await Http.for(`/users/${state.user.id}/stats`).get();

            commit('stats', stats);
        } catch (e) {
            commit('user', null);
        }
    },

    async refreshUserCount({ commit }) {
        const data = await Http.for('leaderboards').get('users');

        commit('count', data.count);
    },

    async login({ commit, dispatch }, { username, password }) {
        try {
            await Http.for('auth').post('login', {
                identifier: username,
                password,
            });

            await dispatch('refresh');

            dispatch('toast/add', { type: 'success', message: 'Welcome back to DevWars!' }, { root: true });

            await dispatch('nuxtServerInit', null, { root: true });

            dispatch('navigate', '/dashboard', { root: true });
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });

            commit('user', null);
        }
    },

    async register({ dispatch }, registration) {
        try {
            await this.$axios.post('/auth/register', registration);

            await dispatch('refresh');

            dispatch('toast/add', { type: 'success', message: 'Welcome to DevWars!' }, { root: true });

            await dispatch('nuxtServerInit', null, { root: true });

            dispatch('navigate', '/dashboard', { root: true });
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async logout({ commit, dispatch }) {
        await Http.for('auth').post('logout');

        await dispatch('navigate', '/', { root: true });

        commit('user', null);
    },

    async settings({ commit, dispatch, state }) {
        try {
            const profile = await this.$axios.patch(`users/${state.user.id}/profile`, state.profile);
            commit('profile', profile.data);
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async password({ dispatch }, data) {
        try {
            await Http.for(`auth/reset/password`).put(data);

            dispatch('toast/success', `We've updated your password!`, {
                root: true,
            });
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async email({ dispatch, commit }, data) {
        try {
            const user = await Http.for('auth/reset/email').post('email', data);

            commit('user', user);

            await dispatch('toast/success', `We've updated your email, please go verify your email.`, { root: true });
            await dispatch('navigate', '/pending', { root: true });
        } catch (e) {
            console.error(e);
            dispatch('toast/error', e.response.data, { root: true });
        }
    },

    async forgot({ dispatch }, email) {
        try {
            await Http.for('auth/forgot/password').save({ username_or_email: email });

            dispatch('toast/success', `Check your email for a guide to reset your password.`, { root: true });

            return true;
        } catch (e) {
            dispatch('toast/error', e.response.data, { root: true });

            return false;
        }
    },

    async resetByToken({ dispatch }, data) {
        await Http.for('auth/reset/password').post({}, data);

        dispatch('toast/success', `We've updated your password, give it a go!`, { root: true });
    },

    async avatar({ dispatch, state }, data) {
        const formData = new FormData();
        formData.append('avatar', data, 'avatar.jpg');

        await Http.axios({
            url: `/users/${state.user.id}/avatar`,
            method: 'PUT',
            data: formData,
            noTransform: true,
        });

        await dispatch('refresh');
    },

    async linkedAccounts({ commit }) {
        const req = await this.$axios.get(`/oauth`);
        const accounts = req.data;

        commit('linkedAccounts', accounts);

        return accounts;
    },

    async connectLinkedAccount({ dispatch, commit }, provider) {
        await this.$axios.get(`/oauth/${provider}`);

        commit('connectLinkedAccount', provider);

        await dispatch('refresh');
    },

    async disconnectLinkedAccount({ dispatch, commit }, provider) {
        await this.$axios.delete(`/oauth/${provider}`);

        commit('removeLinkedAccount', provider);

        await dispatch('refresh');
    },
};
<|endoftext|>


<commit_before>var jsdom = require('jsdom');
var req = require('request');
var _ = require('lodash');
var jquery = require('../dongnelibrary_util').getJqueryString();
var getLibraryNames = require('../dongnelibrary_util.js').getLibraryNames;
var global = {};

var libraryList = [
  {code: 'MA', name: '남양도서관'},
  {code: 'MB', name: '태안도서관'},
  {code: 'MC', name: '삼괴도서관'},
  {code: 'MD', name: '병점도서관'},
  {code: 'ME', name: '샘내작은도서관'},
  {code: 'MF', name: '두빛나래어린이도서관'},
  {code: 'MG', name: '봉담도서관'},
  {code: 'MH', name: '둥지나래어린이도서관'},
  {code: 'MJ', name: '기아행복마루도서관'},
  {code: 'MK', name: '동탄복합문화센터도서관'},
  {code: 'ML', name: '송산도서관'},
  {code: 'MM', name: '정남도서관'}
];

function getLibraryCode(libraryName) {
  var found = _.find(libraryList, function (lib) {
    return lib.name === libraryName;
  });

  if (found) {
    return found.code;
  }
  return '';
}

function exist(str) {
  return !(str === '관외대출자료');
}

function makeJsdomCallback(libraryName, getBook) {
  return function(errors, window) {
    var booklist = [];
    var $ = window.$;
    var $a = $('#wrap > div.data_type5.mb15 > form > table > tbody > tr');
    _.each($a, function (value) {
      var $value = $(value);
      booklist.push({
        libraryName: libraryName,
        title: $value.find('td:nth-child(2) > a').text().trim(),
        exist: exist($value.find('td:nth-child(8)').text().trim())
      });
    });
    if (getBook) {
      getBook(null, {
        totalBookCount: booklist.length,
        booklist: booklist
      });
    }
    window.close();
  }
}

function search(opt, getBook) {
  var title = '';
  var libraryName = '';

  if (opt.debug) {
    global.debug = true;
  }

  if (opt.title) {
    title = opt.title;
  } else {
    if (getBook) {
      getBook({msg: 'Need a book name'});
    }
    return;
  }

  if (opt.libraryName) {
    libraryName = opt.libraryName;
  } else {
    if (getBook) {
      getBook({msg: 'Need a library name'});
    }
    return;
  }

  req.post({
    url: 'http://www.hscitylib.or.kr/UnitySearch/unity_library_result.do',
    timeout: 20000,
    headers: {
      "User-Agent": 'User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36'
    },
    form: {
      beforequery: "IAL:" + title + "*",
      sort: 'RK DESC',
      mgc: getLibraryCode(libraryName),
      jongbook: "_book",
      historycount: "0",
      startpage: "1",
      limitpage: "100",
      mode: '0'
    }
  }, function (err, res, body) {
    if (global.debug === true) {
      console.log(body);
    }
    if (err || (res && res.statusCode !== 200)) {
      var msg = '';

      if (err) {
        msg = err;
      }

      if (res && res.statusCode) {
        msg = msg + " " + res.statusCode;
      }

      if (getBook) {
        getBook({msg: msg});
      }
    } else {
      jsdom.env({
        html: body,
        src: [jquery],
        done: makeJsdomCallback(libraryName, getBook)
      });
    }
  }
  );
}

module.exports = {
  search: search,
  getLibraryNames: function() {
    return getLibraryNames(libraryList);
  }
};
<commit_msg>update search style for hscity<commit_after>var jsdom = require('jsdom');
var req = require('request');
var _ = require('lodash');
var jquery = require('../dongnelibrary_util').getJqueryString();
var getLibraryNames = require('../dongnelibrary_util.js').getLibraryNames;
var global = {};

var libraryList = [
  {code: 'MA', name: '남양도서관'},
  {code: 'MB', name: '태안도서관'},
  {code: 'MC', name: '삼괴도서관'},
  {code: 'MD', name: '병점도서관'},
  {code: 'ME', name: '샘내작은도서관'},
  {code: 'MF', name: '두빛나래어린이도서관'},
  {code: 'MG', name: '봉담도서관'},
  {code: 'MH', name: '둥지나래어린이도서관'},
  {code: 'MJ', name: '기아행복마루도서관'},
  {code: 'MK', name: '동탄복합문화센터도서관'},
  {code: 'ML', name: '송산도서관'},
  {code: 'MM', name: '정남도서관'}
];

function getLibraryCode(libraryName) {
  var found = _.find(libraryList, function (lib) {
    return lib.name === libraryName;
  });

  if (found) {
    return found.code;
  }
  return '';
}

function isRented(str) {
  return !~str.indexOf('대출가능');
}

function makeJsdomCallback(libraryName, getBook) {
  return function(errors, window) {
    var booklist = [];
    var $ = window.$;
    var $a = $('.booklist > li');
    _.each($a, function (value) {
      var $value = $(value);
      booklist.push({
        libraryName: libraryName,
        title: $value.find('ul > li > dl > dt > a').text().trim(),
        exist: !isRented($value.find('ul > li > dl > dd > span').text().trim())
      });
    });
    if (getBook) {
      getBook(null, {
        totalBookCount: booklist.length,
        booklist: booklist
      });
    }
    window.close();
  }
}

function search(opt, getBook) {
  var title = '';
  var libraryName = '';

  if (opt.debug) {
    global.debug = true;
  }

  if (opt.title) {
    title = opt.title;
  } else {
    if (getBook) {
      getBook({msg: 'Need a book name'});
    }
    return;
  }

  if (opt.libraryName) {
    libraryName = opt.libraryName;
  } else {
    if (getBook) {
      getBook({msg: 'Need a library name'});
    }
    return;
  }

  req.post({
    url: 'http://hscitylib.or.kr/kolaseek/booksearch/plusSearchResultList.do',
    timeout: 20000,
    headers: {
      "User-Agent": 'User-Agent:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36'
    },
    form: {
      searchType: 'SIMPLE',
      searchCategory: 'ALL',
      currentPageNo: 1,
      viewStatus: 'IMAGE',
      preSearchKey: 'ALL',
      preSearchKeyword: 'javascript',
      searchKey: 'ALL',
      searchKeyword: 'javascript',
      searchLibraryArr: getLibraryCode(libraryName),
      searchSort: 'SIMILAR',
      searchOrder: 'DESC',
    }
  }, function (err, res, body) {
      console.log(body);
    if (global.debug === true) {
    }
    if (err || (res && res.statusCode !== 200)) {
      var msg = '';

      if (err) {
        msg = err;
      }

      if (res && res.statusCode) {
        msg = msg + " " + res.statusCode;
      }

      if (getBook) {
        getBook({msg: msg});
      }
    } else {
      jsdom.env({
        html: body,
        src: [jquery],
        done: makeJsdomCallback(libraryName, getBook)
      });
    }
  }
  );
}

module.exports = {
  search: search,
  getLibraryNames: function() {
    return getLibraryNames(libraryList);
  }
};
<|endoftext|>


<commit_before>/*jslint node: true*/
"use strict";

var mime = require('mime');
var fs = require('fs');
var glob = require('glob');
var path = require('path');
var $rdf = require('rdflib');
var S = require('string');
var async = require('async');

var debug = require('../logging').handlers;
var acl = require('../acl.js');
var header = require('../header.js');
var metadata = require('../metadata.js');
var ns = require('../vocab/ns.js').ns;
var utils = require('../utils.js');
var subscription = require('../subscription.js');
var HttpError = require('../http-error');

var ldpVocab = require('../vocab/ldp.js');
var turtleExtension = '.ttl';

function get(req, res, next, includeBody) {
    var ldp = req.app.locals.ldp;
    var uri = utils.uriBase(req);
    var filename = utils.uriToFilename(req.path, ldp.root);

    // Add request to subscription service
    if (req.path.slice(-ldp.suffixChanges.length) ===
        ldp.suffixChanges) {
        debug("GET -- Subscribed to " + req.originalUrl);
        return subscription.subscribeToChanges(req, res);
    }

    // Parse accept mime types into a priority (q) ordered array
    res.acceptTypes = header.negotiateContentType(req) || 'text/turtle';

    // Set headers
    res.header('MS-Author-Via', 'SPARQL');

    // Set live updates
    if (ldp.live) {
        // Note not yet in
        // http://www.iana.org/assignments/link-relations/link-relations.xhtml
        header.addLink(res, req.originalUrl + ldp.suffixChanges, 'changes');
        // res.header('Link' , '' + req.path + ldp.suffixSSE + ' ; rel=events' );
        // overwrites the pevious
        res.header('Updates-Via', req.originalUrl + ldp.suffixChanges);
    }

    if (includeBody) {
        debug('GET -- ' + req.originalUrl);
    } else {
        debug('HEAD -- ' + req.originalUrl);
    }

    // Get resource or container
    ldp.get(filename, uri, includeBody, function(err, data, container) {

        // This should be implemented in LDP.prototype.get
        if (err && err.status === 404 && glob.hasMagic(filename)) {
            debug("GET/HEAD -- Glob request");
            return globHandler(req, res, next);
        }

        if (err) {
            debug('GET/HEAD -- Read error: ' + err.status + ' ' + err.message);
            return next(err);
        }

        // Just return that file exists
        // data is of `typeof 'string'` if file is empty, but exists!
        if (data === undefined) {
            return res.sendStatus(200);
        }

        // Container/resource retrieved
        if (!container) {
            var contentType = mime.lookup(filename);
            res.set('content-type', contentType);
            debug('GET/HEAD -- content-type: ' + contentType);

            // Consider acl and meta files text/turtle
            if (path.extname(filename) === ldp.suffixAcl ||
                path.basename(filename) === turtleExtension ||
                path.basename(filename) === ldp.suffixMeta) {
                contentType = 'text/turtle';
            }

            // if data is not text/turtle, just send it
            if (contentType !== 'text/turtle') {
                return res
                    .status(200)
                    .send(data);
            }
        }

        // redirect to file browser if we got text/html with highest priority
        if (container &&
            res.acceptTypes.indexOf('text/html') === 0 &&
            ldp.skin) {
            return res.redirect(303, ldp.skin + req.protocol + '/' + req.get('host') + req.originalUrl);
        }

        // TODO this should be added as a middleware in the routes
        res.locals.turtleData = data;
        return parseLinkedData(req, res, next);
    });
}

function globHandler(req, res, next) {
    var ldp = req.app.locals.ldp;
    var filename = utils.uriToFilename(req.path, ldp.root);
    var uri = utils.uriBase(req);

    var globOptions = {
        noext: true,
        nobrace: true
    };

    glob(filename, globOptions, function(err, matches) {
        if (err || matches.length === 0) {
            debug("GET/HEAD -- No files matching the pattern");
            return next(new HttpError({
                message: "No files matching glob pattern",
                status: 404
            }));
        }

        // Matches found
        var globGraph = $rdf.graph();

        async.each(matches, function(match, done) {
            var baseUri = utils.filenameToBaseUri(match, uri, ldp.root);
            fs.readFile(match, {encoding: "utf8"}, function(err, fileData) {
                if (err) {
                    debug('GET -- Error in globHandler' + err);
                    return done(null);
                }
                aclAllow(match, req, res, function (allowed) {
                    if (!S(match).endsWith(".ttl") || !allowed) {
                        return done(null);
                    }
                    try {
                        $rdf.parse(
                            fileData,
                            globGraph,
                            baseUri,
                            'text/turtle');
                    } catch(parseErr) {
                        debug('GET -- Error in globHandler' + parseErr);
                    }
                    return done(null);
                });
            });
        }, function () {
            var data = $rdf.serialize(
                undefined,
                globGraph,
                null,
                'text/turtle');
            // TODO this should be added as a middleware in the routes
            res.locals.turtleData = data;
            return parseLinkedData(req, res, next);
        });
    });
}

function aclAllow(match, req, res, callback) {
    var ldp = req.app.locals.ldp;

    if (!ldp.webid) {
        return callback(true);
    }

    var relativePath = '/' + path.relative(ldp.root, match);
    res.locals.path = relativePath;
    acl.allow("Read", req, res, function(err) {
        callback(err);
    });
}

function parseLinkedData(req, res, next) {
    var ldp = req.app.locals.ldp;
    var filename = utils.uriToFilename(req.path, ldp.root);
    var uri = utils.uriBase(req);
    var turtleData = res.locals.turtleData;

    var accept = header.parseAcceptRDFHeader(req) || 'text/turtle';
    var baseUri = utils.filenameToBaseUri(filename, uri, ldp.root);

    // Handle Turtle Accept header
    if (accept === 'text/turtle' ||
        accept === 'text/n3' ||
        accept === 'application/turtle' ||
        accept === 'application/n3') {
        return res.status(200)
            .set('content-type', accept)
            .send(turtleData);
    }

    //Handle other file types
    var resourceGraph = $rdf.graph();
    try {
        $rdf.parse(turtleData, resourceGraph, baseUri, 'text/turtle');
    } catch (err) {

        debug("GET/HEAD -- Error parsing data: " + err.message);
        return next(new HttpError({
            message: err.message,
            status: 500
        }));
    }

    // Graph to `accept` type
    $rdf.serialize(undefined, resourceGraph, null, accept, function(err, result) {
        if (result === undefined || err) {
            debug("GET/HEAD -- Serialization error: " + err);
            return next(new HttpError({
                message: err.message,
                status: 500
            }));
        }

        return res
            .status(200)
            .set('content-type', accept)
            .send(result);
    });
}

function getHandler(req, res, next) {
    get(req, res, next, true);
}

function headHandler(req, res, next) {
    get(req, res, next, false);
}

exports.handler = getHandler;
exports.headHandler = headHandler;
<commit_msg>Register acl and meta suffixes as turtle extensions; Simplified extension check<commit_after>/*jslint node: true*/
"use strict";

var mime = require('mime');
var fs = require('fs');
var glob = require('glob');
var path = require('path');
var $rdf = require('rdflib');
var S = require('string');
var async = require('async');

var debug = require('../logging').handlers;
var acl = require('../acl.js');
var header = require('../header.js');
var metadata = require('../metadata.js');
var ns = require('../vocab/ns.js').ns;
var utils = require('../utils.js');
var subscription = require('../subscription.js');
var HttpError = require('../http-error');

var ldpVocab = require('../vocab/ldp.js');
var turtleExtensions = ['.ttl'];

function get(req, res, next, includeBody) {
    var ldp = req.app.locals.ldp;
    var uri = utils.uriBase(req);
    var filename = utils.uriToFilename(req.path, ldp.root);

    // Register acl and meta suffixes as turtle extensions
    utils.pushIfNotExist(turtleExtensions, ldp.suffixAcl);
    utils.pushIfNotExist(turtleExtensions, ldp.suffixMeta);

    // Add request to subscription service
    if (req.path.slice(-ldp.suffixChanges.length) ===
        ldp.suffixChanges) {
        debug("GET -- Subscribed to " + req.originalUrl);
        return subscription.subscribeToChanges(req, res);
    }

    // Parse accept mime types into a priority (q) ordered array
    res.acceptTypes = header.negotiateContentType(req) || 'text/turtle';

    // Set headers
    res.header('MS-Author-Via', 'SPARQL');

    // Set live updates
    if (ldp.live) {
        // Note not yet in
        // http://www.iana.org/assignments/link-relations/link-relations.xhtml
        header.addLink(res, req.originalUrl + ldp.suffixChanges, 'changes');
        // res.header('Link' , '' + req.path + ldp.suffixSSE + ' ; rel=events' );
        // overwrites the pevious
        res.header('Updates-Via', req.originalUrl + ldp.suffixChanges);
    }

    if (includeBody) {
        debug('GET -- ' + req.originalUrl);
    } else {
        debug('HEAD -- ' + req.originalUrl);
    }

    // Get resource or container
    ldp.get(filename, uri, includeBody, function(err, data, container) {

        // This should be implemented in LDP.prototype.get
        if (err && err.status === 404 && glob.hasMagic(filename)) {
            debug("GET/HEAD -- Glob request");
            return globHandler(req, res, next);
        }

        if (err) {
            debug('GET/HEAD -- Read error: ' + err.status + ' ' + err.message);
            return next(err);
        }

        // Just return that file exists
        // data is of `typeof 'string'` if file is empty, but exists!
        if (data === undefined) {
            return res.sendStatus(200);
        }

        // Container/resource retrieved
        if (!container) {
            var contentType = mime.lookup(filename);
            res.set('content-type', contentType);
            debug('GET/HEAD -- content-type: ' + contentType);

            if (utils.hasSuffix(filename, turtleExtensions)) {
                contentType = 'text/turtle';
            }

            // if data is not text/turtle, just send it
            if (contentType !== 'text/turtle') {
                return res
                    .status(200)
                    .send(data);
            }
        }

        // redirect to file browser if we got text/html with highest priority
        if (container &&
            res.acceptTypes.indexOf('text/html') === 0 &&
            ldp.skin) {
            return res.redirect(303, ldp.skin + req.protocol + '/' + req.get('host') + req.originalUrl);
        }

        // TODO this should be added as a middleware in the routes
        res.locals.turtleData = data;
        return parseLinkedData(req, res, next);
    });
}

function globHandler(req, res, next) {
    var ldp = req.app.locals.ldp;
    var filename = utils.uriToFilename(req.path, ldp.root);
    var uri = utils.uriBase(req);

    var globOptions = {
        noext: true,
        nobrace: true
    };

    glob(filename, globOptions, function(err, matches) {
        if (err || matches.length === 0) {
            debug("GET/HEAD -- No files matching the pattern");
            return next(new HttpError({
                message: "No files matching glob pattern",
                status: 404
            }));
        }

        // Matches found
        var globGraph = $rdf.graph();

        async.each(matches, function(match, done) {
            var baseUri = utils.filenameToBaseUri(match, uri, ldp.root);
            fs.readFile(match, {encoding: "utf8"}, function(err, fileData) {
                if (err) {
                    debug('GET -- Error in globHandler' + err);
                    return done(null);
                }
                aclAllow(match, req, res, function (allowed) {
                    if (!S(match).endsWith(".ttl") || !allowed) {
                        return done(null);
                    }
                    try {
                        $rdf.parse(
                            fileData,
                            globGraph,
                            baseUri,
                            'text/turtle');
                    } catch(parseErr) {
                        debug('GET -- Error in globHandler' + parseErr);
                    }
                    return done(null);
                });
            });
        }, function () {
            var data = $rdf.serialize(
                undefined,
                globGraph,
                null,
                'text/turtle');
            // TODO this should be added as a middleware in the routes
            res.locals.turtleData = data;
            return parseLinkedData(req, res, next);
        });
    });
}

function aclAllow(match, req, res, callback) {
    var ldp = req.app.locals.ldp;

    if (!ldp.webid) {
        return callback(true);
    }

    var relativePath = '/' + path.relative(ldp.root, match);
    res.locals.path = relativePath;
    acl.allow("Read", req, res, function(err) {
        callback(err);
    });
}

function parseLinkedData(req, res, next) {
    var ldp = req.app.locals.ldp;
    var filename = utils.uriToFilename(req.path, ldp.root);
    var uri = utils.uriBase(req);
    var turtleData = res.locals.turtleData;

    var accept = header.parseAcceptRDFHeader(req) || 'text/turtle';
    var baseUri = utils.filenameToBaseUri(filename, uri, ldp.root);

    // Handle Turtle Accept header
    if (accept === 'text/turtle' ||
        accept === 'text/n3' ||
        accept === 'application/turtle' ||
        accept === 'application/n3') {
        return res.status(200)
            .set('content-type', accept)
            .send(turtleData);
    }

    //Handle other file types
    var resourceGraph = $rdf.graph();
    try {
        $rdf.parse(turtleData, resourceGraph, baseUri, 'text/turtle');
    } catch (err) {

        debug("GET/HEAD -- Error parsing data: " + err.message);
        return next(new HttpError({
            message: err.message,
            status: 500
        }));
    }

    // Graph to `accept` type
    $rdf.serialize(undefined, resourceGraph, null, accept, function(err, result) {
        if (result === undefined || err) {
            debug("GET/HEAD -- Serialization error: " + err);
            return next(new HttpError({
                message: err.message,
                status: 500
            }));
        }

        return res
            .status(200)
            .set('content-type', accept)
            .send(result);
    });
}

function getHandler(req, res, next) {
    get(req, res, next, true);
}

function headHandler(req, res, next) {
    get(req, res, next, false);
}

exports.handler = getHandler;
exports.headHandler = headHandler;
<|endoftext|>


<commit_before>// Exports an Express middleware factory.
//
// Example:
//
//   const healthchecks = require('healthchecks');
//   const CHECKS_FILE = './checks';
//
//   server.use('/_healthchecks', healthchecks(CHECKS_FILE));
//
// If you want to change the check timeout, use named argument:
//
//   const options = {
//     filename: CHECKS_FILE,
//     timeout:  '5s'     // 5 seconds, can also pass duration in milliseconds
//   };
//   server.use('/_healthchecks', healthchecks(options);

const assert       = require('assert');
const debug        = require('debug')('healthchecks');
const EventEmitter = require('events').EventEmitter;
const File         = require('fs');
const Handlebars   = require('handlebars');
const hrTime       = require('pretty-hrtime');
const HTTP         = require('http');
const ms           = require('ms');
const Path         = require('path');
const URL          = require('url');

// Default timeout for checks; a slow server is a failed server.
const DEFAULT_TIMEOUT = '3s';

// HTTP status codes which we follow as redirects.
const REDIRECT_STATUSES = [301, 302, 303, 307];

// The maximum amount of redirects we will follow.
const MAX_REDIRECT_COUNT = 10;

// Represents a check outcome with the properties url, reason, etc.
function Outcome(url, expected, error, statusCode, body, elapsed) {
  this.url      = url;
  this.elapsed  = hrTime(elapsed);
  if (error && error.code === 'ETIMEDOUT') {
    this.reason   = 'timeout';
    this.timeout  = true;
  } else if (error) {
    this.reason   = 'error';
    this.error    = error;
  } else {

    this.statusCode = statusCode;
    this.body       = body;
    if (statusCode < 200 || statusCode >= 400)
      this.reason   = 'statusCode';
    else {

      const allMatching = expected.every(function(text) {
        return ~body.indexOf(text);
      });
      if (!allMatching)
        this.reason = 'body';

    }
  }
  this.log();
}

// Log outcome, visible when DEBUG=healthchecks
Outcome.prototype.log = function() {
  switch (this.reason) {
    case 'error': {
      debug('%s: Server responded with error %s', this.url, this.error);
      break;
    }
    case 'timeout': {
      debug('%s: Server response timeout', this.url);
      break;
    }
    case 'statusCode': {
      break;
    }
    case 'body': {
      debug('%s: Server response did not contain expected text', this.url);
      break;
    }
  }
};

// Easy way to log check outcome, shows the URL and the reason check failed
Outcome.prototype.toString = function() {
  switch (this.reason) {
    case 'error': {
      return this.url + ' => ' + this.error.message;
    }
    case 'statusCode': {
      return this.url + ' => ' + this.statusCode;
    }
    case undefined: {
      debug('%s: Server responded with status code %s', this.url, this.statusCode);
      return this.url;
    }
    default: {
      return this.url + ' => ' + this.reason;
    }
  }
};

// Our Handlerbars instance.
const handlebars = Handlebars.create();

// Checks the status of the given relative URL.
// This URL, and all possible redirects, are resolved using
// the resolver function.
function runCheck(url, headers, resolver, timeout) {
  return new Promise(function(resolve, reject) {
    const queue     = new EventEmitter;
    const redirects = 0;

    queue.on('request', function(url, redirects) {
      const loopbackURL = resolver(url);
      const request     = {
        host:     loopbackURL.host,
        port:     loopbackURL.port,
        path:     loopbackURL.path,
        headers:  Object.assign({}, headers, {
          'Host': loopbackURL.hostname
        })
      };

      get(request, timeout)
        .then(function(res) {
          if (~REDIRECT_STATUSES.indexOf(res.statusCode)) {
            if (redirects < MAX_REDIRECT_COUNT) {
              const redirectURL = resolver(res.headers.location);
              if (withinSameDomain(redirectURL, loopbackURL))
                queue.emit('request', res.headers.location, redirects + 1);
              else
                resolve(res);
            } else
              reject({ error: new Error('too many redirects'), elapsed: res.elapsed });
          } else
            resolve(res);
        })
        .catch(function(err) {
          reject(err);
        });
    });

    queue.emit('request', url, 0);
  });
}

// Makes an promisified HTTP GET request.
//
// On success, promise is resolved with { statusCode, headers, body, elapsed }.
// On error or timeout, promise is rejected with { error, elapsed }.
//
function get(request, timeout) {
  return new Promise(function(resolve, reject) {
    const start = process.hrtime();

    HTTP.get(request)
      .on('error', function(error) {
        const elapsed = process.hrtime(start);
        reject({ error: error, elapsed: elapsed });
      })
      .on('response', function(response) {
        const elapsed = process.hrtime(start);
        const buffers = [];
        response.on('data', function(buffer) {
          buffers.push(buffer);
        });
        response.on('end', function() {
          const body = Buffer.concat(buffers).toString();
          resolve({
            statusCode: response.statusCode,
            headers:    response.headers,
            body:       body,
            elapsed:    elapsed
          });
        });
      });

    setTimeout(function() {
      const elapsed = process.hrtime(start);
      const error   = new Error('ETIMEDOUT');
      error.code    = 'ETIMEDOUT';
      reject({ error: error, elapsed: elapsed });
    }, timeout);
  });
}

function withinSameDomain(from, to) {
  const fromHost = from.hostname;
  const toHost   = to.hostname;
  return fromHost === toHost ||
         fromHost.endsWith(`.${toHost}`) ||
         toHost.endsWith(`.${fromHost}`);
}

// The check function will run all checks in parallel, and resolve to an object
// with the properties:
// passed  - A list of all check URLs that passed
// failed  - A list of all check URLs that failed
function checkFunction(protocol, hostname, port, requestID, strictSSL) {
  const checks  = this.checks;
  const timeout = this.timeout;

  // Given a relative URL in string form, returns a parsed URL
  // which points to the local server's IP address and port
  // and has the right hostname property to use in the Host header.
  function loopbackResolve(relativeURL) {
    const absoluteURL = URL.parse(URL.resolve(protocol + '://localhost/', relativeURL));
    const loopbackURL = Object.assign({}, absoluteURL, {
      hostname: absoluteURL.hostname,
      host:     hostname,
      port:     port
    });
    return loopbackURL;
  }

  // Each check resolves into an outcome object
  const allChecks = Object.keys(checks).map(function(checkURL) {
    const expected = checks[checkURL];

    return new Promise(function(resolve) {
      // We need to make an HTTP/S request to the current server,
      // based on the hostname/port passed to us,
      // so the HTTP check would go to http://localhost:80/ or some such URL.
      const headers = {
        'User-Agent':   'Mozilla/5.0 (compatible) Healthchecks http://broadly.com',
        'X-Request-Id': requestID || ''
      };
      runCheck(checkURL, headers, loopbackResolve, timeout)
        .then(function(res) {
          resolve(new Outcome(checkURL, expected, null, res.statusCode, res.body, res.elapsed));
        })
        .catch(function(error) {
          resolve(new Outcome(checkURL, expected, error.error, null, null, error.elapsed));
        });
    });
  });

  // Run all checks in parallel
  const allOutcomes = Promise.all(allChecks);

  // Reduce into an object with the passed and failed lists of URLs
  const passedAndFailed = allOutcomes
    .then(function(outcomes) {
      return {
        passed: outcomes.filter(function(outcome) { return !outcome.reason; }),
        failed: outcomes.filter(function(outcome) { return  outcome.reason; })
      };
    });

  // Returns the promise
  return passedAndFailed;
}

// Read the checks file and returns a check function (see checkFunction).
function readChecks(filename, timeout) {
  const checks = File.readFileSync(filename, 'utf-8')
    .split(/[\n\r]+/)                 // Split into lines
    .map(function(line) {             // Ignore leading/trailing spaces
      return line.trim();
    })
    .filter(function(line) {          // Ignore empty lines
      return line.length;
    })
    .filter(function(line) {          // Ignore comments
      return line[0] !== '#';
    })
    .filter(function(line) {          // Ignore name = value pairs
      return !/^\w+=/.test(line);
    })
    .map(function(line) {             // Split line to URL + expected value
      const match = line.match(/^(\S+)\s*(.*)/);
      //debug('Added check %s %s', match[1], match[2]);
      return {
        url:      match[1],
        expected: match[2]
      };
    })
    .map(function(check) {            // Valid URLs only
      // URLs may be relative to the server, so contain an absolute path
      const url = URL.parse(check.url);
      assert(url.pathname && url.pathname[0] === '/', 'Check URL must have absolute pathname');
      assert(!url.protocol || /^https?:$/.test(url.protocol), 'Check URL may only use HTTP/S protocol');
      return check;
    })
    .reduce(function(memo, check) {
      const url   = check.url;
      memo[url] = memo[url] || [];
      if (check.expected)
        memo[url].push(check.expected);
      return memo;
    }, {});

  // Returns a check function that will use these checks / settings
  const context = {
    checks:   checks,
    timeout:  timeout
  };
  debug('Added %d checks', checks.length);

  return checkFunction.bind(context);
}

// Returns a comparer function suitable for Array.sort().
function compare(propName) {
  return function(a, b) {
    if (a[propName] < b[propName])
      return -1;
    if (a[propName] > b[propName])
      return 1;
    return 0;
  };
}

// Call this function to configure and return the middleware.
module.exports = function healthchecks(options) {
  assert(options, 'Missing options');

  // Pass filename as first argument or named option
  const filename    = typeof(options) === 'string' ? options : options.filename;
  assert(filename, 'Missing checks filename');

  // Pass timeout as named option, or use default
  const timeoutArg  = (typeof(options) === 'object' && options.timeout) || DEFAULT_TIMEOUT;
  // If timeout argument is a string (e.g. "3d"), convert to milliseconds
  const timeout     = (typeof(timeoutArg) === 'string') ? ms(timeoutArg) : + timeoutArg;

  const onFailed    = options.onFailed || function() {};
  const strictSSL   = options.strictSSL === false ? false : true;

  // Read all checks form the file and returns a checking function
  const runChecks   = readChecks(filename, timeout);

  // Load Handlebars template for rendering results
  const template    = File.readFileSync(Path.join(__dirname, '/index.hbs'), 'utf-8');
  const render      = handlebars.compile(template);

  // Return the Express middleware
  return function(req, res) {

    const requestID = req.headers['x-request-id'];

    // We use local address/port to health check this server, e.g. the checks
    // may say //www.example.com/ but in development we connect to
    // 127.0.0.1:5000
    const protocol  = req.socket.encrypted ? 'https' : 'http';
    const hostname  = req.socket.localAddress;
    const port      = req.socket.localPort;

    // Run all checks
    debug('Running against %s://%s:%d with request-ID %s', protocol, hostname, port, requestID);
    runChecks(protocol, hostname, port, requestID, strictSSL)
      .then(function(outcomes) {
        debug('%d passed and %d failed', outcomes.passed.length, outcomes.failed.length);

        // Respond with 200 only if all checks passed
        // Respond with 500 if any check fail
        // Respond with 404 if there are no checks to run
        const statusCode  =
          outcomes.failed.length ? 500 :
          outcomes.passed.length ? 200 : 404;
        // Render template
        const html        = render({
          passed: outcomes.passed.sort(compare('url')),
          failed: outcomes.failed.sort(compare('url'))
        });
        res.writeHeader(statusCode);
        res.write(html);
        res.end();

        if (outcomes.failed.length)
          onFailed(outcomes.failed);
      });
  };

};
<commit_msg>Make elapsed time all-inclusive for the check.<commit_after>// Exports an Express middleware factory.
//
// Example:
//
//   const healthchecks = require('healthchecks');
//   const CHECKS_FILE = './checks';
//
//   server.use('/_healthchecks', healthchecks(CHECKS_FILE));
//
// If you want to change the check timeout, use named argument:
//
//   const options = {
//     filename: CHECKS_FILE,
//     timeout:  '5s'     // 5 seconds, can also pass duration in milliseconds
//   };
//   server.use('/_healthchecks', healthchecks(options);

const assert     = require('assert');
const debug      = require('debug')('healthchecks');
const File       = require('fs');
const Handlebars = require('handlebars');
const hrTime     = require('pretty-hrtime');
const HTTP       = require('http');
const ms         = require('ms');
const Path       = require('path');
const URL        = require('url');

// Default timeout for checks; a slow server is a failed server.
const DEFAULT_TIMEOUT = '3s';

// HTTP status codes which we follow as redirects.
const REDIRECT_STATUSES = [301, 302, 303, 307];

// The maximum amount of redirects we will follow.
const MAX_REDIRECT_COUNT = 10;

// Represents a check outcome with the properties url, reason, etc.
function Outcome(url, expected, error, statusCode, body, elapsed) {
  this.url      = url;
  this.elapsed  = hrTime(elapsed);
  if (error && error.code === 'ETIMEDOUT') {
    this.reason   = 'timeout';
    this.timeout  = true;
  } else if (error) {
    this.reason   = 'error';
    this.error    = error;
  } else {

    this.statusCode = statusCode;
    this.body       = body;
    if (statusCode < 200 || statusCode >= 400)
      this.reason   = 'statusCode';
    else {

      const allMatching = expected.every(function(text) {
        return ~body.indexOf(text);
      });
      if (!allMatching)
        this.reason = 'body';

    }
  }
  this.log();
}

// Log outcome, visible when DEBUG=healthchecks
Outcome.prototype.log = function() {
  switch (this.reason) {
    case 'error': {
      debug('%s: Server responded with error %s', this.url, this.error);
      break;
    }
    case 'timeout': {
      debug('%s: Server response timeout', this.url);
      break;
    }
    case 'statusCode': {
      break;
    }
    case 'body': {
      debug('%s: Server response did not contain expected text', this.url);
      break;
    }
  }
};

// Easy way to log check outcome, shows the URL and the reason check failed
Outcome.prototype.toString = function() {
  switch (this.reason) {
    case 'error': {
      return this.url + ' => ' + this.error.message;
    }
    case 'statusCode': {
      return this.url + ' => ' + this.statusCode;
    }
    case undefined: {
      debug('%s: Server responded with status code %s', this.url, this.statusCode);
      return this.url;
    }
    default: {
      return this.url + ' => ' + this.reason;
    }
  }
};

// Our Handlerbars instance.
const handlebars = Handlebars.create();

// Checks the status of the given relative URL.
// This URL, and all possible redirects, are resolved using
// the resolver function.
function runCheck(url, headers, resolver, timeout, redirects) {
  const loopbackURL = resolver(url);
  const request     = {
    host:     loopbackURL.host,
    port:     loopbackURL.port,
    path:     loopbackURL.path,
    headers:  Object.assign({}, headers, {
      'Host': loopbackURL.hostname
    })
  };

  return new Promise(function(resolve, reject) {
    redirects = redirects || 0;
    get(request, timeout)
      .then(function(res) {
        if (~REDIRECT_STATUSES.indexOf(res.statusCode)) {
          if (redirects < MAX_REDIRECT_COUNT) {
            const redirectURL = resolver(res.headers.location);
            if (withinSameDomain(redirectURL, loopbackURL))
              runCheck(res.headers.location, headers, resolver, timeout, redirects + 1)
                .then(resolve, reject);
            else
              resolve(res);
          } else
            reject(new Error('too many redirects'));
        } else
          resolve(res);
      })
      .catch(reject);
  });
}

// Makes an promisified HTTP GET request.
//
// On success, promise is resolved with { statusCode, headers, body }.
// On error or timeout, promise is rejected with error.
//
function get(request, timeout) {
  return new Promise(function(resolve, reject) {
    HTTP.get(request)
      .on('error', reject)
      .on('response', function(response) {
        const buffers = [];
        response.on('data', function(buffer) {
          buffers.push(buffer);
        });
        response.on('end', function() {
          const body = Buffer.concat(buffers).toString();
          resolve({
            statusCode: response.statusCode,
            headers:    response.headers,
            body:       body
          });
        });
      });

    setTimeout(function() {
      const error = new Error('ETIMEDOUT');
      error.code  = 'ETIMEDOUT';
      reject(error);
    }, timeout);
  });
}

function withinSameDomain(from, to) {
  const fromHost = from.hostname;
  const toHost   = to.hostname;
  return fromHost === toHost ||
         fromHost.endsWith(`.${toHost}`) ||
         toHost.endsWith(`.${fromHost}`);
}

// The check function will run all checks in parallel, and resolve to an object
// with the properties:
// passed  - A list of all check URLs that passed
// failed  - A list of all check URLs that failed
function checkFunction(protocol, hostname, port, requestID, strictSSL) {
  const checks  = this.checks;
  const timeout = this.timeout;

  // Given a relative URL in string form, returns a parsed URL
  // which points to the local server's IP address and port
  // and has the right hostname property to use in the Host header.
  function loopbackResolve(relativeURL) {
    const absoluteURL = URL.parse(URL.resolve(protocol + '://localhost/', relativeURL));
    const loopbackURL = Object.assign({}, absoluteURL, {
      hostname: absoluteURL.hostname,
      host:     hostname,
      port:     port
    });
    return loopbackURL;
  }

  // Each check resolves into an outcome object
  const allChecks = Object.keys(checks).map(function(checkURL) {
    const expected = checks[checkURL];

    return new Promise(function(resolve) {
      // We need to make an HTTP/S request to the current server,
      // based on the hostname/port passed to us,
      // so the HTTP check would go to http://localhost:80/ or some such URL.
      const headers = {
        'User-Agent':   'Mozilla/5.0 (compatible) Healthchecks http://broadly.com',
        'X-Request-Id': requestID || ''
      };

      const start = process.hrtime();
      runCheck(checkURL, headers, loopbackResolve, timeout)
        .then(function(res) {
          const elapsed = process.hrtime(start);
          resolve(new Outcome(checkURL, expected, null, res.statusCode, res.body, elapsed));
        })
        .catch(function(error) {
          const elapsed = process.hrtime(start);
          resolve(new Outcome(checkURL, expected, error, null, null, elapsed));
        });
    });
  });

  // Run all checks in parallel
  const allOutcomes = Promise.all(allChecks);

  // Reduce into an object with the passed and failed lists of URLs
  const passedAndFailed = allOutcomes
    .then(function(outcomes) {
      return {
        passed: outcomes.filter(function(outcome) { return !outcome.reason; }),
        failed: outcomes.filter(function(outcome) { return  outcome.reason; })
      };
    });

  // Returns the promise
  return passedAndFailed;
}

// Read the checks file and returns a check function (see checkFunction).
function readChecks(filename, timeout) {
  const checks = File.readFileSync(filename, 'utf-8')
    .split(/[\n\r]+/)                 // Split into lines
    .map(function(line) {             // Ignore leading/trailing spaces
      return line.trim();
    })
    .filter(function(line) {          // Ignore empty lines
      return line.length;
    })
    .filter(function(line) {          // Ignore comments
      return line[0] !== '#';
    })
    .filter(function(line) {          // Ignore name = value pairs
      return !/^\w+=/.test(line);
    })
    .map(function(line) {             // Split line to URL + expected value
      const match = line.match(/^(\S+)\s*(.*)/);
      //debug('Added check %s %s', match[1], match[2]);
      return {
        url:      match[1],
        expected: match[2]
      };
    })
    .map(function(check) {            // Valid URLs only
      // URLs may be relative to the server, so contain an absolute path
      const url = URL.parse(check.url);
      assert(url.pathname && url.pathname[0] === '/', 'Check URL must have absolute pathname');
      assert(!url.protocol || /^https?:$/.test(url.protocol), 'Check URL may only use HTTP/S protocol');
      return check;
    })
    .reduce(function(memo, check) {
      const url   = check.url;
      memo[url] = memo[url] || [];
      if (check.expected)
        memo[url].push(check.expected);
      return memo;
    }, {});

  // Returns a check function that will use these checks / settings
  const context = {
    checks:   checks,
    timeout:  timeout
  };
  debug('Added %d checks', checks.length);

  return checkFunction.bind(context);
}

// Returns a comparer function suitable for Array.sort().
function compare(propName) {
  return function(a, b) {
    if (a[propName] < b[propName])
      return -1;
    if (a[propName] > b[propName])
      return 1;
    return 0;
  };
}

// Call this function to configure and return the middleware.
module.exports = function healthchecks(options) {
  assert(options, 'Missing options');

  // Pass filename as first argument or named option
  const filename    = typeof(options) === 'string' ? options : options.filename;
  assert(filename, 'Missing checks filename');

  // Pass timeout as named option, or use default
  const timeoutArg  = (typeof(options) === 'object' && options.timeout) || DEFAULT_TIMEOUT;
  // If timeout argument is a string (e.g. "3d"), convert to milliseconds
  const timeout     = (typeof(timeoutArg) === 'string') ? ms(timeoutArg) : + timeoutArg;

  const onFailed    = options.onFailed || function() {};
  const strictSSL   = options.strictSSL === false ? false : true;

  // Read all checks form the file and returns a checking function
  const runChecks   = readChecks(filename, timeout);

  // Load Handlebars template for rendering results
  const template    = File.readFileSync(Path.join(__dirname, '/index.hbs'), 'utf-8');
  const render      = handlebars.compile(template);

  // Return the Express middleware
  return function(req, res) {

    const requestID = req.headers['x-request-id'];

    // We use local address/port to health check this server, e.g. the checks
    // may say //www.example.com/ but in development we connect to
    // 127.0.0.1:5000
    const protocol  = req.socket.encrypted ? 'https' : 'http';
    const hostname  = req.socket.localAddress;
    const port      = req.socket.localPort;

    // Run all checks
    debug('Running against %s://%s:%d with request-ID %s', protocol, hostname, port, requestID);
    runChecks(protocol, hostname, port, requestID, strictSSL)
      .then(function(outcomes) {
        debug('%d passed and %d failed', outcomes.passed.length, outcomes.failed.length);

        // Respond with 200 only if all checks passed
        // Respond with 500 if any check fail
        // Respond with 404 if there are no checks to run
        const statusCode  =
          outcomes.failed.length ? 500 :
          outcomes.passed.length ? 200 : 404;
        // Render template
        const html        = render({
          passed: outcomes.passed.sort(compare('url')),
          failed: outcomes.failed.sort(compare('url'))
        });
        res.writeHeader(statusCode);
        res.write(html);
        res.end();

        if (outcomes.failed.length)
          onFailed(outcomes.failed);
      });
  };

};
<|endoftext|>


<commit_before>// Import util
var util = require('util');

// Import my files
var Random = require('./src/random');
var Importer = require('./src/importer');
var Timer = require('./src/timer');
var NEH = require('./src/neh');
var IG = require('./src/ig');

// Overwrite Math.random() function
util._extend(Math, Random.prototype);

// Initialization
var importer = new Importer();
var names = [];
var neh = new NEH();
var ig = new IG();
var nehrpd = 0;
var igrpd = 0;

// Read arguments
var arguments = process.argv.splice(2);
for(var i = 0; i < arguments.length; i++) {
    if (arguments[i].match(/^ta[0-9]+$/)) {
        names.push(arguments[i]);
    }
}

if (names.length > 0) {

    console.log('--------------------------');
    console.log('      Processing...       ');
    console.log('--------------------------');

    for(var j = 0; j < names.length; j++) {

        // Instance data
        var name = names[j];
        var metaData = importer.loadMetaData(name);
        var matrixData = importer.loadMatrixData(name);

        // Set initial seed
        Math.initialSeed(metaData.initialSeed);

        // Run algorithms
        var timer = new Timer();
        var nehrun = neh.run(matrixData);
        var igrun = ig.run(matrixData);

        console.log('          Name:', metaData.name);
        console.log('          Jobs:', metaData.jobs);
        console.log('      Machines:', metaData.machines);
        console.log('   Upper bound:', metaData.upperBound);
        console.log('  NEH Makespan:', nehrun.makespan());
        console.log('    RPD NEH UB:', nehrun.rpd(metaData.upperBound) + '%');
        console.log('   IG Makespan:', igrun.makespan());
        console.log('     RPD IG UB:', igrun.rpd(metaData.upperBound) + '%');
        console.log('  Elapsed time:', timer.elapsedTime('mm:ss') + ' mins');
        console.log('--------------------------');

        // Average rpd
        nehrpd = nehrpd + nehrun.rpd(metaData.upperBound);
        igrpd = igrpd + igrun.rpd(metaData.upperBound);
    }

    console.log(' Average RPD NEH UB:', (Math.round(nehrpd / names.length * 100) / 100) + '%');
    console.log('  Average RPD IG UB:', (Math.round(igrpd / names.length * 100) / 100) + '%');
    console.log('--------------------------');

} else {

    console.log('Usage: node flowshop <TAILLARD INSTANCE NAMES SEPARATED BY SPACES>');

}
<commit_msg>Refactored version<commit_after>// Import util
var util = require('util');

// Import my files
var Random = require('./src/random');
var Importer = require('./src/importer');
var Timer = require('./src/timer');
var NEH = require('./src/neh');
var IG = require('./src/ig');

// Overwrite Math.random() function
util._extend(Math, Random.prototype);

// Initialization
var importer = new Importer();
var names = [];
var neh = new NEH();
var ig = new IG();
var nehrpd = 0;
var igrpd = 0;

// Read arguments
var arguments = process.argv.splice(2);
for(var i = 0; i < arguments.length; i++) {
    if (arguments[i].match(/^ta[0-9]{3}$/)) {
        names.push(arguments[i]);
    } else {
        names = [];
        break;
    }
}

if (names.length > 0) {

    console.log('--------------------------');
    console.log('       Processing...      ');
    console.log('--------------------------');

    for(var j = 0; j < names.length; j++) {

        // Instance data
        var name = names[j];
        var metaData = importer.loadMetaData(name);
        var matrixData = importer.loadMatrixData(name);

        if (metaData) {

            // Set initial seed
            Math.initialSeed(metaData.initialSeed);

            // Run algorithms
            var timer = new Timer();
            var nehrun = neh.run(matrixData);
            var igrun = ig.run(matrixData);

            console.log('          Name:', metaData.name);
            console.log('          Jobs:', metaData.jobs);
            console.log('      Machines:', metaData.machines);
            console.log('   Upper bound:', metaData.upperBound);
            console.log('  NEH Makespan:', nehrun.makespan());
            console.log('    RPD NEH UB:', nehrun.rpd(metaData.upperBound) + '%');
            console.log('   IG Makespan:', igrun.makespan());
            console.log('     RPD IG UB:', igrun.rpd(metaData.upperBound) + '%');
            console.log('  Elapsed time:', timer.elapsedTime('mm:ss') + ' mins');
            console.log('--------------------------');

            // Average rpd
            nehrpd = nehrpd + nehrun.rpd(metaData.upperBound);
            igrpd = igrpd + igrun.rpd(metaData.upperBound);
        } else {

            console.log('   File ' + name + ' not found');
            console.log('--------------------------');
        }
    }

    if (nehrpd > 0 && igrpd > 0) {
        console.log(' Average RPD NEH UB:', (Math.round(nehrpd / names.length * 100) / 100) + '%');
        console.log('  Average RPD IG UB:', (Math.round(igrpd / names.length * 100) / 100) + '%');
        console.log('--------------------------');
    }

} else {

    console.log('Usage: node flowshop <TAILLARD INSTANCE NAMES SEPARATED BY SPACES>');

}
<|endoftext|>


<commit_before>(function($){
$.fn.focusify = function(args){
	var methods = {
		ns: 'focusify',

		init: function(opts){
			var _s = {
					classname: 'infocus',
					parent: '_'
				},
				_this = methods;

			$.extend(_s, opts || {});

			function handleFocusBlur(e){
				var $this = $(this),
					$parent = _s.parent === '_' ? $this.parent() : $this.parents(_s.parent);

				$parent.toggleClass(_s.classname);
			}

			this.each(function(){
				if(!$.data(this, _this.ns)){
					$(this).bind('focus.' + _this.ns + ' blur.' + _this.ns, handleFocusBlur);
					$.data(this, _this.ns, true);
				}
			});
		},

		destroy: function(){
			var _this = methods;

			this.each(function(){
				$(this).unbind('.' + _this.ns);
				$.removeData(this, _this.ns);
			});
		}
	};

	if(arguments.length && args === 'destroy'){
		methods.destroy.call(this);
	}else{
		methods.init.call(this, args);
	}

	return this;
};
})(jQuery);<commit_msg>Moved event handler out to method object literal.<commit_after>(function($){
$.fn.focusify = function(args){
	var methods = {
		ns: 'focusify',

		st: {
			classname: 'infocus',
			parent: '_'
		},

		handleFocusBlur: function(){
			var $this = $(this),
				_this = methods,
				$parent = _this.st.parent === '_' ? $this.parent() : $this.parents(_this.st.parent);

			$parent.toggleClass(_this.st.classname);
		},

		init: function(opts){
			var _this = methods;

			$.extend(_this.st, opts || {});

			this.each(function(){
				if(!$.data(this, _this.ns)){
					$(this).bind('focus.' + _this.ns + ' blur.' + _this.ns, _this.handleFocusBlur);
					$.data(this, _this.ns, true);
				}
			});
		},

		destroy: function(){
			var _this = methods;

			this.each(function(){
				$(this).unbind('.' + _this.ns);
				$.removeData(this, _this.ns);
			});
		}
	};

	if(arguments.length && args === 'destroy'){
		methods.destroy.call(this);
	}else{
		methods.init.call(this, args);
	}

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


<commit_before>/*!
 * forecast.js
 * Copyright (C) 2012 Eric Lippmann
 * forecast.js may be freely distributed under the MIT license.
 */
<commit_msg>Add library initialization<commit_after>/*!
 * forecast.js
 * Copyright (C) 2012 Eric Lippmann
 * forecast.js may be freely distributed under the MIT license.
 */

/**
 * Time series forecasting models.
 */
; (function () {
    'use strict';

    var // Reference to `window` in the browser, `exports`, `global` on
        // the server
        root = this;

    function forecast () {
        if (!(this instanceof forecast)) {
            return new forecast();
        }
    }

    root.forecast = forecast();
}.call(this));
<|endoftext|>


<commit_before>// jshint ignore: start

(function() {

  var width = a.width;
  var height = a.height;
  b.removeChild(a);

  var centerX = width / 2;
  var centerY = height / 2;

  b.innerHTML += '
';

  var playerX = centerX;
  var playerY = centerY;
  var playerAngle = 0;

  var playerVelocityX = 0;
  var playerVelocityY = 0;

  b.style.background = '#666';

  b.onmousemove = function(event) {
    playerAngle = Math.atan2(playerY - event.pageY, playerX - event.pageX);
  };

  b.onkeydown = function(event) {
    var keyCode = event.keyCode;
    console.log(keyCode);
    if (keyCode == 87) {
      playerVelocityY = -10;
    } else if (keyCode == 83) {
      playerVelocityY = 10;
    } else if (keyCode == 65) {
      playerVelocityX = -10;
    } else if (keyCode == 68) {
      playerVelocityX = 10;
    }
  };

  b.onkeyup = function(event) {
    var keyCode = event.keyCode;
    if ((keyCode == 87) || (keyCode == 83)) {
      playerVelocityY = 0;
    } else if ((keyCode == 65) || (keyCode == 68)) {
      playerVelocityX = 0;
    }
  };

  var lastTick = 0;
  function tick(t) {

    var dt = (t - lastTick) / 50;
    lastTick = t;

    p.style.transform = 'rotate(' + (playerAngle * 180 / Math.PI) + 'deg)';
    p.style.left = playerX + 'px';
    p.style.top = playerY + 'px';

    playerX += playerVelocityX * dt;
    playerY += playerVelocityY * dt;

    requestAnimationFrame(tick);

  }

  tick(0);

})();
<commit_msg>minor: move a statement<commit_after>// jshint ignore: start

(function() {

  var width = a.width;
  var height = a.height;
  b.removeChild(a);

  var centerX = width / 2;
  var centerY = height / 2;

  b.style.background = '#666';
  b.innerHTML += '
';

  var playerX = centerX;
  var playerY = centerY;
  var playerAngle = 0;

  var playerVelocityX = 0;
  var playerVelocityY = 0;

  b.onmousemove = function(event) {
    playerAngle = Math.atan2(playerY - event.pageY, playerX - event.pageX);
  };

  b.onkeydown = function(event) {
    var keyCode = event.keyCode;
    console.log(keyCode);
    if (keyCode == 87) {
      playerVelocityY = -10;
    } else if (keyCode == 83) {
      playerVelocityY = 10;
    } else if (keyCode == 65) {
      playerVelocityX = -10;
    } else if (keyCode == 68) {
      playerVelocityX = 10;
    }
  };

  b.onkeyup = function(event) {
    var keyCode = event.keyCode;
    if ((keyCode == 87) || (keyCode == 83)) {
      playerVelocityY = 0;
    } else if ((keyCode == 65) || (keyCode == 68)) {
      playerVelocityX = 0;
    }
  };

  var lastTick = 0;
  function tick(t) {

    var dt = (t - lastTick) / 50;
    lastTick = t;

    p.style.transform = 'rotate(' + (playerAngle * 180 / Math.PI) + 'deg)';
    p.style.left = playerX + 'px';
    p.style.top = playerY + 'px';

    playerX += playerVelocityX * dt;
    playerY += playerVelocityY * dt;

    requestAnimationFrame(tick);

  }

  tick(0);

})();
<|endoftext|>