<commit_before>define(['marionette', 'backbone', 'jquery'], function (Marionette, Backbone, $) {
  'use strict';

  // Handle all anchor clicks if they contain data-transition
  $(document).on('click', 'a[data-transition]', function (e) {
    console.log('handle link');
    var $link = $(e.currentTarget);
    var transition = $link.data('transition');
    var href = $link.attr('href').substring(1);

    e.preventDefault();

    Backbone.trigger('page-transition', href, {
      trigger: true,
      replace: true,
      transition: transition
    });
  });

  Backbone.View.prototype.transitionTo = function (href, transition) {
    Backbone.trigger('page-transition', href, {
      trigger: true,
      replace: true,
      transition: transition
    });
  };

  Marionette.Region.prototype.close = function () {
    var view = this.currentView;
    if (!view || view.isClosed) {
      return;
    }

    var $viewEl = $(this.currentView.el);

    var close = closeView.bind(this, view);

    if (this.transitionNext) {
      var endClass, zIndex;

      // If transitioning back ('prev'), move old view to the right.
      if (this.transitionNext === 'prev') {
        endClass = 'out-right';
        zIndex = 2;
      } else {
        endClass = 'out-left';
        zIndex = 1;
      }

      $viewEl.addClass('transition')
        .addClass(endClass)
        .removeClass('in')
        .css('z-index', zIndex);

      $viewEl.on('transitionend oTransitionEnd webkitTransitionEnd', close);
    } else {
      close();
    }
  };

  Marionette.Region.prototype.open = function (view) {
    var $viewEl = $(view.el);

    if (this.transitionNext) {
      var startClass, zIndex;

      // If transitioning back ('prev'), start new view on the left.
      if (this.transitionNext === 'prev') {
        startClass = 'out-left';
        zIndex = 1;
      } else {
        startClass = 'out-right';
        zIndex = 2;
      }

      $viewEl.addClass('transition')
        .addClass(startClass)
        .css('z-index', zIndex);

      this.$el.append($viewEl);

      // The timeout ensures the element is appended before the class is added.
      setTimeout(function () {
        $viewEl.removeClass(startClass).addClass('in');
      }, 1);
    } else {
      $viewEl.addClass('in');
      this.$el.append($viewEl);
    }

    this.transitionNext = false;
  };

  function closeView(view) {
    // call 'close' or 'remove', depending on which is found
    if (view.close) { view.close(); }
    else if (view.remove) { view.remove(); }

    Marionette.triggerMethod.call(this, 'close');
  }

});
<commit_msg>Remove console log in marionette-transitions<commit_after>define(['marionette', 'backbone', 'jquery'], function (Marionette, Backbone, $) {
  'use strict';

  // Handle all anchor clicks if they contain data-transition
  $(document).on('click', 'a[data-transition]', function (e) {
    var $link = $(e.currentTarget);
    var transition = $link.data('transition');
    var href = $link.attr('href').substring(1);

    e.preventDefault();

    Backbone.trigger('page-transition', href, {
      trigger: true,
      replace: true,
      transition: transition
    });
  });

  Backbone.View.prototype.transitionTo = function (href, transition) {
    Backbone.trigger('page-transition', href, {
      trigger: true,
      replace: true,
      transition: transition
    });
  };

  Marionette.Region.prototype.close = function () {
    var view = this.currentView;
    if (!view || view.isClosed) {
      return;
    }

    var $viewEl = $(this.currentView.el);

    var close = closeView.bind(this, view);

    if (this.transitionNext) {
      var endClass, zIndex;

      // If transitioning back ('prev'), move old view to the right.
      if (this.transitionNext === 'prev') {
        endClass = 'out-right';
        zIndex = 2;
      } else {
        endClass = 'out-left';
        zIndex = 1;
      }

      $viewEl.addClass('transition')
        .addClass(endClass)
        .removeClass('in')
        .css('z-index', zIndex);

      $viewEl.on('transitionend oTransitionEnd webkitTransitionEnd', close);
    } else {
      close();
    }
  };

  Marionette.Region.prototype.open = function (view) {
    var $viewEl = $(view.el);

    if (this.transitionNext) {
      var startClass, zIndex;

      // If transitioning back ('prev'), start new view on the left.
      if (this.transitionNext === 'prev') {
        startClass = 'out-left';
        zIndex = 1;
      } else {
        startClass = 'out-right';
        zIndex = 2;
      }

      $viewEl.addClass('transition')
        .addClass(startClass)
        .css('z-index', zIndex);

      this.$el.append($viewEl);

      // The timeout ensures the element is appended before the class is added.
      setTimeout(function () {
        $viewEl.removeClass(startClass).addClass('in');
      }, 1);
    } else {
      $viewEl.addClass('in');
      this.$el.append($viewEl);
    }

    this.transitionNext = false;
  };

  function closeView(view) {
    // call 'close' or 'remove', depending on which is found
    if (view.close) { view.close(); }
    else if (view.remove) { view.remove(); }

    Marionette.triggerMethod.call(this, 'close');
  }

});
<|endoftext|>


<commit_before>define("p3/store/IdMappingMemoryStore", [
	"dojo/_base/declare", "dojo/_base/lang", "dojo/_base/Deferred",
	"dojo/request", "dojo/when", "dojo/Stateful", "dojo/topic", "dojo/promise/all",
	"dojo/store/Memory", "dojo/store/util/QueryResults"
], function(declare, lang, Deferred,
			request, when, Stateful, Topic, All,
			Memory, QueryResults){

	return declare([Memory, Stateful], {
		baseQuery: {},
		apiServer: window.App.dataServiceURL,
		idProperty: "idx",
		state: null,

		constructor: function(options){
			this._loaded = false;
			if(options.apiServer){
				this.apiServer = options.apiServer;
			}
		},

		reload: function(){
			var self = this;
			delete self._loadingDeferred;
			self._loaded = false;
			self.loadData();
			self.set("refresh");
		},

		query: function(query, opts){
			query = query || {};
			if(this._loaded){
				return this.inherited(arguments);
			}
			else{
				var _self = this;
				var results;
				var qr = QueryResults(when(this.loadData(), function(){
					results = _self.query(query, opts);
					qr.total = when(results, function(results){
						return results.total || results.length
					});
					return results;
				}));

				return qr;
			}
		},

		get: function(id, opts){
			if(this._loaded){
				return this.inherited(arguments);
			}else{
				var _self = this;
				return when(this.loadData(), function(){
					return _self.get(id, options)
				})
			}
		},

		loadData: function(){
			if(this._loadingDeferred){
				return this._loadingDeferred;
			}

			var _self = this;

			// console.warn(this.state, this.state.genome_ids, !this.state.genome_ids);
			if(!this.state.fromIdValue){
				// console.log("No Genome IDS, use empty data set for initial store");

				//this is done as a deferred instead of returning an empty array
				//in order to make it happen on the next tick.  Otherwise it
				//in the query() function above, the callback happens before qr exists
				var def = new Deferred();
				setTimeout(lang.hitch(_self, function(){
					this.setData([]);
					this._loaded = true;
					// def.resolve(true);
				}), 0);
				return def.promise;
			}

			var fromIdGroup = this.state.fromIdGroup;
			var fromId = this.state.fromId;
			var toIdGroup = this.state.toIdGroup;
			var toId = this.state.toId;
			var fromIdValue = this.state.fromIdValue.split(',');

			var summary = {
				total: fromIdValue.length,
				found: 0,
				type: toId
			};

			// console.log(this.state);

			if(fromIdGroup === 'PATRIC'){
				if(toIdGroup === 'PATRIC'){
					this._loadingDeferred = when(request.post(_self.apiServer + '/genome_feature/', {
						handleAs: 'json',
						headers: {
							'Accept': "application/json",
							'Content-Type': "application/solrquery+x-www-form-urlencoded",
							'X-Requested-With': null,
							'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
						},
						data: {
							q: fromId + ":(" + fromIdValue.join(" OR ") + ")",
							rows: fromIdValue.length,
							sort: "genome_name asc,accession asc,start asc"
						}
					}), function(data){

						summary.found = data.length;
						Topic.publish("IDMapping", "updateHeader", summary);

						_self.setData(data);
						_self._loaded = true;
						return true;
					});
				}else{
					// from PATRIC to Other
					var giNumbers = {};
					var accessionGiMap = {};
					var giTarget = {};

					// step 1: get GI from fromId (query to genome_feature)
					// step 2: get UniprotKBAccession from GI numbers (query to id_ref), then create accessionGiMap
					// step 3: get requested id from UniprotKBAccession (query to id_ref), then create giTargetMap

					this._loadingDeferred = when(request.post(_self.apiServer + '/genome_feature/', {
						handleAs: 'json',
						headers: {
							'Accept': "application/json",
							'Content-Type': "application/solrquery+x-www-form-urlencoded",
							'X-Requested-With': null,
							'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
						},
						data: {
							q: fromId + ":(" + fromIdValue.join(" OR ") + ")",
							rows: fromIdValue.length
						}
					}), function(features){
						giNumbers = features.map(function(d){
							return d.gi;
						}).filter(function(d){
							return d !== undefined && d > 0;
						});

						// console.log(giNumbers);

						if(giNumbers.length === 0){
							summary.found = 0;
							Topic.publish("IDMapping", "updateHeader", summary);

							_self.setData([]);
							_self._loaded = true;
							return true;
						}

						// console.log("giNumbers: ", giNumbers);
						return when(request.post(_self.apiServer + '/id_ref/', {
							handleAs: 'json',
							headers: {
								'Accept': "application/json",
								'Content-Type': "application/solrquery+x-www-form-urlencoded",
								'X-Requested-With': null,
								'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
							},
							data: {
								q: "id_type:GI AND id_value:(" + giNumbers.join(" OR ") + ")",
								rows: 25000
							}
						}), function(response){

							if(response.length === 0){
								summary.found = 0;
								Topic.publish("IDMapping", "updateHeader", summary);

								_self.setData([]);
								_self._loaded = true;
								return true;
							}

							response.forEach(function(d){
								accessionGiMap[d['uniprotkb_accession']] = d['id_value'];
							});

							// console.log(accessionGiMap);

							return when(request.post(_self.apiServer + '/id_ref/', {
								handleAs: 'json',
								headers: {
									'Accept': "application/json",
									'Content-Type': "application/solrquery+x-www-form-urlencoded",
									'X-Requested-With': null,
									'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
								},
								data: {
									q: "uniprotkb_accession:(" + Object.keys(accessionGiMap).join(" OR ") + ") AND " + ((toId === 'UniProtKB-Accession') ? 'id_type:GI' : 'id_type:(' + toId + ')'),
									rows: 25000
								}
							}), function(response){

								response.forEach(function(d){
									var accession = d['uniprotkb_accession'];
									var target = d['id_value'];
									var gi = accessionGiMap[accession];

									if(toId === 'UniProtKB-Accession'){
										if(!giTarget.hasOwnProperty(gi)){
											giTarget[gi] = [accession];
										}else{
											giTarget[gi].push(accession);
										}
									}else{
										if(!giTarget.hasOwnProperty(gi)){
											giTarget[gi] = [target];
										}else{
											giTarget[gi].push(target);
										}
									}

								});

								// console.log(giTarget);

								var data = [];
								features.forEach(function(d){
									if(d.hasOwnProperty('gi')){
										var target = giTarget[d['gi']];
										if(target){
											target.forEach(function(t){
												var item = Object.create(d);
												item['target'] = t;
												item['idx'] = item['feature_id'] + '_' + item['target'];
												data.push(item);
											});
										}
									}
								});

								summary.found = data.length;
								Topic.publish("IDMapping", "updateHeader", summary);

								_self.setData(data);
								_self._loaded = true;
								return true;
							});
						});
					});
				}
			}
			else{
				// from Other to PATRIC

				// step 1: get UniProtKBAccession (query to id_ref). skip if fromId equals UniProtKB-Accession
				// step 2: get GI from UniProtKBAccession (query to id_ref) // defUniprotKB2PATRIC()
				// step 3: get PATRIC feature from GI (query to genome_feature) // defUniprotKB2PATRIC()

				var defUniprotKB2PATRIC = function(uniprotKBAccession, accessionTarget){

					return when(request.post(_self.apiServer + '/id_ref/', {
						handleAs: 'json',
						headers: {
							'Accept': "application/json",
							'Content-Type': "application/solrquery+x-www-form-urlencoded",
							'X-Requested-With': null,
							'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
						},
						data: {
							q: "uniprotkb_accession:(" + uniprotKBAccession.join(" OR ") + ") AND id_type:GI",
							rows: 25000
						}
					}), function(response){

						var giNumbers = []; // response.map(function(d){ return d.id_value;});
						var giTarget = [];

						response.forEach(function(d){
							var gi = d['id_value'];
							giNumbers.push(gi);
							var accession = d['uniprotkb_accession'];
							giTarget[gi] = accessionTarget[accession];
						});

						return when(request.post(_self.apiServer + '/genome_feature/', {
							handleAs: 'json',
							headers: {
								'Accept': "application/json",
								'Content-Type': "application/solrquery+x-www-form-urlencoded",
								'X-Requested-With': null,
								'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
							},
							data: {
								q: "gi:(" + giNumbers.join(" OR ") + ") AND annotation:PATRIC",
								rows: 25000
							}
						}), function(response){

							var data = [];
							response.forEach(function(d){
								var item = Object.create(d);
								item['target'] = giTarget[d['gi']];
								item['idx'] = item['feature_id'] + '_' + item['target'];
								data.push(item);
							});
							return data;
						});
					});
				};

				var accessionTargetMap = {};

				if(fromId === 'UniProtKB-Accession'){

					accessionTargetMap = fromIdValue.map(function(d){
						return {d: d};
					});
					this._loadingDeferred = when(defUniprotKB2PATRIC(fromIdValue, accessionTargetMap), function(data){
						summary.found = data.length;
						Topic.publish("IDMapping", "updateHeader", summary);

						_self.setData(data);
						_self._loaded = true;
						return true;
					});
				}else{
					// get UniprotKBAccession via query to id_ref
					this._loadingDeferred = when(request.post(_self.apiServer + '/id_ref/', {
						handleAs: 'json',
						headers: {
							'Accept': "application/json",
							'Content-Type': "application/solrquery+x-www-form-urlencoded",
							'X-Requested-With': null,
							'Authorization': _self.token ? _self.token : (window.App.authorizationToken || "")
						},
						data: {
							q: 'id_type:' + fromId + ' AND id_value:(' + fromIdValue.join(' OR ') + ')',
							rows: 25000
						}
					}), function(response){

						var uniprotkbAccessionList = [];

						response.forEach(function(d){
							var accession = d['uniprotkb_accession'];
							uniprotkbAccessionList.push(accession);
							accessionTargetMap[accession] = d['id_value'];
						});

						return when(defUniprotKB2PATRIC(uniprotkbAccessionList, accessionTargetMap), function(data){
							summary.found = data.length;
							Topic.publish("IDMapping", "updateHeader", summary);

							_self.setData(data);
							_self._loaded = true;
							return true;
						});
					});
				}
			}

			return this._loadingDeferred;
		}
	});
});
<commit_msg>remove renamed build file<commit_after><|endoftext|>


<commit_before>'use strict';

var $interpolateMinErr = minErr('$interpolate');

/**
 * @ngdoc object
 * @name ng.$interpolateProvider
 * @function
 *
 * @description
 *
 * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
 */
function $InterpolateProvider() {
  var startSymbol = '{{';
  var endSymbol = '}}';

  /**
   * @ngdoc method
   * @name ng.$interpolateProvider#startSymbol
   * @methodOf ng.$interpolateProvider
   * @description
   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
   *
   * @param {string=} value new value to set the starting symbol to.
   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
   */
  this.startSymbol = function(value){
    if (value) {
      startSymbol = value;
      return this;
    } else {
      return startSymbol;
    }
  };

  /**
   * @ngdoc method
   * @name ng.$interpolateProvider#endSymbol
   * @methodOf ng.$interpolateProvider
   * @description
   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
   *
   * @param {string=} value new value to set the ending symbol to.
   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
   */
  this.endSymbol = function(value){
    if (value) {
      endSymbol = value;
      return this;
    } else {
      return endSymbol;
    }
  };

  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
    var startSymbolLength = startSymbol.length,
        endSymbolLength = endSymbol.length;

    /**
     * @ngdoc function
     * @name ng.$interpolate
     * @function
     *
     * @requires $parse
     * @requires $sce
     *
     * @description
     *
     * Compiles a string with markup into an interpolation function. This service is used by the
     * HTML {@link ng.$compile $compile} service for data binding. See
     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
     * interpolation markup.
     *
     *

         var $interpolate = ...; // injected
         var exp = $interpolate('Hello {{name}}!');
         expect(exp({name:'Angular'}).toEqual('Hello Angular!');

     *
     *
     * @param {string} text The text with markup to interpolate.
     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
     *    embedded expression in order to return an interpolation function. Strings with no
     *    embedded expression will return null for the interpolation function.
     * @param {string=} trustedContext when provided, the returned function passes the interpolated
     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that
     *    provides Strict Contextual Escaping for details.
     * @returns {function(context)} an interpolation function which is used to compute the interpolated
     *    string. The function has these parameters:
     *
     *    * `context`: an object against which any expressions embedded in the strings are evaluated
     *      against.
     *
     */
    function $interpolate(text, mustHaveExpression, trustedContext) {
      var startIndex,
          endIndex,
          index = 0,
          parts = [],
          length = text.length,
          hasInterpolation = false,
          fn,
          exp,
          concat = [];

      while(index < length) {
        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
          (index != startIndex) && parts.push(text.substring(index, startIndex));
          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
          fn.exp = exp;
          index = endIndex + endSymbolLength;
          hasInterpolation = true;
        } else {
          // we did not find anything, so we have to add the remainder to the parts array
          (index != length) && parts.push(text.substring(index));
          index = length;
        }
      }

      if (!(length = parts.length)) {
        // we added, nothing, must have been an empty string.
        parts.push('');
        length = 1;
      }

      // Concatenating expressions makes it hard to reason about whether some combination of concatenated
      // values are unsafe to use and could easily lead to XSS.  By requiring that a single
      // expression be used for iframe[src], object[src], etc., we ensure that the value that's used
      // is assigned or constructed by some JS code somewhere that is more testable or make it
      // obvious that you bound the value to some user controlled value.  This helps reduce the load
      // when auditing for XSS issues.
      if (trustedContext && parts.length > 1) {
          throw $interpolateMinErr('noconcat',
              "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
              "interpolations that concatenate multiple expressions when a trusted value is " +
              "required.  See http://docs.angularjs.org/api/ng.$sce", text);
      }

      if (!mustHaveExpression  || hasInterpolation) {
        concat.length = length;
        fn = function(context) {
          try {
            for(var i = 0, ii = length, part; i<ii; i++) {
              if (typeof (part = parts[i]) == 'function') {
                part = part(context);
                if (trustedContext) {
                  part = $sce.getTrusted(trustedContext, part);
                } else {
                  part = $sce.valueOf(part);
                }
                if (part == null || part == undefined) {
                  part = '';
                } else if (typeof part != 'string') {
                  part = toJson(part);
                }
              }
              concat[i] = part;
            }
            return concat.join('');
          }
          catch(err) {
            var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString());
            $exceptionHandler(newErr);
          }
        };
        fn.exp = text;
        fn.parts = parts;
        return fn;
      }
    }

    /**
     * @ngdoc method
     * @name ng.$interpolate#startSymbol
     * @methodOf ng.$interpolate
     * @description
     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
     *
     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change
     * the symbol.
     *
     * @returns {string} start symbol.
     */
    $interpolate.startSymbol = function() {
      return startSymbol;
    }

    /**
     * @ngdoc method
     * @name ng.$interpolate#endSymbol
     * @methodOf ng.$interpolate
     * @description
     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
     *
     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change
     * the symbol.
     *
     * @returns {string} start symbol.
     */
    $interpolate.endSymbol = function() {
      return endSymbol;
    }

    return $interpolate;
  }];
}

<commit_msg>docs($interpolate): add example for the provider<commit_after>'use strict';

var $interpolateMinErr = minErr('$interpolate');

/**
 * @ngdoc object
 * @name ng.$interpolateProvider
 * @function
 *
 * @description
 *
 * Used for configuring the interpolation markup. Defaults to `{{` and `}}`.
 *
 * @example
   <doc:example>
     <doc:source>

          //label//

     </doc:source>
     <doc:scenario>
       describe('provider', function() {
          beforeEach(module(function($interpolateProvider) {
            $interpolateProvider.startSymbol('//');
            $interpolateProvider.endSymbol('//');
          }));

          it('should not get confused with same markers', inject(function($interpolate) {
            expect($interpolate('///').parts).toEqual(['///']);
            expect($interpolate('////')()).toEqual('');
            expect($interpolate('//1//')()).toEqual('1');
          }));
       });
     </doc:scenario>
   </doc:example>
 */
function $InterpolateProvider() {
  var startSymbol = '{{';
  var endSymbol = '}}';

  /**
   * @ngdoc method
   * @name ng.$interpolateProvider#startSymbol
   * @methodOf ng.$interpolateProvider
   * @description
   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`.
   *
   * @param {string=} value new value to set the starting symbol to.
   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
   */
  this.startSymbol = function(value){
    if (value) {
      startSymbol = value;
      return this;
    } else {
      return startSymbol;
    }
  };

  /**
   * @ngdoc method
   * @name ng.$interpolateProvider#endSymbol
   * @methodOf ng.$interpolateProvider
   * @description
   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
   *
   * @param {string=} value new value to set the ending symbol to.
   * @returns {string|self} Returns the symbol when used as getter and self if used as setter.
   */
  this.endSymbol = function(value){
    if (value) {
      endSymbol = value;
      return this;
    } else {
      return endSymbol;
    }
  };

  this.$get = ['$parse', '$exceptionHandler', '$sce', function($parse, $exceptionHandler, $sce) {
    var startSymbolLength = startSymbol.length,
        endSymbolLength = endSymbol.length;

    /**
     * @ngdoc function
     * @name ng.$interpolate
     * @function
     *
     * @requires $parse
     * @requires $sce
     *
     * @description
     *
     * Compiles a string with markup into an interpolation function. This service is used by the
     * HTML {@link ng.$compile $compile} service for data binding. See
     * {@link ng.$interpolateProvider $interpolateProvider} for configuring the
     * interpolation markup.
     *
     *

         var $interpolate = ...; // injected
         var exp = $interpolate('Hello {{name}}!');
         expect(exp({name:'Angular'}).toEqual('Hello Angular!');

     *
     *
     * @param {string} text The text with markup to interpolate.
     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have
     *    embedded expression in order to return an interpolation function. Strings with no
     *    embedded expression will return null for the interpolation function.
     * @param {string=} trustedContext when provided, the returned function passes the interpolated
     *    result through {@link ng.$sce#getTrusted $sce.getTrusted(interpolatedResult,
     *    trustedContext)} before returning it.  Refer to the {@link ng.$sce $sce} service that
     *    provides Strict Contextual Escaping for details.
     * @returns {function(context)} an interpolation function which is used to compute the interpolated
     *    string. The function has these parameters:
     *
     *    * `context`: an object against which any expressions embedded in the strings are evaluated
     *      against.
     *
     */
    function $interpolate(text, mustHaveExpression, trustedContext) {
      var startIndex,
          endIndex,
          index = 0,
          parts = [],
          length = text.length,
          hasInterpolation = false,
          fn,
          exp,
          concat = [];

      while(index < length) {
        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) &&
             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) {
          (index != startIndex) && parts.push(text.substring(index, startIndex));
          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex)));
          fn.exp = exp;
          index = endIndex + endSymbolLength;
          hasInterpolation = true;
        } else {
          // we did not find anything, so we have to add the remainder to the parts array
          (index != length) && parts.push(text.substring(index));
          index = length;
        }
      }

      if (!(length = parts.length)) {
        // we added, nothing, must have been an empty string.
        parts.push('');
        length = 1;
      }

      // Concatenating expressions makes it hard to reason about whether some combination of concatenated
      // values are unsafe to use and could easily lead to XSS.  By requiring that a single
      // expression be used for iframe[src], object[src], etc., we ensure that the value that's used
      // is assigned or constructed by some JS code somewhere that is more testable or make it
      // obvious that you bound the value to some user controlled value.  This helps reduce the load
      // when auditing for XSS issues.
      if (trustedContext && parts.length > 1) {
          throw $interpolateMinErr('noconcat',
              "Error while interpolating: {0}\nStrict Contextual Escaping disallows " +
              "interpolations that concatenate multiple expressions when a trusted value is " +
              "required.  See http://docs.angularjs.org/api/ng.$sce", text);
      }

      if (!mustHaveExpression  || hasInterpolation) {
        concat.length = length;
        fn = function(context) {
          try {
            for(var i = 0, ii = length, part; i<ii; i++) {
              if (typeof (part = parts[i]) == 'function') {
                part = part(context);
                if (trustedContext) {
                  part = $sce.getTrusted(trustedContext, part);
                } else {
                  part = $sce.valueOf(part);
                }
                if (part == null || part == undefined) {
                  part = '';
                } else if (typeof part != 'string') {
                  part = toJson(part);
                }
              }
              concat[i] = part;
            }
            return concat.join('');
          }
          catch(err) {
            var newErr = $interpolateMinErr('interr', "Can't interpolate: {0}\n{1}", text, err.toString());
            $exceptionHandler(newErr);
          }
        };
        fn.exp = text;
        fn.parts = parts;
        return fn;
      }
    }

    /**
     * @ngdoc method
     * @name ng.$interpolate#startSymbol
     * @methodOf ng.$interpolate
     * @description
     * Symbol to denote the start of expression in the interpolated string. Defaults to `{{`.
     *
     * Use {@link ng.$interpolateProvider#startSymbol $interpolateProvider#startSymbol} to change
     * the symbol.
     *
     * @returns {string} start symbol.
     */
    $interpolate.startSymbol = function() {
      return startSymbol;
    }

    /**
     * @ngdoc method
     * @name ng.$interpolate#endSymbol
     * @methodOf ng.$interpolate
     * @description
     * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`.
     *
     * Use {@link ng.$interpolateProvider#endSymbol $interpolateProvider#endSymbol} to change
     * the symbol.
     *
     * @returns {string} start symbol.
     */
    $interpolate.endSymbol = function() {
      return endSymbol;
    }

    return $interpolate;
  }];
}

<|endoftext|>


<commit_before>var SourceDiff = SourceDiff || {};

SourceDiff.Diff = function(ignoreLeadingWS) {
    var _ignoreLeadingWS = ignoreLeadingWS;

    var trimWhiteSpace = function(str) {
        if (str) {
            str = str.replace(/\s\s*$/, '');

            if (_ignoreLeadingWS) {
                str = str.replace(/^\s\s*/, '');
            }
        }
        return str;
    };

    var diff = function(s1, s2) {
        var s1Lines = s1.split('\n');    //todo: handle \r?
        var s2Lines = s2.split('\n');

        padBlankLines(s1Lines);
        padBlankLines(s2Lines);

        var prefixLines = trim(s1Lines, s2Lines);

        var matrix = createMatrix(s1Lines, s2Lines);

        fillMatrix(s1Lines, s2Lines, matrix);

        var i = s1Lines.length;
        var j = s2Lines.length;

        var added = [];
        var deleted = [];

        while (i >= 0 && j >= 0) {
            if (trimWhiteSpace(s1Lines[i - 1]) === trimWhiteSpace(s2Lines[j - 1])) {
                i--;
                j--;
            } else if (j >= 0 && (i === 0 || matrix[i][j - 1] >= matrix[i - 1][j])) {
                if (s2Lines[j - 1].length > 0) {
                    added.unshift({line: prefixLines + j - 1, text: s2Lines[j - 1]});   //todo: do I even need to store the text?
                }
                j--;
            } else if (i >= 0 && (j === 0 || matrix[i][j - 1] < matrix[i - 1][j])) {
                if (s1Lines[i - 1].length > 0) {
                    deleted.unshift({line: prefixLines + i - 1, text: s1Lines[i - 1]});
                }
                i--;
            }
        }

        return {added: added, deleted: deleted};
    };

    var createMatrix = function(s1Lines, s2Lines) {
        var matrix = [];
        for (var i = 0; i <= s1Lines.length; i++) {
            matrix[i] = new Array(s2Lines.length + 1);
            matrix[i][0] = 0;
        }

        for (var j = 1; j <= s2Lines.length; j++) {
            matrix[0][j] = 0;
        }

        return matrix;
    };

    var fillMatrix = function(s1Lines, s2Lines, matrix) {
        for (var i = 1; i <= s1Lines.length; i++) {
            for (var j = 1; j <= s2Lines.length; j++) {
                if (s1Lines[i - 1] === s2Lines[j - 1])
                    matrix[i][j] = matrix[i - 1][j - 1] + 1;
                else
                    matrix[i][j] = Math.max(matrix[i][j - 1], matrix[i - 1][j]);
            }
        }
    };

    var padBlankLines = function(lines) {
        if (lines.length == 1 && lines[0] == '') {
            return;
        }

        for (var l = 0; l < lines.length; l++) {
            if (lines[l] == '') {
                lines[l] = ' ';
            }
        }
    };

    var trim = function(s1Lines, s2Lines) {
        var prefixLines = 0;

        while (s1Lines.length > 0 && s2Lines.length > 0 && s1Lines[0] === s2Lines[0]) {
            s1Lines.shift();
            s2Lines.shift();
            prefixLines++;
        }

        while (s1Lines.length > 0 && s2Lines.length > 0 && s1Lines[s1Lines.length - 1] === s2Lines[s2Lines.length - 1]) {
            s1Lines.pop();
            s2Lines.pop();
        }

        return prefixLines;
    };

    return {
        diff: diff,
        trim: trim,   //exposed for testing
        padBlankLines: padBlankLines       //used by DiffFormatter
    };
};<commit_msg>added braces<commit_after>var SourceDiff = SourceDiff || {};

SourceDiff.Diff = function(ignoreLeadingWS) {
    var _ignoreLeadingWS = ignoreLeadingWS;

    var trimWhiteSpace = function(str) {
        if (str) {
            str = str.replace(/\s\s*$/, '');

            if (_ignoreLeadingWS) {
                str = str.replace(/^\s\s*/, '');
            }
        }
        return str;
    };

    var diff = function(s1, s2) {
        var s1Lines = s1.split('\n');    //todo: handle \r?
        var s2Lines = s2.split('\n');

        padBlankLines(s1Lines);
        padBlankLines(s2Lines);

        var prefixLines = trim(s1Lines, s2Lines);

        var matrix = createMatrix(s1Lines, s2Lines);

        fillMatrix(s1Lines, s2Lines, matrix);

        var i = s1Lines.length;
        var j = s2Lines.length;

        var added = [];
        var deleted = [];

        while (i >= 0 && j >= 0) {
            if (trimWhiteSpace(s1Lines[i - 1]) === trimWhiteSpace(s2Lines[j - 1])) {
                i--;
                j--;
            } else if (j >= 0 && (i === 0 || matrix[i][j - 1] >= matrix[i - 1][j])) {
                if (s2Lines[j - 1].length > 0) {
                    added.unshift({line: prefixLines + j - 1, text: s2Lines[j - 1]});   //todo: do I even need to store the text?
                }
                j--;
            } else if (i >= 0 && (j === 0 || matrix[i][j - 1] < matrix[i - 1][j])) {
                if (s1Lines[i - 1].length > 0) {
                    deleted.unshift({line: prefixLines + i - 1, text: s1Lines[i - 1]});
                }
                i--;
            }
        }

        return {added: added, deleted: deleted};
    };

    var createMatrix = function(s1Lines, s2Lines) {
        var matrix = [];
        for (var i = 0; i <= s1Lines.length; i++) {
            matrix[i] = new Array(s2Lines.length + 1);
            matrix[i][0] = 0;
        }

        for (var j = 1; j <= s2Lines.length; j++) {
            matrix[0][j] = 0;
        }

        return matrix;
    };

    var fillMatrix = function(s1Lines, s2Lines, matrix) {
        for (var i = 1; i <= s1Lines.length; i++) {
            for (var j = 1; j <= s2Lines.length; j++) {
                if (s1Lines[i - 1] === s2Lines[j - 1]) {
                    matrix[i][j] = matrix[i - 1][j - 1] + 1;
                } else {
                    matrix[i][j] = Math.max(matrix[i][j - 1], matrix[i - 1][j]);
                }
            }
        }
    };

    var padBlankLines = function(lines) {
        if (lines.length == 1 && lines[0] == '') {
            return;
        }

        for (var l = 0; l < lines.length; l++) {
            if (lines[l] == '') {
                lines[l] = ' ';
            }
        }
    };

    var trim = function(s1Lines, s2Lines) {
        var prefixLines = 0;

        while (s1Lines.length > 0 && s2Lines.length > 0 && s1Lines[0] === s2Lines[0]) {
            s1Lines.shift();
            s2Lines.shift();
            prefixLines++;
        }

        while (s1Lines.length > 0 && s2Lines.length > 0 && s1Lines[s1Lines.length - 1] === s2Lines[s2Lines.length - 1]) {
            s1Lines.pop();
            s2Lines.pop();
        }

        return prefixLines;
    };

    return {
        diff: diff,
        trim: trim,   //exposed for testing
        padBlankLines: padBlankLines       //used by DiffFormatter
    };
};<|endoftext|>


<commit_before>/**
 * A display of a single numeric value.
 * Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and
 * a valueAccessor that returns a single value.
 * @class numberDisplay
 * @memberof dc
 * @mixes dc.baseMixin
 * @example
 * // create a number display under #chart-container1 element using the default global chart group
 * var display1 = dc.numberDisplay('#chart-container1');
 * @param {String|node|d3.selection} parent - Any valid
 * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying
 * a dom block element such as a div; or a dom element or d3 selection.
 * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.
 * Interaction with a chart will only trigger events and redraws within the chart's group.
 * @return {dc.numberDisplay}
 */
dc.numberDisplay = function (parent, chartGroup) {
    var SPAN_CLASS = 'number-display';
    var _formatNumber = d3.format('.2s');
    var _chart = dc.baseMixin({});
    var _html = {one: '', some: '', none: ''};

    // dimension not required
    _chart._mandatoryAttributes(['group']);

    /**
     * Gets or sets an optional object specifying HTML templates to use depending on the number
     * displayed.  The text `%number` will be replaced with the current value.
     * - one: HTML template to use if the number is 1
     * - zero: HTML template to use if the number is 0
     * - some: HTML template to use otherwise
     * @method html
     * @memberof dc.numberDisplay
     * @instance
     * @example
     * numberWidget.html({
     *      one:'%number record',
     *      some:'%number records',
     *      none:'no records'})
     * @param {{one:String, some:String, none:String}} [html={one: '', some: '', none: ''}]
     * @return {{one:String, some:String, none:String}}
     * @return {dc.numberDisplay}
     */
    _chart.html = function (html) {
        if (!arguments.length) {
            return _html;
        }
        if (html.none) {
            _html.none = html.none;//if none available
        } else if (html.one) {
            _html.none = html.one;//if none not available use one
        } else if (html.some) {
            _html.none = html.some;//if none and one not available use some
        }
        if (html.one) {
            _html.one = html.one;//if one available
        } else if (html.some) {
            _html.one = html.some;//if one not available use some
        }
        if (html.some) {
            _html.some = html.some;//if some available
        } else if (html.one) {
            _html.some = html.one;//if some not available use one
        }
        return _chart;
    };

    /**
     * Calculate and return the underlying value of the display
     * @method value
     * @memberof dc.numberDisplay
     * @instance
     * @return {Number}
     */
    _chart.value = function () {
        return _chart.data();
    };

    _chart.data(function (group) {
        var valObj = group.value ? group.value() : group.top(1)[0];
        return _chart.valueAccessor()(valObj);
    });

    _chart.transitionDuration(250); // good default

    _chart._doRender = function () {
        var newValue = _chart.value(),
            span = _chart.selectAll('.' + SPAN_CLASS);

        if (span.empty()) {
            span = span.data([0])
                .enter()
                .append('span')
                .attr('class', SPAN_CLASS);
        }

        span.transition()
            .duration(_chart.transitionDuration())
            .ease('quad-out-in')
            .tween('text', function () {
                var interp = d3.interpolateNumber(this.lastValue || 0, newValue);
                this.lastValue = newValue;
                return function (t) {
                    var html = null, num = _chart.formatNumber()(interp(t));
                    if (newValue === 0 && (_html.none !== '')) {
                        html = _html.none;
                    } else if (newValue === 1 && (_html.one !== '')) {
                        html = _html.one;
                    } else if (_html.some !== '') {
                        html = _html.some;
                    }
                    this.innerHTML = html ? html.replace('%number', num) : num;
                };
            });
    };

    _chart._doRedraw = function () {
        return _chart._doRender();
    };

    /**
     * Get or set a function to format the value for the display.
     * @method formatNumber
     * @memberof dc.numberDisplay
     * @instance
     * @see {@link https://github.com/mbostock/d3/wiki/Formatting d3.format}
     * @param {Function} [formatter=d3.format('.2s')]
     * @return {Function}
     * @return {dc.numberDisplay}
     */
    _chart.formatNumber = function (formatter) {
        if (!arguments.length) {
            return _formatNumber;
        }
        _formatNumber = formatter;
        return _chart;
    };

    return _chart.anchor(parent, chartGroup);
};
<commit_msg>fixed numberDisplay tweening getting stuck on Infinity values<commit_after>/**
 * A display of a single numeric value.
 * Unlike other charts, you do not need to set a dimension. Instead a group object must be provided and
 * a valueAccessor that returns a single value.
 * @class numberDisplay
 * @memberof dc
 * @mixes dc.baseMixin
 * @example
 * // create a number display under #chart-container1 element using the default global chart group
 * var display1 = dc.numberDisplay('#chart-container1');
 * @param {String|node|d3.selection} parent - Any valid
 * {@link https://github.com/mbostock/d3/wiki/Selections#selecting-elements d3 single selector} specifying
 * a dom block element such as a div; or a dom element or d3 selection.
 * @param {String} [chartGroup] - The name of the chart group this chart instance should be placed in.
 * Interaction with a chart will only trigger events and redraws within the chart's group.
 * @return {dc.numberDisplay}
 */
dc.numberDisplay = function (parent, chartGroup) {
    var SPAN_CLASS = 'number-display';
    var _formatNumber = d3.format('.2s');
    var _chart = dc.baseMixin({});
    var _html = {one: '', some: '', none: ''};

    // dimension not required
    _chart._mandatoryAttributes(['group']);

    /**
     * Gets or sets an optional object specifying HTML templates to use depending on the number
     * displayed.  The text `%number` will be replaced with the current value.
     * - one: HTML template to use if the number is 1
     * - zero: HTML template to use if the number is 0
     * - some: HTML template to use otherwise
     * @method html
     * @memberof dc.numberDisplay
     * @instance
     * @example
     * numberWidget.html({
     *      one:'%number record',
     *      some:'%number records',
     *      none:'no records'})
     * @param {{one:String, some:String, none:String}} [html={one: '', some: '', none: ''}]
     * @return {{one:String, some:String, none:String}}
     * @return {dc.numberDisplay}
     */
    _chart.html = function (html) {
        if (!arguments.length) {
            return _html;
        }
        if (html.none) {
            _html.none = html.none;//if none available
        } else if (html.one) {
            _html.none = html.one;//if none not available use one
        } else if (html.some) {
            _html.none = html.some;//if none and one not available use some
        }
        if (html.one) {
            _html.one = html.one;//if one available
        } else if (html.some) {
            _html.one = html.some;//if one not available use some
        }
        if (html.some) {
            _html.some = html.some;//if some available
        } else if (html.one) {
            _html.some = html.one;//if some not available use one
        }
        return _chart;
    };

    /**
     * Calculate and return the underlying value of the display
     * @method value
     * @memberof dc.numberDisplay
     * @instance
     * @return {Number}
     */
    _chart.value = function () {
        return _chart.data();
    };

    _chart.data(function (group) {
        var valObj = group.value ? group.value() : group.top(1)[0];
        return _chart.valueAccessor()(valObj);
    });

    _chart.transitionDuration(250); // good default

    _chart._doRender = function () {
        var newValue = _chart.value(),
            span = _chart.selectAll('.' + SPAN_CLASS);

        if (span.empty()) {
            span = span.data([0])
                .enter()
                .append('span')
                .attr('class', SPAN_CLASS);
        }

        span.transition()
            .duration(_chart.transitionDuration())
            .ease('quad-out-in')
            .tween('text', function () {
                // [XA] don't try and interpolate from Infinity, else this breaks.
                var interpStart = isFinite(this.lastValue) ? this.lastValue : 0;
                var interp = d3.interpolateNumber(interpStart || 0, newValue);
                this.lastValue = newValue;
                return function (t) {
                    var html = null, num = _chart.formatNumber()(interp(t));
                    if (newValue === 0 && (_html.none !== '')) {
                        html = _html.none;
                    } else if (newValue === 1 && (_html.one !== '')) {
                        html = _html.one;
                    } else if (_html.some !== '') {
                        html = _html.some;
                    }
                    this.innerHTML = html ? html.replace('%number', num) : num;
                };
            });
    };

    _chart._doRedraw = function () {
        return _chart._doRender();
    };

    /**
     * Get or set a function to format the value for the display.
     * @method formatNumber
     * @memberof dc.numberDisplay
     * @instance
     * @see {@link https://github.com/mbostock/d3/wiki/Formatting d3.format}
     * @param {Function} [formatter=d3.format('.2s')]
     * @return {Function}
     * @return {dc.numberDisplay}
     */
    _chart.formatNumber = function (formatter) {
        if (!arguments.length) {
            return _formatNumber;
        }
        _formatNumber = formatter;
        return _chart;
    };

    return _chart.anchor(parent, chartGroup);
};
<|endoftext|>


<commit_before>var slug = require('slug'),
    async = require("async"),
    sys = require('sys'),
    exec = require('child_process').exec,
    Mustache = require("mustache"),
    _ = require("lodash"),
    S = require("string");

var pullRepositoryCodeClass = function(container) {

    this.seekServer = function(repository) {

        var arrMatches = null,
            result = null,
            ssh_rePattern = null;

        //SSH type
        if(S(repository).startsWith('ssh')) {
            ssh_rePattern = new RegExp(/^ssh\:\/\/[a-zA-Z0-9]+\@([0-9a-zA-Z\.]+)([:0-9]*).*$/);
            arrMatches = repository.match(ssh_rePattern);

            if (/^\:[0-9]+$/.test(arrMatches[2])) {
                result = {
                    host: arrMatches[1],
                    port: "-p "+arrMatches[2].replace(":", "") //prepares the string
                };
            } else {
                result = {
                    host: arrMatches[1],
                    port: ""
                };
            }

            container.get("logger").info("Found server from repository (SSH)", result);
            return result;
        }

        //Git Type
        if(S(repository).startsWith("git@")) {
            rePattern = new RegExp(/^git@([a-zA-Z0-9\.]+):.*$/);
            arrMatches = repository.match(rePattern);

            result = {
                host: arrMatches[1],
                port: ""
            };

            container.get("logger").info("Found server from repository (GIT)", result);

            return result;
        }

        //HTTP type
        if(S(repository).startsWith("http")) {
            rePattern = new RegExp(/^http(|s):\/\/([a-zA-Z0-9.]+)(|:)(|[0-9]+)\/.*$/);
            arrMatches = repository.match(rePattern);

            result = {
                host: arrMatches[2],
                port: (!_.isEmpty(arrMatches[4])) ? "-p "+arrMatches[4] : ""
            };

            container.get("logger").info("Found server from repository (HTTP)", result);

            return result;
        }

        container.get("logger").error("Error seeking server from git repository description", {
            repository: repository
        });

    };

    this.run = function(buildConfiguration, return_callback, extra_links, type) {

        if(_.isUndefined(type)) type = "default";

        var buildId = buildConfiguration.buildId;
        var repository = buildConfiguration.repository;
        var ssh_key = buildConfiguration.sshKey;
        var ssh_private_key = buildConfiguration.sshPrivateKey;
        var commit = buildConfiguration.commit;
        if(!_.has(buildConfiguration, "hosts")) buildConfiguration.hosts = [];
        var hosts = buildConfiguration.hosts;

        if(_.isUndefined(extra_links)) extra_links = "";

        //Use the image sailfish-git-puller to place all the code inside the workspace
        var containerName = slug(buildId);
        var self = this;

        async.series([
            function(callback) {
                /*
                 * Create the container on the background
                 */
                var dockerCommand = [];
                dockerCommand.push('docker run --rm');
                dockerCommand.push('--name="{{&containerName}}" ');
                dockerCommand.push('-e SAILFISH_SSH_KEY="{{&ssh_key}}"');
                dockerCommand.push('-e SAILFISH_PRIVATE_SSH_KEY="{{&ssh_private_key}}"');
                dockerCommand.push('-e SAILFISH_REPOSITORY="{{&repository}}"');
                dockerCommand.push('-e SAILFISH_REPOSITORY_SERVER="{{&repository_server}}"');
                dockerCommand.push('-e SAILFISH_REPOSITORY_SERVER_PORT="{{&repository_server_port}}"');
                dockerCommand.push('-e SAILFISH_COMMIT="{{&commit}}"');
                dockerCommand.push('-e SAILFISH_TYPE="{{&type}}"');
                dockerCommand.push('-e SAILFISH_HOSTS="{{&hosts}}"');
                dockerCommand.push(extra_links); //Adding extra links if defined
                dockerCommand.push('-v {{&workspace}}/{{containerName}}:/workspace:rw');
                dockerCommand.push("{{&puller_image}}");

                var dockerCommandJoin = dockerCommand.join(" ");

                var seekServerInfo = self.seekServer(repository);
                var dockerCommandFinal = Mustache.render(dockerCommandJoin, {
                    "puller_image": "urodoz/sailfish-git-puller:1.0",
                    "ssh_key": ssh_key,
                    "ssh_private_key": ssh_private_key,
                    "repository": repository,
                    "containerName": containerName,
                    "commit": commit,
                    "hosts": buildConfiguration.hosts.join(","),
                    "repository_server": seekServerInfo.host,
                    "repository_server_port": seekServerInfo.port,
                    "workspace": container.getParameter("workspace_root"),
                    "type": type
                });

                container.get("logger").info("Running container to pull the code", {command: dockerCommandFinal});

                var child = exec(dockerCommandFinal, function(error, stdout, stderr) {
                    //TODO: Control error
                    //Check environment variable setted on the configuration on the running container
                    var chmod777Frame = exec("chmod 777 "+container.getParameter("workspace_root")+"/"+containerName+"/frame", function(error, stdout, stderr) {
                        callback(error, true); //TODO : Control error
                    });

                });
            }
        ], return_callback);

    };

};

module.exports = function(container) {
    return new pullRepositoryCodeClass(container);
};<commit_msg>Removed new line on ssh_key for git pull code<commit_after>var slug = require('slug'),
    async = require("async"),
    sys = require('sys'),
    exec = require('child_process').exec,
    Mustache = require("mustache"),
    _ = require("lodash"),
    S = require("string");

var pullRepositoryCodeClass = function(container) {

    this.seekServer = function(repository) {

        var arrMatches = null,
            result = null,
            ssh_rePattern = null;

        //SSH type
        if(S(repository).startsWith('ssh')) {
            ssh_rePattern = new RegExp(/^ssh\:\/\/[a-zA-Z0-9]+\@([0-9a-zA-Z\.]+)([:0-9]*).*$/);
            arrMatches = repository.match(ssh_rePattern);

            if (/^\:[0-9]+$/.test(arrMatches[2])) {
                result = {
                    host: arrMatches[1],
                    port: "-p "+arrMatches[2].replace(":", "") //prepares the string
                };
            } else {
                result = {
                    host: arrMatches[1],
                    port: ""
                };
            }

            container.get("logger").info("Found server from repository (SSH)", result);
            return result;
        }

        //Git Type
        if(S(repository).startsWith("git@")) {
            rePattern = new RegExp(/^git@([a-zA-Z0-9\.]+):.*$/);
            arrMatches = repository.match(rePattern);

            result = {
                host: arrMatches[1],
                port: ""
            };

            container.get("logger").info("Found server from repository (GIT)", result);

            return result;
        }

        //HTTP type
        if(S(repository).startsWith("http")) {
            rePattern = new RegExp(/^http(|s):\/\/([a-zA-Z0-9.]+)(|:)(|[0-9]+)\/.*$/);
            arrMatches = repository.match(rePattern);

            result = {
                host: arrMatches[2],
                port: (!_.isEmpty(arrMatches[4])) ? "-p "+arrMatches[4] : ""
            };

            container.get("logger").info("Found server from repository (HTTP)", result);

            return result;
        }

        container.get("logger").error("Error seeking server from git repository description", {
            repository: repository
        });

    };

    this.run = function(buildConfiguration, return_callback, extra_links, type) {

        if(_.isUndefined(type)) type = "default";

        var buildId = buildConfiguration.buildId;
        var repository = buildConfiguration.repository;
        var ssh_key = buildConfiguration.sshKey;
        var ssh_private_key = buildConfiguration.sshPrivateKey;
        var commit = buildConfiguration.commit;
        if(!_.has(buildConfiguration, "hosts")) buildConfiguration.hosts = [];
        var hosts = buildConfiguration.hosts;

        if(_.isUndefined(extra_links)) extra_links = "";

        //Use the image sailfish-git-puller to place all the code inside the workspace
        var containerName = slug(buildId);
        var self = this;

        async.series([
            function(callback) {
                /*
                 * Create the container on the background
                 */
                var dockerCommand = [];
                dockerCommand.push('docker run --rm');
                dockerCommand.push('--name="{{&containerName}}" ');
                dockerCommand.push('-e SAILFISH_SSH_KEY="{{&ssh_key}}"');
                dockerCommand.push('-e SAILFISH_PRIVATE_SSH_KEY="{{&ssh_private_key}}"');
                dockerCommand.push('-e SAILFISH_REPOSITORY="{{&repository}}"');
                dockerCommand.push('-e SAILFISH_REPOSITORY_SERVER="{{&repository_server}}"');
                dockerCommand.push('-e SAILFISH_REPOSITORY_SERVER_PORT="{{&repository_server_port}}"');
                dockerCommand.push('-e SAILFISH_COMMIT="{{&commit}}"');
                dockerCommand.push('-e SAILFISH_TYPE="{{&type}}"');
                dockerCommand.push('-e SAILFISH_HOSTS="{{&hosts}}"');
                dockerCommand.push(extra_links); //Adding extra links if defined
                dockerCommand.push('-v {{&workspace}}/{{containerName}}:/workspace:rw');
                dockerCommand.push("{{&puller_image}}");

                var dockerCommandJoin = dockerCommand.join(" ");

                var seekServerInfo = self.seekServer(repository);
                var dockerCommandFinal = Mustache.render(dockerCommandJoin, {
                    "puller_image": "urodoz/sailfish-git-puller:1.0",
                    "ssh_key": ssh_key.replace("\n", ""),
                    "ssh_private_key": ssh_private_key,
                    "repository": repository,
                    "containerName": containerName,
                    "commit": commit,
                    "hosts": buildConfiguration.hosts.join(","),
                    "repository_server": seekServerInfo.host,
                    "repository_server_port": seekServerInfo.port,
                    "workspace": container.getParameter("workspace_root"),
                    "type": type
                });

                container.get("logger").info("Running container to pull the code", {command: dockerCommandFinal});

                var child = exec(dockerCommandFinal, function(error, stdout, stderr) {
                    //TODO: Control error
                    //Check environment variable setted on the configuration on the running container
                    var chmod777Frame = exec("chmod 777 "+container.getParameter("workspace_root")+"/"+containerName+"/frame", function(error, stdout, stderr) {
                        callback(error, true); //TODO : Control error
                    });

                });
            }
        ], return_callback);

    };

};

module.exports = function(container) {
    return new pullRepositoryCodeClass(container);
};<|endoftext|>


<commit_before>(function() {
  var input;
  var Game = {
    user: "X",
    computer: "O",

    visualAfterChoice: function() {
      if ($(event.target).attr('class') == "btn btn-start") {
        UI.toggleDisplayedButton(".btn-start", ".btn-new");
      }
      else {
        UI.toggleDisplayedButton(".btn-restart", ".btn-new");
      }
    },

    visualAfterGameOver: function() {
      $("tr td").unbind();
      UI.toggleDisplayedButton(".btn-new", ".btn-restart");
      this.restartGame();
    },

    winner: function(currentPlayer) {
      return currentPlayer == "X" ? "Player" : "Computer";
    },

    firstMove: function() {
      var input = UI.askFirstMove();
      if (input === null || input === "") {
        return true;
      }
      else if(input == "y" || input == "n") {
        this.visualAfterChoice();
        return input;
      }
      else {
        UI.inputErrorMessage();
        this.firstMove();
      }
    },

    nextTurn: function(currentPlayer) {
      if(GameRules.gameWin(GameBoard)) {
        UI.winMessage(this.winner(currentPlayer));
        this.visualAfterGameOver();
      }
      else if(GameRules.gameTie(GameBoard)) {
        UI.tieMessage();
        this.visualAfterGameOver();
      }
    },

    humanPlay: function(e) {
      var _this = this;
      Human.choiceSpot(e, GameBoard, _this.user);
      _this.nextTurn(_this.user);
    },

    computerPlay: function() {
      var _this = this;
      $("#Computer").show(function() {
        Computer.chooseTheBestSpot(_this.computer);
        _this.nextTurn(_this.computer);
      });
    },

    play: function() {
      var _this = this;
      this.newGame();
      var firstmove = this.firstMove();
      if (firstmove === true) {
        return;
      }
      else if (firstmove === "y") {
        $("#Human").show();
        $("tr td").click(function(e) {
          _this.humanPlay(e);
          UI.hideHumanMessage();
          if (GameRules.gameOver(GameBoard)) {
            return $("tr td").unbind("click");
          }
          _this.computerPlay();
        });
      }
      else {
        this.computerPlay(function() {
          $("tr td").click(function(e) {
            _this.humanPlay(e);
            if (GameRules.gameOver(GameBoard)) {
              return $("tr td").unbind("click");
            }
          });
        });
      }
    },

    startGame: function() {
      var _this = this;
      UI.hideButton(".btn-restart", ".btn-new");
      UI.hideComputerMessage();
      UI.hideHumanMessage();
      $(".btn-start").click(function(e) {
        _this.play();
        e.stopPropagation();
      });
    },

    resetGame: function() {
      $("tr td").empty();
      GameBoard.resetBoard();
    },

    newGame: function() {
      var _this = this;
      $(".btn-new").click(function(e) {
        $(".btn-new").unbind("click");
        _this.resetGame();
        $("tr td").unbind("click");
        _this.play();
        e.stopPropagation();
      });
    },

    restartGame: function() {
      var _this = this;
      $(".btn-restart").click(function(e) {
        _this.resetGame();
        _this.play();
        e.stopPropagation();
      });
    }
  };
  window.Game = Game;
})();
<commit_msg>refactoring play() in Game<commit_after>(function() {
  var input;
  var Game = {
    user: "X",
    computer: "O",

    visualAfterChoice: function() {
      if ($(event.target).attr('class') == "btn btn-start") {
        UI.toggleDisplayedButton(".btn-start", ".btn-new");
      }
      else {
        UI.toggleDisplayedButton(".btn-restart", ".btn-new");
      }
    },

    visualAfterGameOver: function() {
      $("tr td").unbind();
      UI.toggleDisplayedButton(".btn-new", ".btn-restart");
      this.restartGame();
    },

    winner: function(currentPlayer) {
      return currentPlayer == "X" ? "Player" : "Computer";
    },

    firstMove: function() {
      var input = UI.askFirstMove();
      if (input === null || input === "") {
        return true;
      }
      else if(input == "y" || input == "n") {
        this.visualAfterChoice();
        return input;
      }
      else {
        UI.inputErrorMessage();
        this.firstMove();
      }
    },

    nextTurn: function(currentPlayer) {
      if(GameRules.gameWin(GameBoard)) {
        UI.winMessage(this.winner(currentPlayer));
        this.visualAfterGameOver();
      }
      else if(GameRules.gameTie(GameBoard)) {
        UI.tieMessage();
        this.visualAfterGameOver();
      }
    },

    humanPlay: function(e) {
      var _this = this;
      $("#Human").show(function() {
        Human.choiceSpot(e, GameBoard, _this.user);
        _this.nextTurn(_this.user);
        UI.hideHumanMessage();
      });
    },

    computerPlay: function() {
      var _this = this;
      $("#Computer").show(function() {
        Computer.chooseTheBestSpot(_this.computer);
        _this.nextTurn(_this.computer);
      });
    },

    introGame: function() {
      var _this = this;
      this.newGame();
      var firstmove = this.firstMove();
      if (firstmove === true) {
        return;
      }
      this.play(firstmove);
    },

    play: function(firstmove) {
      var _this = this;
      if (firstmove === "y") {
        $("tr td").on('click', function(e) {
          _this.humanPlay(e);
          if (GameRules.gameOver(GameBoard)) {
            return $("tr td").unbind("click");
          }
          _this.computerPlay();
          $("tr td").promise().done(function() {
            _this.play(firstmove);
          });
        });
      }
      else {
        this.computerPlay();
        $("tr td").click(function(e) {
          if (GameRules.gameOver(GameBoard)) {
            return $("tr td").unbind("click");
          }
          UI.hideHumanMessage();
          _this.humanPlay(e);
          _this.computerPlay();
        });
      }
    },

    startGame: function() {
      var _this = this;
      UI.hideButton(".btn-restart", ".btn-new");
      UI.hideComputerMessage();
      UI.hideHumanMessage();
      $(".btn-start").click(function(e) {
        _this.introGame();
        e.stopPropagation();
      });
    },

    resetGame: function() {
      $("tr td").empty();
      GameBoard.resetBoard();
    },

    newGame: function() {
      var _this = this;
      $(".btn-new").click(function(e) {
        $(".btn-new").unbind("click");
        _this.resetGame();
        $("tr td").unbind("click");
        _this.introGame();
        e.stopPropagation();
      });
    },

    restartGame: function() {
      var _this = this;
      $(".btn-restart").click(function(e) {
        _this.resetGame();
        _this.play();
        e.stopPropagation();
      });
    }
  };
  window.Game = Game;
})();
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import classNames from 'classnames';

export default class Grid extends React.Component {
    static propTypes = {
        className: PropTypes.string
    }

    render() {
        var { className, ...otherProps } = this.props;

        var classes = classNames('mdl-grid', className);

        return (

                {this.props.children}

        );
    }
}

class Cell extends React.Component {
    static propTypes = {
        className: PropTypes.string,
        col: PropTypes.number.isRequired,
        phone: PropTypes.number,
        tablet: PropTypes.number
    }

    render() {
        var { className, col, phone, tablet, ...otherProps } = this.props;

        var classes = classNames('mdl-cell', {
            [`mdl-cell--${col}-col`]: true,
            [`mdl-cell--${phone}-col-tablet`]: typeof phone !== 'undefined',
            [`mdl-cell--${tablet}-col-tablet`]: typeof tablet !== 'undefined'
        }, className);

        return (

                {this.props.children}

        );
    }
}

export default Grid;
export { Cell };
<commit_msg>adds 'align' in grid<commit_after>import React, { PropTypes } from 'react';
import classNames from 'classnames';

export default class Grid extends React.Component {
    static propTypes = {
        className: PropTypes.string
    }

    render() {
        var { className, ...otherProps } = this.props;

        var classes = classNames('mdl-grid', className);

        return (

                {this.props.children}

        );
    }
}

class Cell extends React.Component {
    static propTypes = {
        align: PropTypes.oneOf(['top', 'middle', 'bottom', 'stretch']),
        className: PropTypes.string,
        col: PropTypes.number.isRequired,
        phone: PropTypes.number,
        tablet: PropTypes.number
    }

    render() {
        var { align, className, col, phone, tablet, ...otherProps } = this.props;

        var classes = classNames('mdl-cell', {
            [`mdl-cell--${col}-col`]: true,
            [`mdl-cell--${phone}-col-tablet`]: typeof phone !== 'undefined',
            [`mdl-cell--${tablet}-col-tablet`]: typeof tablet !== 'undefined',
            [`mdl-cell--${align}`]: typeof align !== 'undefined'
        }, className);

        return (

                {this.props.children}

        );
    }
}

export default Grid;
export { Cell };
<|endoftext|>


<commit_before>
goog.provide('og.input');
goog.provide('og.input.Input');

og.input.KEY_SPACE = 32;
og.input.KEY_H = 72;
og.input.KEY_C = 67;
og.input.KEY_X = 88;
og.input.KEY_E = 69;
og.input.KEY_Q = 81;
og.input.KEY_W = 87;
og.input.KEY_S = 83;
og.input.KEY_A = 65;
og.input.KEY_D = 68;
og.input.KEY_SHIFT = 16;
og.input.KEY_LEFT = 37;
og.input.KEY_RIGHT = 39;
og.input.KEY_UP = 38;
og.input.KEY_DOWN = 40;
og.input.KEY_F1 = 112;
og.input.MB_LEFT = 0;
og.input.MB_RIGHT = 2;
og.input.MB_MIDDLE = 1;

og.input.Input = function (htmlObject) {
    this.currentlyPressedKeys = {};
    this.pressedKeysCallbacks = {};
    this.charkeysCallbacks = {};
    this._htmlObject = htmlObject;

    var that = this;
    document.onkeydown = function (event) { that.handleKeyDown.call(that, event) };
    document.onkeyup = function (event) { that.handleKeyUp.call(that, event) };
};

og.input.Input.prototype.setEvent = function (event, sender, callback, keyCode) {
    var handle = this;
    switch (event) {
        case "onmousewheel": {
            var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
            if (this._htmlObject.attachEvent) //if IE (and Opera depending on user setting)
                this._htmlObject.attachEvent("on" + mousewheelevt, function (evt) { callback.call(sender, evt); })
            else if (this._htmlObject.addEventListener) //WC3 browsers
                this._htmlObject.addEventListener(mousewheelevt, function (evt) { evt.wheelDelta = evt.detail * (-120); callback.call(sender, evt); }, false)
        }
            break;
        case "onmousedown":
            this._htmlObject.onmousedown = function (event) { callback.call(sender, event); };
            this._htmlObject.oncontextmenu = function (event) { return false; };
            break;
        case "onmouseup":
            this._htmlObject.onmouseup = function (event) { callback.call(sender, event); };
            break;
        case "onmousemove":
            this._htmlObject.onmousemove = function (event) { callback.call(sender, event); };
            break;
        case "onkeypressed":
            this.pressedKeysCallbacks[keyCode] = { callback: callback, sender: sender };
            break;
        case "oncharkeypressed":
            this.charkeysCallbacks[keyCode] = { callback: callback, sender: sender, ch: String.fromCharCode(keyCode) };
            break;
    }
};

og.input.Input.prototype.isKeyPressed = function (keyCode) {
    return this.currentlyPressedKeys[keyCode];
};

og.input.Input.prototype.handleKeyDown = function (event) {
    this.currentlyPressedKeys[event.keyCode] = true;
    for (var ch in this.charkeysCallbacks) {
        if (String.fromCharCode(event.keyCode) == this.charkeysCallbacks[ch].ch) {
            var ccl = this.charkeysCallbacks[ch];
            ccl.callback.call(ccl.sender);
        }
    }
};

og.input.Input.prototype.handleKeyUp = function (event) {
    this.currentlyPressedKeys[event.keyCode] = false;
};

og.input.Input.prototype.handleEvents = function () {
    for (var pk in this.pressedKeysCallbacks) {
        if (this.currentlyPressedKeys[pk]) {
            var cpk = this.pressedKeysCallbacks[pk];
            cpk.callback.call(cpk.sender);
        }
    }
};<commit_msg>mouse position margin/padding bug fixed.<commit_after>
goog.provide('og.input');
goog.provide('og.input.Input');

og.input.KEY_SPACE = 32;
og.input.KEY_H = 72;
og.input.KEY_C = 67;
og.input.KEY_X = 88;
og.input.KEY_E = 69;
og.input.KEY_Q = 81;
og.input.KEY_W = 87;
og.input.KEY_S = 83;
og.input.KEY_A = 65;
og.input.KEY_D = 68;
og.input.KEY_SHIFT = 16;
og.input.KEY_LEFT = 37;
og.input.KEY_RIGHT = 39;
og.input.KEY_UP = 38;
og.input.KEY_DOWN = 40;
og.input.KEY_F1 = 112;
og.input.MB_LEFT = 0;
og.input.MB_RIGHT = 2;
og.input.MB_MIDDLE = 1;

og.input.Input = function (htmlObject) {
    this.currentlyPressedKeys = {};
    this.pressedKeysCallbacks = {};
    this.charkeysCallbacks = {};
    this._htmlObject = htmlObject;

    var that = this;
    document.onkeydown = function (event) { that.handleKeyDown.call(that, event) };
    document.onkeyup = function (event) { that.handleKeyUp.call(that, event) };
};

og.input.Input.prototype.setEvent = function (event, sender, callback, keyCode) {
    var handle = this;
    switch (event) {
        case "onmousewheel": {
            var mousewheelevt = (/Firefox/i.test(navigator.userAgent)) ? "DOMMouseScroll" : "mousewheel";
            if (this._htmlObject.attachEvent) //if IE (and Opera depending on user setting)
                this._htmlObject.attachEvent("on" + mousewheelevt, function (evt) { callback.call(sender, evt); })
            else if (this._htmlObject.addEventListener) //WC3 browsers
                this._htmlObject.addEventListener(mousewheelevt, function (evt) { evt.wheelDelta = evt.detail * (-120); callback.call(sender, evt); }, false)
        }
            break;
        case "onmousedown":
            this._htmlObject.onmousedown = function (event) { callback.call(sender, event); };
            this._htmlObject.oncontextmenu = function (event) { return false; };
            break;
        case "onmouseup":
            this._htmlObject.onmouseup = function (event) { callback.call(sender, event); };
            break;
        case "onmousemove":
            this._htmlObject.onmousemove = function (event) {
                var rect = this.getBoundingClientRect();
                callback.call(sender, { clientX: event.clientX - rect.left, clientY: event.clientY - rect.top });
            };
            break;
        case "onkeypressed":
            this.pressedKeysCallbacks[keyCode] = { callback: callback, sender: sender };
            break;
        case "oncharkeypressed":
            this.charkeysCallbacks[keyCode] = { callback: callback, sender: sender, ch: String.fromCharCode(keyCode) };
            break;
    }
};

og.input.Input.prototype.isKeyPressed = function (keyCode) {
    return this.currentlyPressedKeys[keyCode];
};

og.input.Input.prototype.handleKeyDown = function (event) {
    this.currentlyPressedKeys[event.keyCode] = true;
    for (var ch in this.charkeysCallbacks) {
        if (String.fromCharCode(event.keyCode) == this.charkeysCallbacks[ch].ch) {
            var ccl = this.charkeysCallbacks[ch];
            ccl.callback.call(ccl.sender);
        }
    }
};

og.input.Input.prototype.handleKeyUp = function (event) {
    this.currentlyPressedKeys[event.keyCode] = false;
};

og.input.Input.prototype.handleEvents = function () {
    for (var pk in this.pressedKeysCallbacks) {
        if (this.currentlyPressedKeys[pk]) {
            var cpk = this.pressedKeysCallbacks[pk];
            cpk.callback.call(cpk.sender);
        }
    }
};<|endoftext|>


<commit_before>const EventEmitter = require('events');
const uuid = require('node-uuid');
const util = require('util');
const ItemType = require('./ItemType');

/**
 * @property {Area}    area        Area the item belongs to (warning: this is not the area is currently in but the
 *                                 area it belongs to on a fresh load)
 * @property {object}  attributes  Essentially a blob of whatever attrs the item designer wanted to add
 * @property {array|string}  behaviors Single or list of behaviors this object uses
 * @property {string}  description Long description seen when looking at it
 * @property {number}  id          vnum
 * @property {boolean} isEquipped  Whether or not item is currently equipped
 * @property {Map}     inventory   Current items this item contains
 * @property {boolean} isHeld      Whether or not item is currently in an inventory (npc, player, or another object)
 * @property {string}  name        Name shown in inventory and when equipped
 * @property {Room}    room        Room the item is currently in
 * @property {string}  roomDesc    Description shown when item is seen in a room
 * @property {string}  script      A custom script for this item
 * @property {ItemType|string} type
 * @property {string}  uuid        UUID differentiating all instances of this item
 */
class Item extends EventEmitter {
  constructor (area, item) {
    super();
    const validate = ['keywords', 'name', 'id'];

    for (const prop of validate) {
      if (!(prop in item)) {
        throw new ReferenceError(`Item in area [${area.name}] missing required property [${prop}]`);
      }
    }

    this.area = area;
    this.attributes  = item.attributes || {};
    this.behaviors   = item.behaviors || null;
    this.defaultItems = item.items || [];
    this.description = item.description || 'Nothing special.';
    this.id          = item.id;
    this.globalId    = item.globalId; // EntityFactory key
    this.inventory   = item.inventory || new Map();
    this.isEquipped  = item.isEquipped || false;
    this.isHeld      = item.isHeld || false;
    this.keywords    = item.keywords;
    this.name        = item.name;
    this.room        = item.room || null;
    this.roomDesc    = item.roomDesc || '';
    this.script      = item.script || null;
    this.slot        = item.slot || null;
    this.type        = typeof item.type === 'string' ? ItemType[item.type] : (item.type || ItemType.OBJECT);
    this.uuid        = item.uuid || uuid.v4();
  }

  getAttribute(attr) {
    return this.attributes[attr];
  }

  setAttribute(attr, val) {
    this.attributes[attr] = val;
  }

  hasKeyword(keyword) {
    return this.keywords.indexOf(keyword) !== -1;
  }

  addItem(item) {
    if (this.inventory === null) {
      this.inventory = new Map();
    }
    this.inventory.set(item.uuid, item);
  }

  removeItem(item) {
    this.inventory.delete(item.uuid);

    // if we removed the last item unset the inventory
    // This ensures that when it's reloaded it won't try to set
    // its default inventory. Instead it will persist the fact
    // that all the items were removed from it
    if (!this.inventory.size) {
      this.inventory = null;
    }
  }

  hydrate(state) {
    if (typeof this.area === 'string') {
      this.area = state.AreaManager.getArea(this.area);
    }

    this.defaultItems.forEach(defaultItemId => {
      if (parseInt(defaultItemId, 10)) {
        defaultItemId = this.area.name + ':' + defaultItemId;
      }

      util.log(`\tDIST: Adding item [${defaultItemId}] to item [${this.name}]`);
      const newItem = state.ItemFactory.create(this.area, defaultItemId);
      newItem.hydrate(state);
      state.ItemManager.add(newItem);
      this.addItem(newItem);
    });

    if (this.behaviors) {
      this.behaviors.forEach(behaviorName => {
        let behavior = state.ItemBehaviorManager.get(behaviorName);
        if (!behavior) {
          return;
        }

        behavior.attach(this);
      });
    }
  }

  serialize() {
    const data = {
      area: this.area.name,
      attributes: this.attributes,
      behaviors: this.behaviors,
      defaultInv: this.defaultInv,
      description: this.description,
      id: this.id,
      isEquipped: this.isEquipped,
      isHeld: this.isHeld,
      keywords: this.keywords,
      name: this.name,
      room: this.room ? this.room.id : null,
      roomDesc: this.roomDesc,
      script: this.script,
      slot: this.slot,
      type: this.type,
      uuid: this.uuid,
    };

    data.inventory = this.inventory ?
      Array.from(this.inventory.values()).map(item => item.serialize) :
      this.inventory
    ;

    return data;
  }

  getKey() {
    return this.area.name + ':' + this.id;
  }
}

module.exports = Item;
<commit_msg>fixes #101<commit_after>const EventEmitter = require('events');
const uuid = require('node-uuid');
const util = require('util');
const ItemType = require('./ItemType');

/**
 * @property {Area}    area        Area the item belongs to (warning: this is not the area is currently in but the
 *                                 area it belongs to on a fresh load)
 * @property {object}  attributes  Essentially a blob of whatever attrs the item designer wanted to add
 * @property {array|string}  behaviors Single or list of behaviors this object uses
 * @property {string}  description Long description seen when looking at it
 * @property {number}  id          vnum
 * @property {boolean} isEquipped  Whether or not item is currently equipped
 * @property {Map}     inventory   Current items this item contains
 * @property {boolean} isHeld      Whether or not item is currently in an inventory (npc, player, or another object)
 * @property {string}  name        Name shown in inventory and when equipped
 * @property {Room}    room        Room the item is currently in
 * @property {string}  roomDesc    Description shown when item is seen in a room
 * @property {string}  script      A custom script for this item
 * @property {ItemType|string} type
 * @property {string}  uuid        UUID differentiating all instances of this item
 */
class Item extends EventEmitter {
  constructor (area, item) {
    super();
    const validate = ['keywords', 'name', 'id'];

    for (const prop of validate) {
      if (!(prop in item)) {
        throw new ReferenceError(`Item in area [${area.name}] missing required property [${prop}]`);
      }
    }

    this.area = area;
    this.attributes  = item.attributes || {};
    this.behaviors   = item.behaviors || null;
    this.defaultItems = item.items || [];
    this.description = item.description || 'Nothing special.';
    this.id          = item.id;
    this.globalId    = item.globalId; // EntityFactory key
    this.inventory   = item.inventory || new Map();
    this.isEquipped  = item.isEquipped || false;
    this.isHeld      = item.isHeld || false;
    this.keywords    = item.keywords;
    this.name        = item.name;
    this.room        = item.room || null;
    this.roomDesc    = item.roomDesc || '';
    this.script      = item.script || null;
    this.slot        = item.slot || null;
    this.type        = typeof item.type === 'string' ? ItemType[item.type] : (item.type || ItemType.OBJECT);
    this.uuid        = item.uuid || uuid.v4();
  }

  getAttribute(attr) {
    return this.attributes[attr];
  }

  setAttribute(attr, val) {
    this.attributes[attr] = val;
  }

  hasKeyword(keyword) {
    return this.keywords.indexOf(keyword) !== -1;
  }

  addItem(item) {
    if (this.inventory === null) {
      this.inventory = new Map();
    }
    this.inventory.set(item.uuid, item);
  }

  removeItem(item) {
    this.inventory.delete(item.uuid);

    // if we removed the last item unset the inventory
    // This ensures that when it's reloaded it won't try to set
    // its default inventory. Instead it will persist the fact
    // that all the items were removed from it
    if (!this.inventory.size) {
      this.inventory = null;
    }
  }

  hydrate(state) {
    if (typeof this.area === 'string') {
      this.area = state.AreaManager.getArea(this.area);
    }

    // if the item was saved with a custom inventory hydrate it
    if (Array.isArray(this.inventory)) {
      const itemDefs = this.inventory;
      this.inventory = new Map();
      itemDefs.forEach(itemDef => {
        let newItem = state.ItemFactory.create(state.AreaManager.getArea(itemDef.area), itemDef);
        newItem.hydrate(state);
        state.ItemManager.add(newItem);
        this.addItem(newItem);
      });
    } else {
    // otherwise load its default inv
        this.defaultItems.forEach(defaultItemId => {
          if (parseInt(defaultItemId, 10)) {
            defaultItemId = this.area.name + ':' + defaultItemId;
          }

          util.log(`\tDIST: Adding item [${defaultItemId}] to item [${this.name}]`);
          const newItem = state.ItemFactory.create(this.area, defaultItemId);
          newItem.hydrate(state);
          state.ItemManager.add(newItem);
          this.addItem(newItem);
        });
    }

    if (this.behaviors) {
      this.behaviors.forEach(behaviorName => {
        let behavior = state.ItemBehaviorManager.get(behaviorName);
        if (!behavior) {
          return;
        }

        behavior.attach(this);
      });
    }
  }

  serialize() {
    const data = {
      area: this.area.name,
      attributes: this.attributes,
      behaviors: this.behaviors,
      defaultInv: this.defaultInv,
      description: this.description,
      id: this.id,
      isEquipped: this.isEquipped,
      isHeld: this.isHeld,
      keywords: this.keywords,
      name: this.name,
      room: this.room ? this.room.id : null,
      roomDesc: this.roomDesc,
      script: this.script,
      slot: this.slot,
      type: this.type,
      uuid: this.uuid,
    };

    data.inventory = this.inventory ?
      Array.from(this.inventory.values()).map(item => item.serialize()) :
      this.inventory
    ;

    return data;
  }

  getKey() {
    return this.area.name + ':' + this.id;
  }
}

module.exports = Item;
<|endoftext|>