<commit_before>var async = require('async'),
    Resource = require('./Resource'),
    EventEmitter = require('eventemitter3');

/**
 * Manages the state and loading of multiple resources to load.
 *
 * @class
 * @param [baseUrl=''] {string} The base url for all resources loaded by this loader.
 * @param [concurrency=10] {number} The number of resources to load concurrently.
 */
function Loader(baseUrl, concurrency) {
    EventEmitter.call(this);

    concurrency = concurrency || 10;

    /**
     * The base url for all resources loaded by this loader.
     *
     * @member {string}
     */
    this.baseUrl = baseUrl || '';

    /**
     * The progress percent of the loader going through the queue.
     *
     * @member {number}
     */
    this.progress = 0;

    /**
     * Loading state of the loader, true if it is currently loading resources.
     *
     * @member {boolean}
     */
    this.loading = false;

    /**
     * The percentage of total progress that a single resource represents.
     *
     * @member {number}
     */
    this._progressChunk = 0;

    /**
     * The middleware to run before loading each resource.
     *
     * @member {function[]}
     */
    this._beforeMiddleware = [];

    /**
     * The middleware to run after loading each resource.
     *
     * @member {function[]}
     */
    this._afterMiddleware = [];

    /**
     * The `_loadResource` function bound with this object context.
     *
     * @private
     * @member {function}
     */
    this._boundLoadResource = this._loadResource.bind(this);

    /**
     * The `_onLoad` function bound with this object context.
     *
     * @private
     * @member {function}
     */
    this._boundOnLoad = this._onLoad.bind(this);

    /**
     * The resource buffer that fills until `load` is called to start loading resources.
     *
     * @private
     * @member {Resource[]}
     */
    this._buffer = [];

    /**
     * Used to track load completion.
     *
     * @private
     * @member {number}
     */
    this._numToLoad = 0;

    /**
     * The resources waiting to be loaded.
     *
     * @private
     * @member {Resource[]}
     */
    this._queue = async.queue(this._boundLoadResource, concurrency);

    /**
     * All the resources for this loader keyed by name.
     *
     * @member {object<string, Resource>}
     */
    this.resources = {};

    /**
     * Emitted once per loaded or errored resource.
     *
     * @event progress
     * @memberof Loader#
     */

    /**
     * Emitted once per errored resource.
     *
     * @event error
     * @memberof Loader#
     */

    /**
     * Emitted once per loaded resource.
     *
     * @event load
     * @memberof Loader#
     */

    /**
     * Emitted when the loader begins to process the queue.
     *
     * @event start
     * @memberof Loader#
     */

    /**
     * Emitted when the queued resources all load.
     *
     * @event complete
     * @memberof Loader#
     */
}

Loader.prototype = Object.create(EventEmitter.prototype);
Loader.prototype.constructor = Loader;
module.exports = Loader;

/**
 * Adds a resource (or multiple resources) to the loader queue.
 *
 * This function can take a wide variety of different parameters. The only thing that is always
 * required the url to load. All the following will work:
 *
 * ```js
 * loader
 *     // normal param syntax
 *     .add('key', 'http://...', function () {})
 *     .add('http://...', function () {})
 *     .add('http://...')
 *
 *     // object syntax
 *     .add({
 *         name: 'key2',
 *         url: 'http://...'
 *     }, function () {})
 *     .add({
 *         url: 'http://...'
 *     }, function () {})
 *     .add({
 *         name: 'key3',
 *         url: 'http://...'
 *         onComplete: function () {}
 *     })
 *     .add({
 *         url: 'https://...',
 *         onComplete: function () {},
 *         crossOrigin: true
 *     })
 *
 *     // you can also pass an array of objects or urls or both
 *     .add([
 *         { name: 'key4', url: 'http://...', onComplete: function () {} },
 *         { url: 'http://...', onComplete: function () {} },
 *         'http://...'
 *     ]);
 * ```
 *
 * @alias enqueue
 * @param [name] {string} The name of the resource to load, if not passed the url is used.
 * @param url {string} The url for this resource, relative to the baseUrl of this loader.
 * @param [options] {object} The options for the load.
 * @param [options.crossOrigin] {boolean} Is this request cross-origin? Default is to determine automatically.
 * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.XHR_LOAD_TYPE} How should this resource be loaded?
 * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being
 *      loaded be interpreted when using XHR?
 * @param [callback] {function} Function to call when this specific resource completes loading.
 * @return {Loader}
 */
Loader.prototype.add = Loader.prototype.enqueue = function (name, url, options, cb) {
    // special case of an array of objects or urls
    if (Array.isArray(name)) {
        for (var i = 0; i < name.length; ++i) {
            this.add(name[i]);
        }

        return this;
    }

    // if an object is passed instead of params
    if (typeof name === 'object') {
        cb = url || name.callback || name.onComplete;
        options = name;
        url = name.url;
        name = name.name || name.key || name.url;
    }

    // case where no name is passed shift all args over by one.
    if (typeof url !== 'string') {
        cb = options;
        options = url;
        url = name;
    }

    // now that we shifted make sure we have a proper url.
    if (typeof url !== 'string') {
        throw new Error('No url passed to add resource to loader.');
    }

    // options are optional so people might pass a function and no options
    if (typeof options === 'function') {
        cb = options;
        options = null;
    }

    // check if resource already exists.
    if (this.resources[name]) {
        throw new Error('Resource with name "' + name + '" already exists.');
    }

    // add base url if this isn't a data url
    if (url.indexOf('data:') !== 0) {
        url = this.baseUrl + url;
    }

    // create the store the resource
    this.resources[name] = new Resource(name, url, options);

    if (typeof cb === 'function') {
        this.resources[name].once('afterMiddleware', cb);
    }

    this._numToLoad++;

    // if already loading add it to the worker queue
    if (this._queue.started) {
        this._queue.push(this.resources[name]);
        this._progressChunk = (100 - this.progress) / (this._queue.length() + this._queue.running());
    }
    // otherwise buffer it to be added to the queue later
    else {
        this._buffer.push(this.resources[name]);
        this._progressChunk = 100 / this._buffer.length;
    }

    return this;
};

/**
 * Sets up a middleware function that will run *before* the
 * resource is loaded.
 *
 * @alias pre
 * @param middleware {function} The middleware function to register.
 * @return {Loader}
 */
Loader.prototype.before = Loader.prototype.pre = function (fn) {
    this._beforeMiddleware.push(fn);

    return this;
};

/**
 * Sets up a middleware function that will run *after* the
 * resource is loaded.
 *
 * @alias use
 * @param middleware {function} The middleware function to register.
 * @return {Loader}
 */
Loader.prototype.after = Loader.prototype.use = function (fn) {
    this._afterMiddleware.push(fn);

    return this;
};

/**
 * Resets the queue of the loader to prepare for a new load.
 *
 * @return {Loader}
 */
Loader.prototype.reset = function () {
    // this.baseUrl = baseUrl || '';

    this.progress = 0;

    this.loading = false;

    this._progressChunk = 0;

    // this._beforeMiddleware.length = 0;
    // this._afterMiddleware.length = 0;

    this._buffer.length = 0;

    this._numToLoad = 0;

    this._queue.kill();
    this._queue.started = false;

    this.resources = {};
};

/**
 * Starts loading the queued resources.
 *
 * @fires start
 * @param [callback] {function} Optional callback that will be bound to the `complete` event.
 * @return {Loader}
 */
Loader.prototype.load = function (cb) {
    // register complete callback if they pass one
    if (typeof cb === 'function') {
        this.once('complete', cb);
    }

    // if the queue has already started we are done here
    if (this._queue.started) {
        return this;
    }

    // notify of start
    this.emit('start', this);

    // start the internal queue
    for (var i = 0; i < this._buffer.length; ++i) {
        this._queue.push(this._buffer[i]);
    }

    // empty the buffer
    this._buffer.length = 0;

    return this;
};

/**
 * Loads a single resource.
 *
 * @fires progress
 * @private
 */
Loader.prototype._loadResource = function (resource, dequeue) {
    var self = this;

    resource._dequeue = dequeue;

    this._runMiddleware(resource, this._beforeMiddleware, function () {
        // resource.on('progress', self.emit.bind(self, 'progress'));

        resource.load(self._boundOnLoad);
    });
};

/**
 * Called once each resource has loaded.
 *
 * @fires complete
 * @private
 */
Loader.prototype._onComplete = function () {
    this.emit('complete', this, this.resources);
};

/**
 * Called each time a resources is loaded.
 *
 * @fires progress
 * @fires error
 * @fires load
 * @private
 */
Loader.prototype._onLoad = function (resource) {
    this.progress += this._progressChunk;

    this.emit('progress', this, resource);

    if (resource.error) {
        this.emit('error', resource.error, this, resource);
    }
    else {
        this.emit('load', this, resource);
    }

    // run middleware, this *must* happen before dequeue so sub-assets get added properly
    this._runMiddleware(resource, this._afterMiddleware, function () {
        resource.emit('afterMiddleware', resource);

        this._numToLoad--;

        // do completion check
        if (this._numToLoad === 0) {
            this._onComplete();
        }
    });

    // remove this resource from the async queue
    resource._dequeue();
};

/**
 * Run middleware functions on a resource.
 *
 * @private
 */
Loader.prototype._runMiddleware = function (resource, fns, cb) {
    var self = this;

    async.eachSeries(fns, function (fn, next) {
        fn.call(self, resource, next);
    }, cb.bind(this, resource));
};

Loader.LOAD_TYPE = Resource.LOAD_TYPE;
Loader.XHR_READY_STATE = Resource.XHR_READY_STATE;
Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE;
<commit_msg>only use base url for non absolute urls<commit_after>var async       = require('async'),
    urlParser   = require('url'),
    Resource    = require('./Resource'),
    EventEmitter = require('eventemitter3');

/**
 * Manages the state and loading of multiple resources to load.
 *
 * @class
 * @param [baseUrl=''] {string} The base url for all resources loaded by this loader.
 * @param [concurrency=10] {number} The number of resources to load concurrently.
 */
function Loader(baseUrl, concurrency) {
    EventEmitter.call(this);

    concurrency = concurrency || 10;

    /**
     * The base url for all resources loaded by this loader.
     *
     * @member {string}
     */
    this.baseUrl = baseUrl || '';

    /**
     * The progress percent of the loader going through the queue.
     *
     * @member {number}
     */
    this.progress = 0;

    /**
     * Loading state of the loader, true if it is currently loading resources.
     *
     * @member {boolean}
     */
    this.loading = false;

    /**
     * The percentage of total progress that a single resource represents.
     *
     * @member {number}
     */
    this._progressChunk = 0;

    /**
     * The middleware to run before loading each resource.
     *
     * @member {function[]}
     */
    this._beforeMiddleware = [];

    /**
     * The middleware to run after loading each resource.
     *
     * @member {function[]}
     */
    this._afterMiddleware = [];

    /**
     * The `_loadResource` function bound with this object context.
     *
     * @private
     * @member {function}
     */
    this._boundLoadResource = this._loadResource.bind(this);

    /**
     * The `_onLoad` function bound with this object context.
     *
     * @private
     * @member {function}
     */
    this._boundOnLoad = this._onLoad.bind(this);

    /**
     * The resource buffer that fills until `load` is called to start loading resources.
     *
     * @private
     * @member {Resource[]}
     */
    this._buffer = [];

    /**
     * Used to track load completion.
     *
     * @private
     * @member {number}
     */
    this._numToLoad = 0;

    /**
     * The resources waiting to be loaded.
     *
     * @private
     * @member {Resource[]}
     */
    this._queue = async.queue(this._boundLoadResource, concurrency);

    /**
     * All the resources for this loader keyed by name.
     *
     * @member {object<string, Resource>}
     */
    this.resources = {};

    /**
     * Emitted once per loaded or errored resource.
     *
     * @event progress
     * @memberof Loader#
     */

    /**
     * Emitted once per errored resource.
     *
     * @event error
     * @memberof Loader#
     */

    /**
     * Emitted once per loaded resource.
     *
     * @event load
     * @memberof Loader#
     */

    /**
     * Emitted when the loader begins to process the queue.
     *
     * @event start
     * @memberof Loader#
     */

    /**
     * Emitted when the queued resources all load.
     *
     * @event complete
     * @memberof Loader#
     */
}

Loader.prototype = Object.create(EventEmitter.prototype);
Loader.prototype.constructor = Loader;
module.exports = Loader;

/**
 * Adds a resource (or multiple resources) to the loader queue.
 *
 * This function can take a wide variety of different parameters. The only thing that is always
 * required the url to load. All the following will work:
 *
 * ```js
 * loader
 *     // normal param syntax
 *     .add('key', 'http://...', function () {})
 *     .add('http://...', function () {})
 *     .add('http://...')
 *
 *     // object syntax
 *     .add({
 *         name: 'key2',
 *         url: 'http://...'
 *     }, function () {})
 *     .add({
 *         url: 'http://...'
 *     }, function () {})
 *     .add({
 *         name: 'key3',
 *         url: 'http://...'
 *         onComplete: function () {}
 *     })
 *     .add({
 *         url: 'https://...',
 *         onComplete: function () {},
 *         crossOrigin: true
 *     })
 *
 *     // you can also pass an array of objects or urls or both
 *     .add([
 *         { name: 'key4', url: 'http://...', onComplete: function () {} },
 *         { url: 'http://...', onComplete: function () {} },
 *         'http://...'
 *     ]);
 * ```
 *
 * @alias enqueue
 * @param [name] {string} The name of the resource to load, if not passed the url is used.
 * @param url {string} The url for this resource, relative to the baseUrl of this loader.
 * @param [options] {object} The options for the load.
 * @param [options.crossOrigin] {boolean} Is this request cross-origin? Default is to determine automatically.
 * @param [options.loadType=Resource.LOAD_TYPE.XHR] {Resource.XHR_LOAD_TYPE} How should this resource be loaded?
 * @param [options.xhrType=Resource.XHR_RESPONSE_TYPE.DEFAULT] {Resource.XHR_RESPONSE_TYPE} How should the data being
 *      loaded be interpreted when using XHR?
 * @param [callback] {function} Function to call when this specific resource completes loading.
 * @return {Loader}
 */
Loader.prototype.add = Loader.prototype.enqueue = function (name, url, options, cb) {
    // special case of an array of objects or urls
    if (Array.isArray(name)) {
        for (var i = 0; i < name.length; ++i) {
            this.add(name[i]);
        }

        return this;
    }

    // if an object is passed instead of params
    if (typeof name === 'object') {
        cb = url || name.callback || name.onComplete;
        options = name;
        url = name.url;
        name = name.name || name.key || name.url;
    }

    // case where no name is passed shift all args over by one.
    if (typeof url !== 'string') {
        cb = options;
        options = url;
        url = name;
    }

    // now that we shifted make sure we have a proper url.
    if (typeof url !== 'string') {
        throw new Error('No url passed to add resource to loader.');
    }

    // options are optional so people might pass a function and no options
    if (typeof options === 'function') {
        cb = options;
        options = null;
    }

    // check if resource already exists.
    if (this.resources[name]) {
        throw new Error('Resource with name "' + name + '" already exists.');
    }

    // add base url if this isn't an absolute url
    url = this._handleBaseUrl(url);

    // create the store the resource
    this.resources[name] = new Resource(name, url, options);

    if (typeof cb === 'function') {
        this.resources[name].once('afterMiddleware', cb);
    }

    this._numToLoad++;

    // if already loading add it to the worker queue
    if (this._queue.started) {
        this._queue.push(this.resources[name]);
        this._progressChunk = (100 - this.progress) / (this._queue.length() + this._queue.running());
    }
    // otherwise buffer it to be added to the queue later
    else {
        this._buffer.push(this.resources[name]);
        this._progressChunk = 100 / this._buffer.length;
    }

    return this;
};

Loader.prototype._handleBaseUrl = function (url) {
    var parsedUrl = urlParser.parse(url);

    // absolute url, just use it as is.
    if (parsedUrl.protocol || parsedUrl.pathname.indexOf('//') === 0) {
        return url;
    }

    return this.baseUrl + url;
};

/**
 * Sets up a middleware function that will run *before* the
 * resource is loaded.
 *
 * @alias pre
 * @param middleware {function} The middleware function to register.
 * @return {Loader}
 */
Loader.prototype.before = Loader.prototype.pre = function (fn) {
    this._beforeMiddleware.push(fn);

    return this;
};

/**
 * Sets up a middleware function that will run *after* the
 * resource is loaded.
 *
 * @alias use
 * @param middleware {function} The middleware function to register.
 * @return {Loader}
 */
Loader.prototype.after = Loader.prototype.use = function (fn) {
    this._afterMiddleware.push(fn);

    return this;
};

/**
 * Resets the queue of the loader to prepare for a new load.
 *
 * @return {Loader}
 */
Loader.prototype.reset = function () {
    // this.baseUrl = baseUrl || '';

    this.progress = 0;

    this.loading = false;

    this._progressChunk = 0;

    // this._beforeMiddleware.length = 0;
    // this._afterMiddleware.length = 0;

    this._buffer.length = 0;

    this._numToLoad = 0;

    this._queue.kill();
    this._queue.started = false;

    this.resources = {};
};

/**
 * Starts loading the queued resources.
 *
 * @fires start
 * @param [callback] {function} Optional callback that will be bound to the `complete` event.
 * @return {Loader}
 */
Loader.prototype.load = function (cb) {
    // register complete callback if they pass one
    if (typeof cb === 'function') {
        this.once('complete', cb);
    }

    // if the queue has already started we are done here
    if (this._queue.started) {
        return this;
    }

    // notify of start
    this.emit('start', this);

    // start the internal queue
    for (var i = 0; i < this._buffer.length; ++i) {
        this._queue.push(this._buffer[i]);
    }

    // empty the buffer
    this._buffer.length = 0;

    return this;
};

/**
 * Loads a single resource.
 *
 * @fires progress
 * @private
 */
Loader.prototype._loadResource = function (resource, dequeue) {
    var self = this;

    resource._dequeue = dequeue;

    this._runMiddleware(resource, this._beforeMiddleware, function () {
        // resource.on('progress', self.emit.bind(self, 'progress'));

        resource.load(self._boundOnLoad);
    });
};

/**
 * Called once each resource has loaded.
 *
 * @fires complete
 * @private
 */
Loader.prototype._onComplete = function () {
    this.emit('complete', this, this.resources);
};

/**
 * Called each time a resources is loaded.
 *
 * @fires progress
 * @fires error
 * @fires load
 * @private
 */
Loader.prototype._onLoad = function (resource) {
    this.progress += this._progressChunk;

    this.emit('progress', this, resource);

    if (resource.error) {
        this.emit('error', resource.error, this, resource);
    }
    else {
        this.emit('load', this, resource);
    }

    // run middleware, this *must* happen before dequeue so sub-assets get added properly
    this._runMiddleware(resource, this._afterMiddleware, function () {
        resource.emit('afterMiddleware', resource);

        this._numToLoad--;

        // do completion check
        if (this._numToLoad === 0) {
            this._onComplete();
        }
    });

    // remove this resource from the async queue
    resource._dequeue();
};

/**
 * Run middleware functions on a resource.
 *
 * @private
 */
Loader.prototype._runMiddleware = function (resource, fns, cb) {
    var self = this;

    async.eachSeries(fns, function (fn, next) {
        fn.call(self, resource, next);
    }, cb.bind(this, resource));
};

Loader.LOAD_TYPE = Resource.LOAD_TYPE;
Loader.XHR_READY_STATE = Resource.XHR_READY_STATE;
Loader.XHR_RESPONSE_TYPE = Resource.XHR_RESPONSE_TYPE;
<|endoftext|>


<commit_before>// Analogous to Array.prototype.map
//
// Creates a new object with properties which values are results of calling
// a provided function on every key-value pair in this object.

'use strict';

var forEach = require('./for-each');

module.exports = function (callback, scope) {
	var o = {};
	forEach.call(this, function (value, key) {
		o[key] = callback.call(this, value, key);
	}, scope);
	return o;
};
<commit_msg>Better variable names<commit_after>// Analogous to Array.prototype.map
//
// Creates a new object with properties which values are results of calling
// a provided function on every key-value pair in this object.

'use strict';

var forEach = require('./for-each');

module.exports = function (cb, thisArg) {
	var o = {};
	forEach.call(this, function (value, key) {
		o[key] = cb.call(this, value, key);
	}, thisArg);
	return o;
};
<|endoftext|>


<commit_before>/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the Clear BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/Grid.js
 * @requires OpenLayers/Tile/Image.js
 */

/**
 * Class: OpenLayers.Layer.TMS
 * Create a layer for accessing tiles from services that conform with the
 *     Tile Map Service Specification
 *     (http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification).
 *
 * Example:
 * (code)
 *     var layer = OpenLayers.Layer.TMS(
 *         "My Layer", // name for display in LayerSwitcher
 *         "http://tilecache.osgeo.org/wms-c/Basic.py/", // service endpoint
 *         {layername: "basic", type: "png"} // required properties
 *     );
 * (end)
 *
 * Inherits from:
 *  - <OpenLayers.Layer.Grid>
 */
OpenLayers.Layer.TMS = OpenLayers.Class(OpenLayers.Layer.Grid, {

    /**
     * APIProperty: serviceVersion
     * {String} Service version for tile requests.  Default is "1.0.0".
     */
    serviceVersion: "1.0.0",

    /**
     * APIProperty: layername
     * {String} The identifier for the <TileMap> as advertised by the service.
     *     For example, if the service advertises a <TileMap> with
     *    'href="http://tms.osgeo.org/1.0.0/vmap0"', the <layername> property
     *     would be set to "vmap0".
     */
    layername: null,

    /**
     * APIProperty: type
     * {String} The format extension corresponding to the requested tile image
     *     type.  This is advertised in a <TileFormat> element as the
     *     "extension" attribute.  For example, if the service advertises a
     *     <TileMap> with <TileFormat width="256" height="256" mime-type="image/jpeg" extension="jpg" />,
     *     the <type> property would be set to "jpg".
     */
    type: null,

    /**
     * APIProperty: isBaseLayer
     * {Boolean} Make this layer a base layer.  Default is true.  Set false to
     *     use the layer as an overlay.
     */
    isBaseLayer: true,

    /**
     * APIProperty: tileOrigin
     * {<OpenLayers.LonLat>} Optional origin for aligning the grid of tiles.
     *     If provided, requests for tiles at all resolutions will be aligned
     *     with this location (no tiles shall overlap this location).  If
     *     not provided, the grid of tiles will be aligned with the map's
     *     <maxExtent>.  Default is ``null``.
     *
     * Example:
     * (code)
     *     var layer = OpenLayers.Layer.TMS(
     *         "My Layer",
     *         "http://tilecache.osgeo.org/wms-c/Basic.py/",
     *         {
     *             layername: "basic",
     *             type: "png",
     *             // set if different than the bottom left of map.maxExtent
     *             tileOrigin: new OpenLayers.LonLat(-180, -90)
     *         }
     *     );
     * (end)
     */
    tileOrigin: null,

    /**
     * APIProperty: serverResolutions
     * {Array} A list of all resolutions available on the server.  Only set this
     *     property if the map resolutions differs from the server.
     */
    serverResolutions: null,

    /**
     * APIProperty: zoomOffset
     * {Number} If your cache has more zoom levels than you want to provide
     *     access to with this layer, supply a zoomOffset.  This zoom offset
     *     is added to the current map zoom level to determine the level
     *     for a requested tile.  For example, if you supply a zoomOffset
     *     of 3, when the map is at the zoom 0, tiles will be requested from
     *     level 3 of your cache.  Default is 0 (assumes cache level and map
     *     zoom are equivalent).  Using <zoomOffset> is an alternative to
     *     setting <serverResolutions> if you only want to expose a subset
     *     of the server resolutions.
     */
    zoomOffset: 0,

    /**
     * Constructor: OpenLayers.Layer.TMS
     *
     * Parameters:
     * name - {String} Title to be displayed in a <OpenLayers.Control.LayerSwitcher>
     * url - {String} Service endpoint (without the version number).  E.g.
     *     "http://tms.osgeo.org/".
     * options - {Object} Additional properties to be set on the layer.  The
     *     <layername> and <type> properties must be set here.
     */
    initialize: function(name, url, options) {
        var newArguments = [];
        newArguments.push(name, url, {}, options);
        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
    },

    /**
     * APIMethod:destroy
     */
    destroy: function() {
        // for now, nothing special to do here.
        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
    },

    /**
     * APIMethod: clone
     * Create a complete copy of this layer.
     *
     * Parameters:
     * obj - {Object} Should only be provided by subclasses that call this
     *     method.
     *
     * Returns:
     * {<OpenLayers.Layer.TMS>} An exact clone of this <OpenLayers.Layer.TMS>
     */
    clone: function (obj) {

        if (obj == null) {
            obj = new OpenLayers.Layer.TMS(this.name,
                                           this.url,
                                           this.getOptions());
        }

        //get all additions from superclasses
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);

        // copy/set any non-init, non-simple values here

        return obj;
    },

    /**
     * Method: getURL
     *
     * Parameters:
     * bounds - {<OpenLayers.Bounds>}
     *
     * Returns:
     * {String} A string with the layer's url and parameters and also the
     *          passed-in bounds and appropriate tile size specified as
     *          parameters
     */
    getURL: function (bounds) {
        bounds = this.adjustBounds(bounds);
        var res = this.map.getResolution();
        var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
        var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
        var z = this.serverResolutions != null ?
            OpenLayers.Util.indexOf(this.serverResolutions, res) :
            this.map.getZoom() + this.zoomOffset;
        var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type;
        var url = this.url;
        if (OpenLayers.Util.isArray(url)) {
            url = this.selectUrl(path, url);
        }
        return url + path;
    },

    /**
     * Method: setMap
     * When the layer is added to a map, then we can fetch our origin
     *    (if we don't have one.)
     *
     * Parameters:
     * map - {<OpenLayers.Map>}
     */
    setMap: function(map) {
        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
        if (!this.tileOrigin) {
            this.tileOrigin = new OpenLayers.LonLat(this.map.maxExtent.left,
                                                this.map.maxExtent.bottom);
        }
    },

    CLASS_NAME: "OpenLayers.Layer.TMS"
});
<commit_msg>Clarifying that it is the bottom-left corner of the map.maxExtent property that determines the tileOrigin if not explicitly provided.<commit_after>/* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
 * full list of contributors). Published under the Clear BSD license.
 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/Grid.js
 * @requires OpenLayers/Tile/Image.js
 */

/**
 * Class: OpenLayers.Layer.TMS
 * Create a layer for accessing tiles from services that conform with the
 *     Tile Map Service Specification
 *     (http://wiki.osgeo.org/wiki/Tile_Map_Service_Specification).
 *
 * Example:
 * (code)
 *     var layer = OpenLayers.Layer.TMS(
 *         "My Layer", // name for display in LayerSwitcher
 *         "http://tilecache.osgeo.org/wms-c/Basic.py/", // service endpoint
 *         {layername: "basic", type: "png"} // required properties
 *     );
 * (end)
 *
 * Inherits from:
 *  - <OpenLayers.Layer.Grid>
 */
OpenLayers.Layer.TMS = OpenLayers.Class(OpenLayers.Layer.Grid, {

    /**
     * APIProperty: serviceVersion
     * {String} Service version for tile requests.  Default is "1.0.0".
     */
    serviceVersion: "1.0.0",

    /**
     * APIProperty: layername
     * {String} The identifier for the <TileMap> as advertised by the service.
     *     For example, if the service advertises a <TileMap> with
     *    'href="http://tms.osgeo.org/1.0.0/vmap0"', the <layername> property
     *     would be set to "vmap0".
     */
    layername: null,

    /**
     * APIProperty: type
     * {String} The format extension corresponding to the requested tile image
     *     type.  This is advertised in a <TileFormat> element as the
     *     "extension" attribute.  For example, if the service advertises a
     *     <TileMap> with <TileFormat width="256" height="256" mime-type="image/jpeg" extension="jpg" />,
     *     the <type> property would be set to "jpg".
     */
    type: null,

    /**
     * APIProperty: isBaseLayer
     * {Boolean} Make this layer a base layer.  Default is true.  Set false to
     *     use the layer as an overlay.
     */
    isBaseLayer: true,

    /**
     * APIProperty: tileOrigin
     * {<OpenLayers.LonLat>} Optional origin for aligning the grid of tiles.
     *     If provided, requests for tiles at all resolutions will be aligned
     *     with this location (no tiles shall overlap this location).  If
     *     not provided, the grid of tiles will be aligned with the bottom-left
     *     corner of the map's <maxExtent>.  Default is ``null``.
     *
     * Example:
     * (code)
     *     var layer = OpenLayers.Layer.TMS(
     *         "My Layer",
     *         "http://tilecache.osgeo.org/wms-c/Basic.py/",
     *         {
     *             layername: "basic",
     *             type: "png",
     *             // set if different than the bottom left of map.maxExtent
     *             tileOrigin: new OpenLayers.LonLat(-180, -90)
     *         }
     *     );
     * (end)
     */
    tileOrigin: null,

    /**
     * APIProperty: serverResolutions
     * {Array} A list of all resolutions available on the server.  Only set this
     *     property if the map resolutions differs from the server.
     */
    serverResolutions: null,

    /**
     * APIProperty: zoomOffset
     * {Number} If your cache has more zoom levels than you want to provide
     *     access to with this layer, supply a zoomOffset.  This zoom offset
     *     is added to the current map zoom level to determine the level
     *     for a requested tile.  For example, if you supply a zoomOffset
     *     of 3, when the map is at the zoom 0, tiles will be requested from
     *     level 3 of your cache.  Default is 0 (assumes cache level and map
     *     zoom are equivalent).  Using <zoomOffset> is an alternative to
     *     setting <serverResolutions> if you only want to expose a subset
     *     of the server resolutions.
     */
    zoomOffset: 0,

    /**
     * Constructor: OpenLayers.Layer.TMS
     *
     * Parameters:
     * name - {String} Title to be displayed in a <OpenLayers.Control.LayerSwitcher>
     * url - {String} Service endpoint (without the version number).  E.g.
     *     "http://tms.osgeo.org/".
     * options - {Object} Additional properties to be set on the layer.  The
     *     <layername> and <type> properties must be set here.
     */
    initialize: function(name, url, options) {
        var newArguments = [];
        newArguments.push(name, url, {}, options);
        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
    },

    /**
     * APIMethod:destroy
     */
    destroy: function() {
        // for now, nothing special to do here.
        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
    },

    /**
     * APIMethod: clone
     * Create a complete copy of this layer.
     *
     * Parameters:
     * obj - {Object} Should only be provided by subclasses that call this
     *     method.
     *
     * Returns:
     * {<OpenLayers.Layer.TMS>} An exact clone of this <OpenLayers.Layer.TMS>
     */
    clone: function (obj) {

        if (obj == null) {
            obj = new OpenLayers.Layer.TMS(this.name,
                                           this.url,
                                           this.getOptions());
        }

        //get all additions from superclasses
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);

        // copy/set any non-init, non-simple values here

        return obj;
    },

    /**
     * Method: getURL
     *
     * Parameters:
     * bounds - {<OpenLayers.Bounds>}
     *
     * Returns:
     * {String} A string with the layer's url and parameters and also the
     *          passed-in bounds and appropriate tile size specified as
     *          parameters
     */
    getURL: function (bounds) {
        bounds = this.adjustBounds(bounds);
        var res = this.map.getResolution();
        var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
        var y = Math.round((bounds.bottom - this.tileOrigin.lat) / (res * this.tileSize.h));
        var z = this.serverResolutions != null ?
            OpenLayers.Util.indexOf(this.serverResolutions, res) :
            this.map.getZoom() + this.zoomOffset;
        var path = this.serviceVersion + "/" + this.layername + "/" + z + "/" + x + "/" + y + "." + this.type;
        var url = this.url;
        if (OpenLayers.Util.isArray(url)) {
            url = this.selectUrl(path, url);
        }
        return url + path;
    },

    /**
     * Method: setMap
     * When the layer is added to a map, then we can fetch our origin
     *    (if we don't have one.)
     *
     * Parameters:
     * map - {<OpenLayers.Map>}
     */
    setMap: function(map) {
        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
        if (!this.tileOrigin) {
            this.tileOrigin = new OpenLayers.LonLat(this.map.maxExtent.left,
                                                this.map.maxExtent.bottom);
        }
    },

    CLASS_NAME: "OpenLayers.Layer.TMS"
});
<|endoftext|>


<commit_before>/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/Grid.js
 * @requires OpenLayers/Tile/Image.js
 *
 * Class: OpenLayers.Layer.WMS
 * Instances of OpenLayers.Layer.WMS are used to display data from OGC Web
 *     Mapping Services. Create a new WMS layer with the <OpenLayers.Layer.WMS>
 *     constructor.
 *
 * Inherits from:
 *  - <OpenLayers.Layer.Grid>
 */
OpenLayers.Layer.WMS = OpenLayers.Class(OpenLayers.Layer.Grid, {

    /**
     * Constant: DEFAULT_PARAMS
     * {Object} Hashtable of default parameter key/value pairs
     */
    DEFAULT_PARAMS: { service: "WMS",
                      version: "1.1.1",
                      request: "GetMap",
                      styles: "",
                      exceptions: "application/vnd.ogc.se_inimage",
                      format: "image/jpeg"
                     },

    /**
     * Property: reproject
     * *Deprecated*. See http://trac.openlayers.org/wiki/SpatialMercator
     * for information on the replacement for this functionality.
     * {Boolean} Try to reproject this layer if its coordinate reference system
     *           is different than that of the base layer.  Default is true.
     *           Set this in the layer options.  Should be set to false in
     *           most cases.
     */
    reproject: false,

    /**
     * APIProperty: isBaseLayer
     * {Boolean} Default is true for WMS layer
     */
    isBaseLayer: true,

    /**
     * APIProperty: encodeBBOX
     * {Boolean} Should the BBOX commas be encoded? The WMS spec says 'no',
     * but some services want it that way. Default false.
     */
    encodeBBOX: false,

    /**
     * Constructor: OpenLayers.Layer.WMS
     * Create a new WMS layer object
     *
     * Example:
     * (code)
     * var wms = new OpenLayers.Layer.WMS("NASA Global Mosaic",
     *                                    "http://wms.jpl.nasa.gov/wms.cgi",
     *                                    {layers: "modis,global_mosaic"});
     * (end)
     *
     * Parameters:
     * name - {String} A name for the layer
     * url - {String} Base url for the WMS
     *                (e.g. http://wms.jpl.nasa.gov/wms.cgi)
     * params - {Object} An object with key/value pairs representing the
     *                   GetMap query string parameters and parameter values.
     * options - {Ojbect} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, url, params, options) {
        var newArguments = [];
        //uppercase params
        params = OpenLayers.Util.upperCaseObject(params);
        newArguments.push(name, url, params, options);
        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
        OpenLayers.Util.applyDefaults(
                       this.params,
                       OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS)
                       );

        //layer is transparent
        if (this.params.TRANSPARENT &&
            this.params.TRANSPARENT.toString().toLowerCase() == "true") {

            // unless explicitly set in options, make layer an overlay
            if ( (options == null) || (!options.isBaseLayer) ) {
                this.isBaseLayer = false;
            }

            // jpegs can never be transparent, so intelligently switch the
            //  format, depending on teh browser's capabilities
            if (this.params.FORMAT == "image/jpeg") {
                this.params.FORMAT = OpenLayers.Util.alphaHack() ? "image/gif"
                                                                 : "image/png";
            }
        }

    },

    /**
     * Method: destroy
     * Destroy this layer
     */
    destroy: function() {
        // for now, nothing special to do here.
        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
    },

    /**
     * Method: clone
     * Create a clone of this layer
     *
     * Returns:
     * {<OpenLayers.Layer.WMS>} An exact clone of this layer
     */
    clone: function (obj) {

        if (obj == null) {
            obj = new OpenLayers.Layer.WMS(this.name,
                                           this.url,
                                           this.params,
                                           this.options);
        }

        //get all additions from superclasses
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);

        // copy/set any non-init, non-simple values here

        return obj;
    },

    /**
     * Method: getURL
     * Return a GetMap query string for this layer
     *
     * Parameters:
     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
     *                                request.
     *
     * Returns:
     * {String} A string with the layer's url and parameters and also the
     *          passed-in bounds and appropriate tile size specified as
     *          parameters.
     */
    getURL: function (bounds) {
        bounds = this.adjustBounds(bounds);

        var imageSize = this.getImageSize();
        var s = this.getFullRequestString(
                     {BBOX: this.encodeBBOX ?  bounds.toBBOX() : bounds.toArray(),
                      WIDTH:imageSize.w,
                      HEIGHT:imageSize.h});
        //console.log(s);
        return s;
    },

    /**
     * Method: addTile
     * addTile creates a tile, initializes it, and adds it to the layer div.
     *
     * Parameters:
     * bounds - {<OpenLayers.Bounds>}
     *
     * Returns:
     * {<OpenLayers.Tile.Image>} The added OpenLayers.Tile.Image
     */
    addTile:function(bounds,position) {
        return new OpenLayers.Tile.Image(this, position, bounds,
                                         null, this.tileSize);
    },

    /**
     * APIMethod: mergeNewParams
     * Catch changeParams and uppercase the new params to be merged in
     *     before calling changeParams on the super class.
     *
     *     Once params have been changed, we will need to re-init our tiles.
     *
     * Parameters:
     * newParams - {Object} Hashtable of new params to use
     */
    mergeNewParams:function(newParams) {
        var upperParams = OpenLayers.Util.upperCaseObject(newParams);
        var newArguments = [upperParams];
        OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,
                                                             newArguments);
    },

    /**
     * Method: getFullRequestString
     * Combine the layer's url with its params and these newParams.
     *
     *     Add the SRS parameter from projection -- this is probably
     *     more eloquently done via a setProjection() method, but this
     *     works for now and always.
     *
     * Parameters:
     * newParams - {Object}
     * altUrl - {String} Use this as the url instead of the layer's url
     *
     * Returns:
     * {String}
     */
    getFullRequestString:function(newParams, altUrl) {
        var projection = this.map.getProjection();
        this.params.SRS = (projection == "none") ? null : projection;

        return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(
                                                    this, arguments);
    },

    CLASS_NAME: "OpenLayers.Layer.WMS"
});
<commit_msg>remove added (but commented out) console.log() call from r5002. As long as we're going it, let's give our return string a better variable name and move the newParams into its own variable, too. no functional change here. all tests pass.<commit_after>/* Copyright (c) 2006-2007 MetaCarta, Inc., published under the Clear BSD
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Layer/Grid.js
 * @requires OpenLayers/Tile/Image.js
 *
 * Class: OpenLayers.Layer.WMS
 * Instances of OpenLayers.Layer.WMS are used to display data from OGC Web
 *     Mapping Services. Create a new WMS layer with the <OpenLayers.Layer.WMS>
 *     constructor.
 *
 * Inherits from:
 *  - <OpenLayers.Layer.Grid>
 */
OpenLayers.Layer.WMS = OpenLayers.Class(OpenLayers.Layer.Grid, {

    /**
     * Constant: DEFAULT_PARAMS
     * {Object} Hashtable of default parameter key/value pairs
     */
    DEFAULT_PARAMS: { service: "WMS",
                      version: "1.1.1",
                      request: "GetMap",
                      styles: "",
                      exceptions: "application/vnd.ogc.se_inimage",
                      format: "image/jpeg"
                     },

    /**
     * Property: reproject
     * *Deprecated*. See http://trac.openlayers.org/wiki/SpatialMercator
     * for information on the replacement for this functionality.
     * {Boolean} Try to reproject this layer if its coordinate reference system
     *           is different than that of the base layer.  Default is true.
     *           Set this in the layer options.  Should be set to false in
     *           most cases.
     */
    reproject: false,

    /**
     * APIProperty: isBaseLayer
     * {Boolean} Default is true for WMS layer
     */
    isBaseLayer: true,

    /**
     * APIProperty: encodeBBOX
     * {Boolean} Should the BBOX commas be encoded? The WMS spec says 'no',
     * but some services want it that way. Default false.
     */
    encodeBBOX: false,

    /**
     * Constructor: OpenLayers.Layer.WMS
     * Create a new WMS layer object
     *
     * Example:
     * (code)
     * var wms = new OpenLayers.Layer.WMS("NASA Global Mosaic",
     *                                    "http://wms.jpl.nasa.gov/wms.cgi",
     *                                    {layers: "modis,global_mosaic"});
     * (end)
     *
     * Parameters:
     * name - {String} A name for the layer
     * url - {String} Base url for the WMS
     *                (e.g. http://wms.jpl.nasa.gov/wms.cgi)
     * params - {Object} An object with key/value pairs representing the
     *                   GetMap query string parameters and parameter values.
     * options - {Ojbect} Hashtable of extra options to tag onto the layer
     */
    initialize: function(name, url, params, options) {
        var newArguments = [];
        //uppercase params
        params = OpenLayers.Util.upperCaseObject(params);
        newArguments.push(name, url, params, options);
        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
        OpenLayers.Util.applyDefaults(
                       this.params,
                       OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS)
                       );

        //layer is transparent
        if (this.params.TRANSPARENT &&
            this.params.TRANSPARENT.toString().toLowerCase() == "true") {

            // unless explicitly set in options, make layer an overlay
            if ( (options == null) || (!options.isBaseLayer) ) {
                this.isBaseLayer = false;
            }

            // jpegs can never be transparent, so intelligently switch the
            //  format, depending on teh browser's capabilities
            if (this.params.FORMAT == "image/jpeg") {
                this.params.FORMAT = OpenLayers.Util.alphaHack() ? "image/gif"
                                                                 : "image/png";
            }
        }

    },

    /**
     * Method: destroy
     * Destroy this layer
     */
    destroy: function() {
        // for now, nothing special to do here.
        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
    },

    /**
     * Method: clone
     * Create a clone of this layer
     *
     * Returns:
     * {<OpenLayers.Layer.WMS>} An exact clone of this layer
     */
    clone: function (obj) {

        if (obj == null) {
            obj = new OpenLayers.Layer.WMS(this.name,
                                           this.url,
                                           this.params,
                                           this.options);
        }

        //get all additions from superclasses
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);

        // copy/set any non-init, non-simple values here

        return obj;
    },

    /**
     * Method: getURL
     * Return a GetMap query string for this layer
     *
     * Parameters:
     * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
     *                                request.
     *
     * Returns:
     * {String} A string with the layer's url and parameters and also the
     *          passed-in bounds and appropriate tile size specified as
     *          parameters.
     */
    getURL: function (bounds) {
        bounds = this.adjustBounds(bounds);

        var imageSize = this.getImageSize();
        var newParams = {
            BBOX: this.encodeBBOX ?  bounds.toBBOX() : bounds.toArray(),
            WIDTH:imageSize.w,
            HEIGHT:imageSize.h
        };
        var requestString = this.getFullRequestString(newParams);
        return requestString;
    },

    /**
     * Method: addTile
     * addTile creates a tile, initializes it, and adds it to the layer div.
     *
     * Parameters:
     * bounds - {<OpenLayers.Bounds>}
     *
     * Returns:
     * {<OpenLayers.Tile.Image>} The added OpenLayers.Tile.Image
     */
    addTile:function(bounds,position) {
        return new OpenLayers.Tile.Image(this, position, bounds,
                                         null, this.tileSize);
    },

    /**
     * APIMethod: mergeNewParams
     * Catch changeParams and uppercase the new params to be merged in
     *     before calling changeParams on the super class.
     *
     *     Once params have been changed, we will need to re-init our tiles.
     *
     * Parameters:
     * newParams - {Object} Hashtable of new params to use
     */
    mergeNewParams:function(newParams) {
        var upperParams = OpenLayers.Util.upperCaseObject(newParams);
        var newArguments = [upperParams];
        OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,
                                                             newArguments);
    },

    /**
     * Method: getFullRequestString
     * Combine the layer's url with its params and these newParams.
     *
     *     Add the SRS parameter from projection -- this is probably
     *     more eloquently done via a setProjection() method, but this
     *     works for now and always.
     *
     * Parameters:
     * newParams - {Object}
     * altUrl - {String} Use this as the url instead of the layer's url
     *
     * Returns:
     * {String}
     */
    getFullRequestString:function(newParams, altUrl) {
        var projection = this.map.getProjection();
        this.params.SRS = (projection == "none") ? null : projection;

        return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(
                                                    this, arguments);
    },

    CLASS_NAME: "OpenLayers.Layer.WMS"
});
<|endoftext|>


<commit_before>(function() {
  console.log('commander regeneration')

  var launcher = "/pa/commander_regeneration/commander_regen_launcher.json"
  var event_s = ko.observable(5)
  var simulatePlayers = 1

  var pasteUnits3D = function(config) {
    model.send_message('create_unit', config)
  }

  var regen = function(planet) {
    if (model.players().length < 1) return
    pasteUnits3D({
      army: model.players()[0].id,
      what: launcher,
      planet: planet,
      location: {x: 1, y: 0, z: 0}
    })
  }

  var baselineDefined = false
  var baseline = ko.observable(0)
  var endOfTime = ko.observable(0)
  var liveGameTime = handlers.time
  handlers.time = function(payload) {
    endOfTime(payload.end_time)
    if (!baselineDefined) {
      baselineDefined = true
      baseline(payload.end_time)
    }
    //console.log(time)
    if (liveGameTime) liveGameTime(payload)
  }
  var transpired = ko.computed(function() {
    return endOfTime() - baseline()
  })

  var planets = ko.computed(function() {
    return model.celestialViewModels().length - 1
  })
  var baseEvent_ms = ko.computed(function() {
    if (planets() > 0) {
      return event_s() * 1000 / planets()
    } else {
      return event_s() * 1000
    }
  })
  var targetEventRate = ko.computed(function() {
    if (planets() > 0) {
      return planets() / event_s()
    } else {
      return 0
    }
  })

  var targetEvents = ko.computed(function() {
    return transpired() * targetEventRate()
  })
  var actualEvents = ko.observable(0)
  var wait_ms = ko.computed(function() {
    if (actualEvents() >= targetEvents()) {
      return baseEvent_ms() * (actualEvents() - targetEvents() + 1)
    } else {
      return baseEvent_ms() / (targetEvents() - actualEvents())
    }
  })

  handlers.commanderRegenerationEvents = function(payload) {
    actualEvents(actualEvents() + payload.list.length)
    console.log('events', actualEvents(), targetEvents())
  }

  var tick = function(planet) {
    var n = planets()
    if (n > 0) {
      console.log('regen', actualEvents(), targetEvents(), wait_ms())
      regen(planet)
    }
    if (planet < n-1) {
      setTimeout(tick, wait_ms(), planet + 1)
    } else {
      setTimeout(tick, wait_ms(), 0)
    }
  }

  for (var i = 0;i < simulatePlayers;i++) {
    setTimeout(tick, baseEvent_ms(), 0)
  }

  model.devMode(false)
  model.cheatAllowCreateUnit(false)
  model.sandbox(false)
})()

<commit_msg>estimate for number of players<commit_after>(function() {
  console.log('commander regeneration')

  var launcher = "/pa/commander_regeneration/commander_regen_launcher.json"
  var event_s = ko.observable(3)
  var simulatePlayers = 1

  var pasteUnits3D = function(config) {
    model.send_message('create_unit', config)
  }

  var regen = function(planet) {
    if (model.players().length < 1) return
    pasteUnits3D({
      army: model.players()[0].id,
      what: launcher,
      planet: planet,
      location: {x: 1, y: 0, z: 0}
    })
  }

  var baselineDefined = false
  var baseline = ko.observable(0)
  var endOfTime = ko.observable(0)
  var liveGameTime = handlers.time
  handlers.time = function(payload) {
    endOfTime(payload.end_time)
    if (!baselineDefined) {
      baselineDefined = true
      baseline(payload.end_time)
    }
    //console.log(time)
    if (liveGameTime) liveGameTime(payload)
  }
  var transpired = ko.computed(function() {
    return endOfTime() - baseline()
  })

  var planets = ko.computed(function() {
    return model.celestialViewModels().length - 1
  })
  var connectedClient = function(player) {
    return player.ai == 0 && player.disconnected == false
  }
  var numberOfPlayers = function(player) {return player.slots.length}
  var sum = function(a, b) {return a + b}
  var players = ko.computed(function() {
    var n = model.players().filter(connectedClient).map(numberOfPlayers).reduce(sum, 0)
    if (simulatePlayers > 0) {
      return simulatePlayers
    } else if (n > 0) {
      return n
    } else {
      return 1
    }
  })
  var baseEvent_ms = ko.computed(function() {
    if (planets() > 0) {
      return event_s() * players() * 1000 / planets()
    } else {
      return event_s() * players() * 1000
    }
  })
  var targetEventRate = ko.computed(function() {
    if (planets() > 0) {
      return planets() / event_s()
    } else {
      return 0
    }
  })

  var targetEvents = ko.computed(function() {
    return transpired() * targetEventRate()
  })
  var actualEvents = ko.observable(0)
  var wait_ms = ko.computed(function() {
    if (actualEvents() >= targetEvents()) {
      return baseEvent_ms() * (actualEvents() - targetEvents() + 1)
    } else {
      return baseEvent_ms() / (targetEvents() - actualEvents())
    }
  })

  handlers.commanderRegenerationEvents = function(payload) {
    actualEvents(actualEvents() + payload.list.length)
    console.log('events', actualEvents(), targetEvents())
  }

  var tick = function(planet) {
    var n = planets()
    if (n > 0) {
      console.log('regen', actualEvents(), targetEvents(), wait_ms())
      regen(planet)
    }
    if (planet < n-1) {
      setTimeout(tick, wait_ms(), planet + 1)
    } else {
      setTimeout(tick, wait_ms(), 0)
    }
  }

  for (var i = 0;i < simulatePlayers;i++) {
    console.log('starting regen')
    setTimeout(tick, baseEvent_ms(), 0)
  }

  model.devMode(false)
  model.cheatAllowCreateUnit(false)
  model.sandbox(false)
})()

<|endoftext|>


<commit_before>/**
 * Copyright 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 * Please see distribution for license.
 */
$.register_module({
    name: 'og.blotter.Dialog',
    dependencies: [],
    obj: function () {
        return function (config) {
            var dialog = this, $selector, form_block = '.OG-blotter-form-block', form_wrapper, title, submit;
            dialog.load = function () {
                if(config) {
                    title = "Edit Trade", submit = "Update";
                    og.api.text({module: 'og.blotter.forms.blocks.form_edit_tash'}).pipe(function (template){
                       var type = config.data.security ? config.data.security.type.toLowerCase() : "fungibletrade";
                        $selector = $(template);
                        dialog.create();
                        dialog.populate(type, config.data);
                    });
                }
                else {
                    title = "Add New Tade", submit = "Create";
                    og.api.text({module: 'og.blotter.forms.blocks.form_types_tash'}).pipe(function (template){
                        $selector = $(template)
                        .on('change', function (event) {
                            dialog.populate($(event.target).val());
                        });
                        dialog.create();
                    });
                }
            };
            dialog.populate = function (suffix, data) {
                var str, inner;
                str = 'og.blotter.forms.' + suffix;
                inner = str.split('.').reduce(function (acc, val) {
                    if (typeof acc[val] === 'undefined') dialog.clear();
                    else return acc[val];
                    }, window);
                if(inner) {
                    form_wrapper = new inner(data);
                    $('.ui-dialog-title').html(form_wrapper.title);
                }
            };
            dialog.create = function () {
                og.common.util.ui.dialog({
                    type: 'input', title: title, width: 530, height: 1200, custom: $selector,
                    buttons: {
                        'Create': function () {form_wrapper.submit(); $(this).dialog('close');},
                        'Cancel': function () {$(this).dialog('close');}
                    }
                });
            };
            dialog.clear = function () {
                $(form_block).empty();
                $('.ui-dialog-title').html("Add New Trade");
            };
            dialog.load();
        };
    }
}); <commit_msg>save as new button in dialog<commit_after>/**
 * Copyright 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
 * Please see distribution for license.
 */
$.register_module({
    name: 'og.blotter.Dialog',
    dependencies: [],
    obj: function () {
        return function (config) {
            var dialog = this, $selector, form_block = '.OG-blotter-form-block', form_wrapper, title, submit;
            dialog.load = function () {
                if(config) {
                    title = "Edit Trade", submit = "Update";
                    og.api.text({module: 'og.blotter.forms.blocks.form_edit_tash'}).pipe(function (template){
                       var type = config.data.security ? config.data.security.type.toLowerCase() : "fungibletrade";
                        $selector = $(template);
                        dialog.create();
                        dialog.populate(type, config.data);
                    });
                }
                else {
                    title = "Add New Tade", submit = "Create";
                    og.api.text({module: 'og.blotter.forms.blocks.form_types_tash'}).pipe(function (template){
                        $selector = $(template)
                        .on('change', function (event) {
                            dialog.populate($(event.target).val());
                        });
                        dialog.create();
                    });
                }
            };
            dialog.populate = function (suffix, data) {
                var str, inner;
                str = 'og.blotter.forms.' + suffix;
                inner = str.split('.').reduce(function (acc, val) {
                    if (typeof acc[val] === 'undefined') dialog.clear();
                    else return acc[val];
                    }, window);
                if(inner) {
                    form_wrapper = new inner(data);
                    $('.ui-dialog-title').html(form_wrapper.title);
                }
            };
            dialog.create = function () {
                var buttons = {
                        'Save': function () {form_wrapper.submit(); $(this).dialog('close');},
                        'Save as new' : function () {form_wrapper.submit(); $(this).dialog('close');},
                        'Cancel': function () {$(this).dialog('close');}
                    };
                if(!config) delete buttons['Save as new'];
                og.common.util.ui.dialog({
                    type: 'input', title: title, width: 530, height: 1200, custom: $selector,
                    buttons: buttons
                });
            };
            dialog.clear = function () {
                $(form_block).empty();
                $('.ui-dialog-title').html("Add New Trade");
            };
            dialog.load();
        };
    }
}); <|endoftext|>


<commit_before>/*
 * @copyright 2009 - present by OpenGamma Inc
 * @license See distribution for license
 */
$.register_module({
    name: 'og.views.timeseries',
    dependencies: [
        'og.api.rest',
        'og.api.text',
        'og.common.masthead.menu',
        'og.common.routes',
        'og.common.search_results.core',
        'og.common.util.history',
        'og.common.util.ui.dialog',
        'og.common.util.ui.message',
        'og.common.util.ui.toolbar',
        'og.views.common.layout',
        'og.views.common.state',
        'og.views.common.default_details'
    ],
    obj: function () {
        var api = og.api,
            common = og.common,
            details = common.details,
            history = common.util.history,
            masthead = common.masthead,
            routes = common.routes,
            search, layout,
            ui = common.util.ui,
            module = this,
            page_name = module.name.split('.').pop(),
            filter_rule_str = '/identifier:?/data_source:?/data_provider:?/data_field:?/observation_time:?',
            check_state = og.views.common.state.check.partial('/' + page_name),
            timeseries,
            toolbar_buttons = {
                'new': function () {
                    ui.dialog({
                        type: 'input',
                        title: 'Add New Timeseries',
                        fields: [
                            {type: 'select', name: 'Scheme Type', id: 'scheme',
                                options: [
                                    {name: 'Bloomberg Ticker', value: 'BLOOMBERG_TICKER'},
                                    {name: 'Bloomberg Ticker/Coupon/Maturity', value: 'BLOOMBERG_TCM'},
                                    {name: 'Bloomberg BUID', value: 'BLOOMBERG_BUID'},
                                    {name: 'CUSIP', value: 'CUSIP'},
                                    {name: 'ISIN', value: 'ISIN'},
                                    {name: 'RIC', value: 'RIC'},
                                    {name: 'SEDOL', value: 'CSEDOL1'}
                                ]
                            },
                            {type: 'input', name: 'Data provider', id: 'provider'},
                            {type: 'input', name: 'Data field', id: 'field'},
                            {type: 'input', name: 'Start date(yyyy-mm-dd)', id: 'start'},
                            {type: 'input', name: 'End date(yyyy-mm-dd)', id: 'end'},
                            {type: 'textarea', name: 'Identifiers', id: 'identifiers'}
                        ],
                        buttons: {
                            'OK': function () {
                                $(this).dialog('close');
                                api.rest.timeseries.put({
                                    handler: function (result) {
                                        var args = routes.current().args, rule = module.rules.load_timeseries;
                                        if (result.error) return ui.dialog({type: 'error', message: result.message});
                                        timeseries.search(args);
                                        if (result.meta.id)
                                            return routes.go(routes.hash(rule, args, {add: {id: result.meta.id}}));
                                        routes.go(routes.hash(module.rules.load, args));
                                    },
                                    scheme_type: ui.dialog({return_field_value: 'scheme'}),
                                    data_provider: ui.dialog({return_field_value: 'provider'}),
                                    data_field: ui.dialog({return_field_value: 'field'}),
                                    start: ui.dialog({return_field_value: 'start'}) || '',
                                    end: ui.dialog({return_field_value: 'end'}) || '',
                                    identifier: ui.dialog({return_field_value: 'identifiers'})
                                });
                            }
                        }
                    })
                },
                'delete': function () {
                    ui.dialog({
                        type: 'confirm',
                        title: 'Delete timeseries?',
                        message: 'Are you sure you want to permanently delete this timeseries?',
                        buttons: {
                            'Delete': function () {
                                api.rest.timeseries.del({
                                    handler: function (result) {
                                        var args = routes.current().args, rule = module.rules.load;
                                        ui.dialog({type: 'confirm', action: 'close'});
                                        if (result.error) return ui.dialog({type: 'error', message: result.message});
                                        routes.go(routes.hash(rule, args));
                                    }, id: routes.current().args.id
                                });
                            }
                        }
                    })
                }
            },
            options = {
                slickgrid: {
                    'selector': '.OG-js-search', 'page_type': 'timeseries',
                    'columns': [
                        {
                            id: 'data_source', toolTip: 'data source',
                            name: '<input type="text" placeholder="data source" '
                                + 'class="og-js-data_source-filter" style="width: 70px;">',
                            field: 'data_source', width: 90, cssClass: 'og-uppercase'
                        },
                        {
                            id: 'identifier', toolTip: 'identifier',
                            name: '<input type="text" placeholder="identifier" '
                                + 'class="og-js-identifier-filter" style="width: 130px;">',
                            field: 'identifier', width: 150, cssClass: 'og-link'
                        },
                        {
                            id: 'data_provider', toolTip: 'data provider',
                            name: '<input type="text" placeholder="data provider" '
                                + 'class="og-js-data_provider-filter" style="width: 65px;">',
                            field: 'data_provider', width: 85, cssClass: 'og-link'
                        },
                        {
                            id: 'data_field', toolTip: 'data field',
                            name: '<input type="text" placeholder="data field" '
                                + 'class="og-js-data_field-filter" style="width: 50px;">',
                            field: 'data_field', width: 70, cssClass: 'og-link'
                        },
                        {
                            id: 'observation_time', toolTip: 'observation time',
                            name: '<input type="text" placeholder="observation time" '
                                + 'class="og-js-observation_time-filter" style="width: 100px;">',
                            field: 'observation_time', width: 120, cssClass: 'og-link'
                        }
                    ]
                },
                toolbar: {
                    'default':  {
                        buttons: [
                            {id: 'new', tooltip: 'New', handler: toolbar_buttons['new']},
                            {id: 'save', tooltip: 'Save', enabled: 'OG-disabled'},
                            {id: 'saveas', tooltip: 'Save as', enabled: 'OG-disabled'},
                            {id: 'delete', tooltip: 'Delete', enabled: 'OG-disabled'}
                        ],
                        location: '.OG-tools'
                    },
                    active: {
                        buttons: [
                            {id: 'new', tooltip: 'New', handler: toolbar_buttons['new']},
                            {id: 'save', tooltip: 'Save', enabled: 'OG-disabled'},
                            {id: 'saveas', tooltip: 'Save as', enabled: 'OG-disabled'},
                            {id: 'delete', tooltip: 'Delete', handler: toolbar_buttons['delete']}
                        ],
                        location: '.OG-tools'
                    }
                }
            },
            default_details = og.views.common.default_details.partial(page_name, 'Time Series', options),
            details_page = function (args) {
                layout.inner.options.south.onclose = null;
                layout.inner.close('south');
                api.rest.timeseries.get({
                    dependencies: ['id'],
                    handler: function (result) {
                        if (result.error) return alert(result.message);
                        var json = result.data;
                        api.text({module: module.name, handler: function (template) {
                            var $html, error_html, json_id = json.identifiers, title, header, content;
                            error_html = '\

\
                                    This position has been deleted\

\
                            ';
                            // check if any of the following scheme types are in json.identifiers, in
                            // reverse order of preference, delimiting if multiple, then assign to title
                            ['ISIN', 'SEDOL1', 'CUSIP', 'BLOOMBERG_BUID', 'BLOOMBERG_TICKER'].forEach(function (val) {
                                title = (function (type) {
                                    return json.identifiers.reduce(function (acc, val) {
                                        if (val.scheme === type) acc = acc
                                            ? acc + ', ' + val.value
                                            : type.lang() + ' - ' + val.value;
                                        return acc
                                    }, '')
                                }(val)) || title;
                            });
                            $html = $.tmpl(template, $.extend(json.template_data, {
                                title: title || json.template_data.object_id
                            }));
                            history.put({
                                name: title + ' (' + json.template_data.data_field + ')',
                                item: 'history.timeseries.recent',
                                value: routes.current().hash
                            });
                            // Initial html setup
                            header = $.outer($html.find('> header')[0]);
                            content = $.outer($html.find('> section')[0]);
                            $('.ui-layout-inner-center .ui-layout-header').html(header);
                            $('.ui-layout-inner-center .ui-layout-content').html(content);
                            ui.toolbar(options.toolbar.active);
                            if (json.template_data && json.template_data.deleted) {
                                $('.ui-layout-inner-north').html(error_html);
                                layout.inner.sizePane('north', '0');
                                layout.inner.open('north');
                                $('.OG-tools .og-js-delete').addClass('OG-disabled').unbind();
                            } else {
                                layout.inner.close('north');
                                $('.ui-layout-inner-north').empty();
                            }
                            // Identifiers
                            $('.ui-layout-inner-center .og-js-identifiers').html(
                                json_id.reduce(function (acc, cur) {
                                    return acc + '
'+  cur.scheme +'	'+ cur.value +'
'
                                }, '')
                            );
                            // Plot
                            common.gadgets.timeseries({
                                selector: '.OG-timeseries .og-plots',
                                id: result.data.template_data.object_id
                            });
                            ui.message({location: '.ui-layout-inner-center', destroy: true});
                            layout.inner.resizeAll();
                        }});
                    },
                    id: args.id,
                    cache_for: 10000,
                    loading: function () {
                        ui.message({
                            location: '.ui-layout-inner-center',
                            message: {0: 'loading...', 3000: 'still loading...'}
                        });
                    }
                });
            };
        module.rules = {
            load: {route: '/' + page_name + '/' + filter_rule_str, method: module.name + '.load'},
            load_filter: {
                route: '/' + page_name + '/filter:/:id?' + filter_rule_str, method: module.name + '.load_filter'
            },
            load_timeseries: {
                route: '/' + page_name + '/:id' + filter_rule_str, method: module.name + '.load_' + page_name
            }
        };
        return timeseries = {
            load: function (args) {
                layout = og.views.common.layout;
                check_state({args: args, conditions: [
                    {new_page: function () {
                        timeseries.search(args);
                        masthead.menu.set_tab(page_name);
                    }}
                ]});
                if (args.id) return;
                default_details();
            },
            load_filter: function (args) {
                check_state({args: args, conditions: [
                    {new_value: 'id', stop: true, method: function () {if (args.id) timeseries.load_timeseries(args);}},
                    {new_page: function () {timeseries.load(args);}}
                ]});
                search.filter(args);
            },
            load_timeseries: function (args) {
                check_state({args: args, conditions: [{new_page: timeseries.load}]});
                timeseries.details(args);
            },
            search: function (args) {
                if (!search) search = common.search_results.core();
                search.load($.extend(options.slickgrid, {url: args}));
            },
            details: details_page,
            init: function () {
                for (var rule in module.rules) routes.add(module.rules[rule]);
            },
            rules: module.rules
        };
    }
});<commit_msg>Fixed message text: 'This position has been deleted' -> 'This time series has been deleted'<commit_after>/*
 * @copyright 2009 - present by OpenGamma Inc
 * @license See distribution for license
 */
$.register_module({
    name: 'og.views.timeseries',
    dependencies: [
        'og.api.rest',
        'og.api.text',
        'og.common.masthead.menu',
        'og.common.routes',
        'og.common.search_results.core',
        'og.common.util.history',
        'og.common.util.ui.dialog',
        'og.common.util.ui.message',
        'og.common.util.ui.toolbar',
        'og.views.common.layout',
        'og.views.common.state',
        'og.views.common.default_details'
    ],
    obj: function () {
        var api = og.api,
            common = og.common,
            details = common.details,
            history = common.util.history,
            masthead = common.masthead,
            routes = common.routes,
            search, layout,
            ui = common.util.ui,
            module = this,
            page_name = module.name.split('.').pop(),
            filter_rule_str = '/identifier:?/data_source:?/data_provider:?/data_field:?/observation_time:?',
            check_state = og.views.common.state.check.partial('/' + page_name),
            timeseries,
            toolbar_buttons = {
                'new': function () {
                    ui.dialog({
                        type: 'input',
                        title: 'Add New Timeseries',
                        fields: [
                            {type: 'select', name: 'Scheme Type', id: 'scheme',
                                options: [
                                    {name: 'Bloomberg Ticker', value: 'BLOOMBERG_TICKER'},
                                    {name: 'Bloomberg Ticker/Coupon/Maturity', value: 'BLOOMBERG_TCM'},
                                    {name: 'Bloomberg BUID', value: 'BLOOMBERG_BUID'},
                                    {name: 'CUSIP', value: 'CUSIP'},
                                    {name: 'ISIN', value: 'ISIN'},
                                    {name: 'RIC', value: 'RIC'},
                                    {name: 'SEDOL', value: 'CSEDOL1'}
                                ]
                            },
                            {type: 'input', name: 'Data provider', id: 'provider'},
                            {type: 'input', name: 'Data field', id: 'field'},
                            {type: 'input', name: 'Start date(yyyy-mm-dd)', id: 'start'},
                            {type: 'input', name: 'End date(yyyy-mm-dd)', id: 'end'},
                            {type: 'textarea', name: 'Identifiers', id: 'identifiers'}
                        ],
                        buttons: {
                            'OK': function () {
                                $(this).dialog('close');
                                api.rest.timeseries.put({
                                    handler: function (result) {
                                        var args = routes.current().args, rule = module.rules.load_timeseries;
                                        if (result.error) return ui.dialog({type: 'error', message: result.message});
                                        timeseries.search(args);
                                        if (result.meta.id)
                                            return routes.go(routes.hash(rule, args, {add: {id: result.meta.id}}));
                                        routes.go(routes.hash(module.rules.load, args));
                                    },
                                    scheme_type: ui.dialog({return_field_value: 'scheme'}),
                                    data_provider: ui.dialog({return_field_value: 'provider'}),
                                    data_field: ui.dialog({return_field_value: 'field'}),
                                    start: ui.dialog({return_field_value: 'start'}) || '',
                                    end: ui.dialog({return_field_value: 'end'}) || '',
                                    identifier: ui.dialog({return_field_value: 'identifiers'})
                                });
                            }
                        }
                    })
                },
                'delete': function () {
                    ui.dialog({
                        type: 'confirm',
                        title: 'Delete timeseries?',
                        message: 'Are you sure you want to permanently delete this timeseries?',
                        buttons: {
                            'Delete': function () {
                                api.rest.timeseries.del({
                                    handler: function (result) {
                                        var args = routes.current().args, rule = module.rules.load;
                                        ui.dialog({type: 'confirm', action: 'close'});
                                        if (result.error) return ui.dialog({type: 'error', message: result.message});
                                        routes.go(routes.hash(rule, args));
                                    }, id: routes.current().args.id
                                });
                            }
                        }
                    })
                }
            },
            options = {
                slickgrid: {
                    'selector': '.OG-js-search', 'page_type': 'timeseries',
                    'columns': [
                        {
                            id: 'data_source', toolTip: 'data source',
                            name: '<input type="text" placeholder="data source" '
                                + 'class="og-js-data_source-filter" style="width: 70px;">',
                            field: 'data_source', width: 90, cssClass: 'og-uppercase'
                        },
                        {
                            id: 'identifier', toolTip: 'identifier',
                            name: '<input type="text" placeholder="identifier" '
                                + 'class="og-js-identifier-filter" style="width: 130px;">',
                            field: 'identifier', width: 150, cssClass: 'og-link'
                        },
                        {
                            id: 'data_provider', toolTip: 'data provider',
                            name: '<input type="text" placeholder="data provider" '
                                + 'class="og-js-data_provider-filter" style="width: 65px;">',
                            field: 'data_provider', width: 85, cssClass: 'og-link'
                        },
                        {
                            id: 'data_field', toolTip: 'data field',
                            name: '<input type="text" placeholder="data field" '
                                + 'class="og-js-data_field-filter" style="width: 50px;">',
                            field: 'data_field', width: 70, cssClass: 'og-link'
                        },
                        {
                            id: 'observation_time', toolTip: 'observation time',
                            name: '<input type="text" placeholder="observation time" '
                                + 'class="og-js-observation_time-filter" style="width: 100px;">',
                            field: 'observation_time', width: 120, cssClass: 'og-link'
                        }
                    ]
                },
                toolbar: {
                    'default':  {
                        buttons: [
                            {id: 'new', tooltip: 'New', handler: toolbar_buttons['new']},
                            {id: 'save', tooltip: 'Save', enabled: 'OG-disabled'},
                            {id: 'saveas', tooltip: 'Save as', enabled: 'OG-disabled'},
                            {id: 'delete', tooltip: 'Delete', enabled: 'OG-disabled'}
                        ],
                        location: '.OG-tools'
                    },
                    active: {
                        buttons: [
                            {id: 'new', tooltip: 'New', handler: toolbar_buttons['new']},
                            {id: 'save', tooltip: 'Save', enabled: 'OG-disabled'},
                            {id: 'saveas', tooltip: 'Save as', enabled: 'OG-disabled'},
                            {id: 'delete', tooltip: 'Delete', handler: toolbar_buttons['delete']}
                        ],
                        location: '.OG-tools'
                    }
                }
            },
            default_details = og.views.common.default_details.partial(page_name, 'Time Series', options),
            details_page = function (args) {
                layout.inner.options.south.onclose = null;
                layout.inner.close('south');
                api.rest.timeseries.get({
                    dependencies: ['id'],
                    handler: function (result) {
                        if (result.error) return alert(result.message);
                        var json = result.data;
                        api.text({module: module.name, handler: function (template) {
                            var $html, error_html, json_id = json.identifiers, title, header, content;
                            error_html = '\

\
                                    This time series has been deleted\

\
                            ';
                            // check if any of the following scheme types are in json.identifiers, in
                            // reverse order of preference, delimiting if multiple, then assign to title
                            ['ISIN', 'SEDOL1', 'CUSIP', 'BLOOMBERG_BUID', 'BLOOMBERG_TICKER'].forEach(function (val) {
                                title = (function (type) {
                                    return json.identifiers.reduce(function (acc, val) {
                                        if (val.scheme === type) acc = acc
                                            ? acc + ', ' + val.value
                                            : type.lang() + ' - ' + val.value;
                                        return acc
                                    }, '')
                                }(val)) || title;
                            });
                            $html = $.tmpl(template, $.extend(json.template_data, {
                                title: title || json.template_data.object_id
                            }));
                            history.put({
                                name: title + ' (' + json.template_data.data_field + ')',
                                item: 'history.timeseries.recent',
                                value: routes.current().hash
                            });
                            // Initial html setup
                            header = $.outer($html.find('> header')[0]);
                            content = $.outer($html.find('> section')[0]);
                            $('.ui-layout-inner-center .ui-layout-header').html(header);
                            $('.ui-layout-inner-center .ui-layout-content').html(content);
                            ui.toolbar(options.toolbar.active);
                            if (json.template_data && json.template_data.deleted) {
                                $('.ui-layout-inner-north').html(error_html);
                                layout.inner.sizePane('north', '0');
                                layout.inner.open('north');
                                $('.OG-tools .og-js-delete').addClass('OG-disabled').unbind();
                            } else {
                                layout.inner.close('north');
                                $('.ui-layout-inner-north').empty();
                            }
                            // Identifiers
                            $('.ui-layout-inner-center .og-js-identifiers').html(
                                json_id.reduce(function (acc, cur) {
                                    return acc + '
'+  cur.scheme +'	'+ cur.value +'
'
                                }, '')
                            );
                            // Plot
                            common.gadgets.timeseries({
                                selector: '.OG-timeseries .og-plots',
                                id: result.data.template_data.object_id
                            });
                            ui.message({location: '.ui-layout-inner-center', destroy: true});
                            layout.inner.resizeAll();
                        }});
                    },
                    id: args.id,
                    cache_for: 10000,
                    loading: function () {
                        ui.message({
                            location: '.ui-layout-inner-center',
                            message: {0: 'loading...', 3000: 'still loading...'}
                        });
                    }
                });
            };
        module.rules = {
            load: {route: '/' + page_name + '/' + filter_rule_str, method: module.name + '.load'},
            load_filter: {
                route: '/' + page_name + '/filter:/:id?' + filter_rule_str, method: module.name + '.load_filter'
            },
            load_timeseries: {
                route: '/' + page_name + '/:id' + filter_rule_str, method: module.name + '.load_' + page_name
            }
        };
        return timeseries = {
            load: function (args) {
                layout = og.views.common.layout;
                check_state({args: args, conditions: [
                    {new_page: function () {
                        timeseries.search(args);
                        masthead.menu.set_tab(page_name);
                    }}
                ]});
                if (args.id) return;
                default_details();
            },
            load_filter: function (args) {
                check_state({args: args, conditions: [
                    {new_value: 'id', stop: true, method: function () {if (args.id) timeseries.load_timeseries(args);}},
                    {new_page: function () {timeseries.load(args);}}
                ]});
                search.filter(args);
            },
            load_timeseries: function (args) {
                check_state({args: args, conditions: [{new_page: timeseries.load}]});
                timeseries.details(args);
            },
            search: function (args) {
                if (!search) search = common.search_results.core();
                search.load($.extend(options.slickgrid, {url: args}));
            },
            details: details_page,
            init: function () {
                for (var rule in module.rules) routes.add(module.rules[rule]);
            },
            rules: module.rules
        };
    }
});
<|endoftext|>