<commit_before>// This function will test localstorage to see if its actually available and
// working.
var _getLocalStorage = function() {

  // Set storage to localStorage - if test fails storage is set to null
  var storage = window.localStorage;

  // We initialize the fail flag defaulting to true
  var fail = true;

  // In the test we test the localstorage api setItem/getItem/removeItem this
  // uid will hopefully prevent any overwriting of existing data
  var uid = Random.id();

  try {
    // Use the setItem api
    storage.setItem(uid, uid);
    // Test the getItem api and check if the value could be set and retrieved
    fail = (storage.getItem(uid) !== uid);
    // Test removeItem and clean up the test data
    storage.removeItem(uid);

    // If the test failed then set the storage to null
    if (fail) storage = null;

  } catch(e) {
    // Noop, cant do much about it
  }

  // Return the tested localstorage
  return storage;
};

// Get storage if available
var _storage = _getLocalStorage();

// Check to see if we got any localstorage to add
if (_storage) {

  // Create a namespace to track storage name spacing
  var _localStorageNS = {};

  // Create a noop function
  var noop = function() {};

  // Prefix convention
  var _prefix = function(name) {
    return '_storage.' + name;
  };

  // Prefix database
  var _prefixDatabase = function(name) {
    return _prefix(name) + '.db.';
  };

  // Prefix database record
  var _prefixDatabaseRecord = function(name) {
    return _prefix(name) + '.record';
  };

  // Helper getting and updating the table record
  var _setTableRecord = function(SAInstance, migrationCallback) {

    // Database record name in localstorage
    var recordName = _prefixDatabaseRecord(SAInstance.name);

    // Get the database record
    var oldRecordString = _storage.getItem(recordName);

    // Set the default empty record object
    var record = {};

    try {

      // Get old record object
      record = JSON.parse(oldRecordString) || {};

    } catch(err) {
      // Noop, cant do much about it, we assume that data is lost
    }

    // Set new version helper
    var newVersion = SAInstance.version;

    // Set old version helper
    var oldVersion = record.version || 1.0;

    // Update the record
    record.version = SAInstance.version;

    try {

      // Create new record as string
      var newRecordString = JSON.stringify(record);

      // Store the new record
      _storage.setItem(recordName, newRecordString);

    } catch(err) {
      // Noop, cant do much here
    }

    migrationCallback.call(SAInstance, {
      version: oldVersion
    }, {
      version: newVersion
    });
  };

  // Yeah, got it - add the api to the Storage global
  Store.localStorage = function(options) {
    var self = this;

    if (!(self instanceof Store.localStorage))
      return new Store.localStorage(self.name);

    // Inheritance EventEmitter
    self.eventemitter = new EventEmitter();

    // Make sure options is at least an empty object
    options = options || {};

    // Set the name on the instance
    self.name = options.name;

    // Check to see if the storage is already defined
    if (_localStorageNS[self.name])
      throw new Error('Storage.localStorage "' + self.name + '" is already in use');

    // Make sure that the user dont use '.db.'
    if (/.db./.test(self.name))
      throw new Error('Storage.localStorage "' + self.name + '" contains ".db." this is not allowed');

    // Set the size of db 0 === disable quota
    // TODO: Implement
    self.size = options.size || 0;

    // Set version - if this is bumped then the data is cleared pr. default
    // migration
    self.version = options.version || 1.0;

    // Set migration function
    var migrationFunction = options.migration || function(oldRecord, newRecord) {

      // Check storage versions
      if (oldRecord.version !== newRecord.version) {
        // We allow the user to customize a migration algoritme but here we just
        // clear the storage if versions mismatch
        self.clear(noop);
      }
    };

    // Store the instance
    _localStorageNS[self.name] = self;

    // Set the table record, at the moment this is only handling the version
    _setTableRecord(self, migrationFunction);

  };

  // Simple helper to return the storage type name
  Store.localStorage.prototype.typeName = function() {
    return 'localStorage';
  };

  Store.localStorage.prototype.prefix = function() {
    var self = this;
    return _prefixDatabase(self.name);
  };

  Store.localStorage.prototype.getPrefixedId = function(name) {
    var self = this;
    return self.prefix() + name;
  };

  //////////////////////////////////////////////////////////////////////////////
  // WRAP LOCALSTORAGE API
  //////////////////////////////////////////////////////////////////////////////

  Store.localStorage.prototype.getItem = function(name, callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.getItem require a callback function');

    try {

      // Get the string value
      var jsonObj = _storage.getItem(self.getPrefixedId(name));

      // Try to return the object of the parsed string
      callback(null, JSON.parse(jsonObj));

    } catch(err) {

      // Callback with error
      callback(err);

    }

  };

  Store.localStorage.prototype.setItem = function(name, obj, callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.setItem require a callback function');

    try {

      // Stringify the object
      var jsonObj = JSON.stringify(obj);

      // Try to set the stringified object
      callback(null, _storage.setItem(self.getPrefixedId(name), jsonObj));

    } catch(err) {

      // Callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.removeItem = function(name, callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.removeItem require a callback function');

    try {

      // Try to remove the item
      callback(null, _storage.removeItem(self.getPrefixedId(name)));

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.clear = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.clear require a callback function');

    try {

      // Find all relevant keys for this storage
      self.keys(function(err, keys) {
        if (err) {

          // On error we just callback
          callback(err);

        } else {

          // Iterate over keys and removing them one by one
          for (var i=0; i < keys.length; i++)
            self.removeItem(keys[i], noop);

          // Callback
          callback(null, keys.length);
        }
      });

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.keys = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.keys require a callback function');

    // Result to return
    var result = [];

    try {

      // Create the prefix test
      var regex = new RegExp('^' + self.prefix());

      for (var i = 0; i < _storage.length; i++) {

        // Test if the key is relevant to this store
        if (regex.test(_storage.key(i)))
          // Add the name
          result.push(_storage.key(i).replace(regex, ''));
      }

      // Return the result
      callback(null, result);

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.length = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.length require a callback function');

    try {

      // Get the keys
      self.keys(function(error, keys) {

        // Return the length
        callback(error, keys && keys.length || null);

      });

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.toObject = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.keys require a callback function');

    // Result to return
    var result = {};

    try {

      // Create the prefix test
      var regex = new RegExp('^' + self.prefix());

      for (var i = 0; i < _storage.length; i++) {
        // Helper
        var key = _storage.key(i);

        // Test if the key is relevant to this store
        if (regex.test(key)) {
          try {

            // Get the string value
            var jsonObj = _storage.getItem(key);

            // Try to return the object of the parsed string
            result[key.replace(regex, '')] = EJSON.parse(jsonObj);

          } catch(err) {
            // NOOP
          }
        }

      }

      // Return the result
      callback(null, result);

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  //////////////////////////////////////////////////////////////////////////////
  // WRAP EVENTEMITTER API
  //////////////////////////////////////////////////////////////////////////////

  // Wrap the Event Emitter Api "on"
  Store.localStorage.prototype.on = function(/* arguments */) {
    this.eventemitter.on.apply(this.eventemitter, _.toArray(arguments));
  };

  // Wrap the Event Emitter Api "once"
  Store.localStorage.prototype.once = function(/* arguments */) {
    this.eventemitter.once.apply(this.eventemitter, _.toArray(arguments));
  };

  // Wrap the Event Emitter Api "off"
  Store.localStorage.prototype.off = function(/* arguments */) {
    this.eventemitter.off.apply(this.eventemitter, _.toArray(arguments));
  };

  // Wrap the Event Emitter Api "emit"
  Store.localStorage.prototype.emit = function(/* arguments */) {
    this.eventemitter.emit.apply(this.eventemitter, _.toArray(arguments));
  };

  // Add api helpers
  Store.localStorage.prototype.addListener = Store.localStorage.prototype.on;
  Store.localStorage.prototype.removeListener = Store.localStorage.prototype.off;
  Store.localStorage.prototype.removeAllListeners = Store.localStorage.prototype.off;

  // Add jquery like helpers
  Store.localStorage.prototype.one = Store.localStorage.prototype.once;
  Store.localStorage.prototype.trigger = Store.localStorage.prototype.emit;

  //////////////////////////////////////////////////////////////////////////////
  // WRAP LOCALSTORAGE EVENTHANDLER
  //////////////////////////////////////////////////////////////////////////////

  // This will be a quick test to see if we have any relations to the data
  var _prefixedByUs = new RegExp('^' + _prefix(''));

  // Add event handlers
  if (typeof window.addEventListener !== 'undefined') {
      // Add support for multiple tabs
      window.addEventListener('storage', function(e) {
      // Data changed in another tab, it would have updated localstorage, I'm
      // outdated so reload the tab and localstorage - but we test the prefix on the
      // key - since we actually make writes in the localstorage feature test

      // First of lets make sure that it was actually prefixed by us
      if (e.key && _prefixedByUs.test(e.key)) {

        // Okay, this looks familiar, now we try to lookup the storage instance
        // to emit an event on...

        // Remove the prefix
        var noPrefix = e.key.replace(_prefixedByUs, '');

        // So we know that the name dont contain suffix ".db."
        var elements = noPrefix.split('.db.');

        var storageName = elements.shift();

        // Get the remaining key
        var key = elements.join('.db.');

        // Get the affected storage
        var storageAdapter = _localStorageNS[storageName];

        if (storageAdapter) {

          // Emit the event on the storage
          storageAdapter.emit('storage', {
            key: key,
            newValue: JSON.parse(e.newValue),
            oldValue: JSON.parse(e.oldValue),
            originalKey: e.key,
            updatedAt: new Date(e.timeStamp),
            url: e.url,
            storage: storageAdapter,
          });
        }

      }

    }, false);
}

}<commit_msg>use EJSON<commit_after>// This function will test localstorage to see if its actually available and
// working.
var _getLocalStorage = function() {

  // Set storage to localStorage - if test fails storage is set to null
  var storage = window.localStorage;

  // We initialize the fail flag defaulting to true
  var fail = true;

  // In the test we test the localstorage api setItem/getItem/removeItem this
  // uid will hopefully prevent any overwriting of existing data
  var uid = Random.id();

  try {
    // Use the setItem api
    storage.setItem(uid, uid);
    // Test the getItem api and check if the value could be set and retrieved
    fail = (storage.getItem(uid) !== uid);
    // Test removeItem and clean up the test data
    storage.removeItem(uid);

    // If the test failed then set the storage to null
    if (fail) storage = null;

  } catch(e) {
    // Noop, cant do much about it
  }

  // Return the tested localstorage
  return storage;
};

// Get storage if available
var _storage = _getLocalStorage();

// Check to see if we got any localstorage to add
if (_storage) {

  // Create a namespace to track storage name spacing
  var _localStorageNS = {};

  // Create a noop function
  var noop = function() {};

  // Prefix convention
  var _prefix = function(name) {
    return '_storage.' + name;
  };

  // Prefix database
  var _prefixDatabase = function(name) {
    return _prefix(name) + '.db.';
  };

  // Prefix database record
  var _prefixDatabaseRecord = function(name) {
    return _prefix(name) + '.record';
  };

  // Helper getting and updating the table record
  var _setTableRecord = function(SAInstance, migrationCallback) {

    // Database record name in localstorage
    var recordName = _prefixDatabaseRecord(SAInstance.name);

    // Get the database record
    var oldRecordString = _storage.getItem(recordName);

    // Set the default empty record object
    var record = {};

    try {

      // Get old record object
      record = EJSON.parse(oldRecordString) || {};

    } catch(err) {
      // Noop, cant do much about it, we assume that data is lost
    }

    // Set new version helper
    var newVersion = SAInstance.version;

    // Set old version helper
    var oldVersion = record.version || 1.0;

    // Update the record
    record.version = SAInstance.version;

    try {

      // Create new record as string
      var newRecordString = EJSON.stringify(record);

      // Store the new record
      _storage.setItem(recordName, newRecordString);

    } catch(err) {
      // Noop, cant do much here
    }

    migrationCallback.call(SAInstance, {
      version: oldVersion
    }, {
      version: newVersion
    });
  };

  // Yeah, got it - add the api to the Storage global
  Store.localStorage = function(options) {
    var self = this;

    if (!(self instanceof Store.localStorage))
      return new Store.localStorage(self.name);

    // Inheritance EventEmitter
    self.eventemitter = new EventEmitter();

    // Make sure options is at least an empty object
    options = options || {};

    // Set the name on the instance
    self.name = options.name;

    // Check to see if the storage is already defined
    if (_localStorageNS[self.name])
      throw new Error('Storage.localStorage "' + self.name + '" is already in use');

    // Make sure that the user dont use '.db.'
    if (/.db./.test(self.name))
      throw new Error('Storage.localStorage "' + self.name + '" contains ".db." this is not allowed');

    // Set the size of db 0 === disable quota
    // TODO: Implement
    self.size = options.size || 0;

    // Set version - if this is bumped then the data is cleared pr. default
    // migration
    self.version = options.version || 1.0;

    // Set migration function
    var migrationFunction = options.migration || function(oldRecord, newRecord) {

      // Check storage versions
      if (oldRecord.version !== newRecord.version) {
        // We allow the user to customize a migration algoritme but here we just
        // clear the storage if versions mismatch
        self.clear(noop);
      }
    };

    // Store the instance
    _localStorageNS[self.name] = self;

    // Set the table record, at the moment this is only handling the version
    _setTableRecord(self, migrationFunction);

  };

  // Simple helper to return the storage type name
  Store.localStorage.prototype.typeName = function() {
    return 'localStorage';
  };

  Store.localStorage.prototype.prefix = function() {
    var self = this;
    return _prefixDatabase(self.name);
  };

  Store.localStorage.prototype.getPrefixedId = function(name) {
    var self = this;
    return self.prefix() + name;
  };

  //////////////////////////////////////////////////////////////////////////////
  // WRAP LOCALSTORAGE API
  //////////////////////////////////////////////////////////////////////////////

  Store.localStorage.prototype.getItem = function(name, callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.getItem require a callback function');

    try {

      // Get the string value
      var jsonObj = _storage.getItem(self.getPrefixedId(name));

      // Try to return the object of the parsed string
      callback(null, EJSON.parse(jsonObj));

    } catch(err) {

      // Callback with error
      callback(err);

    }

  };

  Store.localStorage.prototype.setItem = function(name, obj, callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.setItem require a callback function');

    try {

      // Stringify the object
      var jsonObj = EJSON.stringify(obj);

      // Try to set the stringified object
      callback(null, _storage.setItem(self.getPrefixedId(name), jsonObj));

    } catch(err) {

      // Callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.removeItem = function(name, callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.removeItem require a callback function');

    try {

      // Try to remove the item
      callback(null, _storage.removeItem(self.getPrefixedId(name)));

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.clear = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.clear require a callback function');

    try {

      // Find all relevant keys for this storage
      self.keys(function(err, keys) {
        if (err) {

          // On error we just callback
          callback(err);

        } else {

          // Iterate over keys and removing them one by one
          for (var i=0; i < keys.length; i++)
            self.removeItem(keys[i], noop);

          // Callback
          callback(null, keys.length);
        }
      });

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.keys = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.keys require a callback function');

    // Result to return
    var result = [];

    try {

      // Create the prefix test
      var regex = new RegExp('^' + self.prefix());

      for (var i = 0; i < _storage.length; i++) {

        // Test if the key is relevant to this store
        if (regex.test(_storage.key(i)))
          // Add the name
          result.push(_storage.key(i).replace(regex, ''));
      }

      // Return the result
      callback(null, result);

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.length = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.length require a callback function');

    try {

      // Get the keys
      self.keys(function(error, keys) {

        // Return the length
        callback(error, keys && keys.length || null);

      });

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  Store.localStorage.prototype.toObject = function(callback) {
    var self = this;

    // Check if callback is function
    if (typeof callback !== 'function')
      throw new Error('Storage.localStorage.keys require a callback function');

    // Result to return
    var result = {};

    try {

      // Create the prefix test
      var regex = new RegExp('^' + self.prefix());

      for (var i = 0; i < _storage.length; i++) {
        // Helper
        var key = _storage.key(i);

        // Test if the key is relevant to this store
        if (regex.test(key)) {
          try {

            // Get the string value
            var jsonObj = _storage.getItem(key);

            // Try to return the object of the parsed string
            result[key.replace(regex, '')] = EJSON.parse(jsonObj);

          } catch(err) {
            // NOOP
          }
        }

      }

      // Return the result
      callback(null, result);

    } catch(err) {

      // callback with error
      callback(err);

    }
  };

  //////////////////////////////////////////////////////////////////////////////
  // WRAP EVENTEMITTER API
  //////////////////////////////////////////////////////////////////////////////

  // Wrap the Event Emitter Api "on"
  Store.localStorage.prototype.on = function(/* arguments */) {
    this.eventemitter.on.apply(this.eventemitter, _.toArray(arguments));
  };

  // Wrap the Event Emitter Api "once"
  Store.localStorage.prototype.once = function(/* arguments */) {
    this.eventemitter.once.apply(this.eventemitter, _.toArray(arguments));
  };

  // Wrap the Event Emitter Api "off"
  Store.localStorage.prototype.off = function(/* arguments */) {
    this.eventemitter.off.apply(this.eventemitter, _.toArray(arguments));
  };

  // Wrap the Event Emitter Api "emit"
  Store.localStorage.prototype.emit = function(/* arguments */) {
    this.eventemitter.emit.apply(this.eventemitter, _.toArray(arguments));
  };

  // Add api helpers
  Store.localStorage.prototype.addListener = Store.localStorage.prototype.on;
  Store.localStorage.prototype.removeListener = Store.localStorage.prototype.off;
  Store.localStorage.prototype.removeAllListeners = Store.localStorage.prototype.off;

  // Add jquery like helpers
  Store.localStorage.prototype.one = Store.localStorage.prototype.once;
  Store.localStorage.prototype.trigger = Store.localStorage.prototype.emit;

  //////////////////////////////////////////////////////////////////////////////
  // WRAP LOCALSTORAGE EVENTHANDLER
  //////////////////////////////////////////////////////////////////////////////

  // This will be a quick test to see if we have any relations to the data
  var _prefixedByUs = new RegExp('^' + _prefix(''));

  // Add event handlers
  if (typeof window.addEventListener !== 'undefined') {
      // Add support for multiple tabs
      window.addEventListener('storage', function(e) {
      // Data changed in another tab, it would have updated localstorage, I'm
      // outdated so reload the tab and localstorage - but we test the prefix on the
      // key - since we actually make writes in the localstorage feature test

      // First of lets make sure that it was actually prefixed by us
      if (e.key && _prefixedByUs.test(e.key)) {

        // Okay, this looks familiar, now we try to lookup the storage instance
        // to emit an event on...

        // Remove the prefix
        var noPrefix = e.key.replace(_prefixedByUs, '');

        // So we know that the name dont contain suffix ".db."
        var elements = noPrefix.split('.db.');

        var storageName = elements.shift();

        // Get the remaining key
        var key = elements.join('.db.');

        // Get the affected storage
        var storageAdapter = _localStorageNS[storageName];

        if (storageAdapter) {

          // Emit the event on the storage
          storageAdapter.emit('storage', {
            key: key,
            newValue: EJSON.parse(e.newValue),
            oldValue: EJSON.parse(e.oldValue),
            originalKey: e.key,
            updatedAt: new Date(e.timeStamp),
            url: e.url,
            storage: storageAdapter
          });
        }

      }

    }, false);
}

}<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var assert = require('assert');
var restify = require('restify');
var url = require('url');

module.exports = function(options){
  var apiUrls = {};
  apiUrls.ps = '/ps';
  apiUrls.config = '/config';
  apiUrls.status = '/status';
  apiUrls.log = '/log';
  apiUrls.tasks = '/tasks';
  apiUrls.createTask = apiUrls.tasks + '/new';
  apiUrls.collections = '/collections';

  var api = false;
  var client = {};

  /**
   * Setup the restify client
   *
   * @param  {object} options Restify client options like url, timeout and retries
   */
  client.configure = function(options){
    if (!options) { options = {}; }
    var config = {};

    // Cheap and dirty default values.
    config.version = '*';
    config.url = options.url || 'http://localhost:8888';
    if (options.retry) { config.retry = {"retries":options.retry}; }
    config.timeout = options.timeout || 1;

    api = restify.createJsonClient(config);

    if (options.username && options.password) {
      api.basicAuth(options.username, options.password);
    }
  };
  // Configure the restify client
  client.configure(options);

  client.basicAuth = function(user, pass){
    api.basicAuth(user, pass);
  };

  client.ps = function(pid, callback){
    if (!callback && 'function' === typeof pid){
      callback = pid;
    }

    api.get(apiUrls.ps, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.getStatus = function(callback) {
    api.get(apiUrls.status, function(err, req, res, result) {
      callback(err, result);
      api.close();
    })
  };

  client.getConfig = function(callback) {
    api.get(apiUrls.config, function(err, req, res, result) {
      callback(err, result);
      api.close();
    })
  };

  client.setConfig = function(options, callback) {
    var setConfigUrl = url.parse(apiUrls.config);
    setConfigUrl.query = options;
    setConfigUrl = url.format(setConfigUrl);
    api.put(setConfigUrl, function(err, req, res, result) {
      callback(err, result);
      api.close();
    })
  };

  client.showLog = function(options, callback){
    if (!callback && 'function' === typeof options){
      callback = options;
    }

    var key = Object.keys(options.filter)[0];
    var val = options[key];

    var logUrl = (key) ? apiUrls.log+'/'+key+'/'+val : apiUrls.log;
    logUrl+="?lines="+options.lines;
    console.log(logUrl)
    api.get(logUrl, function(err, req, res, result) {
      console.log(err, result.length)
      callback(err, res.body); // This is weird that result is empty and res.body isn't
      api.close();
    });
  };

  client.getCollectionDefaults = function(collection, callback) {
    api.get(apiUrls.collections+'/'+collection+'/defaults', function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.setCollectionDefaults = function(collection, config, callback) {
    api.put(apiUrls.collections+'/'+collection+'/defaults', config, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.setTasks = function(collection, config, callback) {
    api.put(apiUrls.collections+'/'+collection, config, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.getTasks = function(options, callback){
    if (!callback && "function" === typeof options) {
      callback = options;
      options = false;
    }
    // URL BUILDER!
    var taskurl;
    if (options.collection) {
      taskurl = apiUrls.collections + '/' + options.collection;
    } else if (options.all) {
      taskurl = apiUrls.tasks;
    } else if (options.task) {
      taskurl = apiUrls.tasks + '/' + options.task;
    } else {
      return callback('What am I supposed to show? If you want all tasks use --all');
    }

    api.get(taskurl, function(err, req, res, result) {
      // console.log(err, result);
      if (err) {
        return callback(err);
      }

      callback(null, result);
      // api.close();
    });
  };

  client.createTask = function(config, callback){
    api.post(apiUrls.createTask, config, function(err, req, res, result) {
      if (err) {
        return callback(err);
      }

      callback(null, result);
      api.close();
    });
  };

  client.updateTask = function(config, callback){
    api.put(apiUrls.tasks + '/' + config.taskid, config, function(err, req, res, result) {
      if (err) {
        return callback(err);
      }

      callback(null, result);
      api.close();
    });
  };

  client.deleteTask = function(taskid, callback){
    api.del(apiUrls.tasks + '/' + taskid, function(err, req, res) {
      callback(err);
      api.close();
    });
  };

  return client;
};
<commit_msg>Support for enabling and disabling tasks/collections<commit_after>'use strict';

/**
 * Module dependencies.
 */
var assert = require('assert');
var restify = require('restify');
var url = require('url');

module.exports = function(options){
  var apiUrls = {};
  apiUrls.ps = '/ps';
  apiUrls.config = '/config';
  apiUrls.status = '/status';
  apiUrls.log = '/log';
  apiUrls.tasks = '/tasks';
  apiUrls.createTask = apiUrls.tasks + '/new';
  apiUrls.collections = '/collections';

  var api = false;
  var client = {};

  /**
   * Setup the restify client
   *
   * @param  {object} options Restify client options like url, timeout and retries
   */
  client.configure = function(options){
    if (!options) { options = {}; }
    var config = {};

    // Cheap and dirty default values.
    config.version = '*';
    config.url = options.url || 'http://localhost:8888';
    if (options.retry) { config.retry = {"retries":options.retry}; }
    config.timeout = options.timeout || 1;

    api = restify.createJsonClient(config);

    if (options.username && options.password) {
      api.basicAuth(options.username, options.password);
    }
  };
  // Configure the restify client
  client.configure(options);

  client.basicAuth = function(user, pass){
    api.basicAuth(user, pass);
  };

  client.ps = function(pid, callback){
    if (!callback && 'function' === typeof pid){
      callback = pid;
    }

    api.get(apiUrls.ps, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.getStatus = function(callback) {
    api.get(apiUrls.status, function(err, req, res, result) {
      callback(err, result);
      api.close();
    })
  };

  client.getConfig = function(callback) {
    api.get(apiUrls.config, function(err, req, res, result) {
      callback(err, result);
      api.close();
    })
  };

  client.setConfig = function(options, callback) {
    var setConfigUrl = url.parse(apiUrls.config);
    setConfigUrl.query = options;
    setConfigUrl = url.format(setConfigUrl);
    api.put(setConfigUrl, function(err, req, res, result) {
      callback(err, result);
      api.close();
    })
  };

  client.showLog = function(options, callback){
    if (!callback && 'function' === typeof options){
      callback = options;
    }

    var key = Object.keys(options.filter)[0];
    var val = options[key];

    var logUrl = (key) ? apiUrls.log+'/'+key+'/'+val : apiUrls.log;
    logUrl+="?lines="+options.lines;
    console.log(logUrl)
    api.get(logUrl, function(err, req, res, result) {
      console.log(err, result.length)
      callback(err, res.body); // This is weird that result is empty and res.body isn't
      api.close();
    });
  };

  client.getCollectionDefaults = function(collection, callback) {
    api.get(apiUrls.collections+'/'+collection+'/defaults', function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.setCollectionDefaults = function(collection, config, callback) {
    api.put(apiUrls.collections+'/'+collection+'/defaults', config, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.setTasks = function(collection, config, callback) {
    api.put(apiUrls.collections+'/'+collection, config, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.enableTasks = function(options, callback) {
    var enableTasksUrl;
    if (options.collection) {
      enableTasksUrl = apiUrls.collections+'/'+options.collection + '/enable'
    } else if (options.task) {
      enableTasksUrl = apiUrls.tasks+'/' + options.task + '/enable'
    } else {
      return callback(new Error('You did not specify a collection or task to enable'));
    }

    api.put(enableTasksUrl, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.disableTasks = function(options, callback) {
    var disableTasksUrl;
    if (options.collection) {
      disableTasksUrl = apiUrls.collections+'/'+options.collection + '/disable'
    } else if (options.task) {
      disableTasksUrl = apiUrls.tasks+'/' + options.task + '/disable'
    } else {
      return callback(new Error('You did not specify a collection or task to disable'));
    }

    api.put(disableTasksUrl, function(err, req, res, result) {
      callback(err, result);
      api.close();
    });
  };

  client.getTasks = function(options, callback){
    if (!callback && "function" === typeof options) {
      callback = options;
      options = false;
    }
    // URL BUILDER!
    var taskurl;
    if (options.collection) {
      taskurl = apiUrls.collections + '/' + options.collection;
    } else if (options.all) {
      taskurl = apiUrls.tasks;
    } else if (options.task) {
      taskurl = apiUrls.tasks + '/' + options.task;
    } else {
      return callback('What am I supposed to show? If you want all tasks use --all');
    }

    api.get(taskurl, function(err, req, res, result) {
      // console.log(err, result);
      if (err) {
        return callback(err);
      }

      callback(null, result);
      // api.close();
    });
  };

  client.createTask = function(config, callback){
    api.post(apiUrls.createTask, config, function(err, req, res, result) {
      if (err) {
        return callback(err);
      }

      callback(null, result);
      api.close();
    });
  };

  client.updateTask = function(config, callback){
    api.put(apiUrls.tasks + '/' + config.taskid, config, function(err, req, res, result) {
      if (err) {
        return callback(err);
      }

      callback(null, result);
      api.close();
    });
  };

  client.deleteTask = function(taskid, callback){
    api.del(apiUrls.tasks + '/' + taskid, function(err, req, res) {
      callback(err);
      api.close();
    });
  };

  return client;
};
<|endoftext|>


<commit_before>// client.js
// wrapper for api calls to PatentlyClear
var request = require('request');
var _ = require('underscore');
var url = require('url');
var pck = require('./package.json');

var apiHost = 'api.patentlyclear.com';

// **api([api_token = process.env.PC_API_TOKEN])**
// Require-ing this module will return a function that takes your PatentlyClear api token.
// If no token is passed then the library will attempt to use process.env.PC_API_TOKEN (on the server only).
// Simply call this function with your token to access the api functions.
//
//  `var api = new require('patentlyclear')('my api token')`
//  `var api = new require('patentlyclear')() // uses process.env.PC_API_TOKEN`
function contructor(api_token) {

  if (!api_token && process && process.env && process.env.PC_API_TOKEN) {
    api_token = process.env.PC_API_TOKEN;
  }

  if (!api_token) {
    throw new Error('No api_token provided');
  }

  // **getById(id, callback)**
  // Looks up a document by its id
  // Supplying an id that points to multiple resources (such as an application number)
  // will return all forms of that document.

  // Application ID
  // * `api.getById('US20140000001') => {application: {...}}`

  // Grant ID
  // * `api.getById('US8877876') => {grant: {...}}`

  // Application Number (both string and number formats are accepted)
  // * `api.getById('13/538,394') => {application: {...}, grant: {...}}`
  // * `api.getById(13538394) => {application: {...}, grant: {...}}`
  function getById(id, callback) {
    var formattedUrl = url.format({
      protocol: 'http',
      host: apiHost,
      pathname: id,
      query: {
        token: api_token
      }
    });
    request({url: formattedUrl, json: true}, apiResponse(callback));
  }
  this.getById = getById;

  // **search(payload, callback)**
  // Search for a set of documents with a query payload.

  // There are several fields that can be searched on. They are:
  // * terms [string]: Perform a full text search with a set of keywords.
  // * inventor [string]: Search on inventor name.
  // * assignee [string]: Who owns the document.
  // * filing_date {before: Date, after: Date}: When the document was filed.
  // * publication_date {before: Date, after: Date}: When the document was published.
  // * type: [application || grant]: What sort of document it is.
  // * size int: Total number of documents to return. (Max = 100)
  function search(payload, callback) {
    var formattedUrl = url.format({
      protocol: 'http',
      host: apiHost,
      pathname: 'search',
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.search = search;

  // **analyze(field, payload, callback)**
  // Fetches the top trends in a field for a search payload.
  function analyze(field, payload, callback) {
    var formattedUrl = url.format({
      protocol: 'http',
      host: apiHost,
      pathname: 'analyze/' + field,
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.analyze = analyze;

  // **backwardCitation(id, payload, callback)**
  // Fetches the backward citations of `id` (eg. the documents that `id` cites.) that match a given search query.
  // Optionally provide a search payload to filter documents that are retrieved.
  function backwardCitation(id, payload, callback) {
    if (!callback && typeof payload === 'function') {
      callback = payload;
      payload = {};
    }
    var formattedUrl = url.format({
      protocol: 'http',
      host: apiHost,
      pathname: 'backward_citation/' + id,
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.backwardCitation = backwardCitation;

  // **forwardCitation(id, payload, callback)**
  // Fetches the forward citations of `id`. (eg. the documents that cite `id`.)  that match a given search query.
  function forwardCitation(id, payload, callback) {
    if (!callback && typeof payload === 'function') {
      callback = payload;
      payload = {};
    }
    var formattedUrl = url.format({
      protocol: 'http',
      host: apiHost,
      pathname: 'forward_citation/' + id,
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.forwardCitation = forwardCitation;

  // **figure(id, figure_index)**
  // Returns (does not callback!) a url that can be placed in an `<img />` to display a figure from a patent.
  // Note that `figure_index` starts at 1
  function figure(id, figure_index) {
    return url.format({
      protocol: 'http',
      host: apiHost,
      pathname: 'figure/' + id + '/' + figure_index,
      query: {
        token: api_token
      }
    });
  }
  this.figure = figure;

  // **getVersion()**
  // Returns the version of this client
  function getVersion() {
    return pck.version;
  }
  this.getVersion = getVersion;

  return this;
}

function apiResponse(callback) {
  return function(err, response, body) {
    if (err) {
      return callback(err);
    }

    if (response.statusCode !== 200) {
      return callback(body);
    } else {
      if (!_.isArray(body)) {
        body = dateFormat(body);
      } else {
        body = body.map(function(o) {
          return dateFormat(o);
        });
      }
      return callback(null, body);
    }

  };
}
module.exports = contructor;

function dateFormat(obj) {
  if (obj.application) {
    obj.application.filing_date = new Date(obj.application.filing_date);
    obj.application.publication_date = new Date(obj.application.publication_date);
  }
  if (obj.grant) {
    obj.grant.filing_date = new Date(obj.grant.filing_date);
    obj.grant.publication_date = new Date(obj.grant.publication_date);
  }
  return obj;
}<commit_msg>Use https<commit_after>// client.js
// wrapper for api calls to PatentlyClear
var request = require('request');
var _ = require('underscore');
var url = require('url');
var pck = require('./package.json');

var apiHost = 'api.patentlyclear.com';

// **api([api_token = process.env.PC_API_TOKEN])**
// Require-ing this module will return a function that takes your PatentlyClear api token.
// If no token is passed then the library will attempt to use process.env.PC_API_TOKEN (on the server only).
// Simply call this function with your token to access the api functions.
//
//  `var api = new require('patentlyclear')('my api token')`
//  `var api = new require('patentlyclear')() // uses process.env.PC_API_TOKEN`
function contructor(api_token) {

  if (!api_token && process && process.env && process.env.PC_API_TOKEN) {
    api_token = process.env.PC_API_TOKEN;
  }

  if (!api_token) {
    throw new Error('No api_token provided');
  }

  // **getById(id, callback)**
  // Looks up a document by its id
  // Supplying an id that points to multiple resources (such as an application number)
  // will return all forms of that document.

  // Application ID
  // * `api.getById('US20140000001') => {application: {...}}`

  // Grant ID
  // * `api.getById('US8877876') => {grant: {...}}`

  // Application Number (both string and number formats are accepted)
  // * `api.getById('13/538,394') => {application: {...}, grant: {...}}`
  // * `api.getById(13538394) => {application: {...}, grant: {...}}`
  function getById(id, callback) {
    var formattedUrl = url.format({
      protocol: 'https',
      host: apiHost,
      pathname: id,
      query: {
        token: api_token
      }
    });
    request({url: formattedUrl, json: true}, apiResponse(callback));
  }
  this.getById = getById;

  // **search(payload, callback)**
  // Search for a set of documents with a query payload.

  // There are several fields that can be searched on. They are:
  // * terms [string]: Perform a full text search with a set of keywords.
  // * inventor [string]: Search on inventor name.
  // * assignee [string]: Who owns the document.
  // * filing_date {before: Date, after: Date}: When the document was filed.
  // * publication_date {before: Date, after: Date}: When the document was published.
  // * type: [application || grant]: What sort of document it is.
  // * size int: Total number of documents to return. (Max = 100)
  function search(payload, callback) {
    var formattedUrl = url.format({
      protocol: 'https',
      host: apiHost,
      pathname: 'search',
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.search = search;

  // **analyze(field, payload, callback)**
  // Fetches the top trends in a field for a search payload.
  function analyze(field, payload, callback) {
    var formattedUrl = url.format({
      protocol: 'https',
      host: apiHost,
      pathname: 'analyze/' + field,
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.analyze = analyze;

  // **backwardCitation(id, payload, callback)**
  // Fetches the backward citations of `id` (eg. the documents that `id` cites.) that match a given search query.
  // Optionally provide a search payload to filter documents that are retrieved.
  function backwardCitation(id, payload, callback) {
    if (!callback && typeof payload === 'function') {
      callback = payload;
      payload = {};
    }
    var formattedUrl = url.format({
      protocol: 'https',
      host: apiHost,
      pathname: 'backward_citation/' + id,
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.backwardCitation = backwardCitation;

  // **forwardCitation(id, payload, callback)**
  // Fetches the forward citations of `id`. (eg. the documents that cite `id`.)  that match a given search query.
  function forwardCitation(id, payload, callback) {
    if (!callback && typeof payload === 'function') {
      callback = payload;
      payload = {};
    }
    var formattedUrl = url.format({
      protocol: 'https',
      host: apiHost,
      pathname: 'forward_citation/' + id,
      query: {
        token: api_token
      }
    });
    request.post({url: formattedUrl, body: payload, json: true}, apiResponse(callback));
  }
  this.forwardCitation = forwardCitation;

  // **figure(id, figure_index)**
  // Returns (does not callback!) a url that can be placed in an `<img />` to display a figure from a patent.
  // Note that `figure_index` starts at 1
  function figure(id, figure_index) {
    return url.format({
      protocol: 'https',
      host: apiHost,
      pathname: 'figure/' + id + '/' + figure_index,
      query: {
        token: api_token
      }
    });
  }
  this.figure = figure;

  // **getVersion()**
  // Returns the version of this client
  function getVersion() {
    return pck.version;
  }
  this.getVersion = getVersion;

  return this;
}

function apiResponse(callback) {
  return function(err, response, body) {
    if (err) {
      return callback(err);
    }

    if (response.statusCode !== 200) {
      return callback(body);
    } else {
      if (!_.isArray(body)) {
        body = dateFormat(body);
      } else {
        body = body.map(function(o) {
          return dateFormat(o);
        });
      }
      return callback(null, body);
    }

  };
}
module.exports = contructor;

function dateFormat(obj) {
  if (obj.application) {
    obj.application.filing_date = new Date(obj.application.filing_date);
    obj.application.publication_date = new Date(obj.application.publication_date);
  }
  if (obj.grant) {
    obj.grant.filing_date = new Date(obj.grant.filing_date);
    obj.grant.publication_date = new Date(obj.grant.publication_date);
  }
  return obj;
}<|endoftext|>


<commit_before>/*global document, window */
import React from 'react';
import ReactDOM from 'react-dom';
import debug from 'debug';
import { createElementWithContext } from 'fluxible-addons-react';
import app from './app';
import { IntlProvider } from 'react-intl';
import es6Promise from 'es6-promise';
es6Promise.polyfill();

const debugClient = debug('slidewiki-platform');
const dehydratedState = window.App; // Sent from the server

window.React = ReactDOM; // For chrome dev tool support

// expose debug object to browser, so that it can be enabled/disabled from browser:
// https://github.com/visionmedia/debug#browser-support
window.fluxibleDebug = debug;

// Contains utils to download the locale data for the current language, eventually
// requiring the `Intl` polyfill for browser not supporting it
// It is used in client.js *before* rendering the root component.

import { addLocaleData } from 'react-intl';
import isIntlLocaleSupported from 'intl-locales-supported';

// Returns a promise which is resolved when Intl has been polyfilled

function loadIntlPolyfill(locale) {

    if (window.Intl && isIntlLocaleSupported(locale)) {
        // all fine: Intl is in the global scope and the locale data is available
        return Promise.resolve();
    }

    return new Promise((resolve) => {
        debug('Intl or locale data for %s not available, downloading the polyfill...', locale);

        // When building: create a intl chunk with webpack
        // When executing: run the callback once the chunk has been download.
        require.ensure(['intl'], (require) => {
            require('intl'); // apply the polyfill
            debug('Intl polyfill for %s has been loaded', locale);
            resolve();
        }, 'intl');

    });

};

// Returns a promise which is resolved as the required locale-data chunks
// has been downloaded with webpack's require.ensure. For each language,
// we make two different chunks: one for browsers supporting `intl` and one
// for those who don't.
// The react-intl locale-data is required, for example, by the FormattedRelative
// component.
function loadLocaleData(locale) {
    const hasIntl = isIntlLocaleSupported(locale);

    // Make sure ReactIntl is in the global scope: this is required for adding locale-data
    // Since ReactIntl needs the `Intl` polyfill to be required (sic) we must place
    // this require here, when loadIntlPolyfill is supposed to be present
    //require('expose?ReactIntl!react-intl');

    // TODO remove this copy-paste code by using the locale variable
    // TODO replace use of require.ensure with System.import (webpack 2 way)

    return new Promise( (resolve) => {

        switch (locale) {

            // english
            case 'en':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/en',
                        'react-intl/locale-data/en'
                    ], (require) => {
                        require('intl/locale-data/jsonp/en');
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/en'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en-no-intl');
                }
                break;

            // russian
            case 'ru':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/ru',
                        'react-intl/locale-data/ru'
                    ], (require) => {
                        require('intl/locale-data/jsonp/ru');
                        addLocaleData(require('react-intl/locale-data/ru'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ru');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/ru'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/ru'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ru-no-intl');
                }
                break;

                // german
            case 'de':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/de',
                        'react-intl/locale-data/de'
                    ], (require) => {
                        require('intl/locale-data/jsonp/de');
                        addLocaleData(require('react-intl/locale-data/de'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-de');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/de'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/de'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-de-no-intl');
                }
                break;

                // russian
            case 'nl':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/nl',
                        'react-intl/locale-data/nl'
                    ], (require) => {
                        require('intl/locale-data/jsonp/nl');
                        addLocaleData(require('react-intl/locale-data/nl'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-nl');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/nl'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/nl'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-nl-no-intl');
                }
                break;

            //spanish - yes, before the catalonian =)
            case 'es':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/es',
                        'react-intl/locale-data/es'
                    ], (require) => {
                        require('intl/locale-data/jsonp/es');
                        addLocaleData(require('react-intl/locale-data/es'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-es');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/es'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/es'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-es-no-intl');
                }
                break;

            //catalonian
            case 'ca':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/ca',
                        'react-intl/locale-data/ca'
                    ], (require) => {
                        require('intl/locale-data/jsonp/ca');
                        addLocaleData(require('react-intl/locale-data/ca'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ca');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/ca'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/ca'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ca-no-intl');
                }
                break;

            //gaelic - let's see if we can involve external users to help us with the gaelic as well ;
            case 'gd':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/gd',
                        'react-intl/locale-data/gd'
                    ], (require) => {
                        require('intl/locale-data/jsonp/gd');
                        addLocaleData(require('react-intl/locale-data/gd'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-gd');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/gd'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/gd'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-gd-no-intl');
                }
                break;

            //greek
            case 'el':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/el',
                        'react-intl/locale-data/el'
                    ], (require) => {
                        require('intl/locale-data/jsonp/el');
                        addLocaleData(require('react-intl/locale-data/el'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-el');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/el'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/el'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-el-no-intl');
                }
                break;

            //italian
            case 'it':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/it',
                        'react-intl/locale-data/it'
                    ], (require) => {
                        require('intl/locale-data/jsonp/it');
                        addLocaleData(require('react-intl/locale-data/it'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-it');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/it'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/it'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-it-no-intl');
                }
                break;

            //serbian
            case 'sr':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/sr',
                        'react-intl/locale-data/sr'
                    ], (require) => {
                        require('intl/locale-data/jsonp/sr');
                        addLocaleData(require('react-intl/locale-data/sr'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-sr');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/sr'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/sr'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-sr-no-intl');
                }
                break;

                //french
            case 'fr':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/fr',
                        'react-intl/locale-data/fr'
                    ], (require) => {
                        require('intl/locale-data/jsonp/fr');
                        addLocaleData(require('react-intl/locale-data/fr'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-fr');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/fr'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/fr'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-fr-no-intl');
                }
                break;

            default:
                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/en',
                        'react-intl/locale-data/en'
                    ], (require) => {
                        require('intl/locale-data/jsonp/en');
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/en'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en-no-intl');
                }
                break;

        }

    });

};

//removing hash, for redirects
function removeHash () {
    let scrollV, scrollH, loc = window.location;
    if ('pushState' in history)
        history.pushState('', document.title, loc.pathname + loc.search);
    else {
        // Prevent scrolling by storing the page's current scroll offset
        scrollV = document.body.scrollTop;
        scrollH = document.body.scrollLeft;

        loc.hash = '';

        // Restore the scroll offset, should be flicker free
        document.body.scrollTop = scrollV;
        document.body.scrollLeft = scrollH;
    }
}

function renderApp(locale) {
    debugClient('rehydrating app');
    // pass in the dehydrated server state from server.js
    app.rehydrate(dehydratedState, (err, context) => {
        if (err) {
            throw err;
        }
        window.context = context;
        removeHash();
        const mountNode = document.getElementById('app');

        const Root = app.getComponent();
        const messages = require('./intl/'+locale+'.json');
        ReactDOM.render(
            <IntlProvider locale={ locale } messages={messages}>
            <Root context={ context.getComponentContext() } />
            </IntlProvider>
            , mountNode, () => {
                debug('Root component has been mounted');
            });

            // debugClient('React Rendering');
            // ReactDOM.render(
            //     createElementWithContext(context),
            //     mountNode,
            //     () => debugClient('React Rendered')
            // );
    });
}

    // Load the Intl polyfill and required locale data
const locale = document.documentElement.getAttribute('lang');

loadIntlPolyfill(locale)
.then(loadLocaleData.bind(null, locale))
.then(renderApp.bind(null, locale))
.catch( (err) => {
    console.error(err);
});
<commit_msg>Fix bug where back button needs to be clicked twice to work sometimes<commit_after>/*global document, window */
import React from 'react';
import ReactDOM from 'react-dom';
import debug from 'debug';
import { createElementWithContext } from 'fluxible-addons-react';
import app from './app';
import { IntlProvider } from 'react-intl';
import es6Promise from 'es6-promise';
es6Promise.polyfill();

const debugClient = debug('slidewiki-platform');
const dehydratedState = window.App; // Sent from the server

window.React = ReactDOM; // For chrome dev tool support

// expose debug object to browser, so that it can be enabled/disabled from browser:
// https://github.com/visionmedia/debug#browser-support
window.fluxibleDebug = debug;

// Contains utils to download the locale data for the current language, eventually
// requiring the `Intl` polyfill for browser not supporting it
// It is used in client.js *before* rendering the root component.

import { addLocaleData } from 'react-intl';
import isIntlLocaleSupported from 'intl-locales-supported';

// Returns a promise which is resolved when Intl has been polyfilled

function loadIntlPolyfill(locale) {

    if (window.Intl && isIntlLocaleSupported(locale)) {
        // all fine: Intl is in the global scope and the locale data is available
        return Promise.resolve();
    }

    return new Promise((resolve) => {
        debug('Intl or locale data for %s not available, downloading the polyfill...', locale);

        // When building: create a intl chunk with webpack
        // When executing: run the callback once the chunk has been download.
        require.ensure(['intl'], (require) => {
            require('intl'); // apply the polyfill
            debug('Intl polyfill for %s has been loaded', locale);
            resolve();
        }, 'intl');

    });

};

// Returns a promise which is resolved as the required locale-data chunks
// has been downloaded with webpack's require.ensure. For each language,
// we make two different chunks: one for browsers supporting `intl` and one
// for those who don't.
// The react-intl locale-data is required, for example, by the FormattedRelative
// component.
function loadLocaleData(locale) {
    const hasIntl = isIntlLocaleSupported(locale);

    // Make sure ReactIntl is in the global scope: this is required for adding locale-data
    // Since ReactIntl needs the `Intl` polyfill to be required (sic) we must place
    // this require here, when loadIntlPolyfill is supposed to be present
    //require('expose?ReactIntl!react-intl');

    // TODO remove this copy-paste code by using the locale variable
    // TODO replace use of require.ensure with System.import (webpack 2 way)

    return new Promise( (resolve) => {

        switch (locale) {

            // english
            case 'en':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/en',
                        'react-intl/locale-data/en'
                    ], (require) => {
                        require('intl/locale-data/jsonp/en');
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/en'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en-no-intl');
                }
                break;

            // russian
            case 'ru':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/ru',
                        'react-intl/locale-data/ru'
                    ], (require) => {
                        require('intl/locale-data/jsonp/ru');
                        addLocaleData(require('react-intl/locale-data/ru'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ru');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/ru'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/ru'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ru-no-intl');
                }
                break;

                // german
            case 'de':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/de',
                        'react-intl/locale-data/de'
                    ], (require) => {
                        require('intl/locale-data/jsonp/de');
                        addLocaleData(require('react-intl/locale-data/de'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-de');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/de'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/de'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-de-no-intl');
                }
                break;

                // russian
            case 'nl':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/nl',
                        'react-intl/locale-data/nl'
                    ], (require) => {
                        require('intl/locale-data/jsonp/nl');
                        addLocaleData(require('react-intl/locale-data/nl'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-nl');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/nl'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/nl'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-nl-no-intl');
                }
                break;

            //spanish - yes, before the catalonian =)
            case 'es':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/es',
                        'react-intl/locale-data/es'
                    ], (require) => {
                        require('intl/locale-data/jsonp/es');
                        addLocaleData(require('react-intl/locale-data/es'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-es');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/es'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/es'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-es-no-intl');
                }
                break;

            //catalonian
            case 'ca':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/ca',
                        'react-intl/locale-data/ca'
                    ], (require) => {
                        require('intl/locale-data/jsonp/ca');
                        addLocaleData(require('react-intl/locale-data/ca'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ca');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/ca'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/ca'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-ca-no-intl');
                }
                break;

            //gaelic - let's see if we can involve external users to help us with the gaelic as well ;
            case 'gd':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/gd',
                        'react-intl/locale-data/gd'
                    ], (require) => {
                        require('intl/locale-data/jsonp/gd');
                        addLocaleData(require('react-intl/locale-data/gd'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-gd');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/gd'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/gd'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-gd-no-intl');
                }
                break;

            //greek
            case 'el':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/el',
                        'react-intl/locale-data/el'
                    ], (require) => {
                        require('intl/locale-data/jsonp/el');
                        addLocaleData(require('react-intl/locale-data/el'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-el');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/el'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/el'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-el-no-intl');
                }
                break;

            //italian
            case 'it':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/it',
                        'react-intl/locale-data/it'
                    ], (require) => {
                        require('intl/locale-data/jsonp/it');
                        addLocaleData(require('react-intl/locale-data/it'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-it');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/it'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/it'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-it-no-intl');
                }
                break;

            //serbian
            case 'sr':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/sr',
                        'react-intl/locale-data/sr'
                    ], (require) => {
                        require('intl/locale-data/jsonp/sr');
                        addLocaleData(require('react-intl/locale-data/sr'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-sr');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/sr'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/sr'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-sr-no-intl');
                }
                break;

                //french
            case 'fr':

                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/fr',
                        'react-intl/locale-data/fr'
                    ], (require) => {
                        require('intl/locale-data/jsonp/fr');
                        addLocaleData(require('react-intl/locale-data/fr'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-fr');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/fr'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/fr'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-fr-no-intl');
                }
                break;

            default:
                if (!hasIntl) {

                    require.ensure([
                        'intl/locale-data/jsonp/en',
                        'react-intl/locale-data/en'
                    ], (require) => {
                        require('intl/locale-data/jsonp/en');
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('Intl and ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en');
                }
                else {
                    require.ensure([
                        'react-intl/locale-data/en'
                    ], (require) => {
                        addLocaleData(require('react-intl/locale-data/en'));
                        debug('ReactIntl locale-data for %s has been downloaded', locale);
                        resolve();
                    }, 'locale-en-no-intl');
                }
                break;

        }

    });

};

//removing hash, for redirects
function removeHash () {
    let scrollV, scrollH, loc = window.location;
    if ('replaceState' in history)
        history.replaceState('', document.title, loc.pathname + loc.search);
    else {
        // Prevent scrolling by storing the page's current scroll offset
        scrollV = document.body.scrollTop;
        scrollH = document.body.scrollLeft;

        loc.hash = '';

        // Restore the scroll offset, should be flicker free
        document.body.scrollTop = scrollV;
        document.body.scrollLeft = scrollH;
    }
}

function renderApp(locale) {
    debugClient('rehydrating app');
    // pass in the dehydrated server state from server.js
    app.rehydrate(dehydratedState, (err, context) => {
        if (err) {
            throw err;
        }
        window.context = context;
        removeHash();
        const mountNode = document.getElementById('app');

        const Root = app.getComponent();
        const messages = require('./intl/'+locale+'.json');
        ReactDOM.render(
            <IntlProvider locale={ locale } messages={messages}>
            <Root context={ context.getComponentContext() } />
            </IntlProvider>
            , mountNode, () => {
                debug('Root component has been mounted');
            });

            // debugClient('React Rendering');
            // ReactDOM.render(
            //     createElementWithContext(context),
            //     mountNode,
            //     () => debugClient('React Rendered')
            // );
    });
}

    // Load the Intl polyfill and required locale data
const locale = document.documentElement.getAttribute('lang');

loadIntlPolyfill(locale)
.then(loadLocaleData.bind(null, locale))
.then(renderApp.bind(null, locale))
.catch( (err) => {
    console.error(err);
});
<|endoftext|>


<commit_before>config = {
  'roomServer': 'ws://199.21.79.248:444/slither', // Set this to your preferred room.
  'mapServer': 'ws://websocket_server:8000', // Set this to the location of the running web server
  'color': 'red', // Each player should choose a color.
  'name': 'kainar' // Each player should put their username.
}

denSocket = null;
denSnakes = null;
denLbh = null;
denLbs = null;
denReset = null;

denReset = function() {
  denSocket && denSocket.close();
  denSocket = null;
  if (denLbh) denLbh.remove();
  if (denLbs) denLbs.remove();

  if (denSnakes) {
    for (var snakeId in denSnakes) {
      var denSnake = denSnakes[snakeId];
      denSnake.remove();
    }
  }
  denSnakes = {};
}

denSetup = function() {
  denReset();
  ws = new WebSocket(config.roomServer);

  // Setup init.
  denSocket = new WebSocket(config.mapServer);
  denSnakes = {};

  // Setup socket
  denSocket.onmessage = function(e) {
    var data = JSON.parse(e.data);
    if (data.event === 'delete') {
      var denSnake = denSnakes[data.id];
      denSnake.remove();
      delete denSnakes[data.id];
      return;
    }
    if (denSnakes[data.id]) {
      var denSnake = denSnakes[data.id];
      denSnake.style.top = data.top;
      denSnake.style.left = data.left;
      denSnake.score = Math.floor(15 * (fpsls[data.sct] + data.fam / fmlts[data.sct] - 1) - 5) / 1
    } else {
      denSnake = document.createElement("img");
      lc.width = lc.height = 14;
      ctx = lc.getContext("2d");
      ctx.fillStyle = data.color;
      ctx.strokeStyle = "#000000";
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.arc(7, 7, 2.5, 0, pi2);
      ctx.stroke();
      ctx.fill();
      denSnake.src = lc.toDataURL();
      denSnake.className = "nsi";
      denSnake.style.position = "absolute";
      denSnake.style.left = data.left;
      denSnake.style.top = data.top;
      denSnake.style.opacity = 1;
      denSnake.style.zIndex = 13;
      denSnake.name = data.name;
      denSnake.color = data.color;
        denSnake.score = 0;
      denSnakes[data.id] = denSnake;
      trf(myloc, agpu);
      loch.appendChild(denSnake);
    }
  }
  // Setup leaderboard.
  denLbh = document.createElement("div");
  denLbh.className = "nsi";
  denLbh.style.position = "fixed";
  denLbh.style.left = "4px";
  denLbh.style.top = "4px";
  denLbh.style.textAlign = "center";
  denLbh.style.width = "255px";
  denLbh.style.height = "28px";
  denLbh.style.color = "#ffffff";
  denLbh.style.fontFamily = 'Arial, "Helvetica Neue", Helvetica, sans-serif';
  denLbh.style.fontSize = "21px";
  denLbh.style.fontWeight = "bold";
  denLbh.style.overflow = "hidden";
  denLbh.style.opacity = .7;
  denLbh.style.zIndex = 7;
  denLbh.style.cursor = "default";
  var lstr = "Den Leaderboard";
  "de" == lang ? lstr = "Bestenliste" : "fr" == lang ? lstr = "Gagnants" : "pt" == lang && (lstr = "L\u00edderes");
  denLbh.textContent = lstr;
  trf(denLbh, agpu);
  document.body.appendChild(denLbh);

  denLbs = document.createElement("div");
  denLbs.className = "nsi";
  denLbs.style.position = "fixed";
  denLbs.style.textAlign = "center";
  denLbs.style.left = "20px";
  denLbs.style.top = "32px";
  denLbs.style.width = "150px";
  denLbs.style.height = "800px";
  denLbs.style.color = "#ffffff";
  denLbs.style.fontFamily = 'Arial, "Helvetica Neue", Helvetica, sans-serif';
  denLbs.style.fontSize = "12px";
  denLbs.style.overflow = "hidden";
  denLbs.style.opacity = .7;
  denLbs.style.zIndex = 7;
  denLbs.style.cursor = "default";
  denLbs.style.lineHeight = "150%";
  trf(denLbs, agpu);
  document.body.appendChild(denLbs);
  return setInterval(updateUi, 1000);
}

updateLocation = function() {
  denSocket.send(JSON.stringify({
    top: myloc.style.top,
    left: myloc.style.left,
    color: config.color,
    name: config.name,
    // Internal score representation
    sct: snake.sct,
    fam: snake.fam,
  }));
}

updateLeaderboard = function() {
  var scores = "";
  var sortedSnakes = [];
  denLbs.innerHTML = '';

  for (var denSnakeId in denSnakes) {
    if (!denSnakes.hasOwnProperty(denSnakeId)) {
      continue;
    }
    var denSnake = denSnakes[denSnakeId];
    sortedSnakes.push([denSnake, denSnake.score]);
  }
  sortedSnakes.sort(function(a, b) {
    return b[1] - a[1]
  })

  for (var idx in sortedSnakes) {
    var denSnake = sortedSnakes[idx][0];
    var rank = 1 + parseFloat(idx);
    var rankText = '# ' + rank + '    ';
    scores += '' + rankText + denSnake.name + ': ' + denSnake.score + "
";
  }
  denLbs.innerHTML = scores;
}

updateUi = function() {
  if (!connected) {
    denReset();
    clearInterval(denPeriodic);
  } else {
    updateLocation();
    updateLeaderboard();
  }
}

denPeriodic = denSetup();
<commit_msg>Leaderboard works correctly.<commit_after>config = {
  'roomServer': 'ws://199.21.79.248:444/slither', // Set this to your preferred room.
  'mapServer': 'ws://websocket_server:8000', // Set this to the location of the running web server
  'color': 'red', // Each player should choose a color.
  'name': 'kainar' // Each player should put their username.
}

denSocket = null;
denSnakes = null;
denLbh = null;
denLbs = null;
denReset = null;

denReset = function() {
  denSocket && denSocket.close();
  denSocket = null;
  denLbh = document.getElementById("leaderboardTag");
  denLbs = document.getElementById("leaderboardScores");
  if (denLbh) denLbh.remove();
  if (denLbs) denLbs.remove();

  var oldSnakes = document.getElementsByClassName("denSnake");
  for (var i=0; i < oldSnakes.length; i++) {
    oldSnakes[i].remove();
  }
  denSnakes = {};
}

denSetup = function() {
  denReset();
  ws = new WebSocket(config.roomServer);

  // Setup init.
  denSocket = new WebSocket(config.mapServer);
  denSnakes = {};

  // Setup socket
  denSocket.onmessage = function(e) {
    var data = JSON.parse(e.data);
    if (data.event === 'delete') {
      var denSnake = denSnakes[data.id];
      denSnake.remove();
      delete denSnakes[data.id];
      return;
    }
    if (denSnakes[data.id]) {
      var denSnake = denSnakes[data.id];
      denSnake.style.top = data.top;
      denSnake.style.left = data.left;
      denSnake.score = Math.floor(15 * (fpsls[data.sct] + data.fam / fmlts[data.sct] - 1) - 5) / 1
    } else {
      denSnake = document.createElement("img");
      lc.width = lc.height = 14;
      ctx = lc.getContext("2d");
      ctx.fillStyle = data.color;
      ctx.strokeStyle = "#000000";
      ctx.lineWidth = 2;
      ctx.beginPath();
      ctx.arc(7, 7, 2.5, 0, pi2);
      ctx.stroke();
      ctx.fill();
      denSnake.src = lc.toDataURL();
        denSnake.classList.add("nsi");
        denSnake.classList.add("denSnake");
      denSnake.style.position = "absolute";
      denSnake.style.left = data.left;
      denSnake.style.top = data.top;
      denSnake.style.opacity = 1;
      denSnake.style.zIndex = 13;
      denSnake.name = data.name;
      denSnake.color = data.color;
        denSnake.score = 0;
      denSnakes[data.id] = denSnake;
      trf(myloc, agpu);
      loch.appendChild(denSnake);
    }
  }
  // Setup leaderboard.

  denLbh = document.createElement("div");
  denLbh.className = "nsi";
  denLbh.setAttribute('id', 'leaderboardTag');
  denLbh.style.position = "fixed";
  denLbh.style.left = "4px";
  denLbh.style.top = "4px";
  denLbh.style.textAlign = "center";
  denLbh.style.width = "255px";
  denLbh.style.height = "28px";
  denLbh.style.color = "#ffffff";
  denLbh.style.fontFamily = 'Arial, "Helvetica Neue", Helvetica, sans-serif';
  denLbh.style.fontSize = "21px";
  denLbh.style.fontWeight = "bold";
  denLbh.style.overflow = "hidden";
  denLbh.style.opacity = .7;
  denLbh.style.zIndex = 7;
  denLbh.style.cursor = "default";
  var lstr = "Den Leaderboard";
  "de" == lang ? lstr = "Bestenliste" : "fr" == lang ? lstr = "Gagnants" : "pt" == lang && (lstr = "L\u00edderes");
  denLbh.textContent = lstr;
  trf(denLbh, agpu);
  document.body.appendChild(denLbh);

  denLbs = document.createElement("div");
  denLbs.className = "nsi";
  denLbs.setAttribute('id', 'leaderboardScores');
  denLbs.style.position = "fixed";
  denLbs.style.textAlign = "center";
  denLbs.style.left = "20px";
  denLbs.style.top = "32px";
  denLbs.style.width = "150px";
  denLbs.style.height = "800px";
  denLbs.style.color = "#ffffff";
  denLbs.style.fontFamily = 'Arial, "Helvetica Neue", Helvetica, sans-serif';
  denLbs.style.fontSize = "12px";
  denLbs.style.overflow = "hidden";
  denLbs.style.opacity = .7;
  denLbs.style.zIndex = 7;
  denLbs.style.cursor = "default";
  denLbs.style.lineHeight = "150%";
  trf(denLbs, agpu);
  document.body.appendChild(denLbs);
  return setInterval(updateUi, 1000);
}

updateLocation = function() {
  denSocket.send(JSON.stringify({
    top: myloc.style.top,
    left: myloc.style.left,
    color: config.color,
    name: config.name,
    // Internal score representation
    sct: snake.sct,
    fam: snake.fam,
  }));
}

updateLeaderboard = function() {
  var scores = "";
  var sortedSnakes = [];
  denLbs.innerHTML = '';

  for (var denSnakeId in denSnakes) {
    if (!denSnakes.hasOwnProperty(denSnakeId)) {
      continue;
    }
    var denSnake = denSnakes[denSnakeId];
    sortedSnakes.push([denSnake, denSnake.score]);
  }
  sortedSnakes.sort(function(a, b) {
    return b[1] - a[1]
  })

  for (var idx in sortedSnakes) {
    var denSnake = sortedSnakes[idx][0];
    var rank = 1 + parseFloat(idx);
    var rankText = '# ' + rank + '    ';
    scores += '' + rankText + denSnake.name + ': ' + denSnake.score + "
";
  }
  denLbs.innerHTML = scores;
}

updateUi = function() {
  if (!connected) {
    denReset();
    clearInterval(denPeriodic);
  } else {
    updateLocation();
    updateLeaderboard();
  }
}

denPeriodic = denSetup();
<|endoftext|>