<commit_before>'use strict';

const ServerCodeModel   = require('./model'),
      logger            = require('../util/logger'),
      path              = require('path'),
      fs                = require('fs'),
      file              = require('../util/file'),
      JSZip             = require('jszip'),
      ApiServerService = require('./services/api-server');

exports.publish = function(opts) {
  const apiServer = new ApiServerService(opts.app, opts.backendless.apiServer);

  let registered;
  let zipped;
  let model;

  function buildModel() {
    model = ServerCodeModel.build(process.cwd(), file.expand(opts.app.files, { nodir: true }));

    if (model.isEmpty() && !opts.allowEmpty) {
      throw new Error('Nothing to publish');
    }

    if (model.errors.length) {
      throw new Error('Please resolve Model Errors before deploying to production');
    }
  }

  function zip() {
    zipped = generateZip(model, dependencyPatterns().concat(opts.app.files), opts.keepZip);
  }

  function publishHandlers() {
    if (model.handlers.values().length) {
      return apiServer.registerModel(model).then(() => {
        return apiServer.publish(zipped);
      });
    }
  }

  function publishServices() {
    const services = model.services.values();

    if (services.length) {
      return apiServer.unregisterDebugServices()
        .then(() => Promise.all(services.map((s) => {
          return apiServer.publishService(s, zipped);
        })));
    }
  }

  function registerRunner() {
    return apiServer.registerRunner() // http://bugs.backendless.com/browse/BKNDLSS-11655
      .then(() => registered = true);
  }

  function finalize() {
    if (registered) {
      registered = false;

      return apiServer.unregisterRunner();
    }
  }

  return Promise.resolve()
    .then(buildModel)
    .then(zip)
    .then(registerRunner)
    .then(publishHandlers)
    .then(publishServices)
    .then(finalize)
    .catch(err => {
      finalize();

      throw err;
    });
};

function generateZip(model, patterns, keep) {
  logger.info('Preparing app zip file for deployment..');
  logger.debug('File patterns to be included:');

  patterns.forEach(pattern => logger.debug(pattern));

  const zip = new JSZip();
  const expanded = file.expand(patterns);
  let files = 0;

  zip.file('model.json', JSON.stringify(model));

  expanded.forEach(item => {
    if (fs.statSync(item).isDirectory()) {
      zip.folder(item);
    } else {
      zip.file(item, fs.readFileSync(item));
      files++;
    }
  });

  logger.info(`${files} files added into deployment archive`);

  const result = zip.generate({ type: 'nodebuffer' });

  if (keep) {
    fs.writeFile('deploy.zip', result);
    logger.info(`Deployment archive is saved to ${path.resolve('deploy.zip')}`);
  }

  return result;
}

function dependencyPatterns() {
  const pkgFile = path.resolve('package.json');

  const result = ['node_modules/**'];

  if (fs.existsSync(pkgFile)) {
    const pkg = require(pkgFile);

    if (pkg.devDependencies) {
      Object.keys(pkg.devDependencies).forEach(dep => {
        result.push(`!node_modules/${dep}`);
      });
    }
  } else {
    logger.info('Warning. Working directory doesn\'t contain package.json file. ' +
      'CodeRunner is not able to optimize application deployment size');
  }

  return result;
}<commit_msg>fix (publisher) dev dependencies are included into deployment zip file<commit_after>'use strict';

const ServerCodeModel   = require('./model'),
      logger            = require('../util/logger'),
      path              = require('path'),
      fs                = require('fs'),
      file              = require('../util/file'),
      JSZip             = require('jszip'),
      ApiServerService = require('./services/api-server');

exports.publish = function(opts) {
  const apiServer = new ApiServerService(opts.app, opts.backendless.apiServer);

  let registered;
  let zipped;
  let model;

  function buildModel() {
    model = ServerCodeModel.build(process.cwd(), file.expand(opts.app.files, { nodir: true }));

    if (model.isEmpty() && !opts.allowEmpty) {
      throw new Error('Nothing to publish');
    }

    if (model.errors.length) {
      throw new Error('Please resolve Model Errors before deploying to production');
    }
  }

  function zip() {
    zipped = generateZip(model, dependencyPatterns().concat(opts.app.files), opts.keepZip);
  }

  function publishHandlers() {
    if (model.handlers.values().length) {
      return apiServer.registerModel(model).then(() => {
        return apiServer.publish(zipped);
      });
    }
  }

  function publishServices() {
    const services = model.services.values();

    if (services.length) {
      return apiServer.unregisterDebugServices()
        .then(() => Promise.all(services.map((s) => {
          return apiServer.publishService(s, zipped);
        })));
    }
  }

  function registerRunner() {
    return apiServer.registerRunner() // http://bugs.backendless.com/browse/BKNDLSS-11655
      .then(() => registered = true);
  }

  function finalize() {
    if (registered) {
      registered = false;

      return apiServer.unregisterRunner();
    }
  }

  return Promise.resolve()
    .then(buildModel)
    .then(zip)
    .then(registerRunner)
    .then(publishHandlers)
    .then(publishServices)
    .then(finalize)
    .catch(err => {
      finalize();

      throw err;
    });
};

function generateZip(model, patterns, keep) {
  logger.info('Preparing app zip file for deployment..');
  logger.debug('File patterns to be included:');

  patterns.forEach(pattern => logger.debug(pattern));

  const zip = new JSZip();
  const expanded = file.expand(patterns);
  let files = 0;

  zip.file('model.json', JSON.stringify(model));

  expanded.forEach(item => {
    if (fs.statSync(item).isDirectory()) {
      zip.folder(item);
    } else {
      zip.file(item, fs.readFileSync(item));
      files++;
    }
  });

  logger.info(`${files} files added into deployment archive`);

  const result = zip.generate({ type: 'nodebuffer' });

  if (keep) {
    fs.writeFile('deploy.zip', result);
    logger.info(`Deployment archive is saved to ${path.resolve('deploy.zip')}`);
  }

  return result;
}

function dependencyPatterns() {
  const pkgFile = path.resolve('package.json');

  const result = ['node_modules/**'];

  if (fs.existsSync(pkgFile)) {
    const pkg = require(pkgFile);

    if (pkg.devDependencies) {
      Object.keys(pkg.devDependencies).forEach(dep => {
        result.push(`!node_modules/${dep}/**`);
      });
    }
  } else {
    logger.info('Warning. Working directory doesn\'t contain package.json file. ' +
      'CodeRunner is not able to optimize application deployment size');
  }

  return result;
}<|endoftext|>


<commit_before>/**
 * @module opcua.server
 *
 *
 *
 *
 */
var assert = require("better-assert");
var _ = require("underscore");

var EventEmitter = require("events").EventEmitter;
var util = require("util");

var subscription_service = require("../services/subscription_service");
var MonitoredItemNotification = subscription_service.MonitoredItemNotification;
var DataValue = require("../datamodel/datavalue").DataValue;
var Variant = require("../datamodel/variant").Variant;
var DataType = require("../datamodel/variant").DataType;
var StatusCodes = require("../datamodel/opcua_status_code").StatusCodes;

var minimumSamplingInterval = 50;   // 50 ms as a minimum sampling interval
var defaultSamplingInterval = 500; // 500 ms as a default sampling interval
/**
 * a server side monitored item
 *
 * - Once created, the MonitoredItem will raised an "samplingEvent" event every "samplingInterval" millisecond
 *   until {{#crossLink "MonitoredItem/terminate:method"}}{{/crossLink}} is called.
 *
 * - It is up to the  event receiver to call {{#crossLink "MonitoredItem/recordValue:method"}}{{/crossLink}}.
 *
 * @class MonitoredItem
 * @param options  the options
 * @param options.clientHandle     {Number}  - the client handle
 * @param options.samplingInterval {Number}  - the sampling Interval
 * @param options.discardOldest    {boolean} - if discardOldest === true, older items are removed from the queue
 *                                             when
 * @param options.queueSize        {Number} - the size of the queue.
 * @constructor
 */
function MonitoredItem(options) {

    EventEmitter.apply(this, arguments);

    assert(options.hasOwnProperty("clientHandle"));
    assert(options.hasOwnProperty("samplingInterval"));
    assert(_.isFinite(options.clientHandle));
    assert(_.isFinite(options.samplingInterval));
    assert(_.isBoolean(options.discardOldest));
    assert(_.isFinite(options.queueSize));
    assert(options.queueSize > 0);

    var self = this;

    self.clientHandle = options.clientHandle;

    self.samplingInterval = Math.max(self.samplingInterval,minimumSamplingInterval);
    self.samplingInterval = options.samplingInterval || defaultSamplingInterval;

    self.discardOldest = options.discardOldest;
    self.queueSize = options.queueSize;
    self.queue = [];
    self.overflow = false;

    self._samplingId = null;
    self._samplingId = setInterval(function () {
        self._on_sampling_timer();
    }, self.samplingInterval);

    self.oldValue = new Variant({dataType: DataType.Null, value: null});

}
util.inherits(MonitoredItem, EventEmitter);

/**
 * Terminate the  MonitoredItem.
 * @method terminate
 *
 * This will stop the internal sampling timer.
 */
MonitoredItem.prototype.terminate = function () {
    var self = this;
    assert(self._samplingId != null);
    clearInterval(self._samplingId);
    self._samplingId = null;
};

/**
 * @method _on_sampling_timer
 * @private
 * request
 *
 * @example
 *
 *    ```javascript
 *    var monitoredItem = new   MonitoredItem({
 *          ...
 *    });
 *    monitoredItem.on("samplingEvent",function (oldValue) {
 *
 *          var value = readValue();
 *
 *          if ( isDifferent(value, oldValue)) {
 *              monitoredItem.recordValue(value);
 *          }
 *    });
 *    ```
 */
MonitoredItem.prototype._on_sampling_timer = function () {

    var self = this;
    // @event samplingEvent
    // @param oldValue {DataValue} - the last known recorded data value.
    self.emit("samplingEvent", self.oldValue);
};

/**
 * @method recordValue
 * @param variant            {Variant }
 * @param sourceTimestamp    {Date|null}
 * @param sourcePicoseconds  {Number|null}
 *
 */
MonitoredItem.prototype.recordValue = function (variant, sourceTimestamp, sourcePicoseconds) {
    var self = this;
    // store last value
    self.oldValue = variant;

    sourceTimestamp = sourceTimestamp || new Date();
    sourcePicoseconds = sourcePicoseconds || 0;

    // create a MonitoredItemNotification

    var dataValue = new DataValue({
        statusCode: StatusCodes.Good,
        value: variant,
        serverTimestamp: new Date(),
        serverPicoseconds: 0,
        sourceTimestamp: sourceTimestamp,
        sourcePicoseconds: sourcePicoseconds
    });

    // push new value to queue
    self.queue.push(dataValue);

    // discard oldest if necessary
    if (self.queue.length > self.queueSize) {

        self.overflow = true;

        if (self.discardOldest) {
            // remove oldest
            self.queue.shift(); // remove front element
        } else {
            // remove newest
            self.queue.pop();
        }
    }

};

/**
 * @method  extractMonitoredItemNotifications
 * @return {Array.<*>}
 */
MonitoredItem.prototype.extractMonitoredItemNotifications = function () {
    // MonitoredItemNotification
    var self = this;
    var notifications = self.queue.map(function (dataValue) {
        return { clientHandle: self.clientHandle, value: dataValue};
    });
    // empty queue
    self.queue = [];

    return notifications;
};

exports.MonitoredItem = MonitoredItem;
<commit_msg>allow queuesize ==0<commit_after>/**
 * @module opcua.server
 *
 *
 *
 *
 */
var assert = require("better-assert");
var _ = require("underscore");

var EventEmitter = require("events").EventEmitter;
var util = require("util");

var subscription_service = require("../services/subscription_service");
var MonitoredItemNotification = subscription_service.MonitoredItemNotification;
var DataValue = require("../datamodel/datavalue").DataValue;
var Variant = require("../datamodel/variant").Variant;
var DataType = require("../datamodel/variant").DataType;
var StatusCodes = require("../datamodel/opcua_status_code").StatusCodes;

var minimumSamplingInterval = 50;   // 50 ms as a minimum sampling interval
var defaultSamplingInterval = 500; // 500 ms as a default sampling interval
/**
 * a server side monitored item
 *
 * - Once created, the MonitoredItem will raised an "samplingEvent" event every "samplingInterval" millisecond
 *   until {{#crossLink "MonitoredItem/terminate:method"}}{{/crossLink}} is called.
 *
 * - It is up to the  event receiver to call {{#crossLink "MonitoredItem/recordValue:method"}}{{/crossLink}}.
 *
 * @class MonitoredItem
 * @param options  the options
 * @param options.clientHandle     {Number}  - the client handle
 * @param options.samplingInterval {Number}  - the sampling Interval
 * @param options.discardOldest    {boolean} - if discardOldest === true, older items are removed from the queue
 *                                             when
 * @param options.queueSize        {Number} - the size of the queue.
 * @constructor
 */
function MonitoredItem(options) {

    EventEmitter.apply(this, arguments);

    assert(options.hasOwnProperty("clientHandle"));
    assert(options.hasOwnProperty("samplingInterval"));
    assert(_.isFinite(options.clientHandle));
    assert(_.isFinite(options.samplingInterval));
    assert(_.isBoolean(options.discardOldest));
    assert(_.isFinite(options.queueSize));
    assert(options.queueSize >= 0);

    var self = this;

    self.clientHandle = options.clientHandle;

    self.samplingInterval = Math.max(self.samplingInterval,minimumSamplingInterval);
    self.samplingInterval = options.samplingInterval || defaultSamplingInterval;

    self.discardOldest = options.discardOldest;
    self.queueSize = options.queueSize;
    self.queue = [];
    self.overflow = false;

    self._samplingId = null;
    self._samplingId = setInterval(function () {
        self._on_sampling_timer();
    }, self.samplingInterval);

    self.oldValue = new Variant({dataType: DataType.Null, value: null});

}
util.inherits(MonitoredItem, EventEmitter);

/**
 * Terminate the  MonitoredItem.
 * @method terminate
 *
 * This will stop the internal sampling timer.
 */
MonitoredItem.prototype.terminate = function () {
    var self = this;
    assert(self._samplingId != null);
    clearInterval(self._samplingId);
    self._samplingId = null;
};

/**
 * @method _on_sampling_timer
 * @private
 * request
 *
 * @example
 *
 *    ```javascript
 *    var monitoredItem = new   MonitoredItem({
 *          ...
 *    });
 *    monitoredItem.on("samplingEvent",function (oldValue) {
 *
 *          var value = readValue();
 *
 *          if ( isDifferent(value, oldValue)) {
 *              monitoredItem.recordValue(value);
 *          }
 *    });
 *    ```
 */
MonitoredItem.prototype._on_sampling_timer = function () {

    var self = this;
    // @event samplingEvent
    // @param oldValue {DataValue} - the last known recorded data value.
    self.emit("samplingEvent", self.oldValue);
};

/**
 * @method recordValue
 * @param variant            {Variant }
 * @param sourceTimestamp    {Date|null}
 * @param sourcePicoseconds  {Number|null}
 *
 */
MonitoredItem.prototype.recordValue = function (variant, sourceTimestamp, sourcePicoseconds) {
    var self = this;
    // store last value
    self.oldValue = variant;

    sourceTimestamp = sourceTimestamp || new Date();
    sourcePicoseconds = sourcePicoseconds || 0;

    // create a MonitoredItemNotification

    var dataValue = new DataValue({
        statusCode: StatusCodes.Good,
        value: variant,
        serverTimestamp: new Date(),
        serverPicoseconds: 0,
        sourceTimestamp: sourceTimestamp,
        sourcePicoseconds: sourcePicoseconds
    });

    // push new value to queue
    self.queue.push(dataValue);

    // discard oldest if necessary
    if (self.queue.length > self.queueSize) {

        self.overflow = true;

        if (self.discardOldest) {
            // remove oldest
            self.queue.shift(); // remove front element
        } else {
            // remove newest
            self.queue.pop();
        }
    }

};

/**
 * @method  extractMonitoredItemNotifications
 * @return {Array.<*>}
 */
MonitoredItem.prototype.extractMonitoredItemNotifications = function () {
    // MonitoredItemNotification
    var self = this;
    var notifications = self.queue.map(function (dataValue) {
        return { clientHandle: self.clientHandle, value: dataValue};
    });
    // empty queue
    self.queue = [];

    return notifications;
};

exports.MonitoredItem = MonitoredItem;
<|endoftext|>


<commit_before>//--------------------------------------------------------------------------------
// OPCUA Part 4 $5.10 : Attribute Service Set
// This Service Set provides Service sto access Attributes that are part of Nodes.
//--------------------------------------------------------------------------------
var factories = require("./../misc/factories");
var assert = require('better-assert');
var DataValue = require("./../datamodel/datavalue").DataValue;
var Variant   = require("./../datamodel/variant").Variant;
var _ = require("underscore");

require("./../datamodel/part_8_structures");

require("./../datamodel/numeric_range");

var TimestampsToReturn_Schema = {
    name: "TimestampsToReturn",
    enumValues: {
        Invalid:      -1,
        Source:        0,
        Server:        1,
        Both:          2,
        Neither :      3
    },
    decode: function(stream) {

        var v = stream.readInt32();
        console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ".cyan.bold, y)
        if (y<0 || y>3) {
            return TimestampsToReturn.Invalid;
        }
        return TimestampsToReturn.get(value);
    }
};
var TimestampsToReturn = exports.TimestampsToReturn = factories.registerEnumeration(TimestampsToReturn_Schema);

var AttributeIds = {
    NodeId:1,
    NodeClass:2,
    BrowseName:3,
    DisplayName:4,
    Description:5,
    WriteMask:6,
    UserWriteMask:7,
    IsAbstract:8,
    Symmetric:9,
    InverseName:10,
    ContainsNoLoops:11,
    EventNotifier:12,
    Value:13,
    DataType:14,
    ValueRank:15,
    ArrayDimensions:16,
    AccessLevel:17,
    UserAccessLevel:18,
    MinimumSamplingInterval:19,
    Historizing:20,
    Executable:21,
    UserExecutable:22
};
exports.AttributeIds = AttributeIds;
exports.AttributeNameById = _.invert(AttributeIds);

function is_valid_attributeId(attributeId){
    assert(_.isFinite(attributeId));
    return attributeId>=1 && attributeId<=22;
}
exports.is_valid_attributeId = is_valid_attributeId;

var ReadValueId_Schema = {
    name: "ReadValueId",
    fields: [
        { name: "nodeId" ,       fieldType: "NodeId"},
        { name: "attributeId" ,  fieldType: "IntegerId" ,
            validate:function(value){
                return is_valid_attributeId(value);
            },
            defaultValue: AttributeIds.Value
        }, // see AttributeIds

        // IndexRange : This parameter is used to identify a single element of a structure or an array, or a single
        // range of indexes for arrays. If a range of elements  are specified, the values are returned as a composite.
        // The first element is identified by index 0 (zero).
        // This parameter is null if the specified Attribute is not an array or a structure. However, if the specified
        // Attribute is an array or a structure,and this parameter is null, then all elements are to be included in the
        // range.
        { name: "indexRange" ,   fieldType: "NumericRange"    , defaultValue: function() { return null; }},

        // dataEncoding
        //
        //    This parameter specifies the BrowseName of the DataTypeEncoding that the
        //    Server should use when returning the Value Attribute of a Variable. It is an error
        //    to specify this parameter for other Attributes.
        //    A Client can discover what DataTypeEncodings are available by following the
        //    HasEncoding Reference from the DataType Node for a Variable.
        //    OPC UA defines BrowseNames which Servers shall recognize even if the
        //    DataType Nodes are not visible in the Server address space. These
        //    BrowseNames are:
        //      - DefaultBinary  The default or native binary (or non-XML) encoding.
        //      - DefaultXML  The default XML encoding.
        //
        //    Each DataType shall support at least one of these encodings. DataTypes that do
        //    not have a true binary encoding (e.g. they only have a non-XML text encoding)
        //    should use the DefaultBinary name to identify the encoding that is considered to
        //    be the default non-XML encoding. DataTypes that support at least one XML-based
        //    encoding shall identify one of the encodings as the DefaultXML encoding.
        //    Other standards bodies may define other well-known data encodings that could
        //    be supported.
        //
        //    If this parameter is not specified then the Server shall choose either the
        //    DefaultBinary or DefaultXML encoding according to what Message encoding
        //    (see Part 6) is used for the Session. If the Server does not support the encoding
        //    that matches the Message encoding then the Server shall choose the default
        //    encoding that it does support.
        //
        //    If this parameter is specified for a MonitoredItem, the Server shall set the
        //    StructureChanged bit in the StatusCode (see 7.33) if the DataTypeEncoding
        //    changes. The DataTypeEncoding changes if the DataTypeVersion of the
        //    DataTypeDescription or the DataTypeDictionary associated with the
        //    DataTypeEncoding changes
        { name: "dataEncoding",  fieldType: "QualifiedName" }
    ]
};
exports.ReadValueId = factories.registerObject(ReadValueId_Schema);

/**
 * Maximum age of the value to be read in milliseconds. The age of the value is based on the difference between the
 * ServerTimestamp and the time when the Server starts processing the request. For example if the Client specifies a
 * maxAge of 500 milliseconds and it takes 100 milliseconds until the Server starts processing the request, the age of
 * the returned value could be 600 milliseconds prior to the time it was requested.
 * If the Server has one or more values of an Attribute that are within the maximum age, it can return any one of the
 * values or it can read a new value from the data source. The number of values of an Attribute that a Server has
 * depends on the number of MonitoredItems that are defined for the Attribute.
 * In any case, the Client can make no assumption about which copy of the data will be returned.
 * If the Server does not have a value that is within the maximum age, it shall attempt to read a new value from the
 * data source.
 * If the Server cannot meet the requested maxAge, it returns its “best effort” value rather than rejecting the request.
 * This may occur when the time it takes the Server to process and return the new data value after it has been accessed
 * is greater than the specified maximum age.
 * If maxAge is set to 0, the Server shall attempt to read a new value from the data source.
 * If maxAge is set to the max Int32 value or greater, the Server shall attempt to get a cached value.
 * Negative values are invalid for maxAge.
 */

var ReadRequest_Schema = {
    name: "ReadRequest",
    fields: [
        {   name: "requestHeader" ,               fieldType: "RequestHeader"},

        {   name: "maxAge",                       fieldType: "Duration",
            documentation: "Maximum age of the value to be read in milliseconds"
        },
        {   name: "timestampsToReturn" ,          fieldType: "TimestampsToReturn",
            documentation:"An enumeration that specifies the Timestamps to be returned for each requested Variable Value Attribute.",
            defaultValue: TimestampsToReturn.Invalid
        },
        { name: "nodesToRead", isArray:true,    fieldType: "ReadValueId",
            documentation: "List of Nodes and their Attributes to read. For each entry in this list, a StatusCode is " +
                           "returned, and if it indicates success, the Attribute Value is also returned."
        }
    ]
};

exports.ReadRequest = factories.registerObject(ReadRequest_Schema);

var ReadResponse_Schema = {
    name: "ReadResponse",
    fields: [
        { name: "responseHeader" ,                fieldType: "ResponseHeader"},
        {
            name: "results",          isArray:true, fieldType: "DataValue",
            documentation: "List of Attribute values as DataValue. The size and order of this list matches the size and"+
                           " order of the nodesToRead request parameter. There is one entry in this list for each Node "+
                           " contained in the nodesToRead parameter."
        },
        { name: "diagnosticInfos", isArray:true,  fieldType: "DiagnosticInfo" }
    ]
};

exports.ReadResponse = factories.registerObject(ReadResponse_Schema);

<commit_msg>remove trace output<commit_after>//--------------------------------------------------------------------------------
// OPCUA Part 4 $5.10 : Attribute Service Set
// This Service Set provides Service sto access Attributes that are part of Nodes.
//--------------------------------------------------------------------------------
var factories = require("./../misc/factories");
var assert = require('better-assert');
var DataValue = require("./../datamodel/datavalue").DataValue;
var Variant   = require("./../datamodel/variant").Variant;
var _ = require("underscore");

require("./../datamodel/part_8_structures");

require("./../datamodel/numeric_range");

var TimestampsToReturn_Schema = {
    name: "TimestampsToReturn",
    enumValues: {
        Invalid:      -1,
        Source:        0,
        Server:        1,
        Both:          2,
        Neither :      3
    },
    decode: function(stream) {

        var v = stream.readInt32();
        if (y<0 || y>3) {
            return TimestampsToReturn.Invalid;
        }
        return TimestampsToReturn.get(value);
    }
};
var TimestampsToReturn = exports.TimestampsToReturn = factories.registerEnumeration(TimestampsToReturn_Schema);

var AttributeIds = {
    NodeId:1,
    NodeClass:2,
    BrowseName:3,
    DisplayName:4,
    Description:5,
    WriteMask:6,
    UserWriteMask:7,
    IsAbstract:8,
    Symmetric:9,
    InverseName:10,
    ContainsNoLoops:11,
    EventNotifier:12,
    Value:13,
    DataType:14,
    ValueRank:15,
    ArrayDimensions:16,
    AccessLevel:17,
    UserAccessLevel:18,
    MinimumSamplingInterval:19,
    Historizing:20,
    Executable:21,
    UserExecutable:22
};
exports.AttributeIds = AttributeIds;
exports.AttributeNameById = _.invert(AttributeIds);

function is_valid_attributeId(attributeId){
    assert(_.isFinite(attributeId));
    return attributeId>=1 && attributeId<=22;
}
exports.is_valid_attributeId = is_valid_attributeId;

var ReadValueId_Schema = {
    name: "ReadValueId",
    fields: [
        { name: "nodeId" ,       fieldType: "NodeId"},
        { name: "attributeId" ,  fieldType: "IntegerId" ,
            validate:function(value){
                return is_valid_attributeId(value);
            },
            defaultValue: AttributeIds.Value
        }, // see AttributeIds

        // IndexRange : This parameter is used to identify a single element of a structure or an array, or a single
        // range of indexes for arrays. If a range of elements  are specified, the values are returned as a composite.
        // The first element is identified by index 0 (zero).
        // This parameter is null if the specified Attribute is not an array or a structure. However, if the specified
        // Attribute is an array or a structure,and this parameter is null, then all elements are to be included in the
        // range.
        { name: "indexRange" ,   fieldType: "NumericRange"    , defaultValue: function() { return null; }},

        // dataEncoding
        //
        //    This parameter specifies the BrowseName of the DataTypeEncoding that the
        //    Server should use when returning the Value Attribute of a Variable. It is an error
        //    to specify this parameter for other Attributes.
        //    A Client can discover what DataTypeEncodings are available by following the
        //    HasEncoding Reference from the DataType Node for a Variable.
        //    OPC UA defines BrowseNames which Servers shall recognize even if the
        //    DataType Nodes are not visible in the Server address space. These
        //    BrowseNames are:
        //      - DefaultBinary  The default or native binary (or non-XML) encoding.
        //      - DefaultXML  The default XML encoding.
        //
        //    Each DataType shall support at least one of these encodings. DataTypes that do
        //    not have a true binary encoding (e.g. they only have a non-XML text encoding)
        //    should use the DefaultBinary name to identify the encoding that is considered to
        //    be the default non-XML encoding. DataTypes that support at least one XML-based
        //    encoding shall identify one of the encodings as the DefaultXML encoding.
        //    Other standards bodies may define other well-known data encodings that could
        //    be supported.
        //
        //    If this parameter is not specified then the Server shall choose either the
        //    DefaultBinary or DefaultXML encoding according to what Message encoding
        //    (see Part 6) is used for the Session. If the Server does not support the encoding
        //    that matches the Message encoding then the Server shall choose the default
        //    encoding that it does support.
        //
        //    If this parameter is specified for a MonitoredItem, the Server shall set the
        //    StructureChanged bit in the StatusCode (see 7.33) if the DataTypeEncoding
        //    changes. The DataTypeEncoding changes if the DataTypeVersion of the
        //    DataTypeDescription or the DataTypeDictionary associated with the
        //    DataTypeEncoding changes
        { name: "dataEncoding",  fieldType: "QualifiedName" }
    ]
};
exports.ReadValueId = factories.registerObject(ReadValueId_Schema);

/**
 * Maximum age of the value to be read in milliseconds. The age of the value is based on the difference between the
 * ServerTimestamp and the time when the Server starts processing the request. For example if the Client specifies a
 * maxAge of 500 milliseconds and it takes 100 milliseconds until the Server starts processing the request, the age of
 * the returned value could be 600 milliseconds prior to the time it was requested.
 * If the Server has one or more values of an Attribute that are within the maximum age, it can return any one of the
 * values or it can read a new value from the data source. The number of values of an Attribute that a Server has
 * depends on the number of MonitoredItems that are defined for the Attribute.
 * In any case, the Client can make no assumption about which copy of the data will be returned.
 * If the Server does not have a value that is within the maximum age, it shall attempt to read a new value from the
 * data source.
 * If the Server cannot meet the requested maxAge, it returns its “best effort” value rather than rejecting the request.
 * This may occur when the time it takes the Server to process and return the new data value after it has been accessed
 * is greater than the specified maximum age.
 * If maxAge is set to 0, the Server shall attempt to read a new value from the data source.
 * If maxAge is set to the max Int32 value or greater, the Server shall attempt to get a cached value.
 * Negative values are invalid for maxAge.
 */

var ReadRequest_Schema = {
    name: "ReadRequest",
    fields: [
        {   name: "requestHeader" ,               fieldType: "RequestHeader"},

        {   name: "maxAge",                       fieldType: "Duration",
            documentation: "Maximum age of the value to be read in milliseconds"
        },
        {   name: "timestampsToReturn" ,          fieldType: "TimestampsToReturn",
            documentation:"An enumeration that specifies the Timestamps to be returned for each requested Variable Value Attribute.",
            defaultValue: TimestampsToReturn.Invalid
        },
        { name: "nodesToRead", isArray:true,    fieldType: "ReadValueId",
            documentation: "List of Nodes and their Attributes to read. For each entry in this list, a StatusCode is " +
                           "returned, and if it indicates success, the Attribute Value is also returned."
        }
    ]
};

exports.ReadRequest = factories.registerObject(ReadRequest_Schema);

var ReadResponse_Schema = {
    name: "ReadResponse",
    fields: [
        { name: "responseHeader" ,                fieldType: "ResponseHeader"},
        {
            name: "results",          isArray:true, fieldType: "DataValue",
            documentation: "List of Attribute values as DataValue. The size and order of this list matches the size and"+
                           " order of the nodesToRead request parameter. There is one entry in this list for each Node "+
                           " contained in the nodesToRead parameter."
        },
        { name: "diagnosticInfos", isArray:true,  fieldType: "DiagnosticInfo" }
    ]
};

exports.ReadResponse = factories.registerObject(ReadResponse_Schema);

<|endoftext|>


<commit_before>'use strict';
var request = require('request');
var keys = Object.keys || require('object-keys');
var DAYS_THRESHOLD = 5;

// FIXME: Too much logic in a "toString". Remove it from here.
var toString = function(header, body) {
    body = body || '';

    if (!body) {
        return '[Nenhum Pull Request aberto]';
    }

    return header + ':\n\n' + body;
};

module.exports = {
    listPrs: function(repository, criteria, callback) {
        if (arguments.length <= 1) {
            throw new Error('At least one argument must be passed');
        }

        criteria = criteria || 'all';

        var header = criteria === 'all' ?
            'Todos os Pull Requests abertos' :
            'Pull Requests com mais de ' + DAYS_THRESHOLD + ' dias';

        var options = {
            url: 'https://api.github.com/repos/dataeasy/' + repository + '/pulls?state=open&sort=created&direction=desc',
            headers: { 'User-Agent': 'request' }
        };

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

            var prs;
            try {
                prs = JSON.parse(body);
            } catch (error) {
                console.log('Error parsing JSON', error);
                //TODO callback err
                throw error;
            }

            //TODO: Use moment.js
            var date = new Date();
            var todaysDate = date.getFullYear() + (date.getMonth() + 1) + date.getDate();
            var results = '';

            for (var i in prs) {
                var prDate = prs[i].created_at;
                //TODO: slice from ISO string
                prDate = parseInt(prDate.slice(0, 4)) + parseInt(prDate.slice(5, 7)) + parseInt(prDate.slice(8, 10));
                var prAge = todaysDate - prDate;

                var isOldPr = prAge > DAYS_THRESHOLD;

                if (criteria === 'all' || (criteria === 'old' && isOldPr)) {
                    results += prs[i].title + ' | ' + prAge + 'd\n';
                }
            }

            return callback(null, toString(header, results));
        });
    }
};
<commit_msg>Transformando resutls num array<commit_after>'use strict';
var request = require('request');
var keys = Object.keys || require('object-keys');
var DAYS_THRESHOLD = 5;

// FIXME: Too much logic in a "toString". Remove it from here.
var toString = function(header, body) {
    body = body.join('\n');

    if (!body) {
        return '[Nenhum Pull Request aberto]';
    }

    return header + ':\n\n' + body;
};

module.exports = {
    listPrs: function(repository, criteria, callback) {
        if (arguments.length <= 1) {
            throw new Error('At least one argument must be passed');
        }

        criteria = criteria || 'all';

        var header = criteria === 'all' ?
            'Todos os Pull Requests abertos' :
            'Pull Requests com mais de ' + DAYS_THRESHOLD + ' dias';

        var options = {
            url: 'https://api.github.com/repos/dataeasy/' + repository + '/pulls?state=open&sort=created&direction=desc',
            headers: { 'User-Agent': 'request' }
        };

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

            var prs;
            try {
                prs = JSON.parse(body);
            } catch (error) {
                console.log('Error parsing JSON', error);
                //TODO callback err
                throw error;
            }

            //TODO: Use moment.js
            var date = new Date();
            var todaysDate = date.getFullYear() + (date.getMonth() + 1) + date.getDate();
            var results = [];

            for (var i in prs) {
                var prDate = prs[i].created_at;
                //TODO: slice from ISO string
                prDate = parseInt(prDate.slice(0, 4)) + parseInt(prDate.slice(5, 7)) + parseInt(prDate.slice(8, 10));
                var prAge = todaysDate - prDate;

                var isOldPr = prAge > DAYS_THRESHOLD;
                var line;

                if (criteria === 'all' || (criteria === 'old' && isOldPr)) {
                    line = prs[i].title + ' | ' + prAge + 'd';
                    results.push(line);
                }
            }

            return callback(null, toString(header, results));
        });
    }
};
<|endoftext|>


<commit_before>// Set up the template store
var assert = require('assert');
var fs = require('fs');
var _ = require('underscore');
var mustache = require('mustache');
var jsonContentDemux = require('json-content-demux');
var templates = {};

// Helper function to ensure offset values exist as well as values with pixels in the name
function ensureOffsetAndPx(item) {
  // Guarantee offsets exist
  item.offset_x = -item.x;
  item.offset_y = -item.y;

  // Create a px namespace
  var px = {};
  item.px = px;

  // For each of the x, y, offset_x, offset_y, height, width, add a px after that
  ['x', 'y', 'offset_x', 'offset_y', 'height', 'width', 'total_height', 'total_width'].forEach(function (key) {
    px[key] = item[key] + 'px';
  });
}

// Helper function to escape images
function escapeImages(item) {
  // Grab the image
  var img = item.image;

  // Escape the quotes, parentheses, and whitespace
  // http://www.w3.org/TR/CSS21/syndata.html#uri
  var escapedImg = img.replace(/['"\(\)\s]/g, function encodeCssUri (chr) {
    return '%' + chr.charCodeAt(0).toString(16);
  });

  // Save the escapedImg for later
  item.escaped_image = escapedImg;
};

/**
 * @param {Object[]} input Object to convert into CSS
 * @param {String} input[*].name Name to use for the image
 * @param {Number} input[*].x Horizontal coordinate of top-left corner of image
 * @param {Number} input[*].y Vertical coordinate of top-left corner of image
 * @param {Number} input[*].width Horizontal length of image
 * @param {Number} input[*].height Vertical length of image
 * @param {Number} input[*].total_width Horizontal length of spritesheet
 * @param {Number} input[*].total_height Vertical length of spritesheet
 * @param {Number} input[*].image Path to image itself (used as a URL component)
 * @param {Object} [options] Options to convert JSON with
 * @param {String} [options.format="css"] Format to output json in
 * @param {Mixed} [options.formatOpts={}] Options to pass through to the formatter
 */
function templater(input, options) {
  // Fallback and localize options
  options = options || {};
  var format = options.format || 'css';
  var template = templates[format];

  // Assert that the template exists
  assert(template, 'The templater format "' + format + '" could not be found. Please make sure to either add ' +
    'it via addTemplate or the spelling is correct.');

  // Deep clone the input
  input = JSON.parse(JSON.stringify(input));

  // Add on extra data to each item
  input.items.forEach(function addExtraData (item) {
    ensureOffsetAndPx(item);
    escapeImages(item);
  });

  // Process the input via the template
  var retVal = template({
    items: input,
    options: options.formatOpts || {}
  });

  // Return the output
  return retVal;
}

// Helper method to add new templates
function addTemplate(name, fn) {
  templates[name] = fn;
}
function addMustacheTemplate(name, tmplStr) {
  // Break up the template and default options
  var tmplObj = jsonContentDemux(tmplStr);
  var defaults = tmplObj.json || {};
  var tmpl = tmplObj.content;

  // Generate a function which processes objects through the mustache template
  function templateFn(itemObj) {
    // Set up the defaults for the item object
    _.defaults(itemObj.options, defaults);

    // Render the items via the template
    var retStr = mustache.render(tmpl, itemObj);
    return retStr;
  }

  // Save the template
  addTemplate(name, templateFn);
}

// Expose template system
templater.addTemplate = addTemplate;
templater.addMustacheTemplate = addMustacheTemplate;
templater.templates = templates;

// TODO: Expose helper functions

// Add in the templates from templates
var templatesDir = __dirname + '/templates';

addTemplate('json', require(templatesDir + '/json.template.js'));
addTemplate('jsonArray', require(templatesDir + '/json_array.template.js'));
addTemplate('css', require(templatesDir + '/css.template.js'));

var stylusMustache = fs.readFileSync(templatesDir + '/stylus.template.mustache', 'utf8');
addMustacheTemplate('stylus', stylusMustache);

var lessMustache = fs.readFileSync(templatesDir + '/less.template.mustache', 'utf8');
addMustacheTemplate('less', lessMustache);

var sassMustache = fs.readFileSync(templatesDir + '/sass.template.mustache', 'utf8');
addMustacheTemplate('sass', sassMustache);

var scssMustache = fs.readFileSync(templatesDir + '/scss.template.mustache', 'utf8');
addMustacheTemplate('scss', scssMustache);

var scssMapsMustache = fs.readFileSync(templatesDir + '/scss_maps.template.mustache', 'utf8');
addMustacheTemplate('scss_maps', scssMapsMustache);

// Expose templater
module.exports = templater;
<commit_msg>Relocating all items to be defined on constructor<commit_after>// Load in our dependencies
var assert = require('assert');
var fs = require('fs');
var _ = require('underscore');
var mustache = require('mustache');
var jsonContentDemux = require('json-content-demux');

/**
 * @param {Object[]} input Object to convert into CSS
 * @param {String} input[*].name Name to use for the image
 * @param {Number} input[*].x Horizontal coordinate of top-left corner of image
 * @param {Number} input[*].y Vertical coordinate of top-left corner of image
 * @param {Number} input[*].width Horizontal length of image
 * @param {Number} input[*].height Vertical length of image
 * @param {Number} input[*].total_width Horizontal length of spritesheet
 * @param {Number} input[*].total_height Vertical length of spritesheet
 * @param {Number} input[*].image Path to image itself (used as a URL component)
 * @param {Object} [options] Options to convert JSON with
 * @param {String} [options.format="css"] Format to output json in
 * @param {Mixed} [options.formatOpts={}] Options to pass through to the formatter
 */
function templater(input, options) {
  // Fallback and localize options
  options = options || {};
  var format = options.format || 'css';
  var template = templater.templates[format];

  // Assert that the template exists
  assert(template, 'The templater format "' + format + '" could not be found. Please make sure to either add ' +
    'it via addTemplate or the spelling is correct.');

  // Deep clone the input
  input = JSON.parse(JSON.stringify(input));

  // Add on extra data to each item
  input.items.forEach(function addExtraData (item) {
    templater.ensureOffsetAndPx(item);
    templater.escapeImages(item);
  });

  // Process the input via the template
  var retVal = template({
    items: input,
    options: options.formatOpts || {}
  });

  // Return the output
  return retVal;
}

// Helper function to ensure offset values exist as well as values with pixels in the name
templater.ensureOffsetAndPx = function (item) {
  // Guarantee offsets exist
  item.offset_x = -item.x;
  item.offset_y = -item.y;

  // Create a px namespace
  var px = {};
  item.px = px;

  // For each of the x, y, offset_x, offset_y, height, width, add a px after that
  ['x', 'y', 'offset_x', 'offset_y', 'height', 'width', 'total_height', 'total_width'].forEach(function (key) {
    px[key] = item[key] + 'px';
  });
};

// Helper function to escape images
templater.escapeImages = function (item) {
  // Grab the image
  var img = item.image;

  // Escape the quotes, parentheses, and whitespace
  // http://www.w3.org/TR/CSS21/syndata.html#uri
  var escapedImg = img.replace(/['"\(\)\s]/g, function encodeCssUri (chr) {
    return '%' + chr.charCodeAt(0).toString(16);
  });

  // Save the escapedImg for later
  item.escaped_image = escapedImg;
};

// Add template store and helper methods to add new templates
templater.templates = {};
templater.addTemplate = function (name, fn) {
  templater.templates[name] = fn;
};
templater.addMustacheTemplate = function (name, tmplStr) {
  // Break up the template and default options
  var tmplObj = jsonContentDemux(tmplStr);
  var defaults = tmplObj.json || {};
  var tmpl = tmplObj.content;

  // Generate a function which processes objects through the mustache template
  function templateFn(itemObj) {
    // Set up the defaults for the item object
    _.defaults(itemObj.options, defaults);

    // Render the items via the template
    var retStr = mustache.render(tmpl, itemObj);
    return retStr;
  }

  // Save the template
  templater.addTemplate(name, templateFn);
};

// TODO: Expose helper functions

// Add in the templates from templates
var templatesDir = __dirname + '/templates';

templater.addTemplate('json', require(templatesDir + '/json.template.js'));
templater.addTemplate('jsonArray', require(templatesDir + '/json_array.template.js'));
templater.addTemplate('css', require(templatesDir + '/css.template.js'));

var stylusMustache = fs.readFileSync(templatesDir + '/stylus.template.mustache', 'utf8');
templater.addMustacheTemplate('stylus', stylusMustache);

var lessMustache = fs.readFileSync(templatesDir + '/less.template.mustache', 'utf8');
templater.addMustacheTemplate('less', lessMustache);

var sassMustache = fs.readFileSync(templatesDir + '/sass.template.mustache', 'utf8');
templater.addMustacheTemplate('sass', sassMustache);

var scssMustache = fs.readFileSync(templatesDir + '/scss.template.mustache', 'utf8');
templater.addMustacheTemplate('scss', scssMustache);

var scssMapsMustache = fs.readFileSync(templatesDir + '/scss_maps.template.mustache', 'utf8');
templater.addMustacheTemplate('scss_maps', scssMapsMustache);

// Expose templater
module.exports = templater;
<|endoftext|>


<commit_before>var crypto = require('crypto');

// **** Simple functions for generating stored filenames.

function filenameFromBuffer (buffer, extension) {
	// Helper to throw out weird url-unsafe characters and take the first 16
	// characters - which gives us 12 bytes of entropy.
	var filename = buffer.toString('base64')
		.replace(/\+/g, '-')
		.replace(/\//g, '_')
		.replace(/=/g, '')
		.slice(0, 16);

	if (extension) filename = filename + '.' + extension;

	return filename;
}

// Calculate the filename from the sha1 hash of the file contents
exports.contentHashFilename = function (file, i, callback) {
	var hash = crypto.createHash('sha1');
	var calledCallback = false;
	fs.createReadStream(file.path)
		.on('error', function (err) {
			// I'm worried that on('error') might fire after on('readable')
			// happens.
			if (calledCallback) return;
			calledCallback = true;
			callback(err);
		})
		.pipe(hash);

	hash.on('readable', function () {
		var data = hash.read();
		if (data == null) return;

		if (calledCallback) return;
		calledCallback = true;
		// Data is a node Buffer.
		callback(null, filenameFromBuffer(data, file.extension));
	});
};

exports.originalFilename = function (file) {
	return file.originalname;
};

exports.randomFilename = function (file, i, callback) {
	crypto.randomBytes(16, (err, data) => {
		if (err) return callback(err);
		return callback(null, filenameFromBuffer(data, file.extension));
	});
};
<commit_msg>This file needs the fs module<commit_after>var crypto = require('crypto');
var fs = require('fs');

// **** Simple functions for generating stored filenames.

function filenameFromBuffer (buffer, extension) {
	// Helper to throw out weird url-unsafe characters and take the first 16
	// characters - which gives us 12 bytes of entropy.
	var filename = buffer.toString('base64')
		.replace(/\+/g, '-')
		.replace(/\//g, '_')
		.replace(/=/g, '')
		.slice(0, 16);

	if (extension) filename = filename + '.' + extension;

	return filename;
}

// Calculate the filename from the sha1 hash of the file contents
exports.contentHashFilename = function (file, i, callback) {
	var hash = crypto.createHash('sha1');
	var calledCallback = false;
	fs.createReadStream(file.path)
		.on('error', function (err) {
			// I'm worried that on('error') might fire after on('readable')
			// happens.
			if (calledCallback) return;
			calledCallback = true;
			callback(err);
		})
		.pipe(hash);

	hash.on('readable', function () {
		var data = hash.read();
		if (data == null) return;

		if (calledCallback) return;
		calledCallback = true;
		// Data is a node Buffer.
		callback(null, filenameFromBuffer(data, file.extension));
	});
};

exports.originalFilename = function (file) {
	return file.originalname;
};

exports.randomFilename = function (file, i, callback) {
	crypto.randomBytes(16, (err, data) => {
		if (err) return callback(err);
		return callback(null, filenameFromBuffer(data, file.extension));
	});
};
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//     You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//     See the License for the specific language governing permissions and
// limitations under the License.

(function(shared, scope, testing) {

  function groupChildDuration(node) {
    return node._timing.delay + node.activeDuration + node._timing.endDelay;
  }

  function constructor(children, timingInput) {
    if (this._parent === undefined)
      this._parent = null;
    this.children = children || [];
    for (c in this.children) {
      this.children[c]._parent = this;
    }
    this._isAncestor = function(effect) {
      var a = this._parent;
      while (a !== null) {
        if (a == effect)
          return true;
        a = a._parent;
      }
      return false;
    };
    this.append = function()  {
      for (var i in arguments) {
        this.children.push(arguments[i]);
        arguments[i]._parent = this;
      }
      if(this.animation) {
        this.animation._rebuildUnderlyingAnimation();
      }
    };
    this.prepend = function()  {
      for (var i in arguments) {
        this.children.unshift(arguments[i]);
        arguments[i]._parent = this;
      }
      if(this.animation) {
        this.animation._rebuildUnderlyingAnimation();
      }
    };
    this._timingInput = shared.cloneTimingInput(timingInput);
    this._timing = shared.normalizeTimingInput(timingInput, true);
    this.timing = shared.makeTiming(timingInput, true);

    if (this._timing.duration === 'auto') {
      this._timing.duration = this.activeDuration;
    }
  }

  window.SequenceEffect = function() {
    constructor.apply(this, arguments);
  };

  window.GroupEffect = function() {
    constructor.apply(this, arguments);
  };

  constructor.prototype = {
    get firstChild() {
      return this.children.length ? this.children[0] : null;
    },
    get lastChild() {
      return this.children.length ? this.children[this.children.length - 1] : null;
    },
    clone: function() {
      var clonedTiming = shared.cloneTimingInput(this._timingInput);
      var clonedChildren = [];
      for (var i = 0; i < this.children.length; i++) {
        clonedChildren.push(this.children[i].clone());
      }
      return (this instanceof GroupEffect) ?
          new GroupEffect(clonedChildren, clonedTiming) :
          new SequenceEffect(clonedChildren, clonedTiming);
    }
  };

  window.SequenceEffect.prototype = Object.create(constructor.prototype);
  Object.defineProperty(
      window.SequenceEffect.prototype,
      'activeDuration',
      {
        get: function() {
          var total = 0;
          this.children.forEach(function(child) {
            total += groupChildDuration(child);
          });
          return Math.max(total, 0);
        }
      });

  window.GroupEffect.prototype = Object.create(constructor.prototype);
  Object.defineProperty(
      window.GroupEffect.prototype,
      'activeDuration',
      {
        get: function() {
          var max = 0;
          this.children.forEach(function(child) {
            max = Math.max(max, groupChildDuration(child));
          });
          return max;
        }
      });

  scope.newUnderlyingAnimationForGroup = function(group) {
    var underlyingAnimation;
    var timing = null;
    var ticker = function(tf) {
      var animation = underlyingAnimation._wrapper;
      if (animation.playState == 'pending')
        return;

      if (!animation.effect)
        return;

      if (tf == null) {
        animation._removeChildren();
        return;
      }

      // If the group has a negative playback rate and is not fill backwards/both, then it should go
      // out of effect when it reaches the start of its active interval (tf == 0). If it is fill
      // backwards/both then it should stay in effect. calculateTimeFraction will return 0 in the
      // backwards-filling case, and null otherwise.
      if (tf == 0 && animation.playbackRate < 0) {
        if (!timing) {
          timing = shared.normalizeTimingInput(animation.effect.timing);
        }
        tf = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), -1, timing);
        if (isNaN(tf) || tf == null) {
          animation._forEachChild(function(child) {
            child.currentTime = -1;
          });
          animation._removeChildren();
          return;
        }
      }
    };

    underlyingAnimation = scope.timeline.play(new scope.KeyframeEffect(null, ticker, group._timing));
    return underlyingAnimation;
  };

  scope.bindAnimationForGroup = function(animation) {
    animation._animation._wrapper = animation;
    animation._isGroup = true;
    scope.awaitStartTime(animation);
    animation._constructChildren();
    animation._setExternalAnimation(animation);
  };

  scope.groupChildDuration = groupChildDuration;

  // Alias GroupEffect & SequenceEffect to AnimationGroup & AnimationSequence respectively, to
  // support old constructors (Animation*) for a deprecation period. Should be removed after 23 June
  // 2015.
  window.AnimationSequence = function() {
    shared.deprecated('window.AnimationSequence', '2015-03-23', 'Use window.SequenceEffect instead.');
    window.SequenceEffect.apply(this, arguments);
  };
  window.AnimationSequence.prototype = Object.create(window.SequenceEffect.prototype);
  window.AnimationSequence.prototype.constructor = window.AnimationSequence;

  window.AnimationGroup = function() {
    shared.deprecated('window.AnimationGroup', '2015-03-23', 'Use window.GroupEffect instead.');
    window.GroupEffect.apply(this, arguments);
  };
  window.AnimationGroup.prototype = Object.create(window.GroupEffect.prototype);
  window.AnimationGroup.prototype.constructor = window.AnimationGroup;

})(webAnimationsShared, webAnimationsNext, webAnimationsTesting);
<commit_msg>Add exceptions and consolidate<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
//     You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//     See the License for the specific language governing permissions and
// limitations under the License.

(function(shared, scope, testing) {

  function groupChildDuration(node) {
    return node._timing.delay + node.activeDuration + node._timing.endDelay;
  }

  function constructor(children, timingInput) {
    if (this._parent === undefined)
      this._parent = null;
    this.children = children || [];
    for (c in this.children) {
      this.children[c]._parent = this;
    }
    this._isAncestor = function(effect) {
      var a = this._parent;
      while (a !== null) {
        if (a == effect)
          return true;
        a = a._parent;
      }
      return false;
    };
    this._putChild = function(args, isAppend) {
      for (var i in args) {
        if (this._isAncestor(args[i])) {
          throw {
            type: DOMException.HIERARCHY_REQUEST_ERR,
            name: 'HierarchyRequestError',
            message: 'Cannot append an ancestor'
          };
        }
        isAppend ? this.children.push(args[i]) : this.children.unshift(args[i]);
        args[i]._parent = this;
      }
      if (this.animation) {
        this.animation._rebuildUnderlyingAnimation();
      }
    };
    this.append = function()  {
      this._putChild(arguments, true);
    };
    this.prepend = function()  {
      this._putChild(arguments, false);
    };
    this._timingInput = shared.cloneTimingInput(timingInput);
    this._timing = shared.normalizeTimingInput(timingInput, true);
    this.timing = shared.makeTiming(timingInput, true);

    if (this._timing.duration === 'auto') {
      this._timing.duration = this.activeDuration;
    }
  }

  window.SequenceEffect = function() {
    constructor.apply(this, arguments);
  };

  window.GroupEffect = function() {
    constructor.apply(this, arguments);
  };

  constructor.prototype = {
    get firstChild() {
      return this.children.length ? this.children[0] : null;
    },
    get lastChild() {
      return this.children.length ? this.children[this.children.length - 1] : null;
    },
    clone: function() {
      var clonedTiming = shared.cloneTimingInput(this._timingInput);
      var clonedChildren = [];
      for (var i = 0; i < this.children.length; i++) {
        clonedChildren.push(this.children[i].clone());
      }
      return (this instanceof GroupEffect) ?
          new GroupEffect(clonedChildren, clonedTiming) :
          new SequenceEffect(clonedChildren, clonedTiming);
    }
  };

  window.SequenceEffect.prototype = Object.create(constructor.prototype);
  Object.defineProperty(
      window.SequenceEffect.prototype,
      'activeDuration',
      {
        get: function() {
          var total = 0;
          this.children.forEach(function(child) {
            total += groupChildDuration(child);
          });
          return Math.max(total, 0);
        }
      });

  window.GroupEffect.prototype = Object.create(constructor.prototype);
  Object.defineProperty(
      window.GroupEffect.prototype,
      'activeDuration',
      {
        get: function() {
          var max = 0;
          this.children.forEach(function(child) {
            max = Math.max(max, groupChildDuration(child));
          });
          return max;
        }
      });

  scope.newUnderlyingAnimationForGroup = function(group) {
    var underlyingAnimation;
    var timing = null;
    var ticker = function(tf) {
      var animation = underlyingAnimation._wrapper;
      if (animation.playState == 'pending')
        return;

      if (!animation.effect)
        return;

      if (tf == null) {
        animation._removeChildren();
        return;
      }

      // If the group has a negative playback rate and is not fill backwards/both, then it should go
      // out of effect when it reaches the start of its active interval (tf == 0). If it is fill
      // backwards/both then it should stay in effect. calculateTimeFraction will return 0 in the
      // backwards-filling case, and null otherwise.
      if (tf == 0 && animation.playbackRate < 0) {
        if (!timing) {
          timing = shared.normalizeTimingInput(animation.effect.timing);
        }
        tf = shared.calculateTimeFraction(shared.calculateActiveDuration(timing), -1, timing);
        if (isNaN(tf) || tf == null) {
          animation._forEachChild(function(child) {
            child.currentTime = -1;
          });
          animation._removeChildren();
          return;
        }
      }
    };

    underlyingAnimation = scope.timeline.play(new scope.KeyframeEffect(null, ticker, group._timing));
    return underlyingAnimation;
  };

  scope.bindAnimationForGroup = function(animation) {
    animation._animation._wrapper = animation;
    animation._isGroup = true;
    scope.awaitStartTime(animation);
    animation._constructChildren();
    animation._setExternalAnimation(animation);
  };

  scope.groupChildDuration = groupChildDuration;

  // Alias GroupEffect & SequenceEffect to AnimationGroup & AnimationSequence respectively, to
  // support old constructors (Animation*) for a deprecation period. Should be removed after 23 June
  // 2015.
  window.AnimationSequence = function() {
    shared.deprecated('window.AnimationSequence', '2015-03-23', 'Use window.SequenceEffect instead.');
    window.SequenceEffect.apply(this, arguments);
  };
  window.AnimationSequence.prototype = Object.create(window.SequenceEffect.prototype);
  window.AnimationSequence.prototype.constructor = window.AnimationSequence;

  window.AnimationGroup = function() {
    shared.deprecated('window.AnimationGroup', '2015-03-23', 'Use window.GroupEffect instead.');
    window.GroupEffect.apply(this, arguments);
  };
  window.AnimationGroup.prototype = Object.create(window.GroupEffect.prototype);
  window.AnimationGroup.prototype.constructor = window.AnimationGroup;

})(webAnimationsShared, webAnimationsNext, webAnimationsTesting);
<|endoftext|>


<commit_before>var torque = require('../');
var cartocss = require('./cartocss_render');
var Profiler = require('../profiler');
var carto = global.carto || require('carto');
var filters = require('./torque_filters');

  var TAU = Math.PI * 2;
  var DEFAULT_CARTOCSS = [
    '#layer {',
    '  marker-fill: #662506;',
    '  marker-width: 4;',
    '  [value > 1] { marker-fill: #FEE391; }',
    '  [value > 2] { marker-fill: #FEC44F; }',
    '  [value > 3] { marker-fill: #FE9929; }',
    '  [value > 4] { marker-fill: #EC7014; }',
    '  [value > 5] { marker-fill: #CC4C02; }',
    '  [value > 6] { marker-fill: #993404; }',
    '  [value > 7] { marker-fill: #662506; }',
    '}'
  ].join('\n');

  var COMP_OP_TO_CANVAS = {
    "src": 'source-over',
    "src-over": 'source-over',
    "dst-over": 'destination-over',
    "src-in": 'source-in',
    "dst-in": 'destination-in',
    "src-out": 'source-out',
    "dst-out": 'destination-out',
    "src-atop": 'source-atop',
    "dst-atop": 'destination-atop',
    "xor": 'xor',
    "darken": 'darken',
    "lighten": 'lighten'
  }

  function compop2canvas(compop) {
    return COMP_OP_TO_CANVAS[compop] || compop;
  }

  //
  // this renderer just render points depending of the value
  //
  function PointRenderer(canvas, options) {
    if (!canvas) {
      throw new Error("canvas can't be undefined");
    }
    this.options = options;
    this._canvas = canvas;
    this._ctx = canvas.getContext('2d');
    this._sprites = []; // sprites per layer
    this._shader = null;
    this._icons = {};
    this._filters = filters(this._canvas);
    this.setCartoCSS(this.options.cartocss || DEFAULT_CARTOCSS);
    this.TILE_SIZE = 256;
    this._style = null;

    this._forcePoints = false;
  }

  torque.extend(PointRenderer.prototype, torque.Event, {

    clearCanvas: function() {
      var canvas = this._canvas;
      var color = this._Map['-torque-clear-color']
      // shortcut for the default value
      if (color  === "rgba(255, 255, 255, 0)" || !color) {
        this._canvas.width = this._canvas.width;
      } else {
        var ctx = this._ctx;
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        var compop = this._Map['comp-op']
        ctx.globalCompositeOperation = compop2canvas(compop);
        ctx.fillStyle = color;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
    },

    setCanvas: function(canvas) {
      this._canvas = canvas;
      this._ctx = canvas.getContext('2d');
    },

    //
    // sets the cartocss style to render stuff
    //
    setCartoCSS: function(cartocss) {
      // clean sprites
      this.setShader(new carto.RendererJS().render(cartocss));
    },

    setShader: function(shader) {
      // clean sprites
      this._sprites = [];
      this._shader = shader;
      this._Map = this._shader.getDefault().getStyle({}, { zoom: 0 });
      var img_names = this._shader.getImageURLs();
      this._preloadIcons(img_names);
    },

    clearSpriteCache: function() {
      this._sprites = [];
    },

    //
    // generate sprite based on cartocss style
    //
    generateSprite: function(shader, value, shaderVars) {
      var self = this;
      var prof = Profiler.metric('torque.renderer.point.generateSprite').start();
      var st = shader.getStyle({
        value: value
      }, shaderVars);
      if(this._style === null){
        this._style = st;
      }

      var pointSize = st['marker-width'];
      if (!pointSize) {
        return null;
      }

      if (st['marker-opacity'] === 0 && !st['marker-line-opacity']) {
        return null;
      }

      var canvas = this._createCanvas();
      // take into account the exterior ring to calculate the size
      var canvasSize = (st['marker-line-width'] || 0) + pointSize*2;
      var ctx = canvas.getContext('2d');
      var w = ctx.width = canvas.width = ctx.height = canvas.height = Math.ceil(canvasSize);
      ctx.translate(w/2, w/2);

      function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          };
      var img_name = qualifyURL(st["marker-file"] || st["point-file"]);
      if (img_name && this._icons.itemsToLoad === 0) {
          var img = this._icons[img_name];
          img.w = st['marker-width'] || img.width;
          img.h = st['marker-width'] || st['marker-height'];
          cartocss.renderSprite(ctx, img, st);
      }
      else {
        var mt = st['marker-type'];
        if (mt && mt === 'rectangle') {
          cartocss.renderRectangle(ctx, st);
        } else {
          cartocss.renderPoint(ctx, st);
        }
      }
      prof.end(true);
      if (torque.flags.sprites_to_images) {
        var i = this._createImage();
        i.src = canvas.toDataURL();
        return i;
      }

      return canvas;
    },

    //
    // renders all the layers (and frames for each layer) from cartocss
    //
    renderTile: function(tile, key, pos) {
      var prof = Profiler.metric('torque.renderer.point.renderLayers').start();
      var layers = this._shader.getLayers();
      for(var i = 0, n = layers.length; i < n; ++i ) {
        var layer = layers[i];
        if (layer.name() !== "Map") {
          var sprites = this._sprites[i] || (this._sprites[i] = {});
          // frames for each layer
          for(var fr = 0; fr < layer.frames().length; ++fr) {
            var frame = layer.frames()[fr];
            var fr_sprites = sprites[frame] || (sprites[frame] = []);
            this._renderTile(tile, key - frame, frame, fr_sprites, layer);
          }
        }
      }

      prof.end(true);
    },

    _createCanvas: function() {
      return this.options.canvasClass
        ? new this.options.canvasClass()
        : document.createElement('canvas');
    },

    _createImage: function() {
      return this.options.imageClass
        ? new this.options.imageClass()
        : new Image();
    },

    //
    // renders a tile in the canvas for key defined in
    // the torque tile
    //
    _renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars) {
      if (!this._canvas) return;

      var prof = Profiler.metric('torque.renderer.point.renderTile').start();
      var ctx = this._ctx;
      var blendMode = compop2canvas(shader.eval('comp-op')) || this.options.blendmode;
      if (blendMode) {
        ctx.globalCompositeOperation = blendMode;
      }
      if (this.options.cumulative && key > tile.maxDate) {
        //TODO: precache because this tile is not going to change
        key = tile.maxDate;
      }
      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1)
      var activePixels = tile.timeCount[key];
      if (activePixels) {
        var pixelIndex = tile.timeIndex[key];
        for(var p = 0; p < activePixels; ++p) {
          var posIdx = tile.renderDataPos[pixelIndex + p];
          var c = tile.renderData[pixelIndex + p];
          if (c) {
           var sp = sprites[c];
           if (sp === undefined) {
             sp = sprites[c] = this.generateSprite(shader, c, torque.extend({ zoom: tile.z, 'frame-offset': frame_offset }, shaderVars));
           }
           if (sp) {
             var x = tile.x[posIdx]- (sp.width >> 1);
             var y = tileMax - tile.y[posIdx]; // flip mercator
             ctx.drawImage(sp, x, y - (sp.height >> 1));
           }
          }
        }
      }

      prof.end(true);
    },

    setBlendMode: function(b) {
      this.options.blendmode = b;
    },

    /**
     * get active points for a step in active zoom
     * returns a list of bounding boxes [[sw, ne] , [], []] where ne is a {lat: .., lon: ...} obj
     * empty list if there is no active pixels
     */
    getActivePointsBBox: function(tile, step) {
      var positions = [];
      var mercator = new torque.Mercator();

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx]; // flip mercator
         positions.push(mercator.tilePixelBBox(
           tile.coord.x,
           tile.coord.y,
           tile.coord.z,
           x, y
         ));
        }
      }
      return positions;
    },

    // return the value for x, y (tile coordinates)
    // null for no value
    getValueFor: function(tile, step, px, py) {
      var mercator = new torque.Mercator();
      var res = this.options.resolution;
      var res2 = res >> 1;

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx];
         var dx = px + res2 - x;
         var dy = py + res2 - y;
         if (dx >= 0 && dx < res && dy >= 0 && dy < res) {
           return {
             value: c,
             bbox: mercator.tilePixelBBox(
               tile.coord.x,
               tile.coord.y,
               tile.coord.z,
               x - res2, y - res2, res
             )
           }
         }
        }
      }
      return null;
    },
    _preloadIcons: function(img_names){
      var self = this;
      this._icons = {};
      if (img_names.length > 0 && !this._forcePoints){
        for (var i = 0; i<img_names.length; i++){
          var new_img = this._createImage();
          function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          }
          this._icons[qualifyURL(img_names[i])] = null;
          if (typeof self._icons.itemsToLoad === 'undefined'){
            this._icons.itemsToLoad = img_names.length;
          }
          new_img.crossOrigin = "Anonymous";
          new_img.onload = function(e){
            self._icons[this.src] = this;
            if (Object.keys(self._icons).length === img_names.length + 1){
              self._icons.itemsToLoad--;
              if (self._icons.itemsToLoad === 0){
                self.clearSpriteCache();
                self.fire("allIconsLoaded");
              }
            }
          };
          new_img.onerror = function(){
            self._forcePoints = true;
            self.clearSpriteCache();
            console.error("Couldn't get marker-file " + this.src);
          };
          new_img.src = img_names[i];
        }
      }

  },
  applyFilters: function(){
    if(this._style){
      if(this._style['image-filters']){
        function componentToHex(c) {
          var hex = c.toString(16);
          return hex.length == 1 ? "0" + hex : hex;
        }

        function rgbToHex(r, g, b) {
          return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
        }
        var colorize = this._style['image-filters'].args;
        var gradient = {};
        var increment = 1/colorize.length;
        for (var i = 0; i < colorize.length; i++){
          var key = increment * i + increment;
          var rgb = colorize[i].rgb;
          var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]);
          gradient[key] = formattedColor;
        }
        this._filters.gradient(gradient);
        this._filters.draw();
      }
    }
  }
});

  // exports public api
module.exports = PointRenderer;
<commit_msg>- pos from renderTiles<commit_after>var torque = require('../');
var cartocss = require('./cartocss_render');
var Profiler = require('../profiler');
var carto = global.carto || require('carto');
var filters = require('./torque_filters');

  var TAU = Math.PI * 2;
  var DEFAULT_CARTOCSS = [
    '#layer {',
    '  marker-fill: #662506;',
    '  marker-width: 4;',
    '  [value > 1] { marker-fill: #FEE391; }',
    '  [value > 2] { marker-fill: #FEC44F; }',
    '  [value > 3] { marker-fill: #FE9929; }',
    '  [value > 4] { marker-fill: #EC7014; }',
    '  [value > 5] { marker-fill: #CC4C02; }',
    '  [value > 6] { marker-fill: #993404; }',
    '  [value > 7] { marker-fill: #662506; }',
    '}'
  ].join('\n');

  var COMP_OP_TO_CANVAS = {
    "src": 'source-over',
    "src-over": 'source-over',
    "dst-over": 'destination-over',
    "src-in": 'source-in',
    "dst-in": 'destination-in',
    "src-out": 'source-out',
    "dst-out": 'destination-out',
    "src-atop": 'source-atop',
    "dst-atop": 'destination-atop',
    "xor": 'xor',
    "darken": 'darken',
    "lighten": 'lighten'
  }

  function compop2canvas(compop) {
    return COMP_OP_TO_CANVAS[compop] || compop;
  }

  //
  // this renderer just render points depending of the value
  //
  function PointRenderer(canvas, options) {
    if (!canvas) {
      throw new Error("canvas can't be undefined");
    }
    this.options = options;
    this._canvas = canvas;
    this._ctx = canvas.getContext('2d');
    this._sprites = []; // sprites per layer
    this._shader = null;
    this._icons = {};
    this._filters = filters(this._canvas);
    this.setCartoCSS(this.options.cartocss || DEFAULT_CARTOCSS);
    this.TILE_SIZE = 256;
    this._style = null;

    this._forcePoints = false;
  }

  torque.extend(PointRenderer.prototype, torque.Event, {

    clearCanvas: function() {
      var canvas = this._canvas;
      var color = this._Map['-torque-clear-color']
      // shortcut for the default value
      if (color  === "rgba(255, 255, 255, 0)" || !color) {
        this._canvas.width = this._canvas.width;
      } else {
        var ctx = this._ctx;
        ctx.setTransform(1, 0, 0, 1, 0, 0);
        var compop = this._Map['comp-op']
        ctx.globalCompositeOperation = compop2canvas(compop);
        ctx.fillStyle = color;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
    },

    setCanvas: function(canvas) {
      this._canvas = canvas;
      this._ctx = canvas.getContext('2d');
    },

    //
    // sets the cartocss style to render stuff
    //
    setCartoCSS: function(cartocss) {
      // clean sprites
      this.setShader(new carto.RendererJS().render(cartocss));
    },

    setShader: function(shader) {
      // clean sprites
      this._sprites = [];
      this._shader = shader;
      this._Map = this._shader.getDefault().getStyle({}, { zoom: 0 });
      var img_names = this._shader.getImageURLs();
      this._preloadIcons(img_names);
    },

    clearSpriteCache: function() {
      this._sprites = [];
    },

    //
    // generate sprite based on cartocss style
    //
    generateSprite: function(shader, value, shaderVars) {
      var self = this;
      var prof = Profiler.metric('torque.renderer.point.generateSprite').start();
      var st = shader.getStyle({
        value: value
      }, shaderVars);
      if(this._style === null){
        this._style = st;
      }

      var pointSize = st['marker-width'];
      if (!pointSize) {
        return null;
      }

      if (st['marker-opacity'] === 0 && !st['marker-line-opacity']) {
        return null;
      }

      var canvas = this._createCanvas();
      // take into account the exterior ring to calculate the size
      var canvasSize = (st['marker-line-width'] || 0) + pointSize*2;
      var ctx = canvas.getContext('2d');
      var w = ctx.width = canvas.width = ctx.height = canvas.height = Math.ceil(canvasSize);
      ctx.translate(w/2, w/2);

      function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          };
      var img_name = qualifyURL(st["marker-file"] || st["point-file"]);
      if (img_name && this._icons.itemsToLoad === 0) {
          var img = this._icons[img_name];
          img.w = st['marker-width'] || img.width;
          img.h = st['marker-width'] || st['marker-height'];
          cartocss.renderSprite(ctx, img, st);
      }
      else {
        var mt = st['marker-type'];
        if (mt && mt === 'rectangle') {
          cartocss.renderRectangle(ctx, st);
        } else {
          cartocss.renderPoint(ctx, st);
        }
      }
      prof.end(true);
      if (torque.flags.sprites_to_images) {
        var i = this._createImage();
        i.src = canvas.toDataURL();
        return i;
      }

      return canvas;
    },

    //
    // renders all the layers (and frames for each layer) from cartocss
    //
    renderTile: function(tile, key) {
      var prof = Profiler.metric('torque.renderer.point.renderLayers').start();
      var layers = this._shader.getLayers();
      for(var i = 0, n = layers.length; i < n; ++i ) {
        var layer = layers[i];
        if (layer.name() !== "Map") {
          var sprites = this._sprites[i] || (this._sprites[i] = {});
          // frames for each layer
          for(var fr = 0; fr < layer.frames().length; ++fr) {
            var frame = layer.frames()[fr];
            var fr_sprites = sprites[frame] || (sprites[frame] = []);
            this._renderTile(tile, key - frame, frame, fr_sprites, layer);
          }
        }
      }

      prof.end(true);
    },

    _createCanvas: function() {
      return this.options.canvasClass
        ? new this.options.canvasClass()
        : document.createElement('canvas');
    },

    _createImage: function() {
      return this.options.imageClass
        ? new this.options.imageClass()
        : new Image();
    },

    //
    // renders a tile in the canvas for key defined in
    // the torque tile
    //
    _renderTile: function(tile, key, frame_offset, sprites, shader, shaderVars) {
      if (!this._canvas) return;

      var prof = Profiler.metric('torque.renderer.point.renderTile').start();
      var ctx = this._ctx;
      var blendMode = compop2canvas(shader.eval('comp-op')) || this.options.blendmode;
      if (blendMode) {
        ctx.globalCompositeOperation = blendMode;
      }
      if (this.options.cumulative && key > tile.maxDate) {
        //TODO: precache because this tile is not going to change
        key = tile.maxDate;
      }
      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1)
      var activePixels = tile.timeCount[key];
      if (activePixels) {
        var pixelIndex = tile.timeIndex[key];
        for(var p = 0; p < activePixels; ++p) {
          var posIdx = tile.renderDataPos[pixelIndex + p];
          var c = tile.renderData[pixelIndex + p];
          if (c) {
           var sp = sprites[c];
           if (sp === undefined) {
             sp = sprites[c] = this.generateSprite(shader, c, torque.extend({ zoom: tile.z, 'frame-offset': frame_offset }, shaderVars));
           }
           if (sp) {
             var x = tile.x[posIdx]- (sp.width >> 1);
             var y = tileMax - tile.y[posIdx]; // flip mercator
             ctx.drawImage(sp, x, y - (sp.height >> 1));
           }
          }
        }
      }

      prof.end(true);
    },

    setBlendMode: function(b) {
      this.options.blendmode = b;
    },

    /**
     * get active points for a step in active zoom
     * returns a list of bounding boxes [[sw, ne] , [], []] where ne is a {lat: .., lon: ...} obj
     * empty list if there is no active pixels
     */
    getActivePointsBBox: function(tile, step) {
      var positions = [];
      var mercator = new torque.Mercator();

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx]; // flip mercator
         positions.push(mercator.tilePixelBBox(
           tile.coord.x,
           tile.coord.y,
           tile.coord.z,
           x, y
         ));
        }
      }
      return positions;
    },

    // return the value for x, y (tile coordinates)
    // null for no value
    getValueFor: function(tile, step, px, py) {
      var mercator = new torque.Mercator();
      var res = this.options.resolution;
      var res2 = res >> 1;

      var tileMax = this.options.resolution * (this.TILE_SIZE/this.options.resolution - 1);
      //this.renderer.renderTile(tile, this.key, pos.x, pos.y);
      var activePixels = tile.timeCount[step];
      var pixelIndex = tile.timeIndex[step];
      for(var p = 0; p < activePixels; ++p) {
        var posIdx = tile.renderDataPos[pixelIndex + p];
        var c = tile.renderData[pixelIndex + p];
        if (c) {
         var x = tile.x[posIdx];
         var y = tileMax - tile.y[posIdx];
         var dx = px + res2 - x;
         var dy = py + res2 - y;
         if (dx >= 0 && dx < res && dy >= 0 && dy < res) {
           return {
             value: c,
             bbox: mercator.tilePixelBBox(
               tile.coord.x,
               tile.coord.y,
               tile.coord.z,
               x - res2, y - res2, res
             )
           }
         }
        }
      }
      return null;
    },
    _preloadIcons: function(img_names){
      var self = this;
      this._icons = {};
      if (img_names.length > 0 && !this._forcePoints){
        for (var i = 0; i<img_names.length; i++){
          var new_img = this._createImage();
          function qualifyURL(url) {
            var a = document.createElement('a');
              a.href = url;
              return a.href;
          }
          this._icons[qualifyURL(img_names[i])] = null;
          if (typeof self._icons.itemsToLoad === 'undefined'){
            this._icons.itemsToLoad = img_names.length;
          }
          new_img.crossOrigin = "Anonymous";
          new_img.onload = function(e){
            self._icons[this.src] = this;
            if (Object.keys(self._icons).length === img_names.length + 1){
              self._icons.itemsToLoad--;
              if (self._icons.itemsToLoad === 0){
                self.clearSpriteCache();
                self.fire("allIconsLoaded");
              }
            }
          };
          new_img.onerror = function(){
            self._forcePoints = true;
            self.clearSpriteCache();
            console.error("Couldn't get marker-file " + this.src);
          };
          new_img.src = img_names[i];
        }
      }

  },
  applyFilters: function(){
    if(this._style){
      if(this._style['image-filters']){
        function componentToHex(c) {
          var hex = c.toString(16);
          return hex.length == 1 ? "0" + hex : hex;
        }

        function rgbToHex(r, g, b) {
          return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
        }
        var colorize = this._style['image-filters'].args;
        var gradient = {};
        var increment = 1/colorize.length;
        for (var i = 0; i < colorize.length; i++){
          var key = increment * i + increment;
          var rgb = colorize[i].rgb;
          var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]);
          gradient[key] = formattedColor;
        }
        this._filters.gradient(gradient);
        this._filters.draw();
      }
    }
  }
});

  // exports public api
module.exports = PointRenderer;
<|endoftext|>


<commit_before>
/*
  Apply this mixin to your vue components to get reactive information
  about the component's size.

  For example:

    <script>

      const responsiveElement = require('./responsive-element-mixin.js')

      export default {
        mixins: [responsiveElement],
        props: {
    ...

  This adds a new reactive property called `elSize` to your vue model:

    elSize: {
      width: 0,    // component's $el width (px)
      height: 0,   // component's $el height (px)
    },
*/

const ResizeSensor = require('css-element-queries/src/ResizeSensor');

module.exports = {
  data() {
    return {
      // becomes available for use
      elSize: { width: 0, height: 0 },
    };
  },
  methods: {
    _updateEl() {
      this.elSize.width = this.$el.clientWidth;
      this.elSize.height = this.$el.clientHeight;
    },
  },
  mounted() {
    this._updateEl();
    this.$options._resizeSensor = new ResizeSensor(this.$el, this._updateEl);
  },
  beforeDestroy() {
    this.$options._resizeSensor.detach(this.$el, this.update);
  },
};

<commit_msg>drive-by bug fix<commit_after>
/*
  Apply this mixin to your vue components to get reactive information
  about the component's size.

  For example:

    <script>

      const responsiveElement = require('./responsive-element-mixin.js')

      export default {
        mixins: [responsiveElement],
        props: {
    ...

  This adds a new reactive property called `elSize` to your vue model:

    elSize: {
      width: 0,    // component's $el width (px)
      height: 0,   // component's $el height (px)
    },
*/

const ResizeSensor = require('css-element-queries/src/ResizeSensor');

module.exports = {
  data() {
    return {
      // becomes available for use
      elSize: { width: 0, height: 0 },
    };
  },
  methods: {
    _updateEl() {
      this.elSize.width = this.$el.clientWidth;
      this.elSize.height = this.$el.clientHeight;
    },
  },
  mounted() {
    this._updateEl();
    this.$options._resizeSensor = new ResizeSensor(this.$el, this._updateEl);
  },
  beforeDestroy() {
    this.$options._resizeSensor.detach(this.$el, this._updateEl);
  },
};

<|endoftext|>


<commit_before>$(function() {
    $("#textCSV").click(function(event) {
        input = $("#id_JSONTransactions").val()
        parseCSV(input)
    });

    $('#fileCSV').click(function(event) {
        input = $('#id_JSONTransactionsFile')[0].files[0]
        parseCSV(input)
    });
});

function parseCSV(csv) {

    complete = function(results, file) {
        sendPost(results);
        // NOTE: need a delay so that the pies load before the table shows
    };
    Configuration = {
        delimiter: "", // auto-detect
        newline: "", // auto-detect
        quoteChar: '"',
        header: true,
        dynamicTyping: true,
        preview: 0,
        encoding: "",
        worker: false,
        comments: true,
        step: undefined,
        complete: complete,
        error: undefined,
        download: false,
        skipEmptyLines: true,
        chunk: undefined,
        fastMode: undefined,
        beforeFirstChunk: undefined,
        withCredentials: undefined
    };
    Papa.parse(csv, Configuration);
}

function sendPost(json) {
    csrftoken = Cookies.get('csrftoken')

    function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    frm = $("#textCSVForm");
    $.ajax({
            url: frm.attr('action'),
            type: frm.attr('method'),
            dataType: '',
            data: {
                'json': JSON.stringify(json.data)
            },
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        })
        .done(function(response) {
            sortedJSON = JSON.parse(response);
            getUserGraphs(sortedJSON.catagories);
            createTable(sortedJSON.transactions);
        })
        .fail(function() {})
        .always(function() {});
}

function getUserGraphs(data) {
    var income = [],
        expenses = [],
        dataProvider;
    for (var i = 0; i < data.length; i++) {
        if (data[i][1] > 0) {
            income.push({
                'catName': data[i][0],
                'ammount': data[i][1]
            })
        } else {
            expenses.push({
                'catName': data[i][0],
                'ammount': data[i][1] * -1
            })
        }
    }
    for (var l = 0; l < 2; l++) {
        if (l === 0) {
            dataProvider = income;
        } else {
            dataProvider = expenses;
        }
        var chart = AmCharts.makeChart("chartdiv" + l.toString(), {
            "type": "pie",
            "theme": "light",
            "dataProvider": dataProvider,
            "valueField": "ammount",
            "titleField": "catName",
            "balloon": {
                "fixedPosition": true
            },
            "export": {
                "enabled": false
            }
        });
    }
}

var dataTable;

function createTable(input) {
    var rows = [],
        headers = Object.keys(input[0]);

    for (var i = 0; i < input.length; i++) {
        rows.push(Object.keys(input[i]).map(function(key) {
            return input[i][key];
        }))
    }

    options = {
        data: {
            'headings': headers,
            "rows": rows
        }
    }

    // Check to see if initialized
    if (dataTable) {
        // Wipe the table
        dataTable.clear();

        // Destroy the containers
        dataTable.wrapper.parentNode.replaceChild(dataTable.table, dataTable.wrapper);
    }

    // Initialize with the data
    dataTable = new DataTable("#transactionsInfo", options);

    $("#transactionsInfo").css('visibility', 'visible');
}
<commit_msg>Fixes table<commit_after>$(function() {
    $("#textCSV").click(function(event) {
        input = $("#id_JSONTransactions").val()
        parseCSV(input)
    });

    $('#fileCSV').click(function(event) {
        input = $('#id_JSONTransactionsFile')[0].files[0]
        parseCSV(input)
    });
});

function parseCSV(csv) {

    complete = function(results, file) {
        sendPost(results);
        // NOTE: need a delay so that the pies load before the table shows
    };
    Configuration = {
        delimiter: "", // auto-detect
        newline: "", // auto-detect
        quoteChar: '"',
        header: true,
        dynamicTyping: true,
        preview: 0,
        encoding: "",
        worker: false,
        comments: true,
        step: undefined,
        complete: complete,
        error: undefined,
        download: false,
        skipEmptyLines: true,
        chunk: undefined,
        fastMode: undefined,
        beforeFirstChunk: undefined,
        withCredentials: undefined
    };
    Papa.parse(csv, Configuration);
}

function sendPost(json) {
    csrftoken = Cookies.get('csrftoken')

    function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    frm = $("#textCSVForm");
    $.ajax({
            url: frm.attr('action'),
            type: frm.attr('method'),
            dataType: '',
            data: {
                'json': JSON.stringify(json.data)
            },
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        })
        .done(function(response) {
            sortedJSON = JSON.parse(response);
            getUserGraphs(sortedJSON.catagories);
            createTable(sortedJSON.transactions);
        })
        .fail(function() {})
        .always(function() {});
}

function getUserGraphs(data) {
    var income = [],
        expenses = [],
        dataProvider;
    for (var i = 0; i < data.length; i++) {
        if (data[i][1] > 0) {
            income.push({
                'catName': data[i][0],
                'ammount': data[i][1]
            })
        } else {
            expenses.push({
                'catName': data[i][0],
                'ammount': data[i][1] * -1
            })
        }
    }
    for (var l = 0; l < 2; l++) {
        if (l === 0) {
            dataProvider = income;
        } else {
            dataProvider = expenses;
        }
        var chart = AmCharts.makeChart("chartdiv" + l.toString(), {
            "type": "pie",
            "theme": "light",
            "dataProvider": dataProvider,
            "valueField": "ammount",
            "titleField": "catName",
            "balloon": {
                "fixedPosition": true
            },
            "export": {
                "enabled": false
            }
        });
    }
}

var dataTable;

function createTable(input) {
    var rows = [],
        headers = Object.keys(input[0]);

    for (var i = 0; i < input.length; i++) {
        rows.push(Object.keys(input[i]).map(function(key) {
            return input[i][key];
        }))
    }

    options = {
        data: {
            'headings': headers,
            "rows": rows
        }
    }

    if (dataTable) {
      dataTable.destroy()
    }

    dataTable = new DataTable("#transactionsInfo", options);

    $("#transactionsInfo").css('visibility', 'visible');
}
<|endoftext|>