<commit_before>var React       = require('react/addons');

var _val = {};

module.exports = React.createClass({

  /**
   * Calls the change handler supplied
   * to this component.
   */
  emitChange: function () {
    if (this.props.onChange) {
      this.props.onChange(_val);
    }
  },

  /**
   * Updates the value of an integer input.
   *
   * Params:
   *
   * - __val__ : The value object to update
   * - __event__: The click event that was triggered
   */
  updateIntegerVal: function (val, event) {
    val.value = parseInt(event.target.value);
    this.emitChange();
  },

  /**
   * Adds an item to an array input.
   *
   * Params:
   *
   * - __val__: The value object of the array to append to
   */
  addItemToArray: function (val) {
    val.value.push({})
    this.forceUpdate();
  },

  /**
   * Constructs an array input
   *
   * Params:
   *
   * - __schema__: The schema for the array input
   * - __val__: The value object to be used for the array
   */
  buildArray: function (schema, val) {
    if (!val.value) {
      val.value = [];
    }
    return (

        {schema.label ?
{schema.label}
 : null}
        {val.value.map(function (value, index) {
          return (

              {index}:
              {this.buildItem(schema.items, value)}

          );
        }.bind(this))}

          <button onClick={this.addItemToArray.bind(this, val)}>Add Item</button>

    );
  },

  /**
   * Constructs an integer input
   *
   * Params:
   *
   * - __schema__: The schema for the integer input
   * - __val__: The value object to be used for the input
   */
  buildInteger: function (schema, val) {
    var placeholder = schema.label || '';
    return (<input type="number" pattern="\d*" placeholder={placeholder} onChange={this.updateIntegerVal.bind(this, val)} />);
  },

  /**
   * Constructs a generic item
   *
   * Params:
   *
   * - __schema__: The schema for the generic input item
   * - __val__: The value object to be used for the item
   */
  buildItem: function (schema, val) {
    switch (schema.type) {
      case "integer":
        return this.buildInteger(schema, val);

      case "array":
        return this.buildArray(schema, val)

      default:
        return (<fieldset />);
    }
  },

  render: function () {
    return this.buildItem(this.props, _val);
  }
});<commit_msg>get the real value from the data input<commit_after>var React       = require('react/addons');

var _val = {};

module.exports = React.createClass({

  /**
   * The all data in this component is stored
   * in the value key of an object.  This is
   * to ensure that parameters are always
   * passed by reference instead of by value
   * (hence preserving all relationships).
   *
   * This function iterates through an object,
   * removing all the "value" keys.
   */
  getRealVal: function (val) {
    var realVal;
    if (Array.isArray(val.value)) {
      realVal = val.value.map(function (v) {
        return this.getRealVal(v);
      }.bind(this));
    } else {
      realVal = val.value;
    }
    return realVal;
  },

  /**
   * Calls the change handler supplied
   * to this component.
   */
  emitChange: function () {
    var val;
    if (this.props.onChange) {
      val = this.getRealVal(_val);
      this.props.onChange(val);
    }
  },

  /**
   * Updates the value of an integer input.
   *
   * Params:
   *
   * - __val__ : The value object to update
   * - __event__: The click event that was triggered
   */
  updateIntegerVal: function (val, event) {
    val.value = parseInt(event.target.value);
    this.emitChange();
  },

  /**
   * Adds an item to an array input.
   *
   * Params:
   *
   * - __val__: The value object of the array to append to
   */
  addItemToArray: function (val) {
    val.value.push({})
    this.forceUpdate();
  },

  /**
   * Constructs an array input
   *
   * Params:
   *
   * - __schema__: The schema for the array input
   * - __val__: The value object to be used for the array
   */
  buildArray: function (schema, val) {
    if (!val.value) {
      val.value = [];
    }
    return (

        {schema.label ?
{schema.label}
 : null}
        {val.value.map(function (value, index) {
          return (

              {index}:
              {this.buildItem(schema.items, value)}

          );
        }.bind(this))}

          <button onClick={this.addItemToArray.bind(this, val)}>Add Item</button>

    );
  },

  /**
   * Constructs an integer input
   *
   * Params:
   *
   * - __schema__: The schema for the integer input
   * - __val__: The value object to be used for the input
   */
  buildInteger: function (schema, val) {
    var placeholder = schema.label || '';
    return (<input type="number" pattern="\d*" placeholder={placeholder} onChange={this.updateIntegerVal.bind(this, val)} />);
  },

  /**
   * Constructs a generic item
   *
   * Params:
   *
   * - __schema__: The schema for the generic input item
   * - __val__: The value object to be used for the item
   */
  buildItem: function (schema, val) {
    switch (schema.type) {
      case "integer":
        return this.buildInteger(schema, val);

      case "array":
        return this.buildArray(schema, val)

      default:
        return (<fieldset />);
    }
  },

  render: function () {
    return this.buildItem(this.props, _val);
  }
});<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react'

import * as Paths from './../../Paths'
import { OverlayWidget } from '../OverlayWidget'
import { TellAFriend } from './../'
import Choices from './Choices'

class MatchWidget extends Component {

  constructor(props, context) {
    super(props, context)
    this.state = {
      numberSelected: undefined,
      letterSelected: undefined,
      combined: false,
    }
  }

  redirectTo(e) {
    const { mobilization, widget, editable } = this.props
    if (e) e.preventDefault()
    if (editable) {
      this.context.router.transitionTo(
        Paths.matchChoicesMobilizationWidget(mobilization.id, widget.id)
      )
    }
  }

  handleCombineClick(e) {
    if (e) e.preventDefault()
    this.setState({ combined: true })
  }

  renderChoices() {
    const { selectedChoice1, selectedChoiceA } = this.state
    const { editable, loading } = this.props
    const { widget: { settings: {
        title_text,
        labelChoices1,
        labelChoicesA,
        choices1,
        choicesA
      }}
    } = this.props
    const optionsChoices1 = choices1 ? choices1.split(',') : []
    const optionsChoicesA = choicesA ? choicesA.split(',') : []

    return (
      <OverlayWidget editable={editable} onClick={::this.redirectTo}>

{title_text}

          <Choices
            title={labelChoices1}
            selected={this.state.numberSelected}
            options={optionsChoices1}
            disabled={false}
            onChange={(option) => {
              this.setState({ selectedChoice1: option.target.value })
            }}
            classNames={['mb2']}
          />
          <Choices
            { ...this.props }
            title={labelChoicesA}
            selected={this.state.letterSelected}
            options={optionsChoicesA}
            disabled={!(selectedChoice1)}
            onChange={(option) => {
              this.setState({ selectedChoiceA: option.target.value })
            }}
            classNames={['mb2']}
          />
          <button
            className="match caps button bg-darken-4 p2 full-width mt1 mb2"
            onClick={::this.handleCombineClick}
            disabled={loading || !(selectedChoice1 && selectedChoiceA)}>
            {loading ? 'Combinando...' : 'Combinar' }
          </button>

      </OverlayWidget>
    )
  }

  findMatchItem() {
    const { widget } = this.props
    const matchList = widget.match_list.filter((match) => {
      return match.first_choice === this.state.selectedChoice1 && match.second_choice === this.state.selectedChoiceA
    })
    if (matchList && matchList.length > 0) {
      return matchList[0]
    }
  }

  renderShareButtons() {
    ////
    // @todo
    // - talvez prop `message` configurável?
    ////
    const matchItem = this.findMatchItem()
    const { selectedChoice1, selectedChoiceA } = this.state
    const combinationImageUrl = matchItem
      ? matchItem.goal_image
      : 'https://placeholdit.imgix.net/~text?txtsize=28&bg=e9e9e9&txtclr=364C55&txt=300%C3%97300&w=300&h=300&txt=Imagem%20n%C3%A3o%20configurada'
    const share = Paths.shareMatchWrapper(matchItem.widget_id, matchItem.id)

    return <TellAFriend {...this.props}
      message="Resultado da sua combinação"
      href={ window.location.origin + share }
      imageUrl={combinationImageUrl}
      imageWidth="100%" />
  }

  render() {
    const { combined } = this.state
    return (

        { combined ? this.renderShareButtons() : this.renderChoices() }

    )
  }
}

MatchWidget.propTypes = {
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired
}

MatchWidget.contextTypes = {
  router: PropTypes.object.isRequired,
}

export default MatchWidget
<commit_msg>Fix MatchWidget share path.<commit_after>import React, { Component, PropTypes } from 'react'

import * as Paths from './../../Paths'
import { OverlayWidget } from '../OverlayWidget'
import { TellAFriend } from './../'
import Choices from './Choices'

class MatchWidget extends Component {

  constructor(props, context) {
    super(props, context)
    this.state = {
      numberSelected: undefined,
      letterSelected: undefined,
      combined: false,
    }
  }

  redirectTo(e) {
    const { mobilization, widget, editable } = this.props
    if (e) e.preventDefault()
    if (editable) {
      this.context.router.transitionTo(
        Paths.matchChoicesMobilizationWidget(mobilization.id, widget.id)
      )
    }
  }

  handleCombineClick(e) {
    if (e) e.preventDefault()
    this.setState({ combined: true })
  }

  renderChoices() {
    const { selectedChoice1, selectedChoiceA } = this.state
    const { editable, loading } = this.props
    const { widget: { settings: {
        title_text,
        labelChoices1,
        labelChoicesA,
        choices1,
        choicesA
      }}
    } = this.props
    const optionsChoices1 = choices1 ? choices1.split(',') : []
    const optionsChoicesA = choicesA ? choicesA.split(',') : []

    return (
      <OverlayWidget editable={editable} onClick={::this.redirectTo}>

{title_text}

          <Choices
            title={labelChoices1}
            selected={this.state.numberSelected}
            options={optionsChoices1}
            disabled={false}
            onChange={(option) => {
              this.setState({ selectedChoice1: option.target.value })
            }}
            classNames={['mb2']}
          />
          <Choices
            { ...this.props }
            title={labelChoicesA}
            selected={this.state.letterSelected}
            options={optionsChoicesA}
            disabled={!(selectedChoice1)}
            onChange={(option) => {
              this.setState({ selectedChoiceA: option.target.value })
            }}
            classNames={['mb2']}
          />
          <button
            className="match caps button bg-darken-4 p2 full-width mt1 mb2"
            onClick={::this.handleCombineClick}
            disabled={loading || !(selectedChoice1 && selectedChoiceA)}>
            {loading ? 'Combinando...' : 'Combinar' }
          </button>

      </OverlayWidget>
    )
  }

  findMatchItem() {
    const { widget } = this.props
    const matchList = widget.match_list.filter((match) => {
      return match.first_choice === this.state.selectedChoice1 && match.second_choice === this.state.selectedChoiceA
    })
    if (matchList && matchList.length > 0) {
      return matchList[0]
    }
  }

  renderShareButtons() {
    ////
    // @todo
    // - talvez prop `message` configurável?
    ////
    const matchItem = this.findMatchItem()
    const { selectedChoice1, selectedChoiceA } = this.state
    let combinationImageUrl = 'https://placeholdit.imgix.net/~text?txtsize=28&bg=e9e9e9&txtclr=364C55&txt=300%C3%97300&w=300&h=300&txt=Imagem%20n%C3%A3o%20configurada'
    let share = ''
    if (matchItem) {
      combinationImageUrl = matchItem.goal_image
      share = Paths.shareMatchWrapper(matchItem.widget_id, matchItem.id)
    }

    return <TellAFriend {...this.props}
      message="Resultado da sua combinação"
      href={ window.location.origin + share }
      imageUrl={combinationImageUrl}
      imageWidth="100%" />
  }

  render() {
    const { combined } = this.state
    return (

        { combined ? this.renderShareButtons() : this.renderChoices() }

    )
  }
}

MatchWidget.propTypes = {
  mobilization: PropTypes.object.isRequired,
  widget: PropTypes.object.isRequired
}

MatchWidget.contextTypes = {
  router: PropTypes.object.isRequired,
}

export default MatchWidget
<|endoftext|>


<commit_before>// 'use strict';
// var logger = require('logger');
// var should = require('should');
// var assert = require('assert');
// var StorySerializer = require('serializers/storySerializer');
//
// describe('Story serializer test', function() {
//     var story = {
//         name: 'pruebaRA',
//         title: 'titulo',
//         createdAt: '2016-04-12T15:41:38.000Z',
//         updatedAt: '2016-04-12T15:41:38.125Z',
//         id: '9',
//         visible: true,
//         details: 'Detalles',
//         date: '2012-07-10T00:00:00.000Z',
//         email: 'raul.requero@vizzuality.com',
//         location: 'Segovia',
//         userId: 'aaaa',
//         media: [{
//             url: '',
//             embed_url: '',
//             preview_url: '',
//             mime_type: 'image/jpeg',
//             order: 0
//         }, {
//             url: '20131022123544995734_20.jpg',
//             embed_url: '',
//             preview_url: 'thumb_20131022123544995734_20.jpg',
//             mime_type: 'image/jpeg',
//             order: 1
//         }],
//         lat: 40.4344902028538,
//         lng: -3.70132373942569
//     };
//
//
//     before(function*() {
//
//     });
//
//     it('Generate correct jsonapi response of the story', function() {
//         let response = StorySerializer.serialize(story);
//         response.should.not.be.a.Array();
//         response.should.have.property('data');
//         let data = response.data;
//         data.should.have.property('type');
//         data.should.have.property('attributes');
//         data.should.have.property('id');
//         data.type.should.equal('story');
//         data.id.should.equal(story.id);
//         data.attributes.should.have.property('name');
//         data.attributes.should.have.property('title');
//         data.attributes.should.have.property('createdAt');
//         data.attributes.should.have.property('updatedAt');
//         data.attributes.should.have.property('visible');
//         data.attributes.should.have.property('details');
//         data.attributes.should.have.property('date');
//         data.attributes.should.have.property('email');
//         data.attributes.should.have.property('location');
//         data.attributes.should.have.property('userId');
//         data.attributes.should.have.property('media');
//
//         data.attributes.name.should.be.equal(story.name);
//         data.attributes.title.should.be.equal(story.title);
//         data.attributes.createdAt.should.be.equal(story.createdAt);
//         data.attributes.updatedAt.should.be.equal(story.updatedAt);
//         data.attributes.visible.should.be.equal(story.visible);
//         data.attributes.details.should.be.equal(story.details);
//         data.attributes.date.should.be.equal(story.date);
//         data.attributes.email.should.be.equal(story.email);
//         data.attributes.location.should.be.equal(story.location);
//         data.attributes.userId.should.be.equal(story.userId);
//         data.attributes.media.should.be.length(story.media.length);
//
//     });
//
//
//     after(function*() {
//
//     });
// });
<commit_msg>remove unneccesary file<commit_after><|endoftext|>


<commit_before>/**
 * AngularJS module connections, used for displaying a modal with a mini-search interface
 * This module depends on the outter container has ng-app="connections" and ng-controller="openConnections"
 *
 *
 * @requires portal-filters infinite-scroll modules
 * @author Minh Duc Nguyen <minh.nguyen@ands.org.au>
 */
angular.module('connections',['portal-filters', 'infinite-scroll']).
/**
 * Search factory to use for solr searching, used default RDA search protocol
 * @param  module $http
 * @return promise
 */
factory('searches', function($http){
	return{
		search: function(filters){
			var promise = $http.post(base_url+'search/filter/', {'filters':filters}).then(function(response){
				return response.data;
			});
			return promise;
		}
	}
}).
/**
 * Default controller for connections module. This controller auto-fire on start
 * @param  $scope
 * @param  factory searches
 * @return void
 */
controller('openConnections', function($scope, searches){

	/**
	 * Default Scope assignment
	 * @type $rootScope
	 */
	$scope.results = {};
	$scope.filters = {};
	$scope.facet = {};
	$scope.query = '';
	$scope.facet_limit = 5;
	$scope.relations = [];
	$scope.page = 1;
	$scope.numFound = 0;
	$scope.loading = false;
	$scope.done = false;
	$scope.class_name = $('#class').text();

	/**
	 * Triggers when an action ng-click="open($event)" occur
	 * This will do a search then open the modal containing the search result
	 * @param event $event
	 * @return void
	 */
	$scope.open = function($event){

		/**
		 * The relation type is set within the target event
		 * This relation type will determine the class and type we will search for
		 */
		var relation_type = $($event.target).attr('relation_type');
		$scope.filters = {};
		switch(relation_type){
			case 'collection':
				$scope.filters['class'] = 'collection';
				delete $scope.filters['type'];
				break;
			case 'activity':
				$scope.filters['class'] = 'activity';
				delete $scope.filters['type'];
				break;
			case 'service':
				$scope.filters['class'] = 'service';
				delete $scope.filters['type'];
				break;
			case 'party_multi':
				$scope.filters['class'] = 'party';
				delete $scope.filters['group'];
				break;
			case 'party_one':
				$scope.filters['class'] = 'party';
				$scope.filters['type'] = 'person';
		}

		//search
		$scope.search();

		//dialog setup and open
		var c = $('#connections_layout_container');
		$('.ui-widget-overlay').live('click', function() {
			c.dialog( "close" );
		});

		c.dialog({
			width:900,
			modal:true
		});

		//Change the title of the dialog
		$('#ui-dialog-title-connections_layout_container').html($scope.getTitle());
	}

	/**
	 * Helper function to return the title for displaying on the dialog
	 * @return string
	 */
	$scope.getTitle = function(){
		if($scope.filters['class']=='collection'){
			return 'Related Collections';
		}else if($scope.filters['class']=='activity'){
			return 'Related Activities';
		}else if($scope.filters['class']=='service'){
			return 'Related Services';
		}else if($scope.filters['class']=='party'){
			if($scope.filters['type']=='person'){
				return 'Related Researchers';
			}else if($scope.filters['type']=='group'){
				return 'Related Organisations & Groups';
			}
		}else{
			return 'Related Objects';
		}
	}

	/**
	 * Watch every instance changes of $scope.query
	 * and do a search accordingly
	 * @return void
	 */
	$scope.$watch('query', function(){
		$scope.filters['q'] = $scope.query;
        $scope.search();
	});

	/**
	 * Watch every instance change of the result set
	 * If we have enough result then stop searching
	 * @return $scope.done
	 */
	$scope.$watch('results.docs', function(){
		var total_found = $('.ro_preview').length;
		if($scope.results && $scope.results.docs && $scope.numFound <= $scope.results.docs.length){
			$scope.done = true;
		}
	}, true);

	/**
	 * Load the next page and append it to the result set
	 * This function requires the dialog to be open, there's more to search and not currently doing a search
	 * @return void
	 */
	$scope.load_more = function(){
		if(($('#connections_layout_container').dialog('isOpen')===true) && !$scope.done && !$scope.loading){
			$scope.loading = true;
			var ro_id = $('#registry_object_id').text();
			$scope.page++;
			$scope.filters['related_object_id'] = ro_id;
			$scope.filters['include_facet_subjects'] = 1;
			$scope.filters['p'] = $scope.page;
			searches.search($scope.filters).then(function(data){
				$scope.loading = false;
				$.each(data.result.docs, function(){
					$scope.results.docs.push(this);
				});
				$scope.getRelations();
			});
		}
	}

	/**
	 * Select a facet
	 * Change variables then redo the search
	 * @param  string type
	 * @param  string value
	 * @return $scope.search
	 */
	$scope.select = function(type, value){
		$scope.filters[type] = value;
		$scope.search();
	}

	/**
	 * Deselect a facet
	 * Delete the variable then redo the search
	 * @param  string type
	 * @return $scope.search
	 */
	$scope.deselect = function(type){
		delete $scope.filters[type];
		$scope.search();
	}

	/**
	 * Check if a value type pair is selected
	 * @param  facet_type type
	 * @param  value v
	 * @return boolean
	 */
	$scope.infacet = function(type, v){
		if($scope.filters[type]==v.title){
			return true;
		}else return false;
	}

	/**
	 * Actual Search function
	 * Used registry_object_id from the DOM as related_object_id restraint
	 * Include subject facets
	 *
	 * @return result set
	 */
	$scope.search = function(){
		var ro_id = $('#registry_object_id').text();
		$scope.page = 1;
		$scope.done = false;
		$scope.filters['related_object_id'] = ro_id;
		$scope.filters['include_facet_subjects'] = 1;
		$scope.filters['p'] = $scope.page;
		searches.search($scope.filters).then(function(data){
			$scope.numFound = data.numFound;
			$scope.relations = [];
			$scope.results = data.result;
			$scope.facet = data.facet_result;
			$scope.getRelations();
		});
	}

	/**
	 * Update the relation array, for use in displaying relations next to search result
	 * Works by matching the registry object id pair to the relation and relation class
	 * Filters are utilized in the front end
	 * @return void
	 */
	$scope.getRelations = function(){
		var ro_id = $('#registry_object_id').text();
		$.each($scope.results.docs, function(){
			var ind = this.related_object_id.indexOf(ro_id);
			var relation = this.related_object_relation[ind];
			var related_class = this.related_object_class[ind];
			$scope.relations[this.id] = {related_relation:relation, related_class:related_class};
		});
	}
});<commit_msg>Fix - Encoding for subjects in connections explorer<commit_after>/**
 * AngularJS module connections, used for displaying a modal with a mini-search interface
 * This module depends on the outter container has ng-app="connections" and ng-controller="openConnections"
 *
 *
 * @requires portal-filters infinite-scroll modules
 * @author Minh Duc Nguyen <minh.nguyen@ands.org.au>
 */
angular.module('connections',['portal-filters', 'infinite-scroll']).
/**
 * Search factory to use for solr searching, used default RDA search protocol
 * @param  module $http
 * @return promise
 */
factory('searches', function($http){
	return{
		search: function(filters){
			var promise = $http.post(base_url+'search/filter/', {'filters':filters}).then(function(response){
				return response.data;
			});
			return promise;
		}
	}
}).
/**
 * Default controller for connections module. This controller auto-fire on start
 * @param  $scope
 * @param  factory searches
 * @return void
 */
controller('openConnections', function($scope, searches){

	/**
	 * Default Scope assignment
	 * @type $rootScope
	 */
	$scope.results = {};
	$scope.filters = {};
	$scope.facet = {};
	$scope.query = '';
	$scope.facet_limit = 5;
	$scope.relations = [];
	$scope.page = 1;
	$scope.numFound = 0;
	$scope.loading = false;
	$scope.done = false;
	$scope.class_name = $('#class').text();

	/**
	 * Triggers when an action ng-click="open($event)" occur
	 * This will do a search then open the modal containing the search result
	 * @param event $event
	 * @return void
	 */
	$scope.open = function($event){

		/**
		 * The relation type is set within the target event
		 * This relation type will determine the class and type we will search for
		 */
		var relation_type = $($event.target).attr('relation_type');
		$scope.filters = {};
		switch(relation_type){
			case 'collection':
				$scope.filters['class'] = 'collection';
				delete $scope.filters['type'];
				break;
			case 'activity':
				$scope.filters['class'] = 'activity';
				delete $scope.filters['type'];
				break;
			case 'service':
				$scope.filters['class'] = 'service';
				delete $scope.filters['type'];
				break;
			case 'party_multi':
				$scope.filters['class'] = 'party';
				delete $scope.filters['group'];
				break;
			case 'party_one':
				$scope.filters['class'] = 'party';
				$scope.filters['type'] = 'person';
		}

		//search
		$scope.search();

		//dialog setup and open
		var c = $('#connections_layout_container');
		$('.ui-widget-overlay').live('click', function() {
			c.dialog( "close" );
		});

		c.dialog({
			width:900,
			modal:true
		});

		//Change the title of the dialog
		$('#ui-dialog-title-connections_layout_container').html($scope.getTitle());
	}

	/**
	 * Helper function to return the title for displaying on the dialog
	 * @return string
	 */
	$scope.getTitle = function(){
		if($scope.filters['class']=='collection'){
			return 'Related Collections';
		}else if($scope.filters['class']=='activity'){
			return 'Related Activities';
		}else if($scope.filters['class']=='service'){
			return 'Related Services';
		}else if($scope.filters['class']=='party'){
			if($scope.filters['type']=='person'){
				return 'Related Researchers';
			}else if($scope.filters['type']=='group'){
				return 'Related Organisations & Groups';
			}
		}else{
			return 'Related Objects';
		}
	}

	/**
	 * Watch every instance changes of $scope.query
	 * and do a search accordingly
	 * @return void
	 */
	$scope.$watch('query', function(){
		$scope.filters['q'] = $scope.query;
        $scope.search();
        if($scope.results && $scope.results.docs && $scope.numFound <= $scope.results.docs.length){
            $scope.done = true;
        }
	});

	/**
	 * Watch every instance change of the result set
	 * If we have enough result then stop searching
	 * @return $scope.done
	 */
	$scope.$watch('results.docs', function(){
		var total_found = $('.ro_preview').length;
		if($scope.results && $scope.results.docs && $scope.numFound <= $scope.results.docs.length){
			$scope.done = true;
		}
        console.log(!$scope.done && !$scope.loading);
	}, true);

	/**
	 * Load the next page and append it to the result set
	 * This function requires the dialog to be open, there's more to search and not currently doing a search
	 * @return void
	 */
	$scope.load_more = function(){
		if(($('#connections_layout_container').dialog('isOpen')===true) && !$scope.done && !$scope.loading){
			$scope.loading = true;
			var ro_id = $('#registry_object_id').text();
			$scope.page++;
			$scope.filters['related_object_id'] = ro_id;
			$scope.filters['include_facet_subjects'] = 1;
			$scope.filters['p'] = $scope.page;
			searches.search($scope.filters).then(function(data){
				$scope.loading = false;
				$.each(data.result.docs, function(){
					$scope.results.docs.push(this);
				});
				$scope.getRelations();
			});
		}
	}

	/**
	 * Select a facet
	 * Change variables then redo the search
	 * @param  string type
	 * @param  string value
	 * @return $scope.search
	 */
	$scope.select = function(type, value){
		$scope.filters[type] = value;
		$scope.search();
	}

	/**
	 * Deselect a facet
	 * Delete the variable then redo the search
	 * @param  string type
	 * @return $scope.search
	 */
	$scope.deselect = function(type){
		delete $scope.filters[type];
		$scope.search();
	}

	/**
	 * Check if a value type pair is selected
	 * @param  facet_type type
	 * @param  value v
	 * @return boolean
	 */
	$scope.infacet = function(type, v){
		if($scope.filters[type]==v.title){
			return true;
		}else return false;
	}

	/**
	 * Actual Search function
	 * Used registry_object_id from the DOM as related_object_id restraint
	 * Include subject facets
	 *
	 * @return result set
	 */
	$scope.search = function(){
		var ro_id = $('#registry_object_id').text();
		$scope.page = 1;
		$scope.done = false;
		$scope.filters['related_object_id'] = ro_id;
		$scope.filters['include_facet_subjects'] = 1;
		$scope.filters['p'] = $scope.page;
		searches.search($scope.filters).then(function(data){
			$scope.numFound = data.numFound;
			$scope.relations = [];
			$scope.results = data.result;
			$scope.facet = data.facet_result;
            $.each($scope.facet, function(){
                $.each(this.values, function(){
                    this.title = this.title.replace(/>/g, '>');
                });
            });
			$scope.getRelations();
		});
	}

	/**
	 * Update the relation array, for use in displaying relations next to search result
	 * Works by matching the registry object id pair to the relation and relation class
	 * Filters are utilized in the front end
	 * @return void
	 */
	$scope.getRelations = function(){
		var ro_id = $('#registry_object_id').text();
		$.each($scope.results.docs, function(){
			var ind = this.related_object_id.indexOf(ro_id);
			var relation = this.related_object_relation[ind];
			var related_class = this.related_object_class[ind];
			$scope.relations[this.id] = {related_relation:relation, related_class:related_class};
		});
	}
});<|endoftext|>


<commit_before>var Vec3 = require('./Vec3');
var Vec4 = require('./Vec4');

var EPSILON = Math.pow(2, -24);

var Y_AXIS = [0,1,0];
var TEMP_VEC3_0 = [0,0,0];
var TEMP_VEC3_1 = [0,0,0];
var TEMP_VEC3_2 = [0,0,0];
var TEMP_VEC3_3 = [0,0,0];

function create() {
    return [0, 0, 0, 1];
}

function equals(a,b) {
    return a[0] == b[0] &&
           a[1] == b[1] &&
           a[2] == b[2] &&
           a[3] == b[3];
}

function identity(a){
    a[0] = a[1] = a[2] = 0.0;
    a[3] = 1.0;
    return a;
}

function copy(a){
    return a.slice(0);
}

function set(a,b){
    a[0] = b[0];
    a[1] = b[1];
    a[2] = b[2];
    a[3] = b[3];
    return a;
}

function set4(a,x,y,z,w){
    a[0] = x;
    a[1] = y;
    a[2] = z;
    a[3] = w;
    return a;
}

function mult(a,b){
    var ax = a[0];
    var ay = a[1];
    var az = a[2];
    var aw = a[3];
    var bx = b[0];
    var by = b[1];
    var bz = b[2];
    var bw = b[3];

    a[0] = aw * bx + ax * bw + ay * bz - az * by;
    a[1] = aw * by + ay * bw + az * bx - ax * bz;
    a[2] = aw * bz + az * bw + ax * by - ay * bx;
    a[3] = aw * bw - ax * bx - ay * by - az * bz;

    return a;
}

function length(a){
    var x = a[0];
    var y = a[1];
    var z = a[2];
    var w = a[3];
    return Math.sqrt(x * x + y * y + z * z + w * w);
}

function normalize(a){
    var l = length(a);
    if(l > EPSILON){
        l = 1.0 / l;
        a[0] *= l;
        a[1] *= l;
        a[2] *= l;
        a[3] *= l;
    }
    return a;
}

function dot(a,b){
    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}

function setAxisAngle3(a, angle, x, y, z){
    var angle_2 = angle * 0.5;
    var sin_2   = Math.sin(angle_2);
    a[0] = x * sin_2;
    a[1] = y * sin_2;
    a[2] = z * sin_2;
    a[3] = Math.cos(angle_2);
    return normalize(a);
}

function setAxisAngle(a, angle, v){
    return setAxisAngle3(a, angle, v[0], v[1], v[2]);
}

function fromMat39(a, m0, m1, m2,
                      m3, m4, m5,
                      m6, m7, m8){

    var trace = m0 + m4 + m8;
    var s;

    if(trace >= 0){
        s = Math.sqrt(trace + 1);
        a[3] = 0.5 * s;
        s = 0.5 / s;
        a[0] = (m5 - m7) * s;
        a[1] = (m6 - m2) * s;
        a[2] = (m1 - m3) * s;

    }
    else if ((m0 > m4) && (m0 > m8)) {
        s = Math.sqrt(1.0 + m0 - m4 - m8);
        a[0] = s * 0.5;
        s = 0.5 / s;
        a[1] = (m1 + m3) * s;
        a[2] = (m6 + m2) * s;
        a[3] = (m5 - m7) * s;

    }
    else if (m4 > m8) {
        s = Math.sqrt(1.0 + m4 - m0 - m8);
        a[1] = s * 0.5;
        s = 0.5 / s;
        a[0] = (m1 + m3) * s;
        a[2] = (m5 + m7) * s;
        a[3] = (m6 - m2) * s;

    }
    else {
        s = Math.sqrt(1.0 + m8 - m0 - m4);
        a[2] = s * 0.5;
        s = 0.5 / s;
        a[0] = (m6 + m2) * s;
        a[1] = (m5 + m7) * s;
        a[3] = (m1 - m3) * s;
    }
    return a;
}

function fromMat3(a, m){
    return fromMat39(a, m[0], m[1], m[2],
        m[3], m[4], m[5],
        m[6], m[7], m[8]);
}

function fromMat4(a, m){
    return fromMat39(a, m[ 0], m[ 1], m[ 2],
        m[ 4], m[ 5], m[ 6],
        m[ 8], m[ 9], m[10]);
}

function setAxes9(a, xx, xy, xz, yx, yy, yz, zx, zy, zz){
    return fromMat39(a, xx, xy, xz, yx, yy, yz, zx, zy, zz);
}

function setAxes(a, x, y, z){
    return setAxes9(a, x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]);
}

function getAngle(a){
    return Math.acos(a[3]) * 2.0;
}

function getAxisAngle(a, out){
    out[3] = getAngle(a);
    getAxis(a,out);
    return out;
}

function fromDirection(a, direction, up){
    up = Vec3.set(TEMP_VEC3_0,up === undefined ? Y_AXIS : up);

    var tangent   = TEMP_VEC3_1;
    var normal    = TEMP_VEC3_2;
    var bitangent = TEMP_VEC3_3;

    tangent   = Vec3.normalize(Vec3.set(tangent,direction));
    bitangent = Vec3.normalize(Vec3.cross(Vec3.set(bitangent,up),tangent));

    normal    = Vec3.cross(Vec3.set(normal,tangent),bitangent);

    return setAxes(a, bitangent, normal, tangent);
}

function fromTo9(a, fromx, fromy, fromz, tox, toy, toz, upx, upy, upz){
    var from      = Vec3.set3(TEMP_VEC3_0,fromx,fromy,fromz);
    var to        = Vec3.set3(TEMP_VEC3_1,tox,toy,toz);
    var direction = Vec3.normalize(Vec3.sub(to,from));
    var up        = Vec3.set3(TEMP_VEC3_2,upx,upy,upz);

    return fromDirection(a, direction, up);
}

function fromTo(a, from, to, up){
    return fromTo9(a, from[0], from[1], from[2], to[0], to[1], to[2], up[0], up[1], up[2]);
}

function getAxis(a,out){
    var w = a[3];
    var s = 1.0 / Math.sqrt(1.0 - w * w);
    out[0] = a[0] * s;
    out[1] = a[1] * s;
    out[2] = a[2] * s;
    return out;
}

function slerp(a,b,t){
    //http://jsperf.com/quaternion-slerp-implementations
    var ax = a[0];
    var ay = a[1];
    var az = a[2];
    var aw = a[3];
    var bx = b[0];
    var by = b[1];
    var bz = b[2];
    var bw = b[3];

    var omega, cosom, sinom, scale0, scale1;

    cosom = dot(a,b);

    if ( cosom < 0.0 ) {
        cosom = -cosom;
        a[0] = - bx;
        a[1] = - by;
        a[2] = - bz;
        a[3] = - bw;
    } else  {
        a[0] = bx;
        a[1] = by;
        a[2] = bz;
        a[3] = bw;
    }

    if ( (1.0 - cosom) > 0.000001 ) {
        omega = Math.acos(cosom);
        sinom = Math.sin(omega);
        scale0 = Math.sin((1.0 - t) * omega) / sinom;
        scale1 = Math.sin(t * omega) / sinom;
    } else {
        scale0 = 1.0 - t;
        scale1 = t;
    }

    a[0] = scale0 * ax + scale1 * a[0];
    a[1] = scale0 * ay + scale1 * a[1];
    a[2] = scale0 * az + scale1 * a[2];
    a[3] = scale0 * aw + scale1 * a[3];
    return a;
}

var Quat = {
    create : create,
    equals : equals,
    identity : identity,
    copy : copy,
    set  : set,
    set4 : set4,
    mult : mult,
    dot : dot,
    length : length,
    normalize : normalize,
    setAxisAngle3 : setAxisAngle3,
    setAxisAngle  : setAxisAngle,
    fromMat3 : fromMat3,
    fromMat4 : fromMat4,
    setAxes9 : setAxes9,
    setAxes  : setAxes,
    getAngle : getAngle,
    getAxis  : getAxis,
    getAxisAngle : getAxisAngle,
    fromDirection : fromDirection,
    slerp : slerp,
    fromTo9 : fromTo9,
    fromTo  : fromTo
};

module.exports = Quat;
<commit_msg>Quat added invert<commit_after>var Vec3 = require('./Vec3');
var Vec4 = require('./Vec4');

var EPSILON = Math.pow(2, -24);

var Y_AXIS = [0,1,0];
var TEMP_VEC3_0 = [0,0,0];
var TEMP_VEC3_1 = [0,0,0];
var TEMP_VEC3_2 = [0,0,0];
var TEMP_VEC3_3 = [0,0,0];

function create() {
    return [0, 0, 0, 1];
}

function equals(a,b) {
    return a[0] == b[0] &&
           a[1] == b[1] &&
           a[2] == b[2] &&
           a[3] == b[3];
}

function identity(a){
    a[0] = a[1] = a[2] = 0.0;
    a[3] = 1.0;
    return a;
}

function copy(a){
    return a.slice(0);
}

function set(a,b){
    a[0] = b[0];
    a[1] = b[1];
    a[2] = b[2];
    a[3] = b[3];
    return a;
}

function set4(a,x,y,z,w){
    a[0] = x;
    a[1] = y;
    a[2] = z;
    a[3] = w;
    return a;
}

function mult(a,b){
    var ax = a[0];
    var ay = a[1];
    var az = a[2];
    var aw = a[3];
    var bx = b[0];
    var by = b[1];
    var bz = b[2];
    var bw = b[3];

    a[0] = aw * bx + ax * bw + ay * bz - az * by;
    a[1] = aw * by + ay * bw + az * bx - ax * bz;
    a[2] = aw * bz + az * bw + ax * by - ay * bx;
    a[3] = aw * bw - ax * bx - ay * by - az * bz;

    return a;
}

function invert(a) {
    var l = dot(a,a);
    l = l ? 1.0 / l : 0.0;

    a[0] *= -l;
    a[1] *= -l;
    a[2] *= -l;
    a[3] *=  l;
    return a;
}

function length(a){
    var x = a[0];
    var y = a[1];
    var z = a[2];
    var w = a[3];
    return Math.sqrt(x * x + y * y + z * z + w * w);
}

function normalize(a){
    var l = length(a);
    if(l > EPSILON){
        l = 1.0 / l;
        a[0] *= l;
        a[1] *= l;
        a[2] *= l;
        a[3] *= l;
    }
    return a;
}

function dot(a,b){
    return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
}

function setAxisAngle3(a, angle, x, y, z){
    var angle_2 = angle * 0.5;
    var sin_2   = Math.sin(angle_2);
    a[0] = x * sin_2;
    a[1] = y * sin_2;
    a[2] = z * sin_2;
    a[3] = Math.cos(angle_2);
    return normalize(a);
}

function setAxisAngle(a, angle, v){
    return setAxisAngle3(a, angle, v[0], v[1], v[2]);
}

function fromMat39(a, m0, m1, m2,
                      m3, m4, m5,
                      m6, m7, m8){

    var trace = m0 + m4 + m8;
    var s;

    if(trace >= 0){
        s = Math.sqrt(trace + 1);
        a[3] = 0.5 * s;
        s = 0.5 / s;
        a[0] = (m5 - m7) * s;
        a[1] = (m6 - m2) * s;
        a[2] = (m1 - m3) * s;

    }
    else if ((m0 > m4) && (m0 > m8)) {
        s = Math.sqrt(1.0 + m0 - m4 - m8);
        a[0] = s * 0.5;
        s = 0.5 / s;
        a[1] = (m1 + m3) * s;
        a[2] = (m6 + m2) * s;
        a[3] = (m5 - m7) * s;

    }
    else if (m4 > m8) {
        s = Math.sqrt(1.0 + m4 - m0 - m8);
        a[1] = s * 0.5;
        s = 0.5 / s;
        a[0] = (m1 + m3) * s;
        a[2] = (m5 + m7) * s;
        a[3] = (m6 - m2) * s;

    }
    else {
        s = Math.sqrt(1.0 + m8 - m0 - m4);
        a[2] = s * 0.5;
        s = 0.5 / s;
        a[0] = (m6 + m2) * s;
        a[1] = (m5 + m7) * s;
        a[3] = (m1 - m3) * s;
    }
    return a;
}

function fromMat3(a, m){
    return fromMat39(a, m[0], m[1], m[2],
        m[3], m[4], m[5],
        m[6], m[7], m[8]);
}

function fromMat4(a, m){
    return fromMat39(a, m[ 0], m[ 1], m[ 2],
        m[ 4], m[ 5], m[ 6],
        m[ 8], m[ 9], m[10]);
}

function setAxes9(a, xx, xy, xz, yx, yy, yz, zx, zy, zz){
    return fromMat39(a, xx, xy, xz, yx, yy, yz, zx, zy, zz);
}

function setAxes(a, x, y, z){
    return setAxes9(a, x[0], x[1], x[2], y[0], y[1], y[2], z[0], z[1], z[2]);
}

function getAngle(a){
    return Math.acos(a[3]) * 2.0;
}

function getAxisAngle(a, out){
    out[3] = getAngle(a);
    getAxis(a,out);
    return out;
}

function fromDirection(a, direction, up){
    up = Vec3.set(TEMP_VEC3_0,up === undefined ? Y_AXIS : up);

    var tangent   = TEMP_VEC3_1;
    var normal    = TEMP_VEC3_2;
    var bitangent = TEMP_VEC3_3;

    tangent   = Vec3.normalize(Vec3.set(tangent,direction));
    bitangent = Vec3.normalize(Vec3.cross(Vec3.set(bitangent,up),tangent));

    normal    = Vec3.cross(Vec3.set(normal,tangent),bitangent);

    return setAxes(a, bitangent, normal, tangent);
}

function fromTo9(a, fromx, fromy, fromz, tox, toy, toz, upx, upy, upz){
    var from      = Vec3.set3(TEMP_VEC3_0,fromx,fromy,fromz);
    var to        = Vec3.set3(TEMP_VEC3_1,tox,toy,toz);
    var direction = Vec3.normalize(Vec3.sub(to,from));
    var up        = Vec3.set3(TEMP_VEC3_2,upx,upy,upz);

    return fromDirection(a, direction, up);
}

function fromTo(a, from, to, up){
    return fromTo9(a, from[0], from[1], from[2], to[0], to[1], to[2], up[0], up[1], up[2]);
}

function getAxis(a,out){
    var w = a[3];
    var s = 1.0 / Math.sqrt(1.0 - w * w);
    out[0] = a[0] * s;
    out[1] = a[1] * s;
    out[2] = a[2] * s;
    return out;
}

function slerp(a,b,t){
    //http://jsperf.com/quaternion-slerp-implementations
    var ax = a[0];
    var ay = a[1];
    var az = a[2];
    var aw = a[3];
    var bx = b[0];
    var by = b[1];
    var bz = b[2];
    var bw = b[3];

    var omega, cosom, sinom, scale0, scale1;

    cosom = dot(a,b);

    if ( cosom < 0.0 ) {
        cosom = -cosom;
        a[0] = - bx;
        a[1] = - by;
        a[2] = - bz;
        a[3] = - bw;
    } else  {
        a[0] = bx;
        a[1] = by;
        a[2] = bz;
        a[3] = bw;
    }

    if ( (1.0 - cosom) > 0.000001 ) {
        omega = Math.acos(cosom);
        sinom = Math.sin(omega);
        scale0 = Math.sin((1.0 - t) * omega) / sinom;
        scale1 = Math.sin(t * omega) / sinom;
    } else {
        scale0 = 1.0 - t;
        scale1 = t;
    }

    a[0] = scale0 * ax + scale1 * a[0];
    a[1] = scale0 * ay + scale1 * a[1];
    a[2] = scale0 * az + scale1 * a[2];
    a[3] = scale0 * aw + scale1 * a[3];
    return a;
}

var Quat = {
    create : create,
    equals : equals,
    identity : identity,
    copy : copy,
    set  : set,
    set4 : set4,
    mult : mult,
    invert : invert,
    dot : dot,
    length : length,
    normalize : normalize,
    setAxisAngle3 : setAxisAngle3,
    setAxisAngle  : setAxisAngle,
    fromMat3 : fromMat3,
    fromMat4 : fromMat4,
    setAxes9 : setAxes9,
    setAxes  : setAxes,
    getAngle : getAngle,
    getAxis  : getAxis,
    getAxisAngle : getAxisAngle,
    fromDirection : fromDirection,
    slerp : slerp,
    fromTo9 : fromTo9,
    fromTo  : fromTo
};

module.exports = Quat;
<|endoftext|>


<commit_before><commit_msg>推送数据修改<commit_after><|endoftext|>


<commit_before>const Message = require('primea-message')
const CapsManager = require('./capsManager.js')
const Inbox = require('./inbox.js')

module.exports = class Actor {
  /**
   * the Kernel manages the varous message passing functions and provides
   * an interface for the containers to use
   * @param {Object} opts
   * @param {Object} opts.id - the UUID of the Kernel
   * @param {Object} opts.state - the state of the container
   * @param {Object} opts.hypervisor - the instance of the hypervisor
   * @param {Object} opts.container - the container constuctor and argments
   */
  constructor (opts) {
    this.state = opts.state.value
    this.code = opts.state.value.code
    this.treeNode = opts.state.node
    this.hypervisor = opts.hypervisor
    this.id = opts.id
    this.container = new opts.container.Constructor(this, opts.container.args)
    this.inbox = new Inbox({
      actor: this,
      hypervisor: opts.hypervisor
    })

    this.ticks = 0
    this.containerState = 'idle'

    this.caps = new CapsManager(opts.state.caps)
  }

  /**
   * Mints a new capabilitly with a given tag
   * @param {*} tag - a tag which can be used to identify caps
   * @return {Object}
   */
  mintCap (tag = 0) {
    return {
      destId: this.id,
      tag: tag
    }
  }

  /**
   * adds a message to this containers message queue
   * @param {string} portName
   * @param {object} message
   */
  queue (message) {
    this.inbox.queue(message)
    this._startMessageLoop()
  }

  /**
   * runs the creation routine for the actor
   * @param {object} message
   * @returns {Promise}
   */
  async create (message) {
    await this.message(message, 'onCreation')
    this._startMessageLoop()
  }

  // waits for the next message
  async _startMessageLoop () {
    // this ensure we only every have one loop running at a time
    if (this.containerState !== 'running') {
      this.containerState = 'running'
      while (1) {
        const message = await this.inbox.getNextMessage()
        if (!message) break

        // if the message we recived had more ticks then we currently have then
        // update it
        if (message._fromTicks > this.ticks) {
          this.ticks = message._fromTicks
          this.hypervisor.scheduler.update(this)
        }
        // run the next message
        await this.message(message)
      }

      this.containerState = 'idle'
      this.container.onIdle()
    }
  }

  /**
   * Runs the shutdown routine for the actor
   */
  shutdown () {
    this.hypervisor.scheduler.done(this.id)
  }

  /**
   * Runs the startup routine for the actor
   */
  startup () {
    return this.container.onStartup()
  }

  /**
   * run the Actor with a given message
   * @param {object} message - the message to run
   * @param {String} method - which method to run
   * @returns {Promise}
   */
  async message (message, method = 'onMessage') {
    const responseCap = message.responseCap
    delete message.responseCap

    let result
    try {
      result = await this.container[method](message)
    } catch (e) {
      console.log(e)
      result = {
        exception: true,
        exceptionError: e
      }
    }

    if (responseCap) {
      this.send(responseCap, new Message({
        data: result
      }))
    }
  }

  /**
   * updates the number of ticks that the container has run
   * @param {Number} count - the number of ticks to add
   */
  incrementTicks (count) {
    this.ticks += count
    this.hypervisor.scheduler.update(this)
  }

  /**
   * creates an actor
   * @param {Integer} type - the type id for the container
   * @param {Object} message - an intial [message](https://github.com/primea/js-primea-message) to send newly created actor
   */
  createActor (type, message) {
    const id = this._generateNextId()
    return this.hypervisor.createActor(type, message, id)
  }

  _generateNextId () {
    const id = {
      nonce: this.state.nonce,
      parent: this.id
    }

    this.state.nonce++
    return id
  }

  /**
   * sends a message to a given port
   * @param {Object} portRef - the port
   * @param {Message} message - the message
   */
  send (cap, message) {
    message._fromTicks = this.ticks
    message._fromId = this.id
    message.tag = cap.tag

    return this.hypervisor.send(cap, message)
  }
}
<commit_msg>kernel -> actor<commit_after>const Message = require('primea-message')
const CapsManager = require('./capsManager.js')
const Inbox = require('./inbox.js')

module.exports = class Actor {
  /**
   * the Actor manages the varous message passing functions and provides
   * an interface for the containers to use
   * @param {Object} opts
   * @param {Object} opts.id - the UUID of the Actor
   * @param {Object} opts.state - the state of the container
   * @param {Object} opts.hypervisor - the instance of the hypervisor
   * @param {Object} opts.container - the container constuctor and argments
   */
  constructor (opts) {
    this.state = opts.state.value
    this.code = opts.state.value.code
    this.treeNode = opts.state.node
    this.hypervisor = opts.hypervisor
    this.id = opts.id
    this.container = new opts.container.Constructor(this, opts.container.args)
    this.inbox = new Inbox({
      actor: this,
      hypervisor: opts.hypervisor
    })

    this.ticks = 0
    this.containerState = 'idle'

    this.caps = new CapsManager(opts.state.caps)
  }

  /**
   * Mints a new capabilitly with a given tag
   * @param {*} tag - a tag which can be used to identify caps
   * @return {Object}
   */
  mintCap (tag = 0) {
    return {
      destId: this.id,
      tag: tag
    }
  }

  /**
   * adds a message to this containers message queue
   * @param {string} portName
   * @param {object} message
   */
  queue (message) {
    this.inbox.queue(message)
    this._startMessageLoop()
  }

  /**
   * runs the creation routine for the actor
   * @param {object} message
   * @returns {Promise}
   */
  async create (message) {
    await this.message(message, 'onCreation')
    this._startMessageLoop()
  }

  // waits for the next message
  async _startMessageLoop () {
    // this ensure we only every have one loop running at a time
    if (this.containerState !== 'running') {
      this.containerState = 'running'
      while (1) {
        const message = await this.inbox.getNextMessage()
        if (!message) break

        // if the message we recived had more ticks then we currently have then
        // update it
        if (message._fromTicks > this.ticks) {
          this.ticks = message._fromTicks
          this.hypervisor.scheduler.update(this)
        }
        // run the next message
        await this.message(message)
      }

      this.containerState = 'idle'
      this.container.onIdle()
    }
  }

  /**
   * Runs the shutdown routine for the actor
   */
  shutdown () {
    this.hypervisor.scheduler.done(this.id)
  }

  /**
   * Runs the startup routine for the actor
   */
  startup () {
    return this.container.onStartup()
  }

  /**
   * run the Actor with a given message
   * @param {object} message - the message to run
   * @param {String} method - which method to run
   * @returns {Promise}
   */
  async message (message, method = 'onMessage') {
    const responseCap = message.responseCap
    delete message.responseCap

    let result
    try {
      result = await this.container[method](message)
    } catch (e) {
      console.log(e)
      result = {
        exception: true,
        exceptionError: e
      }
    }

    if (responseCap) {
      this.send(responseCap, new Message({
        data: result
      }))
    }
  }

  /**
   * updates the number of ticks that the container has run
   * @param {Number} count - the number of ticks to add
   */
  incrementTicks (count) {
    this.ticks += count
    this.hypervisor.scheduler.update(this)
  }

  /**
   * creates an actor
   * @param {Integer} type - the type id for the container
   * @param {Object} message - an intial [message](https://github.com/primea/js-primea-message) to send newly created actor
   */
  createActor (type, message) {
    const id = this._generateNextId()
    return this.hypervisor.createActor(type, message, id)
  }

  _generateNextId () {
    const id = {
      nonce: this.state.nonce,
      parent: this.id
    }

    this.state.nonce++
    return id
  }

  /**
   * sends a message to a given port
   * @param {Object} portRef - the port
   * @param {Message} message - the message
   */
  send (cap, message) {
    message._fromTicks = this.ticks
    message._fromId = this.id
    message.tag = cap.tag

    return this.hypervisor.send(cap, message)
  }
}
<|endoftext|>


<commit_before>var AWS      = require('aws-sdk');
var config   = require('./config');
var fs       = require('fs');
var tmp      = require('tmp');
var processx = require('child_process');
var when     = require('when');
var nodefn   = require('when/node/function');
var es       = require('event-stream');
var request  = require('superagent');
var ipp      = require('ipp');
var _        = require('underscore');
var diacritics = require('diacritics');

function AgentClass() {

    var SQS = new AWS.SQS({
        accessKeyId: config.awsAccessKeys.global.accessKeyId,
        secretAccessKey: config.awsAccessKeys.global.secretAccessKey,
        region: 'us-east-1',
        apiVersion: '2012-11-05',
    });

    //============================================================
    //
    //
    //============================================================
    function selectQueue(message)
    {
        var box = normalize(message.box);

        if(message.anonymous) // For printshop
            return 'ipp://localhost:631/classes/printshop';

        return 'ipp://localhost:631/classes/default';
    }

    //============================================================
    //
    //
    //============================================================
    this.processMessage = function processMessage(message) {

        message = JSON.parse(JSON.stringify(message));//fullclone object;

        message.printerUri = message.printerUri || selectQueue(message);

        console.log('Processing:', message);

        var filenames = [ nodefn.call(tmp.tmpName, { postfix: '.pdf'       } ),
                          nodefn.call(tmp.tmpName, { postfix: '.ps'        } ),
                          nodefn.call(tmp.tmpName, { postfix: '.custom.ps' } ) ];

        return when.all(filenames).then(function (filenames) {

            return when(download(message.url, filenames[0])).then(function () {

                return convertToPS(filenames[0], filenames[1]);

            }).then(function () {

                return prepare(filenames[1], filenames[2], message);

            }).then(function () {

                return print(filenames[2], message);

            }).then(function (jobUri) {

                if(!message.id)
                    return;

                return nodefn.call(SQS.sendMessage.bind(SQS), {
                    QueueUrl: config.printsmart.awsQueues.updateJobStatus,
                    MessageBody: JSON.stringify({ 'id': message.id, 'printerUri': message.printerUri, 'jobUri': jobUri })
                });

            }).then(function () {

                return when.map(filenames, function (filepath) { return nodefn.call(fs.unlink, filepath); } );
            });

        });
    };
}

module.exports = exports = new AgentClass();

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

//============================================================
//
//
//============================================================
function download(inputUrl, outputPath) {

    var deferred = when.defer();

    var req = request.get(inputUrl);

    var stream = fs.createWriteStream(outputPath);

    req.pipe(stream);

    stream.on('finish', function() {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function convertToPS(filePath, outputPath) {

    var deferred = when.defer();

    var ls = processx.spawn('pdftops', ['-paper', 'letter', '-level1', filePath, outputPath]);

    ls.stdout.on('data', function (data) { console.log('stdout: ' + data); });
    ls.stderr.on('data', function (data) { console.log('stderr: ' + data); });

    ls.on('close', function (code) {

        if(code==0) deferred.resolve(outputPath);
        else        deferred.reject(code);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function prepare(inputPath, outputPath, message) {

    var deferred = when.defer();
    var page = 0;

    var rStream = fs.createReadStream(inputPath, { encoding: 'utf8' });
    var wStream = fs.createWriteStream(outputPath);

    wStream.write('@PJL SET FINISH = LEFT1POINT\n', 'UTF-8');

    var transform = function (line) {

        // if(line=='%%EndSetup') {
        //
        //     line  = '%%BeginFeature: *Duplex NoTumble\n';
        //     line += '(<<) cvx exec /Duplex true /Tumble false (>>) cvx exec setpagedevice\n';
        //     line += '%%EndFeature\n';
        //     line += '%%BeginFeature: *Stapling Single-Portrait\n';
        //     line += '<< /Staple 3 /StapleDetails << /Type 1 /StapleLocation (SinglePortrait) >> >> setpagedevice\n';
        //     line += '%%EndFeature\n';
        //     line += '%%EndSetup';
        // }

        if(line=='%%Page: 1 1') page = 1;
        if(line=='%%Page: 2 2') page = 2;

        if(!message.anonymous && line=='showpage' && page==1) {

            line  = 'newpath\n';

            // TOP OF PAGE

            // NAME
            line += '/Helvetica-Bold findfont 12 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 20 sub 190 exch moveto\n';
            line += '('+escape(diacritics.remove(message.name||"Not Named"))+') show\n';

            // COUNTRY

            if(message.government) {
                line += '/Helvetica-Bold findfont 10 scalefont setfont\n';
                line += 'currentpagedevice /PageSize get aload pop exch pop 36 sub 190 exch moveto\n';
                line += '('+escape(diacritics.remove(message.government))+') show\n';
            }

            line += '/Helvetica findfont 7 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 48 sub 190 exch moveto\n';
            line += '(SCBD PrintSmart - Copy printed ON-DEMAND) show\n';

            // TOP LEFT

            var box = [message.box, initials(message.name||"")].join(' - ');

            line += '/Helvetica-Bold findfont 24 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 30 sub 40 exch moveto\n';
            line += '('+escape(diacritics.remove(box||"NOT-SET"))+') show\n';

            // TOP RIGHT

            var tag = diacritics.remove(message.tag||"");

            if(message.tag) {
                line += '/Helvetica-Bold findfont 24 scalefont setfont\n';
                line += 'currentpagedevice /PageSize get aload pop exch pop 30 sub 472 exch moveto\n';
                line += '('+escape(diacritics.remove(tag))+') true charpath 1 setlinewidth 0.0 setgray stroke\n';
            }

            line += 'showpage';
        }

        return line + '\n';
    };

    rStream.pipe(es.split())
           .pipe(es.mapSync(transform))
           .pipe(es.wait())
           .pipe(wStream);

    wStream.on('finish', function () {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//
//============================================================
function escape (text) {
    return text.replace(/\\/, '\\\\')
               .replace(/\(/, '\\(')
               .replace(/\)/, '\\)');
}

//============================================================
//
//
//
//============================================================
function initials (name) {

    var names = (name||"").toString().toLocaleUpperCase().split(' ');

    return _.chain(names).map(function(n){
        return (n||"").replace(/[^A-Z\s]+/gi, '').charAt(0);
    }).compact().value().join('');
}

//============================================================
//
//
//
//============================================================
function normalize (text) {

    text = (text||"").toString();

    while(text.length<4)
        text = '0'+text;

    return text;
}

//============================================================
//
//
//============================================================
function print(filename, message) {

    var printer = ipp.Printer(message.printerUri);

    var title  = message.box + ': ' + message.symbol + ' (' + message.language + ') - ' + message.name;
    var copies = Math.round(message.copies || 1);

    var options = {
        'operation-attributes-tag': {
            'job-name': title,
            'requesting-user-name': 'PrintSmart',
            'document-format': 'application/postscript'
        },
        "job-attributes-tag": {
            'sides': 'two-sided-long-edge',
            'finishings': ['staple'],
            'copies' : copies
        },
        data: fs.readFileSync(filename)
    };

    if(options['job-attributes-tag'].copies)
        console.log("Copies: ", copies);

    return when(nodefn.call(printer.execute.bind(printer), "Print-Job", options), function (res) {
        return res['job-attributes-tag']['job-uri'];
    });
}
<commit_msg>Fix name of the person is cropped on the top<commit_after>var AWS      = require('aws-sdk');
var config   = require('./config');
var fs       = require('fs');
var tmp      = require('tmp');
var processx = require('child_process');
var when     = require('when');
var nodefn   = require('when/node/function');
var es       = require('event-stream');
var request  = require('superagent');
var ipp      = require('ipp');
var _        = require('underscore');
var diacritics = require('diacritics');

function AgentClass() {

    var SQS = new AWS.SQS({
        accessKeyId: config.awsAccessKeys.global.accessKeyId,
        secretAccessKey: config.awsAccessKeys.global.secretAccessKey,
        region: 'us-east-1',
        apiVersion: '2012-11-05',
    });

    //============================================================
    //
    //
    //============================================================
    function selectQueue(message)
    {
        var box = normalize(message.box);

        if(message.anonymous) // For printshop
            return 'ipp://localhost:631/classes/printshop';

        return 'ipp://localhost:631/classes/default';
    }

    //============================================================
    //
    //
    //============================================================
    this.processMessage = function processMessage(message) {

        message = JSON.parse(JSON.stringify(message));//fullclone object;

        message.printerUri = message.printerUri || selectQueue(message);

        console.log('Processing:', message);

        var filenames = [ nodefn.call(tmp.tmpName, { postfix: '.pdf'       } ),
                          nodefn.call(tmp.tmpName, { postfix: '.ps'        } ),
                          nodefn.call(tmp.tmpName, { postfix: '.custom.ps' } ) ];

        return when.all(filenames).then(function (filenames) {

            return when(download(message.url, filenames[0])).then(function () {

                return convertToPS(filenames[0], filenames[1]);

            }).then(function () {

                return prepare(filenames[1], filenames[2], message);

            }).then(function () {

                return print(filenames[2], message);

            }).then(function (jobUri) {

                if(!message.id)
                    return;

                return nodefn.call(SQS.sendMessage.bind(SQS), {
                    QueueUrl: config.printsmart.awsQueues.updateJobStatus,
                    MessageBody: JSON.stringify({ 'id': message.id, 'printerUri': message.printerUri, 'jobUri': jobUri })
                });

            }).then(function () {

                return when.map(filenames, function (filepath) { return nodefn.call(fs.unlink, filepath); } );
            });

        });
    };
}

module.exports = exports = new AgentClass();

//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************
//****************************************************************************************************

//============================================================
//
//
//============================================================
function download(inputUrl, outputPath) {

    var deferred = when.defer();

    var req = request.get(inputUrl);

    var stream = fs.createWriteStream(outputPath);

    req.pipe(stream);

    stream.on('finish', function() {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function convertToPS(filePath, outputPath) {

    var deferred = when.defer();

    var ls = processx.spawn('pdftops', ['-paper', 'letter', '-level1', filePath, outputPath]);

    ls.stdout.on('data', function (data) { console.log('stdout: ' + data); });
    ls.stderr.on('data', function (data) { console.log('stderr: ' + data); });

    ls.on('close', function (code) {

        if(code==0) deferred.resolve(outputPath);
        else        deferred.reject(code);
    });

    return deferred.promise;
}

//============================================================
//
//
//============================================================
function prepare(inputPath, outputPath, message) {

    var deferred = when.defer();
    var page = 0;

    var rStream = fs.createReadStream(inputPath, { encoding: 'utf8' });
    var wStream = fs.createWriteStream(outputPath);

    wStream.write('@PJL SET FINISH = LEFT1POINT\n', 'UTF-8');

    var transform = function (line) {

        // if(line=='%%EndSetup') {
        //
        //     line  = '%%BeginFeature: *Duplex NoTumble\n';
        //     line += '(<<) cvx exec /Duplex true /Tumble false (>>) cvx exec setpagedevice\n';
        //     line += '%%EndFeature\n';
        //     line += '%%BeginFeature: *Stapling Single-Portrait\n';
        //     line += '<< /Staple 3 /StapleDetails << /Type 1 /StapleLocation (SinglePortrait) >> >> setpagedevice\n';
        //     line += '%%EndFeature\n';
        //     line += '%%EndSetup';
        // }

        if(line=='%%Page: 1 1') page = 1;
        if(line=='%%Page: 2 2') page = 2;

        if(!message.anonymous && line=='showpage' && page==1) {

            line  = 'newpath\n';

            // TOP OF PAGE

            // NAME
            line += '/Helvetica-Bold findfont 12 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 22 sub 190 exch moveto\n';
            line += '('+escape(diacritics.remove(message.name||"Not Named"))+') show\n';

            // COUNTRY

            if(message.government) {
                line += '/Helvetica-Bold findfont 10 scalefont setfont\n';
                line += 'currentpagedevice /PageSize get aload pop exch pop 36 sub 190 exch moveto\n';
                line += '('+escape(diacritics.remove(message.government))+') show\n';
            }

            line += '/Helvetica findfont 7 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 48 sub 190 exch moveto\n';
            line += '(SCBD PrintSmart - Copy printed ON-DEMAND) show\n';

            // TOP LEFT

            var box = [message.box, initials(message.name||"")].join(' - ');

            line += '/Helvetica-Bold findfont 24 scalefont setfont\n';
            line += 'currentpagedevice /PageSize get aload pop exch pop 30 sub 40 exch moveto\n';
            line += '('+escape(diacritics.remove(box||"NOT-SET"))+') show\n';

            // TOP RIGHT

            var tag = diacritics.remove(message.tag||"");

            if(message.tag) {
                line += '/Helvetica-Bold findfont 24 scalefont setfont\n';
                line += 'currentpagedevice /PageSize get aload pop exch pop 30 sub 472 exch moveto\n';
                line += '('+escape(diacritics.remove(tag))+') true charpath 1 setlinewidth 0.0 setgray stroke\n';
            }

            line += 'showpage';
        }

        return line + '\n';
    };

    rStream.pipe(es.split())
           .pipe(es.mapSync(transform))
           .pipe(es.wait())
           .pipe(wStream);

    wStream.on('finish', function () {
        deferred.resolve(outputPath);
    });

    return deferred.promise;
}

//============================================================
//
//
//
//============================================================
function escape (text) {
    return text.replace(/\\/, '\\\\')
               .replace(/\(/, '\\(')
               .replace(/\)/, '\\)');
}

//============================================================
//
//
//
//============================================================
function initials (name) {

    var names = (name||"").toString().toLocaleUpperCase().split(' ');

    return _.chain(names).map(function(n){
        return (n||"").replace(/[^A-Z\s]+/gi, '').charAt(0);
    }).compact().value().join('');
}

//============================================================
//
//
//
//============================================================
function normalize (text) {

    text = (text||"").toString();

    while(text.length<4)
        text = '0'+text;

    return text;
}

//============================================================
//
//
//============================================================
function print(filename, message) {

    var printer = ipp.Printer(message.printerUri);

    var title  = message.box + ': ' + message.symbol + ' (' + message.language + ') - ' + message.name;
    var copies = Math.round(message.copies || 1);

    var options = {
        'operation-attributes-tag': {
            'job-name': title,
            'requesting-user-name': 'PrintSmart',
            'document-format': 'application/postscript'
        },
        "job-attributes-tag": {
            'sides': 'two-sided-long-edge',
            'finishings': ['staple'],
            'copies' : copies
        },
        data: fs.readFileSync(filename)
    };

    if(options['job-attributes-tag'].copies)
        console.log("Copies: ", copies);

    return when(nodefn.call(printer.execute.bind(printer), "Print-Job", options), function (res) {
        return res['job-attributes-tag']['job-uri'];
    });
}
<|endoftext|>


<commit_before>/*
 * @copyright 2012 - present by OpenGamma Inc
 * @license See distribution for license
 */
$.register_module({
    name: 'og.common.gadgets.securities_identifiers',
    dependencies: [],
    obj: function () {
        var api = og.api, dependencies = ['id'], template, empty = ''.lang(),
            prefix = 'securities_identifiers_', counter = 1;
        return function (config) {
            var gadget = this, height = config.height || 150, render,
                version = config.version !== '*' ? config.version : void 0;
            gadget.resize = $.noop;
            render = function (result, html_template) {
                var ids = result.data.identifiers, keys = Object.keys(ids), alive = prefix + counter++, data = {
                    alive: alive, empty: empty,
                    ids: keys.map(function (key) {return {key: key.lang(), value: ids[key].replace(key + '-', '')};})
                };
                $(config.selector).html((template || (template = Handlebars.compile(html_template)))(data))
                    .find('table').awesometable({height: height});
                gadget.alive = function () {return !!$('.' + alive).length;};
                og.common.gadgets.manager.register(gadget);
            };
            $.when(
                api.rest.securities.get({dependencies: dependencies, id: config.id, cache_for: 500, version: version}),
                api.text({module: 'og.views.gadgets.securities_identifiers_tash'})
            ).then(render);
        };
    }
});<commit_msg>turning securities identifer gadget function into a constructor<commit_after>/*
 * @copyright 2012 - present by OpenGamma Inc
 * @license See distribution for license
 */
$.register_module({
    name: 'og.common.gadgets.securities_identifiers',
    dependencies: [],
    obj: function () {
        var api = og.api, dependencies = ['id'], template, empty = ''.lang(),
            prefix = 'securities_identifiers_', counter = 1;
        return function (config) {
            var gadget = this, height = config.height || 150, render, alive = prefix + counter++,
                version = config.version !== '*' ? config.version : void 0;
            gadget.alive = function () {return !!$('.' + alive).length;};
            gadget.resize = $.noop;
            render = function (result, html_template) {
                var ids = result.data.identifiers, keys = Object.keys(ids), data = {
                    alive: alive, empty: empty,
                    ids: keys.map(function (key) {return {key: key.lang(), value: ids[key].replace(key + '-', '')};})
                };
                $(config.selector).html((template || (template = Handlebars.compile(html_template)))(data))
                    .find('table').awesometable({height: height});
                og.common.gadgets.manager.register(gadget);
            };
            $.when(
                api.rest.securities.get({dependencies: dependencies, id: config.id, cache_for: 500, version: version}),
                api.text({module: 'og.views.gadgets.securities_identifiers_tash'})
            ).then(render);
        };
    }
});<|endoftext|>


<commit_before>import IW from './IW.js';
import {Avatar} from './Idol.js';
import Position from './Position.js';

export default class Team extends IW {
  constructor(name, positionMap) {
    super();
    this.origin = new Position(0,-2);
    this.name = name;
    this.avatars = [];
    for (let [pos,card] of positionMap) {
      this.avatars.push(new Avatar(card,this,pos));
    }
  }

  survivals() {
    return this.avatars.filter(function (avt) {return avt.life > 0;});
  }

  battle(defender) {

    this.role = "aggressor";
    defender.role = "defender";
    this.opponent = defender;
    defender.opponent = this;
    let avatars = this.avatars.concat(defender.avatars);

    let performRound = function (avatars) {

      if (avatars.length > 0)
        avatars = avatars.filter(function (avt) {
          let fieldFactor = 10;
          if (avt.life > 0) {
            avt.speed = avt.card.speed() * fieldFactor + Math.random();
            return true;
          }
          return false;
        });
      else return;

      if (avatars.length == 0)
        return;
      else if (avatars.length > 1)
        avatars.sort(function(a,b){ return b.speed - a.speed; });

      avatars[0].action();
      performRound(avatars.slice(1));
    }

    for (let ri = 0; ri < 50; ri++) {
      let sAggs = this.survivals();
      let sDefs = defender.survivals();

      if (IW.battleLog) {
        console.log("===Turn:",ri+1,"=============================================");
        if (sAggs.length) {
          console.log("    Aggressors");
          for(let avt of sAggs) {
            console.log("      ",avt.desc());
          }
        }

        if (sDefs.length) {
          console.log("    Defenders");
          for(let avt of defender.survivals()) {
            console.log("      ",avt.desc());
          }
        }
        console.log("--------------------------------------------------------");
      }

      if (sDefs.length == 0) return this;
      else if (sAggs.length == 0) return defender;

      performRound(avatars);
    }
  }

  receive(act) {

    let oldALife = act.avatar.life;
    let oldTLife = act.target.life;

    let powerFactor = 0.175;
    let power = act.power;
    act.target.life -= power;

    let barfunc = function (max,before,after) {
      if (after < 0) after = 0;
      let bsize = 10;
      let ra = Math.ceil(bsize*after/max);
      let rb = Math.ceil(bsize*before/max);
      return "◌".repeat(bsize-rb)+"×".repeat(rb-ra)+"◉".repeat(ra);
    }

    if (IW.battleLog) {

      let oft = (this.role == "defender" ? "" : "    ");

      console.log(oft,act.avatar.desc(), "attacks");
      console.log(oft,"├"+barfunc(act.avatar.maxLife,oldALife,act.avatar.life)+"┘",oldALife.toFixed(2),"-",power.toFixed(2),"=",act.target.life.toFixed(2));
      console.log(oft,"│  ", act.target.desc());
      console.log(oft,"└────"+barfunc(act.target.maxLife,oldTLife,act.target.life)+"┘",oldTLife.toFixed(2),"-",power.toFixed(2),"=",act.target.life.toFixed(2));
    }
  }
}
<commit_msg>Make it works with BabelJS<commit_after>import IW from './IW.js';
import {Avatar} from './Idol.js';
import Position from './Position.js';

export default class Team extends IW {
  constructor(name, positionMap) {
    super();
    this.origin = new Position(0,-2);
    this.name = name;
    this.avatars = [];
    for (let [pos,card] of positionMap) {
      this.avatars.push(new Avatar(card,this,pos));
    }
  }

  survivals() {
    return this.avatars.filter(function (avt) {return avt.life > 0;});
  }

  battle(defender) {

    this.role = "aggressor";
    defender.role = "defender";
    this.opponent = defender;
    defender.opponent = this;
    let avatars = this.avatars.concat(defender.avatars);

    function performRound(avatars) {

      if (avatars.length > 0)
        avatars = avatars.filter(function (avt) {
          let fieldFactor = 10;
          if (avt.life > 0) {
            avt.speed = avt.card.speed() * fieldFactor + Math.random();
            return true;
          }
          return false;
        });
      else return;

      if (avatars.length == 0)
        return;
      else if (avatars.length > 1)
        avatars.sort(function(a,b){ return b.speed - a.speed; });

      avatars[0].action();
      performRound(avatars.slice(1));
    }

    for (let ri = 0; ri < 50; ri++) {
      let sAggs = this.survivals();
      let sDefs = defender.survivals();

      if (IW.battleLog) {
        console.log("===Turn:",ri+1,"=============================================");
        if (sAggs.length) {
          console.log("    Aggressors");
          for(let avt of sAggs) {
            console.log("      ",avt.desc());
          }
        }

        if (sDefs.length) {
          console.log("    Defenders");
          for(let avt of defender.survivals()) {
            console.log("      ",avt.desc());
          }
        }
        console.log("--------------------------------------------------------");
      }

      if (sDefs.length == 0) return this;
      else if (sAggs.length == 0) return defender;

      performRound(avatars);
    }
  }

  receive(act) {

    let oldALife = act.avatar.life;
    let oldTLife = act.target.life;

    let powerFactor = 0.175;
    let power = act.power;
    act.target.life -= power;

    let barfunc = function (max,before,after) {
      if (after < 0) after = 0;
      let bsize = 10;
      let ra = Math.ceil(bsize*after/max);
      let rb = Math.ceil(bsize*before/max);
      return "◌".repeat(bsize-rb)+"×".repeat(rb-ra)+"◉".repeat(ra);
    }

    if (IW.battleLog) {

      let oft = (this.role == "defender" ? "" : "    ");

      console.log(oft,act.avatar.desc(), "attacks");
      console.log(oft,"├"+barfunc(act.avatar.maxLife,oldALife,act.avatar.life)+"┘",oldALife.toFixed(2),"-",power.toFixed(2),"=",act.target.life.toFixed(2));
      console.log(oft,"│  ", act.target.desc());
      console.log(oft,"└────"+barfunc(act.target.maxLife,oldTLife,act.target.life)+"┘",oldTLife.toFixed(2),"-",power.toFixed(2),"=",act.target.life.toFixed(2));
    }
  }
}
<|endoftext|>


<commit_before>/*
 * Ahoy.js
 * Simple, powerful JavaScript analytics
 * https://github.com/ankane/ahoy.js
 * v0.1.0
 * MIT License
 */

/*jslint browser: true, indent: 2, plusplus: true, vars: true */

(function (window) {
  "use strict";

  var config = {
    urlPrefix: "",
    visitsUrl: "/ahoy/visits",
    eventsUrl: "/ahoy/events",
    cookieDomain: null,
    page: null,
    platform: "Web",
    useBeacon: false,
    startOnReady: true
  };

  var ahoy = window.ahoy || window.Ahoy || {};

  ahoy.configure = function (options) {
    for (var key in options) {
      if (options.hasOwnProperty(key)) {
        config[key] = options[key];
      }
    }
  };

  // legacy
  ahoy.configure(ahoy);

  var $ = window.jQuery || window.Zepto || window.$;
  var visitId, visitorId, track;
  var visitTtl = 4 * 60; // 4 hours
  var visitorTtl = 2 * 365 * 24 * 60; // 2 years
  var isReady = false;
  var queue = [];
  var canStringify = typeof(JSON) !== "undefined" && typeof(JSON.stringify) !== "undefined";
  var eventQueue = [];

  function visitsUrl() {
    return config.urlPrefix + config.visitsUrl;
  }

  function eventsUrl() {
    return config.urlPrefix + config.eventsUrl;
  }

  function canTrackNow() {
    return (config.useBeacon || config.trackNow) && canStringify && typeof(window.navigator.sendBeacon) !== "undefined";
  }

  // cookies

  // http://www.quirksmode.org/js/cookies.html
  function setCookie(name, value, ttl) {
    var expires = "";
    var cookieDomain = "";
    if (ttl) {
      var date = new Date();
      date.setTime(date.getTime() + (ttl * 60 * 1000));
      expires = "; expires=" + date.toGMTString();
    }
    var domain = config.cookieDomain || config.domain;
    if (domain) {
      cookieDomain = "; domain=" + domain;
    }
    document.cookie = name + "=" + escape(value) + expires + cookieDomain + "; path=/";
  }

  function getCookie(name) {
    var i, c;
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (i = 0; i < ca.length; i++) {
      c = ca[i];
      while (c.charAt(0) === ' ') {
        c = c.substring(1, c.length);
      }
      if (c.indexOf(nameEQ) === 0) {
        return unescape(c.substring(nameEQ.length, c.length));
      }
    }
    return null;
  }

  function destroyCookie(name) {
    setCookie(name, "", -1);
  }

  function log(message) {
    if (getCookie("ahoy_debug")) {
      window.console.log(message);
    }
  }

  function setReady() {
    var callback;
    while (callback = queue.shift()) {
      callback();
    }
    isReady = true;
  }

  function ready(callback) {
    if (isReady) {
      callback();
    } else {
      queue.push(callback);
    }
  }

  // http://stackoverflow.com/a/2117523/1177228
  function generateId() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    });
  }

  function saveEventQueue() {
    // TODO add stringify method for IE 7 and under
    if (canStringify) {
      setCookie("ahoy_events", JSON.stringify(eventQueue), 1);
    }
  }

  // from jquery-ujs

  function csrfToken() {
    return $("meta[name=csrf-token]").attr("content");
  }

  function csrfParam() {
    return $("meta[name=csrf-param]").attr("content");
  }

  function CSRFProtection(xhr) {
    var token = csrfToken();
    if (token) xhr.setRequestHeader("X-CSRF-Token", token);
  }

  function sendRequest(url, data, success) {
    if (canStringify) {
      $.ajax({
        type: "POST",
        url: url,
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        beforeSend: CSRFProtection,
        success: success
      });
    }
  }

  function eventData(event) {
    var data = {
      events: [event],
      visit_token: event.visit_token,
      visitor_token: event.visitor_token
    };
    delete event.visit_token;
    delete event.visitor_token;
    return data;
  }

  function trackEvent(event) {
    ready( function () {
      sendRequest(eventsUrl(), eventData(event), function() {
        // remove from queue
        for (var i = 0; i < eventQueue.length; i++) {
          if (eventQueue[i].id == event.id) {
            eventQueue.splice(i, 1);
            break;
          }
        }
        saveEventQueue();
      });
    });
  }

  function trackEventNow(event) {
    ready( function () {
      var data = eventData(event);
      var param = csrfParam();
      var token = csrfToken();
      if (param && token) data[param] = token;
      var payload = new Blob([JSON.stringify(data)], {type : "application/json; charset=utf-8"});
      navigator.sendBeacon(eventsUrl(), payload);
    });
  }

  function page() {
    return config.page || window.location.pathname;
  }

  function eventProperties(e) {
    var $target = $(e.currentTarget);
    return {
      tag: $target.get(0).tagName.toLowerCase(),
      id: $target.attr("id"),
      "class": $target.attr("class"),
      page: page(),
      section: $target.closest("*[data-section]").data("section")
    };
  }

  function createVisit() {
    isReady = false;

    visitId = ahoy.getVisitId();
    visitorId = ahoy.getVisitorId();
    track = getCookie("ahoy_track");

    if (visitId && visitorId && !track) {
      // TODO keep visit alive?
      log("Active visit");
      setReady();
    } else {
      if (track) {
        destroyCookie("ahoy_track");
      }

      if (!visitId) {
        visitId = generateId();
        setCookie("ahoy_visit", visitId, visitTtl);
      }

      // make sure cookies are enabled
      if (getCookie("ahoy_visit")) {
        log("Visit started");

        if (!visitorId) {
          visitorId = generateId();
          setCookie("ahoy_visitor", visitorId, visitorTtl);
        }

        var data = {
          visit_token: visitId,
          visitor_token: visitorId,
          platform: config.platform,
          landing_page: window.location.href,
          screen_width: window.screen.width,
          screen_height: window.screen.height
        };

        // referrer
        if (document.referrer.length > 0) {
          data.referrer = document.referrer;
        }

        log(data);

        sendRequest(visitsUrl(), data, setReady);
      } else {
        log("Cookies disabled");
        setReady();
      }
    }
  }

  ahoy.getVisitId = ahoy.getVisitToken = function () {
    return getCookie("ahoy_visit");
  };

  ahoy.getVisitorId = ahoy.getVisitorToken = function () {
    return getCookie("ahoy_visitor");
  };

  ahoy.reset = function () {
    destroyCookie("ahoy_visit");
    destroyCookie("ahoy_visitor");
    destroyCookie("ahoy_events");
    destroyCookie("ahoy_track");
    return true;
  };

  ahoy.debug = function (enabled) {
    if (enabled === false) {
      destroyCookie("ahoy_debug");
    } else {
      setCookie("ahoy_debug", "t", 365 * 24 * 60); // 1 year
    }
    return true;
  };

  ahoy.track = function (name, properties) {
    // generate unique id
    var event = {
      id: generateId(),
      name: name,
      properties: properties || {},
      time: (new Date()).getTime() / 1000.0
    };

    // wait for createVisit to log
    $( function () {
      log(event);
    });

    ready( function () {
      if (!ahoy.getVisitId()) {
        createVisit();
      }

      event.visit_token = ahoy.getVisitId();
      event.visitor_token = ahoy.getVisitorId();

      if (canTrackNow()) {
        trackEventNow(event);
      } else {
        eventQueue.push(event);
        saveEventQueue();

        // wait in case navigating to reduce duplicate events
        setTimeout( function () {
          trackEvent(event);
        }, 1000);
      }
    });
  };

  ahoy.trackView = function () {
    var properties = {
      url: window.location.href,
      title: document.title,
      page: page()
    };
    ahoy.track("$view", properties);
  };

  ahoy.trackClicks = function () {
    $(document).on("click", "a, button, input[type=submit]", function (e) {
      var $target = $(e.currentTarget);
      var properties = eventProperties(e);
      properties.text = properties.tag == "input" ? $target.val() : $.trim($target.text().replace(/[\s\r\n]+/g, " "));
      properties.href = $target.attr("href");
      ahoy.track("$click", properties);
    });
  };

  ahoy.trackSubmits = function () {
    $(document).on("submit", "form", function (e) {
      var properties = eventProperties(e);
      ahoy.track("$submit", properties);
    });
  };

  ahoy.trackChanges = function () {
    $(document).on("change", "input, textarea, select", function (e) {
      var properties = eventProperties(e);
      ahoy.track("$change", properties);
    });
  };

  ahoy.trackAll = function() {
    ahoy.trackView();
    ahoy.trackClicks();
    ahoy.trackSubmits();
    ahoy.trackChanges();
  };

  ahoy.start = function () {
    createVisit();

    // push events from queue
    try {
      eventQueue = JSON.parse(getCookie("ahoy_events") || "[]");
    } catch (e) {
      // do nothing
    }

    for (var i = 0; i < eventQueue.length; i++) {
      trackEvent(eventQueue[i]);
    }

    ahoy.start = function () {};
  };

  if (config.startOnReady) { $(ahoy.start); }

  window.ahoy = ahoy;
}(window));
<commit_msg>Pass optional additional properties when tracking page view<commit_after>/*
 * Ahoy.js
 * Simple, powerful JavaScript analytics
 * https://github.com/ankane/ahoy.js
 * v0.1.0
 * MIT License
 */

/*jslint browser: true, indent: 2, plusplus: true, vars: true */

(function (window) {
  "use strict";

  var config = {
    urlPrefix: "",
    visitsUrl: "/ahoy/visits",
    eventsUrl: "/ahoy/events",
    cookieDomain: null,
    page: null,
    platform: "Web",
    useBeacon: false,
    startOnReady: true
  };

  var ahoy = window.ahoy || window.Ahoy || {};

  ahoy.configure = function (options) {
    for (var key in options) {
      if (options.hasOwnProperty(key)) {
        config[key] = options[key];
      }
    }
  };

  // legacy
  ahoy.configure(ahoy);

  var $ = window.jQuery || window.Zepto || window.$;
  var visitId, visitorId, track;
  var visitTtl = 4 * 60; // 4 hours
  var visitorTtl = 2 * 365 * 24 * 60; // 2 years
  var isReady = false;
  var queue = [];
  var canStringify = typeof(JSON) !== "undefined" && typeof(JSON.stringify) !== "undefined";
  var eventQueue = [];

  function visitsUrl() {
    return config.urlPrefix + config.visitsUrl;
  }

  function eventsUrl() {
    return config.urlPrefix + config.eventsUrl;
  }

  function canTrackNow() {
    return (config.useBeacon || config.trackNow) && canStringify && typeof(window.navigator.sendBeacon) !== "undefined";
  }

  // cookies

  // http://www.quirksmode.org/js/cookies.html
  function setCookie(name, value, ttl) {
    var expires = "";
    var cookieDomain = "";
    if (ttl) {
      var date = new Date();
      date.setTime(date.getTime() + (ttl * 60 * 1000));
      expires = "; expires=" + date.toGMTString();
    }
    var domain = config.cookieDomain || config.domain;
    if (domain) {
      cookieDomain = "; domain=" + domain;
    }
    document.cookie = name + "=" + escape(value) + expires + cookieDomain + "; path=/";
  }

  function getCookie(name) {
    var i, c;
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (i = 0; i < ca.length; i++) {
      c = ca[i];
      while (c.charAt(0) === ' ') {
        c = c.substring(1, c.length);
      }
      if (c.indexOf(nameEQ) === 0) {
        return unescape(c.substring(nameEQ.length, c.length));
      }
    }
    return null;
  }

  function destroyCookie(name) {
    setCookie(name, "", -1);
  }

  function log(message) {
    if (getCookie("ahoy_debug")) {
      window.console.log(message);
    }
  }

  function setReady() {
    var callback;
    while (callback = queue.shift()) {
      callback();
    }
    isReady = true;
  }

  function ready(callback) {
    if (isReady) {
      callback();
    } else {
      queue.push(callback);
    }
  }

  // http://stackoverflow.com/a/2117523/1177228
  function generateId() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    });
  }

  function saveEventQueue() {
    // TODO add stringify method for IE 7 and under
    if (canStringify) {
      setCookie("ahoy_events", JSON.stringify(eventQueue), 1);
    }
  }

  // from jquery-ujs

  function csrfToken() {
    return $("meta[name=csrf-token]").attr("content");
  }

  function csrfParam() {
    return $("meta[name=csrf-param]").attr("content");
  }

  function CSRFProtection(xhr) {
    var token = csrfToken();
    if (token) xhr.setRequestHeader("X-CSRF-Token", token);
  }

  function sendRequest(url, data, success) {
    if (canStringify) {
      $.ajax({
        type: "POST",
        url: url,
        data: JSON.stringify(data),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        beforeSend: CSRFProtection,
        success: success
      });
    }
  }

  function eventData(event) {
    var data = {
      events: [event],
      visit_token: event.visit_token,
      visitor_token: event.visitor_token
    };
    delete event.visit_token;
    delete event.visitor_token;
    return data;
  }

  function trackEvent(event) {
    ready( function () {
      sendRequest(eventsUrl(), eventData(event), function() {
        // remove from queue
        for (var i = 0; i < eventQueue.length; i++) {
          if (eventQueue[i].id == event.id) {
            eventQueue.splice(i, 1);
            break;
          }
        }
        saveEventQueue();
      });
    });
  }

  function trackEventNow(event) {
    ready( function () {
      var data = eventData(event);
      var param = csrfParam();
      var token = csrfToken();
      if (param && token) data[param] = token;
      var payload = new Blob([JSON.stringify(data)], {type : "application/json; charset=utf-8"});
      navigator.sendBeacon(eventsUrl(), payload);
    });
  }

  function page() {
    return config.page || window.location.pathname;
  }

  function eventProperties(e) {
    var $target = $(e.currentTarget);
    return {
      tag: $target.get(0).tagName.toLowerCase(),
      id: $target.attr("id"),
      "class": $target.attr("class"),
      page: page(),
      section: $target.closest("*[data-section]").data("section")
    };
  }

  function createVisit() {
    isReady = false;

    visitId = ahoy.getVisitId();
    visitorId = ahoy.getVisitorId();
    track = getCookie("ahoy_track");

    if (visitId && visitorId && !track) {
      // TODO keep visit alive?
      log("Active visit");
      setReady();
    } else {
      if (track) {
        destroyCookie("ahoy_track");
      }

      if (!visitId) {
        visitId = generateId();
        setCookie("ahoy_visit", visitId, visitTtl);
      }

      // make sure cookies are enabled
      if (getCookie("ahoy_visit")) {
        log("Visit started");

        if (!visitorId) {
          visitorId = generateId();
          setCookie("ahoy_visitor", visitorId, visitorTtl);
        }

        var data = {
          visit_token: visitId,
          visitor_token: visitorId,
          platform: config.platform,
          landing_page: window.location.href,
          screen_width: window.screen.width,
          screen_height: window.screen.height
        };

        // referrer
        if (document.referrer.length > 0) {
          data.referrer = document.referrer;
        }

        log(data);

        sendRequest(visitsUrl(), data, setReady);
      } else {
        log("Cookies disabled");
        setReady();
      }
    }
  }

  ahoy.getVisitId = ahoy.getVisitToken = function () {
    return getCookie("ahoy_visit");
  };

  ahoy.getVisitorId = ahoy.getVisitorToken = function () {
    return getCookie("ahoy_visitor");
  };

  ahoy.reset = function () {
    destroyCookie("ahoy_visit");
    destroyCookie("ahoy_visitor");
    destroyCookie("ahoy_events");
    destroyCookie("ahoy_track");
    return true;
  };

  ahoy.debug = function (enabled) {
    if (enabled === false) {
      destroyCookie("ahoy_debug");
    } else {
      setCookie("ahoy_debug", "t", 365 * 24 * 60); // 1 year
    }
    return true;
  };

  ahoy.track = function (name, properties) {
    // generate unique id
    var event = {
      id: generateId(),
      name: name,
      properties: properties || {},
      time: (new Date()).getTime() / 1000.0
    };

    // wait for createVisit to log
    $( function () {
      log(event);
    });

    ready( function () {
      if (!ahoy.getVisitId()) {
        createVisit();
      }

      event.visit_token = ahoy.getVisitId();
      event.visitor_token = ahoy.getVisitorId();

      if (canTrackNow()) {
        trackEventNow(event);
      } else {
        eventQueue.push(event);
        saveEventQueue();

        // wait in case navigating to reduce duplicate events
        setTimeout( function () {
          trackEvent(event);
        }, 1000);
      }
    });
  };

  ahoy.trackView = function (additional_properties) {
    var properties = {
      url: window.location.href,
      title: document.title,
      page: page()
    };

    if (typeof additional_properties !== 'undefined' ) {
      for(var attr_name in additional_properties) {
        if (additional_properties.hasOwnProperty(attr_name)) {
          properties[attr_name] = additional_properties[attr_name];
        }
      }
    }
    ahoy.track("$view", properties);
  };

  ahoy.trackClicks = function () {
    $(document).on("click", "a, button, input[type=submit]", function (e) {
      var $target = $(e.currentTarget);
      var properties = eventProperties(e);
      properties.text = properties.tag == "input" ? $target.val() : $.trim($target.text().replace(/[\s\r\n]+/g, " "));
      properties.href = $target.attr("href");
      ahoy.track("$click", properties);
    });
  };

  ahoy.trackSubmits = function () {
    $(document).on("submit", "form", function (e) {
      var properties = eventProperties(e);
      ahoy.track("$submit", properties);
    });
  };

  ahoy.trackChanges = function () {
    $(document).on("change", "input, textarea, select", function (e) {
      var properties = eventProperties(e);
      ahoy.track("$change", properties);
    });
  };

  ahoy.trackAll = function() {
    ahoy.trackView();
    ahoy.trackClicks();
    ahoy.trackSubmits();
    ahoy.trackChanges();
  };

  ahoy.start = function () {
    createVisit();

    // push events from queue
    try {
      eventQueue = JSON.parse(getCookie("ahoy_events") || "[]");
    } catch (e) {
      // do nothing
    }

    for (var i = 0; i < eventQueue.length; i++) {
      trackEvent(eventQueue[i]);
    }

    ahoy.start = function () {};
  };

  if (config.startOnReady) { $(ahoy.start); }

  window.ahoy = ahoy;
}(window));
<|endoftext|>