<commit_before>
import { Observable, ObservableObject } from '../observable';
import CacheMapException from './CacheMapException';

class CacheMap extends ObservableObject {

    constructor(cacheMapId, entrySchema, entriesAreObservables) {
        this._cacheMapId = cacheMapId;
        this._entrySchema = entrySchema;
        this._entriesAreObservables = entriesAreObservables;
        this._entries = {};
    }

    _remove(entryId) {
        const entry = this.find(entryId);
        if (this._entriesAreObservables) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.removeParentObserver(this.observer);
        }
        delete this._entries[entryId];
        this._markAsChanged();
    }

    get cacheMapId() {
        return this._cacheMapId;
    }

    get entriesAreObservables() {
        return this._entriesAreObservables;
    }

    createEntry() {
        return null;
    }

    ids() {
        return Object.keys(this._views);
    }

    exists(entryId) {
        return this._entries.hasOwnProperty(entryId);
    }

    find(entryId) {
        return this.exists(entryId)
            ? this._entries[entryId] : undefined;
    }

    set(entryId, entry) {
        if (this.exists(entryId)) {
            this._remove(entryId);
        }
        this._entries[entryId] = entry;
        if (this._entriesAreObservables) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.addParentObserver(this.observer);
        }
        this._markAsChanged();
        return this;
    }

    remove(entryId) {
        if (!this.exists(entryId)) {
            throw new CacheMapException('Try to remove entry which doesn\'t exist!');
        }
        this._remove(entryId);
        return this;
    }
}

export default CacheMap;
<commit_msg>renamed entrySchema => entryType<commit_after>
import { Observable, ObservableObject } from '../observable';
import CacheMapException from './CacheMapException';

class CacheMap extends ObservableObject {

    constructor(cacheMapId, entryType, entriesAreObservables) {
        this._cacheMapId = cacheMapId;
        this._entryType = entryType;
        this._entriesAreObservables = entriesAreObservables;
        this._entries = {};
    }

    _remove(entryId) {
        const entry = this.find(entryId);
        if (this._entriesAreObservables) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.removeParentObserver(this.observer);
        }
        delete this._entries[entryId];
        this._markAsChanged();
    }

    get cacheMapId() {
        return this._cacheMapId;
    }

    get entriesAreObservables() {
        return this._entriesAreObservables;
    }

    createEntry() {
        return null;
    }

    ids() {
        return Object.keys(this._views);
    }

    exists(entryId) {
        return this._entries.hasOwnProperty(entryId);
    }

    find(entryId) {
        return this.exists(entryId)
            ? this._entries[entryId] : undefined;
    }

    set(entryId, entry) {
        if (this.exists(entryId)) {
            this._remove(entryId);
        }
        this._entries[entryId] = entry;
        if (this._entriesAreObservables) {
            if (!entry instanceof Observable) {
                throw new CacheMapException('Cache entry must be instanceof Observable!');
            }
            entry.addParentObserver(this.observer);
        }
        this._markAsChanged();
        return this;
    }

    remove(entryId) {
        if (!this.exists(entryId)) {
            throw new CacheMapException('Try to remove entry which doesn\'t exist!');
        }
        this._remove(entryId);
        return this;
    }
}

export default CacheMap;
<|endoftext|>


<commit_before>/**
 * Camera is used to select the objects to display in a scene.
 *   A camera doesn't rotate or scale objects in the x and y axis,
 *   only the coordinates are changed to the transformation defined.
 *
 * @param {!Object=} options Setup options.
 * @param {!Grape2D.Vector=} options.scale The scale to be applied. There
 *		are two ways to define the scale. This method is one, the other
 *		is defined it directly in the transformation. If the two are set,
 *		then the two are applied.
 * @param {!Grape2D.Vector=} options.lookAt Defines the (center) position,
 *		to where the camera is looking at.
 * @param {!Grape2D.Matrix=} options.transformation Transformation matrix
 *		to be applied to the object coordinates.
 * @constructor
 */
Grape2D.Camera = function(options) {
	options = options || {};
	/**
	 * Scale relative to the camera initialization.
	 *
	 * @type {!Grape2D.Vector}
	 * @private
	 */
	this.rscale = new Grape2D.Vector(1, 1);
	/**
	 * Scale set by the user, should be defined in the matrix.
	 *
	 * @type {!Grape2D.Vector}
	 * @private
	 */
	this.scale = options.scale || new Grape2D.Vector(1, 1);
	/**
	 * The position to where the camera is looking at.
	 *
	 * @type {!Grape2D.Vector}
	 * @private
	 */
	this.lookAt = options.lookAt || new Grape2D.Vector();
	/**
	 * The transformation matrix to aply to the object coordinates.
	 *
	 * @type {!Grape2D.Matrix}
	 * @private
	 */
	this.transformation = options.transformation || new Grape2D.Matrix();

	/**
	 * Computed matrix
	 *
	 * @type {!Grape2D.Matrix}
	 * @private
	 */
	this.cM = new Grape2D.Matrix();
	/**
	 * Inverse of the computed matrix
	 *
	 * @type {!Grape2D.Matrix}
	 * @private
	 */
	this.icM = new Grape2D.Matrix();
	this.computeMatrix();
};

Grape2D.Camera.prototype = {
	constructor: Grape2D.Camera,
	/**
	 * Computes the matrix for better performances.
	 *
	 * @protected
	 */
	computeMatrix: function() {
		this.cM = this.transformation.clone();
		//This operations should work fine, and it avoids a multiplication
		//between the _cM matrix and a vector when converting coordinates
		this.cM.v[0] *= this.scale.x * this.rscale.x;
		this.cM.v[1] *= this.scale.x * this.rscale.x;
		this.cM.v[2] *= this.scale.x * this.rscale.x;

		this.cM.v[3] *= this.scale.y * this.rscale.y;
		this.cM.v[4] *= this.scale.y * this.rscale.y;
		this.cM.v[5] *= this.scale.y * this.rscale.y;

		this.icM = this.cM.clone().invert();
	},
	/**
	 * Applies the transformation, on a vector in the World Coordinate
	 * System (WCS), to get a vector in the Viewport (Renderer) Coordinate
	 * System (VSC).
	 *
	 * @param  {!Grape2D.Renderer} renderer The viewport.
	 * @param  {!Grape2D.Vector} vector Vector in the WCS.
	 * @return {!Grape2D.Vector} A vector in the VCS
	 * @public
	 */
	wcsToViewport: function(renderer, vector) {
		var v = this.cM.multiplyByVector(vector.clone().sub(this.lookAt));

		v.x += renderer.getHalfWidth();
		v.y += renderer.getHalfHeight();

		return v;
	},
	/**
	 * Applies the transformation, on a vector in the Viewport Coordinate
	 * System (VCS), to get a vector in the World Coordinate System (WSC).
	 *
	 * @param  {!Grape2D.Renderer} renderer The viewport.
	 * @param  {!Grape2D.Vector} vector Vector in the VCS.
	 * @return {!Grape2D.Vector} A vector in the WCS
	 * @public
	 */
	viewportToWcs: function(renderer, vector) {
		var v = vector.clone();

		v.x -= renderer.getHalfWidth();
		v.y -= renderer.getHalfWidth();

		v = this.icM.multiplyByVector(v).sub(this.lookAt);

		return v;
	},
	/**
	 * Sets a new scale.
	 *
	 * @param  {!Grape2D.Vector} scale The new scale.
	 * @public
	 */
	rescale: function(scale) {
		this.rscale.x = scale.x / this.scale.x;
		this.rscale.y = scale.y / this.scale.y;
		this.computeMatrix();
	},
	/**
	 * Sets the center position to where the camera is looking at.
	 *
	 * @param  {!Grape2D.Vector} position The new look at.
	 * @public
	 */
	setLookAt: function(position) {
		this.lookAt.set(position);
	},
	/**
	 * Gets the look at property.
	 *
	 * @return {!Grape2D.Vector} The look at.
	 */
	getLookAt: function() {
		return this.lookAt;
	},
	/**
	 * Gets the current scale. Scale defined in the transformation is
	 * not taken into account.
	 *
	 * @return {!Grape2D.Vector} Scale
	 */
	getScale: function() {
		return this.scale;
	},
	/**
	 * Creates a shape, based on the camera transformation and
	 *   renderer properties.
	 *
	 * @param  {!Grape2D.Renderer} renderer The renderer.
	 * @return {!Grape2D.Shape} A bounding volume representing the
	 *   camera view region.
	 */
	computeShape: function(renderer) {
		var pos = new Grape2D.Vector().set(this.lookAt),
			w = renderer.getWidth() / this.scale.x,
			h = renderer.getHeight() / this.scale.y;

		return new Grape2D.AABB({
			position: pos,
			width: w,
			height: h
		});
	}
};<commit_msg>Fixed unauthorized usage of properties. They now use vector.setX(value), instead of vector.x = value<commit_after>/**
 * Camera is used to select the objects to display in a scene.
 *   A camera doesn't rotate or scale objects in the x and y axis,
 *   only the coordinates are changed to the transformation defined.
 *
 * @param {!Object=} options Setup options.
 * @param {!Grape2D.Vector=} options.scale The scale to be applied. There
 *		are two ways to define the scale. This method is one, the other
 *		is defined it directly in the transformation. If the two are set,
 *		then the two are applied.
 * @param {!Grape2D.Vector=} options.lookAt Defines the (center) position,
 *		to where the camera is looking at.
 * @param {!Grape2D.Matrix=} options.transformation Transformation matrix
 *		to be applied to the object coordinates.
 * @constructor
 */
Grape2D.Camera = function(options) {
	options = options || {};
	/**
	 * Scale relative to the camera initialization.
	 *
	 * @type {!Grape2D.Vector}
	 * @private
	 */
	this.rscale = new Grape2D.Vector(1, 1);
	/**
	 * Scale set by the user, should be defined in the matrix.
	 *
	 * @type {!Grape2D.Vector}
	 * @private
	 */
	this.scale = options.scale || new Grape2D.Vector(1, 1);
	/**
	 * The position to where the camera is looking at.
	 *
	 * @type {!Grape2D.Vector}
	 * @private
	 */
	this.lookAt = options.lookAt || new Grape2D.Vector();
	/**
	 * The transformation matrix to aply to the object coordinates.
	 *
	 * @type {!Grape2D.Matrix}
	 * @private
	 */
	this.transformation = options.transformation || new Grape2D.Matrix();

	/**
	 * Computed matrix
	 *
	 * @type {!Grape2D.Matrix}
	 * @private
	 */
	this.cM = new Grape2D.Matrix();
	/**
	 * Inverse of the computed matrix
	 *
	 * @type {!Grape2D.Matrix}
	 * @private
	 */
	this.icM = new Grape2D.Matrix();
	this.computeMatrix();
};

Grape2D.Camera.prototype = {
	constructor: Grape2D.Camera,
	/**
	 * Computes the matrix for better performances.
	 *
	 * @protected
	 */
	computeMatrix: function() {
		this.cM = this.transformation.clone();
		//This operations should work fine, and it avoids a multiplication
		//between the _cM matrix and a vector when converting coordinates
		this.cM.v[0] *= this.scale.getX() * this.rscale.getX();
		this.cM.v[1] *= this.scale.getX() * this.rscale.getX();
		this.cM.v[2] *= this.scale.getX() * this.rscale.getX();

		this.cM.v[3] *= this.scale.getY() * this.rscale.getY();
		this.cM.v[4] *= this.scale.getY() * this.rscale.getY();
		this.cM.v[5] *= this.scale.getY() * this.rscale.getY();

		this.icM = this.cM.clone().invert();
	},
	/**
	 * Applies the transformation, on a vector in the World Coordinate
	 * System (WCS), to get a vector in the Viewport (Renderer) Coordinate
	 * System (VSC).
	 *
	 * @param  {!Grape2D.Renderer} renderer The viewport.
	 * @param  {!Grape2D.Vector} vector Vector in the WCS.
	 * @return {!Grape2D.Vector} A vector in the VCS
	 * @public
	 */
	wcsToViewport: function(renderer, vector) {
		var v = this.cM.multiplyByVector(vector.clone().sub(this.lookAt));

		v.setX(v.getX()+renderer.getHalfWidth());
		v.setY(v.getY()+renderer.getHalfHeight());

		return v;
	},
	/**
	 * Applies the transformation, on a vector in the Viewport Coordinate
	 * System (VCS), to get a vector in the World Coordinate System (WSC).
	 *
	 * @param  {!Grape2D.Renderer} renderer The viewport.
	 * @param  {!Grape2D.Vector} vector Vector in the VCS.
	 * @return {!Grape2D.Vector} A vector in the WCS
	 * @public
	 */
	viewportToWcs: function(renderer, vector) {
		var v = vector.clone();

		v.setX(v.getX()-renderer.getHalfWidth());
		v.setY(v.getY()-renderer.getHalfHeight());

		v = this.icM.multiplyByVector(v).sub(this.lookAt);

		return v;
	},
	/**
	 * Sets a new scale.
	 *
	 * @param  {!Grape2D.Vector} scale The new scale.
	 * @public
	 */
	rescale: function(scale) {
		this.rscale.setX( scale.getX() / this.scale.getX() );
		this.rscale.setY( scale.getY() / this.scale.getY() );
		this.computeMatrix();
	},
	/**
	 * Sets the center position to where the camera is looking at.
	 *
	 * @param  {!Grape2D.Vector} position The new look at.
	 * @public
	 */
	setLookAt: function(position) {
		this.lookAt.set(position);
	},
	/**
	 * Gets the look at property.
	 *
	 * @return {!Grape2D.Vector} The look at.
	 */
	getLookAt: function() {
		return this.lookAt;
	},
	/**
	 * Gets the current scale. Scale defined in the transformation is
	 * not taken into account.
	 *
	 * @return {!Grape2D.Vector} Scale
	 */
	getScale: function() {
		return this.scale;
	},
	/**
	 * Creates a shape, based on the camera transformation and
	 *   renderer properties.
	 *
	 * @param  {!Grape2D.Renderer} renderer The renderer.
	 * @return {!Grape2D.Shape} A bounding volume representing the
	 *   camera view region.
	 */
	computeShape: function(renderer) {
		var pos = new Grape2D.Vector().set(this.lookAt),
			w = renderer.getWidth() / this.scale.getX(),
			h = renderer.getHeight() / this.scale.getY();

		return new Grape2D.AABB({
			position: pos,
			width: w,
			height: h
		});
	}
};<|endoftext|>


<commit_before>/**
 * @fileOverview Line
 */
import React, { Component, PropTypes } from 'react';
import { findDOMNode } from 'react-dom';
import Animate from 'react-smooth';
import classNames from 'classnames';
import pureRender from '../util/PureRender';
import Curve from '../shape/Curve';
import Dot from '../shape/Dot';
import Layer from '../container/Layer';
import { PRESENTATION_ATTRIBUTES, getPresentationAttributes } from '../util/ReactUtils';

@pureRender
class Line extends Component {

  static displayName = 'Line';

  static propTypes = {
    ...PRESENTATION_ATTRIBUTES,
    className: PropTypes.string,
    type: PropTypes.oneOf(['linear', 'monotone', 'step', 'stepBefore', 'stepAfter']),
    unit: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    name: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    dataKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
    yAxisId: PropTypes.number,
    xAxisId: PropTypes.number,
    legendType: PropTypes.string,

     // whether have dot in line
    dot: PropTypes.oneOfType([PropTypes.object, PropTypes.element, PropTypes.bool]),
    label: PropTypes.oneOfType([PropTypes.object, PropTypes.element, PropTypes.bool]),

    points: PropTypes.arrayOf(PropTypes.shape({
      x: PropTypes.number,
      y: PropTypes.number,
      value: PropTypes.value,
    })),
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func,
    onClick: PropTypes.func,
    isAnimationActive: PropTypes.bool,
    animationBegin: PropTypes.number,
    animationDuration: PropTypes.number,
    animationEasing: PropTypes.oneOf(['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear']),
  };

  static defaultProps = {
    xAxisId: 0,
    yAxisId: 0,
    dot: true,
    legendType: 'line',
    stroke: '#3182bd',
    strokeWidth: 1,
    fill: '#fff',
    points: [],
    onClick() {},
    onMouseEnter() {},
    onMouseLeave() {},
    isAnimationActive: true,
    animationBegin: 0,
    animationDuration: 1500,
    animationEasing: 'ease',
  };

  state = {
    isAnimationFinished: false,
    totalLength: 0,
  };

  constructor(props) {
    super(props);
    this.onClick = this.props.onClick.bind(this);
    this.onMouseEnter = this.props.onMouseEnter.bind(this);
    this.onMouseLeave = this.props.onMouseLeave.bind(this);
  }

  componentDidMount() {
    const { isAnimationActive } = this.props;

    if (!isAnimationActive) {
      return;
    }

    const curveDom = findDOMNode(this.refs.curve);
    const totalLength = (curveDom && curveDom.getTotalLength && curveDom.getTotalLength()) || 0;

    this.setState({ totalLength });
  }

  handleAnimationEnd() {
    this.setState({ isAnimationFinished: true });
  }

  renderDots() {
    const { isAnimationActive } = this.props;

    if (isAnimationActive && !this.state.isAnimationFinished) {
      return null;
    }

    const { dot, points } = this.props;
    const lineProps = getPresentationAttributes(this.props);
    const customDotProps = getPresentationAttributes(dot);
    const isDotElement = React.isValidElement(dot);

    const dots = points.map((entry, i) => {
      const dotProps = {
        key: `dot-${i}`,
        r: 3,
        ...lineProps,
        ...customDotProps,
        cx: entry.x,
        cy: entry.y,
        index: i,
        payload: entry,
      };

      return isDotElement ?
        React.cloneElement(dot, dotProps) :
        <Dot className="recharts-line-dot" {...dotProps} />;
    });

    return <Layer className="recharts-line-dots">{dots}</Layer>;
  }

  renderLabels() {
    const { points, label } = this.props;
    const lineProps = getPresentationAttributes(this.props);
    const customLabelProps = getPresentationAttributes(label);
    const isLabelElement = React.isValidElement(label);

    const labels = points.map((entry, i) => {
      const x = entry.x + entry.width / 2;
      const y = entry.y;
      const labelProps = {
        textAnchor: 'middle',
        ...entry,
        ...lineProps,
        ...customLabelProps,
        index: i,
        key: `label-${i}`,
        payload: entry,
      };

      return isLabelElement ?
        React.cloneElement(label, labelProps) :
        (<text {...labelProps} className="recharts-line-label">{entry.value}</text>);
    });

    return <Layer className="recharts-line-labels">{labels}</Layer>;
  }

  render() {
    const {
      dot,
      points,
      label,
      className,
      isAnimationActive,
      animationBegin,
      animationDuration,
      animationEasing,
      ...other,
    } = this.props;
    const { totalLength } = this.state;

    if (!points || !points.length) {
      return null;
    }
    const hasSinglePoint = points.length === 1;
    const layerClass = classNames('recharts-line', className);

    return (
      <Layer className={layerClass}>
        {!hasSinglePoint && (
          <Animate isActive={isAnimationActive}
            begin={animationBegin}
            canBegin={totalLength > 0}
            from={`0px ${(totalLength === 0 ? 1 : totalLength)} px`}
            to={`${totalLength} px 0px`}
            easing={animationEasing}
            duration={animationDuration}
            attributeName="strokeDasharray"
            onAnimationEnd={::this.handleAnimationEnd}
          >
            <Curve
              {...other}
              className="recharts-line-curve"
              fill="none"
              onClick={this.onClick}
              onMouseEnter={this.onMouseEnter}
              onMouseLeave={this.onMouseLeave}
              points={points}
              ref="curve"
            />
          </Animate>
        )}
        {(hasSinglePoint || dot) && this.renderDots()}
        {label && this.renderLabels()}
      </Layer>
    );
  }
}

export default Line;
<commit_msg>fix(cartesian/Line.js): fix Line animation bug<commit_after>/**
 * @fileOverview Line
 */
import React, { Component, PropTypes } from 'react';
import { findDOMNode } from 'react-dom';
import Animate from 'react-smooth';
import classNames from 'classnames';
import pureRender from '../util/PureRender';
import Curve from '../shape/Curve';
import Dot from '../shape/Dot';
import Layer from '../container/Layer';
import { PRESENTATION_ATTRIBUTES, getPresentationAttributes } from '../util/ReactUtils';

@pureRender
class Line extends Component {

  static displayName = 'Line';

  static propTypes = {
    ...PRESENTATION_ATTRIBUTES,
    className: PropTypes.string,
    type: PropTypes.oneOf(['linear', 'monotone', 'step', 'stepBefore', 'stepAfter']),
    unit: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    name: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    dataKey: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
    yAxisId: PropTypes.number,
    xAxisId: PropTypes.number,
    legendType: PropTypes.string,

     // whether have dot in line
    dot: PropTypes.oneOfType([PropTypes.object, PropTypes.element, PropTypes.bool]),
    label: PropTypes.oneOfType([PropTypes.object, PropTypes.element, PropTypes.bool]),

    points: PropTypes.arrayOf(PropTypes.shape({
      x: PropTypes.number,
      y: PropTypes.number,
      value: PropTypes.value,
    })),
    onMouseEnter: PropTypes.func,
    onMouseLeave: PropTypes.func,
    onClick: PropTypes.func,
    isAnimationActive: PropTypes.bool,
    animationBegin: PropTypes.number,
    animationDuration: PropTypes.number,
    animationEasing: PropTypes.oneOf(['ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear']),
  };

  static defaultProps = {
    xAxisId: 0,
    yAxisId: 0,
    dot: true,
    legendType: 'line',
    stroke: '#3182bd',
    strokeWidth: 1,
    fill: '#fff',
    points: [],
    onClick() {},
    onMouseEnter() {},
    onMouseLeave() {},
    isAnimationActive: true,
    animationBegin: 0,
    animationDuration: 1500,
    animationEasing: 'ease',
  };

  state = {
    isAnimationFinished: false,
    totalLength: 0,
  };

  constructor(props) {
    super(props);
    this.onClick = this.props.onClick.bind(this);
    this.onMouseEnter = this.props.onMouseEnter.bind(this);
    this.onMouseLeave = this.props.onMouseLeave.bind(this);
  }

  componentDidMount() {
    const { isAnimationActive } = this.props;

    if (!isAnimationActive) {
      return;
    }

    const curveDom = findDOMNode(this.refs.curve);
    const totalLength = (curveDom && curveDom.getTotalLength && curveDom.getTotalLength()) || 0;

    this.setState({ totalLength });
  }

  handleAnimationEnd() {
    this.setState({ isAnimationFinished: true });
  }

  renderDots() {
    const { isAnimationActive } = this.props;

    if (isAnimationActive && !this.state.isAnimationFinished) {
      return null;
    }

    const { dot, points } = this.props;
    const lineProps = getPresentationAttributes(this.props);
    const customDotProps = getPresentationAttributes(dot);
    const isDotElement = React.isValidElement(dot);

    const dots = points.map((entry, i) => {
      const dotProps = {
        key: `dot-${i}`,
        r: 3,
        ...lineProps,
        ...customDotProps,
        cx: entry.x,
        cy: entry.y,
        index: i,
        payload: entry,
      };

      return isDotElement ?
        React.cloneElement(dot, dotProps) :
        <Dot className="recharts-line-dot" {...dotProps} />;
    });

    return <Layer className="recharts-line-dots">{dots}</Layer>;
  }

  renderLabels() {
    const { points, label } = this.props;
    const lineProps = getPresentationAttributes(this.props);
    const customLabelProps = getPresentationAttributes(label);
    const isLabelElement = React.isValidElement(label);

    const labels = points.map((entry, i) => {
      const x = entry.x + entry.width / 2;
      const y = entry.y;
      const labelProps = {
        textAnchor: 'middle',
        ...entry,
        ...lineProps,
        ...customLabelProps,
        index: i,
        key: `label-${i}`,
        payload: entry,
      };

      return isLabelElement ?
        React.cloneElement(label, labelProps) :
        (<text {...labelProps} className="recharts-line-label">{entry.value}</text>);
    });

    return <Layer className="recharts-line-labels">{labels}</Layer>;
  }

  render() {
    const {
      dot,
      points,
      label,
      className,
      isAnimationActive,
      animationBegin,
      animationDuration,
      animationEasing,
      ...other,
    } = this.props;
    const { totalLength } = this.state;

    if (!points || !points.length) {
      return null;
    }
    const hasSinglePoint = points.length === 1;
    const layerClass = classNames('recharts-line', className);

    return (
      <Layer className={layerClass}>
        {!hasSinglePoint && (
          <Animate isActive={isAnimationActive}
            begin={animationBegin}
            canBegin={totalLength > 0}
            from={`0px ${(totalLength === 0 ? 1 : totalLength)}px`}
            to={`${totalLength}px 0px`}
            easing={animationEasing}
            duration={animationDuration}
            attributeName="strokeDasharray"
            onAnimationEnd={::this.handleAnimationEnd}
          >
            <Curve
              {...other}
              className="recharts-line-curve"
              fill="none"
              onClick={this.onClick}
              onMouseEnter={this.onMouseEnter}
              onMouseLeave={this.onMouseLeave}
              points={points}
              ref="curve"
            />
          </Animate>
        )}
        {(hasSinglePoint || dot) && this.renderDots()}
        {label && this.renderLabels()}
      </Layer>
    );
  }
}

export default Line;
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ImageStylePropTypes
 * @flow
 */
'use strict';

var ImageResizeMode = require('ImageResizeMode');
var LayoutPropTypes = require('LayoutPropTypes');
var ReactPropTypes = require('ReactPropTypes');

var ImageStylePropTypes = {
  ...LayoutPropTypes,
  resizeMode: ReactPropTypes.oneOf(Object.keys(ImageResizeMode)),
  backgroundColor: ReactPropTypes.string,
  borderColor: ReactPropTypes.string,
  borderWidth: ReactPropTypes.number,
  borderRadius: ReactPropTypes.number,

  // iOS-Specific style to "tint" an image.
  // It changes the color of all the non-transparent pixels to the tintColor
  tintColor: ReactPropTypes.string,
  opacity: ReactPropTypes.number,
};

// Image doesn't support padding correctly (#4841912)
var unsupportedProps = Object.keys({
  padding: null,
  paddingTop: null,
  paddingLeft: null,
  paddingRight: null,
  paddingBottom: null,
  paddingVertical: null,
  paddingHorizontal: null,
});

for (var i = 0; i < unsupportedProps.length; i++) {
  delete ImageStylePropTypes[unsupportedProps[i]];
}

module.exports = ImageStylePropTypes;
<commit_msg>[ReactNative] Remove padding restriction on images<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule ImageStylePropTypes
 * @flow
 */
'use strict';

var ImageResizeMode = require('ImageResizeMode');
var LayoutPropTypes = require('LayoutPropTypes');
var ReactPropTypes = require('ReactPropTypes');

var ImageStylePropTypes = {
  ...LayoutPropTypes,
  resizeMode: ReactPropTypes.oneOf(Object.keys(ImageResizeMode)),
  backgroundColor: ReactPropTypes.string,
  borderColor: ReactPropTypes.string,
  borderWidth: ReactPropTypes.number,
  borderRadius: ReactPropTypes.number,

  // iOS-Specific style to "tint" an image.
  // It changes the color of all the non-transparent pixels to the tintColor
  tintColor: ReactPropTypes.string,
  opacity: ReactPropTypes.number,
};

module.exports = ImageStylePropTypes;
<|endoftext|>


<commit_before>'use strict';
define(
    [
        'three',
        'SpaceShip',
        'Debug'
    ],
    function(THREE, SpaceShip, Debug) {
        return class Player extends SpaceShip {

            // ##############################################
            // # Constructor ################################
            // ##############################################

            constructor(scene, name, options) {
                if(!scene || !name || !options) {
                    throw new Error('Star has not been initialized properly.');
                }

                options.model = 'assets/models/ship.json';

                super(scene, name, options);

                this.accelerationChange = new THREE.Vector3(0, 0, 0);
            }

            // ##############################################
            // # Public functions ###########################
            // ##############################################

            accelerate() {
                this.accelerationChange.x = 2E-24;
            }

            // ##############################################

            decelerate() {
                this.accelerationChange.x = -2E-24;
            }

            // ##############################################

            turnLeft() {
                // Get the angle in radians so we can add to it
                let angle = Math.atan2(this.orientation.y, this.orientation.x);
                angle += 180 / Math.PI / 360 / 30;

                this.orientation.x = Math.cos(angle);
                this.orientation.y = Math.sin(angle);
            }

            // ##############################################

            turnRight() {
                // Get the angle in radians so we can add to it
                let angle = Math.atan2(this.orientation.y, this.orientation.x);
                angle -= 180 / Math.PI / 360 / 30;

                this.orientation.x = Math.cos(angle);
                this.orientation.y = Math.sin(angle);
            }

            // ##############################################

            update(deltaT, smoothDeltaT, spaceObjects) {
                super.update(deltaT, smoothDeltaT, spaceObjects);

                Debug.log(this.orientation);

                Debug.log(
                    Math.round(this.acceleration.x * 10000) / 10000 + ' ' +
                    Math.round(this.acceleration.y * 10000) / 10000 + ' ' +
                    Math.round(this.acceleration.z * 10000) / 10000
                );
            }

            // ##############################################

            force(position, mass, id, gameObjects) {
                let vec = super.force(position, mass, id, gameObjects);

                vec.add(this.accelerationChange.multiply(this.orientation));

                this.accelerationChange.set(0, 0, 0);

                return vec;
            }
        }
    }
);<commit_msg>Fixed parameter check<commit_after>'use strict';
define(
    [
        'three',
        'SpaceShip',
        'Debug'
    ],
    function(THREE, SpaceShip, Debug) {
        return class Player extends SpaceShip {

            // ##############################################
            // # Constructor ################################
            // ##############################################

            constructor(scene, name, options) {
                if(!scene || !name || !options || typeof(options) !== 'object') {
                    throw new Error('Player has not been initialized properly.');
                }

                options.model = 'assets/models/ship.json';

                super(scene, name, options);

                this.accelerationChange = new THREE.Vector3(0, 0, 0);
            }

            // ##############################################
            // # Public functions ###########################
            // ##############################################

            accelerate() {
                this.accelerationChange.x = 2E-24;
            }

            // ##############################################

            decelerate() {
                this.accelerationChange.x = -2E-24;
            }

            // ##############################################

            turnLeft() {
                // Get the angle in radians so we can add to it
                let angle = Math.atan2(this.orientation.y, this.orientation.x);
                angle += 180 / Math.PI / 360 / 30;

                this.orientation.x = Math.cos(angle);
                this.orientation.y = Math.sin(angle);
            }

            // ##############################################

            turnRight() {
                // Get the angle in radians so we can add to it
                let angle = Math.atan2(this.orientation.y, this.orientation.x);
                angle -= 180 / Math.PI / 360 / 30;

                this.orientation.x = Math.cos(angle);
                this.orientation.y = Math.sin(angle);
            }

            // ##############################################

            update(deltaT, smoothDeltaT, spaceObjects) {
                super.update(deltaT, smoothDeltaT, spaceObjects);

                Debug.log(this.orientation);

                Debug.log(
                    Math.round(this.acceleration.x * 10000) / 10000 + ' ' +
                    Math.round(this.acceleration.y * 10000) / 10000 + ' ' +
                    Math.round(this.acceleration.z * 10000) / 10000
                );
            }

            // ##############################################

            force(position, mass, id, gameObjects) {
                let vec = super.force(position, mass, id, gameObjects);

                vec.add(this.accelerationChange.multiply(this.orientation));

                this.accelerationChange.set(0, 0, 0);

                return vec;
            }
        }
    }
);<|endoftext|>


<commit_before>// @flow
import React, { Component } from 'react'
import expect from 'expect'
import { shallow, mount } from 'enzyme'
import jsdom from 'mocha-jsdom'

import styleSheet from '../models/StyleSheet'
import { resetStyled, expectCSSMatches } from './utils'

let styled

describe('basic', () => {
  /**
   * Make sure the setup is the same for every test
   */
  beforeEach(() => {
    styled = resetStyled()
  })

  it('should not throw an error when called', () => {
    styled.div``
  })

  it('should inject a stylesheet when a component is created', () => {
    const Comp = styled.div``
    shallow(<Comp />)
    expect(styleSheet.injected).toBe(true)
  })

  it('should generate only component class by default', () => {
    styled.div``
    expectCSSMatches('.sc-a {}')
  })

  it('should generate only component class even if rendered if no styles are passed', () => {
    const Comp = styled.div``
    shallow(<Comp />)
    expectCSSMatches('.sc-a {}')
  })

  it('should inject styles', () => {
    const Comp = styled.div`
      color: blue;
    `
    shallow(<Comp />)
    expectCSSMatches('.sc-a { } .b { color: blue; }')
  })

  it('should inject only once for a styled component, no matter how often it\'s mounted', () => {
    const Comp = styled.div`
      color: blue;
    `
    shallow(<Comp />)
    shallow(<Comp />)
    expectCSSMatches('.sc-a {} .b { color: blue; }')
  })

  describe('jsdom tests', () => {
    jsdom()

    let Comp
    let WrapperComp
    let wrapper

    beforeEach(() => {
      Comp = styled.div``
      WrapperComp = class extends Component {
        testRef: any;
        render() {
          return <Comp innerRef={(comp) => { this.testRef = comp }} />
        }
      }

      wrapper = mount(<WrapperComp />)
    })

    it('should pass ref to the component', () => {
      // $FlowFixMe
      expect(wrapper.node.testRef).toExist()
    })

    it('should not pass innerRef to the component', () => {
      // $FlowFixMe
      expect(wrapper.node.ref).toNotExist()
    })

    class InnerComponent extends Component {
      render() {
        return null
      }
    }

    it('should not leak the innerRef prop to the wrapped child', () => {
      const OuterComponent = styled(InnerComponent)``

      class Wrapper extends Component {
        testRef: any;

        render() {
          return <OuterComponent innerRef={(comp) => { this.testRef = comp }} />
        }
      }

      const wrapper = mount(<Wrapper />)
      const innerComponent = wrapper.find(InnerComponent).first()

      // $FlowFixMe
      expect(wrapper.node.testRef).toBe(innerComponent.node)
      expect(innerComponent.prop('innerRef')).toNotExist()
    })

    it('should pass the full className to the wrapped child', () => {
      const OuterComponent = styled(InnerComponent)``

      class Wrapper extends Component {
        render() {
          return <OuterComponent className="test"/>
        }
      }

      const wrapper = mount(<Wrapper />)
      expect(wrapper.find(InnerComponent).prop('className'))
        .toBe('test sc-c d')
    })

    it('should pass the innerRef to the wrapped styled component', () => {
      const OuterComponent = styled(Comp)``

      class Wrapper extends Component {
        testRef: any;
        innerRef = (comp) => { this.testRef = comp }

        render() {
          return <OuterComponent innerRef={this.innerRef} />
        }
      }

      const wrapper = mount(<Wrapper />)
      const innerComponent = wrapper.find(Comp).first()
      const outerComponent = wrapper.find(OuterComponent).first()

      // $FlowFixMe
      expect(wrapper.node.testRef).toBe(innerComponent.getDOMNode())

      // $FlowFixMe
      expect(innerComponent.prop('innerRef')).toBe(wrapper.node.innerRef)
    })
  })
})
<commit_msg>Replace dodgy innerRef test for single styled-component<commit_after>// @flow
import React, { Component } from 'react'
import expect from 'expect'
import { shallow, mount } from 'enzyme'
import jsdom from 'mocha-jsdom'

import styleSheet from '../models/StyleSheet'
import { resetStyled, expectCSSMatches } from './utils'

let styled

describe('basic', () => {
  /**
   * Make sure the setup is the same for every test
   */
  beforeEach(() => {
    styled = resetStyled()
  })

  it('should not throw an error when called', () => {
    styled.div``
  })

  it('should inject a stylesheet when a component is created', () => {
    const Comp = styled.div``
    shallow(<Comp />)
    expect(styleSheet.injected).toBe(true)
  })

  it('should generate only component class by default', () => {
    styled.div``
    expectCSSMatches('.sc-a {}')
  })

  it('should generate only component class even if rendered if no styles are passed', () => {
    const Comp = styled.div``
    shallow(<Comp />)
    expectCSSMatches('.sc-a {}')
  })

  it('should inject styles', () => {
    const Comp = styled.div`
      color: blue;
    `
    shallow(<Comp />)
    expectCSSMatches('.sc-a { } .b { color: blue; }')
  })

  it('should inject only once for a styled component, no matter how often it\'s mounted', () => {
    const Comp = styled.div`
      color: blue;
    `
    shallow(<Comp />)
    shallow(<Comp />)
    expectCSSMatches('.sc-a {} .b { color: blue; }')
  })

  describe('jsdom tests', () => {
    jsdom()

    it('should pass the ref to the component', () => {
      const Comp = styled.div``

      class Wrapper extends Component {
        testRef: any;
        innerRef = (comp) => { this.testRef = comp }

        render() {
          return <Comp innerRef={this.innerRef} />
        }
      }

      const wrapper = mount(<Wrapper />)
      const component = wrapper.find(Comp).first()

      // $FlowFixMe
      expect(wrapper.node.testRef).toBe(component.getDOMNode())
      expect(component.find('div').prop('innerRef')).toNotExist()
    })

    class InnerComponent extends Component {
      render() {
        return null
      }
    }

    it('should not leak the innerRef prop to the wrapped child', () => {
      const OuterComponent = styled(InnerComponent)``

      class Wrapper extends Component {
        testRef: any;

        render() {
          return <OuterComponent innerRef={(comp) => { this.testRef = comp }} />
        }
      }

      const wrapper = mount(<Wrapper />)
      const innerComponent = wrapper.find(InnerComponent).first()

      // $FlowFixMe
      expect(wrapper.node.testRef).toBe(innerComponent.node)
      expect(innerComponent.prop('innerRef')).toNotExist()
    })

    it('should pass the full className to the wrapped child', () => {
      const OuterComponent = styled(InnerComponent)``

      class Wrapper extends Component {
        render() {
          return <OuterComponent className="test"/>
        }
      }

      const wrapper = mount(<Wrapper />)
      expect(wrapper.find(InnerComponent).prop('className'))
        .toBe('test sc-a b')
    })

    it('should pass the innerRef to the wrapped styled component', () => {
      const InnerComponent = styled.div``
      const OuterComponent = styled(InnerComponent)``

      class Wrapper extends Component {
        testRef: any;
        innerRef = (comp) => { this.testRef = comp }

        render() {
          return <OuterComponent innerRef={this.innerRef} />
        }
      }

      const wrapper = mount(<Wrapper />)
      const innerComponent = wrapper.find(InnerComponent).first()
      const outerComponent = wrapper.find(OuterComponent).first()

      // $FlowFixMe
      expect(wrapper.node.testRef).toBe(innerComponent.getDOMNode())

      // $FlowFixMe
      expect(innerComponent.prop('innerRef')).toBe(wrapper.node.innerRef)
    })
  })
})
<|endoftext|>


<commit_before>import test from 'tape'
import Entry, { version } from '../entry'
import moment from 'moment'

test('Entry class has a version number', t => {
  const e = new Entry('8am-10am worked on things')
  t.ok(version >= 1, 'current version is 1')
  t.equals(e.version, version, 'new entries get version')

  t.end()
})

test('simple entry construction 8am-10pm', t => {
  const e = new Entry('8am-10am worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-10am worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 10, 'start is 10am')

  t.end()
})

test('simple entry construction 8am-5pm', t => {
  const e = new Entry('8am-5pm worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-5pm worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 17, 'end is 5pm')

  t.end()
})

test('no times specified does not generate dates', t => {
  const e = new Entry('worked on some things')
  const { start, end } = e.getDates()
  t.notOk(e.hasDates, 'flag indicates that no dates are present')
  t.notOk(start, 'no start date provided')
  t.notOk(end, 'no end date provided')

  t.end()
})

test('passing date influences the dates', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg, {date})
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start has the same day')
  t.ok(moment(end).isSame(date, 'day'), 'end has the same day')

  t.end()
})

test('no date defaults to today', t => {
  const date = new Date()
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg)
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start date is today')
  t.ok(moment(end).isSame(date, 'day'), 'end date is today')

  t.end()
})

test('created date added to entry', t => {
  const today = new Date()
  const e = new Entry('8am-5pm working on things')
  const json = e.toJSON()

  t.ok(e.ref, 'ref is set')
  t.ok(moment(today).isSame(e.ref, 'second'), 'ref date is today')
  t.ok(json.ref, 'ref is set on json')
  t.ok(moment(today).isSame(json.ref, 'second'), 'json.ref date is today')
  t.end()
})

test('passed reference date added to entry', t => {
  const date = new Date(2016, 0, 1, 12, 15, 30) // Jan 1, 2016 12:15:30
  const e = new Entry('8am-5pm working on things', {date})
  const json = e.toJSON()

  t.ok(e.ref, 'ref is set')
  t.ok(moment(date).isSame(e.ref, 'second'), 'ref date is Jan 1')
  t.ok(json.ref, 'ref is set on json')
  t.ok(moment(date).isSame(json.ref, 'second'), 'json.ref date is Jan 1')
  t.end()
})

test('duration set for 8am-10am', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e.duration, 'duration is present')
  t.equals(e.duration.hour, 2, '8am-10am is 2 hours')
  t.equals(e.duration.minute, 0, '8am-10am has 0 minutes')

  t.end()
})

test('duration set for 8am-1:30pm', t => {
  const e = new Entry('8am-1:30pm worked on some things')

  t.equals(e.duration.hour, 5, '8am-1:30pm is 5 hours')
  t.equals(e.duration.minute, 30, '8am-1:30pm trails 30 min')

  t.end()
})

test('duration set for 11pm-2am', t => {
  const e = new Entry('11pm-2am worked on some things')

  t.equals(e.duration.hour, 3, '11pm-2am is 3 hours')

  t.end()
})

test('includes yesterday in message', t => {
  const yesterday = moment().subtract(1, 'day')
  const e = new Entry('yesterday 4-5pm worked on some things #test')

  t.ok(yesterday.isSame(e.start, 'day'), 'sets start to yesterday')
  t.ok(yesterday.isSame(e.end, 'day'), 'sets end to yesterday')
  t.equals(e.time, 'yesterday 4-5pm', 'time component includes \'yesterday\'')

  t.end()
})

test('specific day of week in message', t => {
  const date = new Date(2016, 2, 24) // Thurs, March 24
  const monday = moment(new Date(2016, 2, 21)) // Mon, March 21
  const e = new Entry('monday 4-5pm worked on some things #test', {date})

  t.ok(monday.isSame(e.start, 'day'), 'start is monday')
  t.ok(monday.isSame(e.end, 'day'), 'end is monday')

  t.end()
})

test('specific date in message', t => {
  const date = new Date(2016, 2, 24) // Thurs, March 24
  const mar15 = moment(new Date(2016, 2, 15)) // Mon, March 21
  const e = new Entry('Mar 15 4-5pm worked on some things #test', {date})

  t.ok(mar15.isSame(e.start, 'day'), 'start is mar 15')
  t.ok(mar15.isSame(e.end, 'day'), 'end is mar 15')

  t.end()
})

test('constructor assigns _id', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e._id, '_id is ok')
  t.end()
})

test('parse #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag2')

  t.ok(e.tags.has('#tag1'), 'tags are parsed into a Set')
  t.ok(e.tags.has('#tag2'), 'tags are parsed into a Set')
  t.end()
})

test('parse unique #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag1')

  t.equals(e.tags.size, 1, 'tags only appear once')
  t.ok(e.tags.has('#tag1'), 'tags are parsed')
  t.end()
})

test('parse #hyphened-tags and #underscored_tags', t => {
  const e = new Entry('8-10am worked on things #hyphened-tag #underscored_tag')

  t.ok(e.tags.has('#hyphened-tag'), 'hyphened tag is parsed into a Set')
  t.ok(e.tags.has('#underscored_tag'), 'underscore tag is parsed into a Set')
  t.end()
})

test('parsed time string is present', t => {
  const e = new Entry('8-10am worked on things')

  t.equals(e.time, '8-10am', 'entry.time contains matched string')
  t.end()
})

test('toJSON() returns a json obj', t => {
  const e = new Entry('8am-10am worked on some things #tag1 #tag2')

  const json = e.toJSON()
  t.equals(json.message, '8am-10am worked on some things #tag1 #tag2', 'message')
  t.ok(json.hasDates, 'hasDates')
  t.equals(e.start, json.start, 'start')
  t.equals(e.end, json.end, 'end')
  t.equals(json.duration.seconds, 2*60*60, 'duration seconds')
  t.equals(json.time, e.time, 'time')
  t.equals(json._id, e._id, '_id')
  t.equals(json.version, version, 'version')
  t.deepEquals(json.tags, [...e.tags], 'tags array')
  t.ok(moment(json.startArr).isSame(json.start), 'start and startArr are same date')
  t.ok(moment(json.endArr).isSame(json.end), 'end and endArr are same date')
  t.ok(json.startArr instanceof Array, 'startArr is an array')
  t.ok(json.endArr instanceof Array, 'endArr is an array')

  t.end()
})

test('fromJSON() will create an Entry from existing document', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const existing = new Entry('8am-10am worked on things #tag1 #tag2', {date})
  const json = existing.toJSON()
  const e = Entry.fromJSON(json)

  t.equals(existing._id, e._id, '_id matches')
  t.equals(existing.version, e.version, 'version matches')
  t.equals(existing.message, e.message, 'message matches')
  t.equals(e.tags.size, 2, '2 tags')
  t.equals(moment(existing.start).toString(), moment(e.start).toString(), 'start matches')
  t.equals(moment(existing.end).toString(), moment(e.end).toString(), 'end matches')
  t.equals(moment(existing.ref).toString(), moment(e.ref).toString(), 'ref matches')
  t.equals(e.time, '8am-10am', 'time is preserved')

  t.end()

})
<commit_msg>test that 'Good Friday' parses, fails<commit_after>import test from 'tape'
import Entry, { version } from '../entry'
import moment from 'moment'

test('Entry class has a version number', t => {
  const e = new Entry('8am-10am worked on things')
  t.ok(version >= 1, 'current version is 1')
  t.equals(e.version, version, 'new entries get version')

  t.end()
})

test('simple entry construction 8am-10pm', t => {
  const e = new Entry('8am-10am worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-10am worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 10, 'start is 10am')

  t.end()
})

test('simple entry construction 8am-5pm', t => {
  const e = new Entry('8am-5pm worked on things')
  const { start, end } = e.getDates()
  t.ok(e.hasDates, 'entry has dates')
  t.equals(e.message, '8am-5pm worked on things')
  t.equals(start.getHours(), 8, 'start is 8am')
  t.equals(end.getHours(), 17, 'end is 5pm')

  t.end()
})

test('no times specified does not generate dates', t => {
  const e = new Entry('worked on some things')
  const { start, end } = e.getDates()
  t.notOk(e.hasDates, 'flag indicates that no dates are present')
  t.notOk(start, 'no start date provided')
  t.notOk(end, 'no end date provided')

  t.end()
})

test('passing date influences the dates', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg, {date})
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start has the same day')
  t.ok(moment(end).isSame(date, 'day'), 'end has the same day')

  t.end()
})

test('no date defaults to today', t => {
  const date = new Date()
  const msg = '8am-5pm worked on some things'
  const e = new Entry(msg)
  const { start, end } = e.getDates()

  t.ok(moment(start).isSame(date, 'day'), 'start date is today')
  t.ok(moment(end).isSame(date, 'day'), 'end date is today')

  t.end()
})

test('created date added to entry', t => {
  const today = new Date()
  const e = new Entry('8am-5pm working on things')
  const json = e.toJSON()

  t.ok(e.ref, 'ref is set')
  t.ok(moment(today).isSame(e.ref, 'second'), 'ref date is today')
  t.ok(json.ref, 'ref is set on json')
  t.ok(moment(today).isSame(json.ref, 'second'), 'json.ref date is today')
  t.end()
})

test('passed reference date added to entry', t => {
  const date = new Date(2016, 0, 1, 12, 15, 30) // Jan 1, 2016 12:15:30
  const e = new Entry('8am-5pm working on things', {date})
  const json = e.toJSON()

  t.ok(e.ref, 'ref is set')
  t.ok(moment(date).isSame(e.ref, 'second'), 'ref date is Jan 1')
  t.ok(json.ref, 'ref is set on json')
  t.ok(moment(date).isSame(json.ref, 'second'), 'json.ref date is Jan 1')
  t.end()
})

test('duration set for 8am-10am', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e.duration, 'duration is present')
  t.equals(e.duration.hour, 2, '8am-10am is 2 hours')
  t.equals(e.duration.minute, 0, '8am-10am has 0 minutes')

  t.end()
})

test('duration set for 8am-1:30pm', t => {
  const e = new Entry('8am-1:30pm worked on some things')

  t.equals(e.duration.hour, 5, '8am-1:30pm is 5 hours')
  t.equals(e.duration.minute, 30, '8am-1:30pm trails 30 min')

  t.end()
})

test('duration set for 11pm-2am', t => {
  const e = new Entry('11pm-2am worked on some things')

  t.equals(e.duration.hour, 3, '11pm-2am is 3 hours')

  t.end()
})

test('includes yesterday in message', t => {
  const yesterday = moment().subtract(1, 'day')
  const e = new Entry('yesterday 4-5pm worked on some things #test')

  t.ok(yesterday.isSame(e.start, 'day'), 'sets start to yesterday')
  t.ok(yesterday.isSame(e.end, 'day'), 'sets end to yesterday')
  t.equals(e.time, 'yesterday 4-5pm', 'time component includes \'yesterday\'')

  t.end()
})

test('specific day of week in message', t => {
  const date = new Date(2016, 2, 24) // Thurs, March 24
  const monday = moment(new Date(2016, 2, 21)) // Mon, March 21
  const e = new Entry('monday 4-5pm worked on some things #test', {date})

  t.ok(monday.isSame(e.start, 'day'), 'start is monday')
  t.ok(monday.isSame(e.end, 'day'), 'end is monday')

  t.end()
})

test('specific date in message', t => {
  const date = new Date(2016, 2, 24) // Thurs, March 24
  const mar15 = moment(new Date(2016, 2, 15)) // Mon, March 21
  const e = new Entry('Mar 15 4-5pm worked on some things #test', {date})

  t.ok(mar15.isSame(e.start, 'day'), 'start is mar 15')
  t.ok(mar15.isSame(e.end, 'day'), 'end is mar 15')

  t.end()
})

test('proper holiday names', t => {
  const date = new Date(2016, 2, 25) // Fri, March 25
  const e = new Entry('8-4pm Good Friday #stat', {date})

  t.ok(moment(date).isSame(e.start, 'day'), 'start is good friday')
  t.ok(moment(date).isSame(e.end, 'day'), 'end is good friday')

  t.end()
})

test('constructor assigns _id', t => {
  const e = new Entry('8am-10am worked on some things')

  t.ok(e._id, '_id is ok')
  t.end()
})

test('parse #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag2')

  t.ok(e.tags.has('#tag1'), 'tags are parsed into a Set')
  t.ok(e.tags.has('#tag2'), 'tags are parsed into a Set')
  t.end()
})

test('parse unique #tags', t => {
  const e = new Entry('8-10am worked on things #tag1 #tag1')

  t.equals(e.tags.size, 1, 'tags only appear once')
  t.ok(e.tags.has('#tag1'), 'tags are parsed')
  t.end()
})

test('parse #hyphened-tags and #underscored_tags', t => {
  const e = new Entry('8-10am worked on things #hyphened-tag #underscored_tag')

  t.ok(e.tags.has('#hyphened-tag'), 'hyphened tag is parsed into a Set')
  t.ok(e.tags.has('#underscored_tag'), 'underscore tag is parsed into a Set')
  t.end()
})

test('parsed time string is present', t => {
  const e = new Entry('8-10am worked on things')

  t.equals(e.time, '8-10am', 'entry.time contains matched string')
  t.end()
})

test('toJSON() returns a json obj', t => {
  const e = new Entry('8am-10am worked on some things #tag1 #tag2')

  const json = e.toJSON()
  t.equals(json.message, '8am-10am worked on some things #tag1 #tag2', 'message')
  t.ok(json.hasDates, 'hasDates')
  t.equals(e.start, json.start, 'start')
  t.equals(e.end, json.end, 'end')
  t.equals(json.duration.seconds, 2*60*60, 'duration seconds')
  t.equals(json.time, e.time, 'time')
  t.equals(json._id, e._id, '_id')
  t.equals(json.version, version, 'version')
  t.deepEquals(json.tags, [...e.tags], 'tags array')
  t.ok(moment(json.startArr).isSame(json.start), 'start and startArr are same date')
  t.ok(moment(json.endArr).isSame(json.end), 'end and endArr are same date')
  t.ok(json.startArr instanceof Array, 'startArr is an array')
  t.ok(json.endArr instanceof Array, 'endArr is an array')

  t.end()
})

test('fromJSON() will create an Entry from existing document', t => {
  const date = new Date('Jan 25, 2015 0:00:00')
  const existing = new Entry('8am-10am worked on things #tag1 #tag2', {date})
  const json = existing.toJSON()
  const e = Entry.fromJSON(json)

  t.equals(existing._id, e._id, '_id matches')
  t.equals(existing.version, e.version, 'version matches')
  t.equals(existing.message, e.message, 'message matches')
  t.equals(e.tags.size, 2, '2 tags')
  t.equals(moment(existing.start).toString(), moment(e.start).toString(), 'start matches')
  t.equals(moment(existing.end).toString(), moment(e.end).toString(), 'end matches')
  t.equals(moment(existing.ref).toString(), moment(e.ref).toString(), 'ref matches')
  t.equals(e.time, '8am-10am', 'time is preserved')

  t.end()

})
<|endoftext|>


<commit_before>var ModelCube = {
	// color and normal
	vertices: [
		-1.0, 1.0, 1.0,		0.0, 1.0, 0.0,
		1.0, 1.0, 1.0,		0.0, 1.0, 0.0,
		1.0, 1.0, -1.0,		0.0, 1.0, 0.0,
		-1.0, 1.0, -1.0,	0.0, 1.0, 0.0,

		-1.0, -1.0, 1.0,	0.0, -1.0, 0.0,
		1.0, -1.0, 1.0,		0.0, -1.0, 0.0,
		1.0, -1.0, -1.0,	0.0, -1.0, 0.0,
		-1.0, -1.0, -1.0,	0.0, -1.0, 0.0,

		-1.0, -1.0, -1.0,	-1.0, 0.0, 0.0,
		-1.0, -1.0, 1.0,	-1.0, 0.0, 0.0,
		-1.0, 1.0, 1.0,		-1.0, 0.0, 0.0,
		-1.0, 1.0, -1.0,	-1.0, 0.0, 0.0,

		1.0, -1.0, -1.0,	1.0, 0.0, 0.0,
		1.0, -1.0, 1.0,		1.0, 0.0, 0.0,
		1.0, 1.0, 1.0,		1.0, 0.0, 0.0,
		1.0, 1.0, -1.0,		1.0, 0.0, 0.0,

		-1.0, -1.0, 1.0,	0.0, 0.0, 1.0,
		1.0, -1.0, 1.0,		0.0, 0.0, 1.0,
		1.0, 1.0, 1.0,		0.0, 0.0, 1.0,
		-1.0, 1.0, 1.0,		0.0, 0.0, 1.0,

		-1.0, -1.0, -1.0,	0.0, 0.0, -1.0,
		1.0, -1.0, -1.0,	0.0, 0.0, -1.0,
		1.0, 1.0, -1.0,		0.0, 0.0, -1.0,
		-1.0, 1.0, -1.0,	0.0, 0.0, -1.0,
	],

    indices: [
        3,0,1,		2,3,1,

        6,5,4,		7,6,4,

        11,8,9,		10,11,9,

        14,13,12,	15,14,12,

        19,16,17,	18,19,17,

        22,21,20,	23,22,20
    ]
};
<commit_msg>correct a comment<commit_after>var ModelCube = {
	// position and normal
	vertices: [
		-1.0, 1.0, 1.0,		0.0, 1.0, 0.0,
		1.0, 1.0, 1.0,		0.0, 1.0, 0.0,
		1.0, 1.0, -1.0,		0.0, 1.0, 0.0,
		-1.0, 1.0, -1.0,	0.0, 1.0, 0.0,

		-1.0, -1.0, 1.0,	0.0, -1.0, 0.0,
		1.0, -1.0, 1.0,		0.0, -1.0, 0.0,
		1.0, -1.0, -1.0,	0.0, -1.0, 0.0,
		-1.0, -1.0, -1.0,	0.0, -1.0, 0.0,

		-1.0, -1.0, -1.0,	-1.0, 0.0, 0.0,
		-1.0, -1.0, 1.0,	-1.0, 0.0, 0.0,
		-1.0, 1.0, 1.0,		-1.0, 0.0, 0.0,
		-1.0, 1.0, -1.0,	-1.0, 0.0, 0.0,

		1.0, -1.0, -1.0,	1.0, 0.0, 0.0,
		1.0, -1.0, 1.0,		1.0, 0.0, 0.0,
		1.0, 1.0, 1.0,		1.0, 0.0, 0.0,
		1.0, 1.0, -1.0,		1.0, 0.0, 0.0,

		-1.0, -1.0, 1.0,	0.0, 0.0, 1.0,
		1.0, -1.0, 1.0,		0.0, 0.0, 1.0,
		1.0, 1.0, 1.0,		0.0, 0.0, 1.0,
		-1.0, 1.0, 1.0,		0.0, 0.0, 1.0,

		-1.0, -1.0, -1.0,	0.0, 0.0, -1.0,
		1.0, -1.0, -1.0,	0.0, 0.0, -1.0,
		1.0, 1.0, -1.0,		0.0, 0.0, -1.0,
		-1.0, 1.0, -1.0,	0.0, 0.0, -1.0,
	],

    indices: [
        3,0,1,		2,3,1,

        6,5,4,		7,6,4,

        11,8,9,		10,11,9,

        14,13,12,	15,14,12,

        19,16,17,	18,19,17,

        22,21,20,	23,22,20
    ]
};
<|endoftext|>


<commit_before>define(['text!./material-carousel.html', '../tools/animations'],
function(htmlString, animations) {

	function ViewModel(params) {
		this.frameCount = ko.observable();
		this.interval = params.interval || 10000; //10 seconds by default

		var self = this;
		this.frames = ko.pureComputed(function() {
			return new Array(self.frameCount());
		});
	}
	ViewModel.prototype = {
	};

	ko.bindingHandlers._material_carousel = {
		'init': function(element, valueAccessor) {
			var el = $(element),
				frames = el.find('.frame');

			if (!frames.length) {
				//the component template hasn't been injected yet, must wait
				var initFn = arguments.callee;
				setTimeout(function() {
					initFn(element, valueAccessor);
				}, 50);
				return;
			}

			var options = ko.unwrap(valueAccessor());
			options.frameCount(frames.length);

			setTimeout(function() { //wait for DOM update
				var controls = el.find('.control'),
					stopOnClickFrames = el.find('.stop-on-click'),
					selection = 0,
					animating = false,
					interval = setInterval(tick, options.interval);

				selectFrame(0);

				controls.each(function(index, el) {
					$(el).click(function() {
						stop();
						animateToFrame(index, animations.timing, true);
					});
				});

				stopOnClickFrames.each(function(index, el) {
					if (!$(el).is('iframe'))
						$(el).click(stop);
					else {
						var listener = window.addEventListener('blur', function() {
							if (document.activeElement === el) {
								stop();
								window.removeEventListener('blur', listener);
							}
						});
					}
				});

				ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
					clearInterval(interval);
					controls.each(function(el) {
						$(el).off('click');
					});
				});

				//#region Internal functions

				function tick() {
					animateToFrame((selection + 1) % frames.length, animations.carouselTiming);
				}

				function selectFrame(newSelection) {
					$(frames[newSelection]).addClass('selected');
					$(controls[newSelection]).addClass('selected');
					selection = newSelection;
				}

				function animateToFrame(newSelection, timing, correctDirection) {
					if (selection == newSelection || animating)
						return;

					animating = true;
					var overflowContainer = $(element).addClass('hide-overflow-x');
					$(element).data('selectedTab', newSelection);

					var selectedEl = el.find('.frames > .frame.selected'),
						newSelectedEl = el.find('.frames > .frame:nth-child(' + (newSelection + 1) + ')');

					var selectedElAnimation = animations.slideLeft,
						newSelectionAnimation = animations.slideFromRight;

					if (correctDirection && selection > newSelection) {
						selectedElAnimation = animations.slideRight;
						newSelectionAnimation = animations.slideFromLeft;
					}

					$(controls[selection]).removeClass('selected');
					$(controls[newSelection]).addClass('selected');
					controls.addClass('animating');

					selectedEl.addClass('animating').removeClass('selected');
					var anim1 = selectedEl[0].animate(selectedElAnimation, timing);
					anim1.onfinish = function() {
						selectedEl.removeClass('animating');
					};

					newSelectedEl.addClass('animating selected');
					var anim2 = newSelectedEl[0].animate(newSelectionAnimation, timing);
					anim2.onfinish = function() {
						controls.removeClass('animating');
						newSelectedEl.removeClass('animating');
						overflowContainer.removeClass('hide-overflow-x');
						selection = newSelection;
						animating = false;
					};
				}

				function stop() {
					if (interval) {
						clearInterval(interval);
						interval = null;
					}
				}

				//#endregion
			});
		}
	};

    return {
		'viewModel': ViewModel,
		'template': htmlString
	};
});
<commit_msg>Changed material-carousel behavior<commit_after>define(['text!./material-carousel.html', '../tools/animations'],
function(htmlString, animations) {

	function ViewModel(params) {
		this.frameCount = ko.observable();
		this.interval = params.interval || 10000; //10 seconds by default

		var self = this;
		this.frames = ko.pureComputed(function() {
			return new Array(self.frameCount());
		});
	}

	ko.bindingHandlers._material_carousel = (function() {
		var init = function(element, valueAccessor) {
			var el = $(element),
				options = ko.unwrap(valueAccessor()),
				frames = el.find('.frame');

			if (!frames.length) {
				//the component template hasn't been injected yet, must wait
				setTimeout(function() {
					init(element, valueAccessor);
				}, 50);
				return;
			}
			options.frameCount(frames.length);
			setTimeout(boot); //wait for DOM update before boot
			return;

			function boot() {
				var controls = el.find('.control'),
					stopOnClickFrames = el.find('.stop-on-click'),
					selection = 0,
					animating = false,
					interval;

				controls.each(function(index, el) {
					$(el).click(function() {
						stop();
						animateToFrame(index, animations.timing, true);
					});
				});

				stopOnClickFrames.each(function(index, el) {
					if (!$(el).is('iframe'))
						$(el).click(stop);
					else {
						var listener = window.addEventListener('blur', function() {
							if (document.activeElement === el) {
								stop();
								window.removeEventListener('blur', listener);
							}
						});
					}
				});

				//set up observer to start the carousel spin when it becomes visible
				var observer = new IntersectionObserver(function(entries) {
					entries.forEach(function(entry) {
						if (entry.isIntersecting)
							start();
						else
							stop();
					});
				});
				observer.observe(element);

				ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
					observer.unobserve(element);
					stop();
					controls.each(function(el) {
						$(el).off('click');
					});
				});

				selectFrame(0);
				return;

				//#region Internal functions

				function selectFrame(newSelection) {
					$(frames[newSelection]).addClass('selected');
					$(controls[newSelection]).addClass('selected');
					selection = newSelection;
				}

				function start() {
					if (!interval)
						interval = setInterval(tick, options.interval);

					function tick() {
						animateToFrame((selection + 1) % frames.length, animations.carouselTiming);
					}
				}

				function stop() {
					if (interval) {
						clearInterval(interval);
						interval = null;
					}
				}

				function animateToFrame(newSelection, timing, correctDirection) {
					if (selection == newSelection || animating)
						return;

					animating = true;
					var overflowContainer = $(element).addClass('hide-overflow-x');
					$(element).data('selectedTab', newSelection);

					var selectedEl = el.find('.frames > .frame.selected'),
						newSelectedEl = el.find('.frames > .frame:nth-child(' + (newSelection + 1) + ')');

					var selectedElAnimation = animations.slideLeft,
						newSelectionAnimation = animations.slideFromRight;

					if (correctDirection && selection > newSelection) {
						selectedElAnimation = animations.slideRight;
						newSelectionAnimation = animations.slideFromLeft;
					}

					$(controls[selection]).removeClass('selected');
					$(controls[newSelection]).addClass('selected');
					controls.addClass('animating');

					selectedEl.addClass('animating').removeClass('selected');
					var anim1 = selectedEl[0].animate(selectedElAnimation, timing);
					anim1.onfinish = function() {
						selectedEl.removeClass('animating');
					};

					newSelectedEl.addClass('animating selected');
					var anim2 = newSelectedEl[0].animate(newSelectionAnimation, timing);
					anim2.onfinish = function() {
						controls.removeClass('animating');
						newSelectedEl.removeClass('animating');
						overflowContainer.removeClass('hide-overflow-x');
						selection = newSelection;
						animating = false;
					};
				}

				//#endregion
			}
		};
		return {
			'init': init
		};
	})();

    return {
		'viewModel': ViewModel,
		'template': htmlString
	};
});
<|endoftext|>


<commit_before>
/* medea - an Open Source, WebGL-based 3d engine for next-generation browser games.
 * (or alternatively, for clumsy and mostly useless tech demos written solely for fun)
 *
 * medea is (c) 2011, Alexander C. Gessler
 * licensed under the terms and conditions of the 3-clause BSD license.
 */

 // note: json2.js may be needed for contemporary browsers with incomplete HTML5 support
medea.define('sceneloader_assimp2json',['mesh','filesystem', 'json2.js'],function(undefined) {
	"use strict";
	var medea = this;

	var LoadMaterial = function(w,material_idx) {
		if (w.materials[material_idx]) {
			return w.materials[material_idx];
		}
		var inmaterial = w.scene.materials[material_idx].properties, props = {};

		// scan for some common material properties and pass them on to
		// the user-defined material resolver, whose task is to match
		// those standard properties to the application's material
		// framework.
		for(var i = 0; i < inmaterial.length; ++i) {
			var prop = inmaterial[i];

			if(prop.key === '$clr.diffuse') {
				props['diffuse'] = prop.value;
			}
			else if(prop.key === '$clr.specular') {
				props['specular'] = prop.value;
			}
			else if(prop.key === '$clr.diffuse') {
				props['diffuse'] = prop.value;
			}
			else if(prop.key === '$clr.emissive') {
				props['emissive'] = prop.value;
			}
			else if(prop.key === '$mat.shininess') {
				props['shininess'] = prop.value;
			}
			else if(prop.key === '$mat.shadingm') {
				props['shading_model'] = {
					3 : 'Phong',
					4 : 'Blinn',
					5 : 'Toon'
				}[prop.value] || 'Gouraud';
			}
			else if(prop.key === '$tex.file') {
				var n = {
					1 : 'diffuse',
					2 : 'specular',
					3 : 'ambient',
					4 : 'emissive',
					5 : 'height',
					6 : 'normal',
					7 : 'shininess',
					8 : 'opacity'
				}[prop.semantic];

				if(n) {
					props[n+'_texture'] = prop.value;

				}
			}
		}

		var mat = w.materials[material_idx] = w.material_resolver(props);
		mat.imported_mat_data = props;
		return mat;
	};

	var LoadMesh = function(w,mesh_idx) {
		if (w.meshes[mesh_idx]) {
			return w.meshes[mesh_idx];
		}
		var inmesh = w.scene.meshes[mesh_idx];

		// requirements: only one primitive type per mesh, no polygons
		// this should always be fullfilled for scenes produced by the original assimp2json tool.
		if(inmesh.primitivetypes !== 1 && inmesh.primitivetypes !== 2 && inmesh.primitivetypes !== 4) {
			throw "expect pure, triangulated meshes with only a single type of primitives";
		}

		// the same applies to the number of unique vertices in the mesh -
		// with the original assimp2json tool, we can always fit them
		// into 16 bit index buffers.
		if(inmesh.vertices.length >= 65536) {
			throw "mesh size is too big, need to be able to use 16 bit indices";
		}

		var indices = new Array(inmesh.faces.length*inmesh.faces[0].length);
		for(var i = 0, n = 0, end = inmesh.faces.length; i < end; ++i) {
			var f = inmesh.faces[i];
			for(var j = 0, e = f.length; j < e; ++j, ++n) {
				indices[n] = f[j];
			}
		}

		// note: this modifies the input mesh, but copying would be too expensive
		// and would bring no extra value, after all we access each mesh only once.
		inmesh['positions'] = inmesh['vertices'];
		inmesh['uvs'] = inmesh['texturecoords'];

		// flip v component of UV coordinates
		if(inmesh['uvs']) {
			for(var i = 0; i < inmesh['uvs'].length; ++i) {
				var uv = inmesh['uvs'][i], c = inmesh['numuvcomponents'][i];
				for(var n = 0, e = uv.length/c; n < e; ++n) {
					uv[n*c+1] = 1.0-uv[n*c+1];
				}
			}
		}

		var outmesh = medea.CreateSimpleMesh(inmesh,indices,LoadMaterial(w,inmesh.materialindex));

		w.meshes[mesh_idx] = outmesh;
		return outmesh;
	};

	var LoadNode = function(w,anchor,node) {

		var outnd = anchor.AddChild(node.name);
		outnd.LocalTransform(mat4.transpose(mat4.create(node.transformation)));

		if(node.meshes) {
			for(var i = 0; i < node.meshes.length; ++i) {
				outnd.AddEntity(LoadMesh(w,node.meshes[i]));
			}
		}

		if(node.children) {
			for(var i = 0; i < node.children.length; ++i) {
				LoadNode(w,outnd,node.children[i]);
			}
		}
	};

	var LoadScene = function(scene,anchor,callback,material_resolver) {
		// batch the working set together in a dumpbin and pass it around to get rid of parameter hell
		var working = {
			callback : callback,
			scene : scene,
			material_resolver : material_resolver,

			meshes : new Array(scene.meshes.length),
			materials : new Array(scene.materials.length)
		};

		LoadNode(working,anchor,scene.rootnode);
		callback(true);
	};

	medea._LoadScene_assimp2json = function(src,anchor,callback,material_resolver) {
		medea.DebugAssert(material_resolver, "need a valid material resolver");

		// see if we got a JSON DOM or a unparsed string
		if(src.rootnode === undefined) {
			try {
				src = JSON.parse(src);
			}
			catch(e) {
				// #ifdef DEBUG
				medea.DebugAssert("Failed to read assimp2json scene from JSON, JSON.parse failed: " + e);
				callback(false);
				// #endif
				return;
			}
		}

		try {
			LoadScene(src, anchor, callback, material_resolver);
		}
		catch(e) {
			// #ifdef DEBUG
			medea.DebugAssert("Failed to read assimp2json scene: " + e);
			callback(false);
			// #endif
			return;
		}
	};
}, ['_LoadScene_assimp2json']);

<commit_msg>sceneloader_assimp2json: fix erroneous error message.<commit_after>
/* medea - an Open Source, WebGL-based 3d engine for next-generation browser games.
 * (or alternatively, for clumsy and mostly useless tech demos written solely for fun)
 *
 * medea is (c) 2011, Alexander C. Gessler
 * licensed under the terms and conditions of the 3-clause BSD license.
 */

 // note: json2.js may be needed for contemporary browsers with incomplete HTML5 support
medea.define('sceneloader_assimp2json',['mesh','filesystem', 'json2.js'],function(undefined) {
	"use strict";
	var medea = this;

	var LoadMaterial = function(w,material_idx) {
		if (w.materials[material_idx]) {
			return w.materials[material_idx];
		}
		var inmaterial = w.scene.materials[material_idx].properties, props = {};

		// scan for some common material properties and pass them on to
		// the user-defined material resolver, whose task is to match
		// those standard properties to the application's material
		// framework.
		for(var i = 0; i < inmaterial.length; ++i) {
			var prop = inmaterial[i];

			if(prop.key === '$clr.diffuse') {
				props['diffuse'] = prop.value;
			}
			else if(prop.key === '$clr.specular') {
				props['specular'] = prop.value;
			}
			else if(prop.key === '$clr.diffuse') {
				props['diffuse'] = prop.value;
			}
			else if(prop.key === '$clr.emissive') {
				props['emissive'] = prop.value;
			}
			else if(prop.key === '$mat.shininess') {
				props['shininess'] = prop.value;
			}
			else if(prop.key === '$mat.shadingm') {
				props['shading_model'] = {
					3 : 'Phong',
					4 : 'Blinn',
					5 : 'Toon'
				}[prop.value] || 'Gouraud';
			}
			else if(prop.key === '$tex.file') {
				var n = {
					1 : 'diffuse',
					2 : 'specular',
					3 : 'ambient',
					4 : 'emissive',
					5 : 'height',
					6 : 'normal',
					7 : 'shininess',
					8 : 'opacity'
				}[prop.semantic];

				if(n) {
					props[n+'_texture'] = prop.value;

				}
			}
		}

		var mat = w.materials[material_idx] = w.material_resolver(props);
		mat.imported_mat_data = props;
		return mat;
	};

	var LoadMesh = function(w,mesh_idx) {
		if (w.meshes[mesh_idx]) {
			return w.meshes[mesh_idx];
		}
		var inmesh = w.scene.meshes[mesh_idx];

		// requirements: only one primitive type per mesh, no polygons
		// this should always be fullfilled for scenes produced by the original assimp2json tool.
		if(inmesh.primitivetypes !== 1 && inmesh.primitivetypes !== 2 && inmesh.primitivetypes !== 4) {
			throw "expect pure, triangulated meshes with only a single type of primitives";
		}

		// the same applies to the number of unique vertices in the mesh -
		// with the original assimp2json tool, we can always fit them
		// into 16 bit index buffers.
		if(inmesh.vertices.length > 65536 * 3) {
			throw "mesh size is too big, need to be able to use 16 bit indices";
		}

		var indices = new Array(inmesh.faces.length*inmesh.faces[0].length);
		for(var i = 0, n = 0, end = inmesh.faces.length; i < end; ++i) {
			var f = inmesh.faces[i];
			for(var j = 0, e = f.length; j < e; ++j, ++n) {
				indices[n] = f[j];
			}
		}

		// note: this modifies the input mesh, but copying would be too expensive
		// and would bring no extra value, after all we access each mesh only once.
		inmesh['positions'] = inmesh['vertices'];
		inmesh['uvs'] = inmesh['texturecoords'];

		// flip v component of UV coordinates
		if(inmesh['uvs']) {
			for(var i = 0; i < inmesh['uvs'].length; ++i) {
				var uv = inmesh['uvs'][i], c = inmesh['numuvcomponents'][i];
				for(var n = 0, e = uv.length/c; n < e; ++n) {
					uv[n*c+1] = 1.0-uv[n*c+1];
				}
			}
		}

		var outmesh = medea.CreateSimpleMesh(inmesh,indices,LoadMaterial(w,inmesh.materialindex));

		w.meshes[mesh_idx] = outmesh;
		return outmesh;
	};

	var LoadNode = function(w,anchor,node) {

		var outnd = anchor.AddChild(node.name);
		outnd.LocalTransform(mat4.transpose(mat4.create(node.transformation)));

		if(node.meshes) {
			for(var i = 0; i < node.meshes.length; ++i) {
				outnd.AddEntity(LoadMesh(w,node.meshes[i]));
			}
		}

		if(node.children) {
			for(var i = 0; i < node.children.length; ++i) {
				LoadNode(w,outnd,node.children[i]);
			}
		}
	};

	var LoadScene = function(scene,anchor,callback,material_resolver) {
		// batch the working set together in a dumpbin and pass it around to get rid of parameter hell
		var working = {
			callback : callback,
			scene : scene,
			material_resolver : material_resolver,

			meshes : new Array(scene.meshes.length),
			materials : new Array(scene.materials.length)
		};

		LoadNode(working,anchor,scene.rootnode);
		callback(true);
	};

	medea._LoadScene_assimp2json = function(src,anchor,callback,material_resolver) {
		medea.DebugAssert(material_resolver, "need a valid material resolver");

		// see if we got a JSON DOM or a unparsed string
		if(src.rootnode === undefined) {
			try {
				src = JSON.parse(src);
			}
			catch(e) {
				// #ifdef DEBUG
				medea.DebugAssert("Failed to read assimp2json scene from JSON, JSON.parse failed: " + e);
				callback(false);
				// #endif
				return;
			}
		}

		try {
			LoadScene(src, anchor, callback, material_resolver);
		}
		catch(e) {
			// #ifdef DEBUG
			medea.DebugAssert("Failed to read assimp2json scene: " + e);
			callback(false);
			// #endif
			return;
		}
	};
}, ['_LoadScene_assimp2json']);

<|endoftext|>


<commit_before>(function () {
    'use strict';

    describe('The todo controller', function () {
        var $scope, controller, $controller, $compile, $q, todoService;
        var completedTodo = {description: 'do something else', completed: true},
            testData = [
                {
                    "description": "do something",
                    "completed": false
                },
                completedTodo
            ];

        beforeEach(function () {
            module('todo');

            inject(function ($rootScope, _$controller_, _$compile_, _$q_, _todoService_) {
                $scope = $rootScope.$new();
                $controller = _$controller_;
                $compile = _$compile_;
                $q = _$q_;
                todoService = _todoService_;
            });
        });

        it('should make the todo array available by default when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            expect(todoService.get).toHaveBeenCalled();
            expect(todoService.get.calls.count()).toBe(1);
            expect(controller.todos).toBe(testData)
        });

        it('should make an empty todo array available by default when api response is nok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return error();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            expect(todoService.get).toHaveBeenCalled();
            expect(todoService.get.calls.count()).toBe(1);
            expect(controller.todos).toEqual([])
        });

        it('should get remaining todos', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            expect(controller.remaining()).toBe(1);
            expect(todoService.get.calls.count()).toBe(1);
        });

        it('should add a todo and fetch todos when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'add').and.callFake(function (parameters, success, error) {
                return success();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();
            controller.description = 'description';

            controller.addTodo($scope.description);

            expect(todoService.add).toHaveBeenCalledWith({description: 'description'}, jasmine.any(Function));
            expect(controller.description).toBe('');
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should update a todo and fetch todos when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'update').and.callFake(function (parameters, success, error) {
                return success();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.update({description: 'description', completed: true});

            expect(todoService.update).toHaveBeenCalledWith({description: 'description', completed: true},
                jasmine.any(Function), jasmine.any(Function));
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should update a todo and fetch todos when api response is nok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'update').and.callFake(function (parameters, success, error) {
                return error();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.update(completedTodo);

            expect(todoService.update).toHaveBeenCalledWith(completedTodo,
                jasmine.any(Function), jasmine.any(Function));
            expect(todoService.get).toHaveBeenCalled();
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should archive a todo and fetch todos when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'archive').and.callFake(function (parameters, success, error) {
                return success();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.archive();

            $scope.$apply();

            expect(todoService.archive).toHaveBeenCalledWith(completedTodo, jasmine.any(Function), jasmine.any(Function));
            expect(todoService.archive.calls.count()).toBe(1);
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should archive a todo and fetch todos when api response is nok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'archive').and.callFake(function (parameters, success, error) {
                return error();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.archive();

            $scope.$apply();

            expect(todoService.archive).toHaveBeenCalledWith(completedTodo, jasmine.any(Function), jasmine.any(Function));
            expect(todoService.archive.calls.count()).toBe(1);
            expect(todoService.get.calls.count()).toBe(2);
        });
    });
})();<commit_msg>Fail a test for support<commit_after>(function () {
    'use strict';

    describe('The todo controller', function () {
        var $scope, controller, $controller, $compile, $q, todoService;
        var completedTodo = {description: 'do something else', completed: true},
            testData = [
                {
                    "description": "do something",
                    "completed": false
                },
                completedTodo
            ];

        beforeEach(function () {
            module('todo');

            inject(function ($rootScope, _$controller_, _$compile_, _$q_, _todoService_) {
                $scope = $rootScope.$new();
                $controller = _$controller_;
                $compile = _$compile_;
                $q = _$q_;
                todoService = _todoService_;
            });
        });

        it('should make the todo array available by default when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            // should fail
            controller2 = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            expect(todoService.get).toHaveBeenCalled();
            expect(todoService.get.calls.count()).toBe(1);
            expect(controller.todos).toBe(testData)
        });

        it('should make an empty todo array available by default when api response is nok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return error();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            expect(todoService.get).toHaveBeenCalled();
            expect(todoService.get.calls.count()).toBe(1);
            expect(controller.todos).toEqual([])
        });

        it('should get remaining todos', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            expect(controller.remaining()).toBe(1);
            expect(todoService.get.calls.count()).toBe(1);
        });

        it('should add a todo and fetch todos when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'add').and.callFake(function (parameters, success, error) {
                return success();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();
            controller.description = 'description';

            controller.addTodo($scope.description);

            expect(todoService.add).toHaveBeenCalledWith({description: 'description'}, jasmine.any(Function));
            expect(controller.description).toBe('');
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should update a todo and fetch todos when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'update').and.callFake(function (parameters, success, error) {
                return success();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.update({description: 'description', completed: true});

            expect(todoService.update).toHaveBeenCalledWith({description: 'description', completed: true},
                jasmine.any(Function), jasmine.any(Function));
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should update a todo and fetch todos when api response is nok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'update').and.callFake(function (parameters, success, error) {
                return error();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.update(completedTodo);

            expect(todoService.update).toHaveBeenCalledWith(completedTodo,
                jasmine.any(Function), jasmine.any(Function));
            expect(todoService.get).toHaveBeenCalled();
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should archive a todo and fetch todos when api response is ok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'archive').and.callFake(function (parameters, success, error) {
                return success();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.archive();

            $scope.$apply();

            expect(todoService.archive).toHaveBeenCalledWith(completedTodo, jasmine.any(Function), jasmine.any(Function));
            expect(todoService.archive.calls.count()).toBe(1);
            expect(todoService.get.calls.count()).toBe(2);
        });

        it('should archive a todo and fetch todos when api response is nok', function () {
            spyOn(todoService, 'get').and.callFake(function (parameters, success, error) {
                return success(testData);
            });

            spyOn(todoService, 'archive').and.callFake(function (parameters, success, error) {
                return error();
            });

            controller = $controller('TodoController', {
                $scope: $scope,
                todoService: todoService,
                $q: $q
            });
            $scope.$digest();

            controller.archive();

            $scope.$apply();

            expect(todoService.archive).toHaveBeenCalledWith(completedTodo, jasmine.any(Function), jasmine.any(Function));
            expect(todoService.archive.calls.count()).toBe(1);
            expect(todoService.get.calls.count()).toBe(2);
        });
    });
})();<|endoftext|>