/**
* Component module
* @module Component
* @property {string} id Component id
* @property {string} label Component label
* @property {ComponentType} type Component type
* @property {number} V Voltage
* @property {number} R Resistance
* @property {number} I Impedence
* @property {boolean} openEnded Component is an open-ended component or not e.g., Ground
* @property {boolean} active Component is active or not
* @property {boolean} traveled Component has been traveled by Traverser or not
* @property {Positions[]} pins Component pins
* @property {Board} board STATIC property which references to the Board object
*/
'use strict';
const ComponentDefault = {
type : 0,
label : undefined,
V : 0, R : 0, I : 0,
openEnded : false,
active : true,
traveled : false
};
class Component {
constructor({ type = 0,
label = undefined,
V = 0, R = 0, I = 0,
openEnded = false,
active = true,
traveled = false } = ComponentDefault)
{
this.id = (Date.now() + Math.random()).toString();
this.label = label || 'Component-'+ this.id;
this.type = type;
this.V = V;
this.R = R;
this.I = I;
this.openEnded = openEnded;
this.active = active;
this.traveled = traveled;
/* For openEnded components :
pin 0 is the part connected to the circuit
pin 1 is the open end
*/
this.pins = [];
}
/**
* Place Component onto specified Slots <br>
* Uses [Board#place]{@link module:Board#place}
*
* @public
* @instance
* @method place
* @param {Position[]} positions
* @example
* let component = new Component();
* component.place([0,0],[0,5]);
*/
place(...positions) {
if(!Component.board)
Utility.logger('Component.board not set!');
if(!this.validatePositions(positions))
Utility.logger('Invalid positions provided - ' + positions.toString());
if(Component.hasDuplicatePositions(positions))
Utility.logger('Pins of the same component cannot share the same slot.');
// If .place() is consecutively called without calling .remove()
// then we'll do it ourselves.
if(this.pins.length > 1)
this.remove();
this.pins = positions;
Component.board.place(this, positions);
}
/**
* Remove Component from board <br>
* Uses [Board#remove]{@link module:Board#remove}
*
* @public
* @instance
* @method remove
*
* @example
* let component = new Component();
* component.place([0,0],[0,5]);
* component.remove();
*/
remove() {
if(!Component.board)
Utility.logger('Component.board not set!');
Component.board.remove(this);
this.pins = [];
}
/**
* Returns array of pin positions except the one passed in
*
* @public
* @instance
* @method getOtherPins
* @param {Position} pos
* @returns {Positions[]}
*/
getOtherPins(pos) {
return this.pins.filter((pinPos) => {
return !(pinPos.toString() === pos.toString());
});
}
/**
* Validate positions provided <br>
* Each position must be an Array that contains only two positive integers
*
* @private
* @method validatePositions
* @param {Positions[]} positions
* @example
* [1,2], [2,3] // the only valid format
* ['a',2], [2,3] // invalid
* [], [1] // invalid
*/
validatePositions(positions) {
return positions.length == 2 &&
!positions.some((position) => {
return !(position instanceof Array) || !(/^\d+\,\d+$/.test(position.toString()));
});
}
/**
* Return true if duplicate pins are found
*
* @public
* @static
* @method hasDuplicatePositions
* @param {Positions[]} pins Array of pins e.g. [[1,1], [2,2], [4,4]]
* @returns {boolean}
*/
static hasDuplicatePositions(pins) {
return pins
.map(pin => pin.toString())
.some((pin, index, arr) => index !== arr.lastIndexOf(pin));
}
}
/**
* Component's saved reference to the board
*
* @public
* @static
* @name Component#board
*/
Component.board = undefined;
module.exports = Component;