Skip to content

Commit

Permalink
Convert model elements to TypeScript, see #749
Browse files Browse the repository at this point in the history
  • Loading branch information
samreid committed Oct 15, 2021
1 parent 20768f3 commit a4262a4
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 48 deletions.
1 change: 1 addition & 0 deletions js/model/CircuitElement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -504,4 +504,5 @@ const getSenseForNegative = ( current: number ) => current < 0 ? 'forward' :
'unspecified';

circuitConstructionKitCommon.register( 'CircuitElement', CircuitElement );
export {CircuitElementOptions};
export default CircuitElement;
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@
*/

import Emitter from '../../../axon/js/Emitter.js';
import Tandem from '../../../tandem/js/Tandem.js';
import circuitConstructionKitCommon from '../circuitConstructionKitCommon.js';
import FixedCircuitElement from './FixedCircuitElement.js';
import FixedCircuitElement, {FixedCircuitElementOptions} from './FixedCircuitElement.js';
import Vertex from './Vertex.js';

type DynamicCircuitElementOptions = {} & FixedCircuitElementOptions;

// This class should not be instantiated directly, instead subclasses should provide implementations for getCircuitProperties
// and the subclasses should be used instead.
class DynamicCircuitElement extends FixedCircuitElement {
abstract class DynamicCircuitElement extends FixedCircuitElement {
mnaVoltageDrop: number;
mnaCurrent: number;
clearEmitter: Emitter<[]>;

/**
* @param {Vertex} startVertex
Expand All @@ -21,7 +28,9 @@ class DynamicCircuitElement extends FixedCircuitElement {
* @param {Tandem} tandem
* @param {Object} [options]
*/
constructor( startVertex, endVertex, length, tandem, options ) {

// @ts-ignore options
constructor( startVertex: Vertex, endVertex: Vertex, length: number, tandem: Tandem, options: object ) {
super( startVertex, endVertex, length, tandem, options );

// @public {number} - value of the voltage drop set and read by the modified nodal analysis. This is in addition
Expand Down Expand Up @@ -60,4 +69,5 @@ class DynamicCircuitElement extends FixedCircuitElement {
}

circuitConstructionKitCommon.register( 'DynamicCircuitElement', DynamicCircuitElement );
export {DynamicCircuitElementOptions};
export default DynamicCircuitElement;
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,22 @@ QUnit.module( 'DynamicCircuit' );
const dt = 1 / 60;
const errorThreshold = 1E-2;

const testVRCCircuit = ( v, r, c, assert ) => {
const testVRCCircuit = ( v: number, r: number, c: number, assert: Assert ) => {
const resistor = new ModifiedNodalAnalysisCircuitElement( 1, 2, null, r );
const battery = new DynamicCircuitResistiveBattery( 0, 1, v, 0 );
const capacitor = new DynamicCapacitor(
new DynamicCircuitCapacitor( 2, 0, c ),
new DynamicElementState( 0.0, v / r )
);

// @ts-ignore
let dynamicCircuit = new DynamicCircuit( [ resistor ], [ battery ], [ capacitor ], [] );

for ( let i = 0; i < ITERATIONS; i++ ) {//takes 0.3 sec on my machine
const t = i * dt;

const companionSolution = dynamicCircuit.solveItWithSubdivisions( dt );
// @ts-ignore
const voltage = companionSolution.getVoltage( resistor );
const desiredVoltageAtTPlusDT = -v * Math.exp( -( t + dt ) / r / c );
const error = Math.abs( voltage - desiredVoltageAtTPlusDT );
Expand Down Expand Up @@ -64,16 +67,18 @@ QUnit.test( 'test RC Circuit should have voltage exponentially decay with T RC f
testVRCCircuit( 3, 7, 100, assert );
} );

const testVRLCircuit = ( V, R, L, assert ) => {
const testVRLCircuit = ( V: number, R: number, L: number, assert: Assert ) => {
const resistor = new ModifiedNodalAnalysisCircuitElement( 1, 2, null, R );
const battery = new DynamicCircuitResistiveBattery( 0, 1, V, 0 );
const inductor = new DynamicInductor( new DynamicCircuitInductor( 2, 0, L ), new DynamicElementState( V, 0.0 ) );
// @ts-ignore
let circuit = new DynamicCircuit( [ resistor ], [ battery ], [], [ inductor ] );

// let x = '';
for ( let i = 0; i < ITERATIONS; i++ ) {
const t = i * dt;
const solution = circuit.solveItWithSubdivisions( dt );
// @ts-ignore
const current = solution.getCurrent( resistor );
const expectedCurrent = V / R * ( 1 - Math.exp( -( t + dt ) * R / L ) );//positive, by definition of MNA.Battery
const error = Math.abs( current - expectedCurrent );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,19 @@
*/

import merge from '../../../phet-core/js/merge.js';
import Tandem from '../../../tandem/js/Tandem.js';
import circuitConstructionKitCommon from '../circuitConstructionKitCommon.js';
import CircuitElement from './CircuitElement.js';
import CircuitElement, {CircuitElementOptions} from './CircuitElement.js';
import Vertex from './Vertex.js';

class FixedCircuitElement extends CircuitElement {
type FixedCircuitElementOptions = {
numberOfDecimalPlaces: number
} & CircuitElementOptions;

abstract class FixedCircuitElement extends CircuitElement {
numberOfDecimalPlaces: number;
distanceBetweenVertices: number;
isFixedCircuitElement: boolean;

/**
* @param {Vertex} startVertex
Expand All @@ -21,17 +30,17 @@ class FixedCircuitElement extends CircuitElement {
* @param {Tandem} tandem
* @param {Object} [options]
*/
constructor( startVertex, endVertex, chargePathLength, tandem, options ) {
constructor( startVertex: Vertex, endVertex: Vertex, chargePathLength: number, tandem: Tandem, options?: Partial<FixedCircuitElementOptions> ) {

options = merge( {
const filledOptions = merge( {
numberOfDecimalPlaces: 1
}, options );
}, options ) as FixedCircuitElementOptions;

// Super constructor
super( startVertex, endVertex, chargePathLength, tandem, options );
super( startVertex, endVertex, chargePathLength, tandem, filledOptions );

// @public (read-only) {number} - the number of decimal places to show in readouts and controls
this.numberOfDecimalPlaces = options.numberOfDecimalPlaces;
this.numberOfDecimalPlaces = filledOptions.numberOfDecimalPlaces;

// @public (read-only) {number} The distance from one vertex to another (as the crow flies), used for rotation
// about a vertex
Expand All @@ -43,4 +52,5 @@ class FixedCircuitElement extends CircuitElement {
}

circuitConstructionKitCommon.register( 'FixedCircuitElement', FixedCircuitElement );
export {FixedCircuitElementOptions};
export default FixedCircuitElement;
26 changes: 19 additions & 7 deletions js/model/Fuse.js → js/model/Fuse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,43 @@ import BooleanProperty from '../../../axon/js/BooleanProperty.js';
import NumberProperty from '../../../axon/js/NumberProperty.js';
import Range from '../../../dot/js/Range.js';
import merge from '../../../phet-core/js/merge.js';
import Tandem from '../../../tandem/js/Tandem.js';
import CCKCConstants from '../CCKCConstants.js';
import circuitConstructionKitCommon from '../circuitConstructionKitCommon.js';
import FixedCircuitElement from './FixedCircuitElement.js';
import Circuit from './Circuit.js';
import FixedCircuitElement, {FixedCircuitElementOptions} from './FixedCircuitElement.js';
import Vertex from './Vertex.js';

type FuseOptions = {
fuseLength: number
currentRating: number
} & FixedCircuitElementOptions;

class Fuse extends FixedCircuitElement {
currentRatingProperty: NumberProperty;
isTrippedProperty: BooleanProperty;
resistanceProperty: NumberProperty;
timeCurrentRatingExceeded: number;

/**
* @param {Vertex} startVertex
* @param {Vertex} endVertex
* @param {Tandem} tandem
* @param {Object} [options]
*/
constructor( startVertex, endVertex, tandem, options ) {
options = merge( {
constructor( startVertex: Vertex, endVertex: Vertex, tandem: Tandem, options?: Partial<FuseOptions> ) {
const filledOptions = merge( {
resistance: CCKCConstants.MINIMUM_RESISTANCE,
fuseLength: CCKCConstants.RESISTOR_LENGTH, // Same length as a resistor
currentRating: 4, // Amps
isCurrentReentrant: true, // Changing the current can trip a fuse, which changes the current
numberOfDecimalPlaces: 1
}, options );
}, options ) as FuseOptions;

super( startVertex, endVertex, options.fuseLength, tandem, options );
super( startVertex, endVertex, filledOptions.fuseLength, tandem, filledOptions );

// @public {Property.<number>} the current at which the fuse trips, in amps
this.currentRatingProperty = new NumberProperty( options.currentRating, {
this.currentRatingProperty = new NumberProperty( filledOptions.currentRating, {
range: new Range( 0.5, 20 )
} );

Expand Down Expand Up @@ -66,7 +78,7 @@ class Fuse extends FixedCircuitElement {
* @param {Circuit} circuit
* @public
*/
step( time, dt, circuit ) {
step( time: number, dt: number, circuit: Circuit ) {
super.step( time, dt, circuit );
// When the current exceeds the max, trip the fuse. This cannot be modeled as a property link because it
// creates a reentrant property loop which doesn't update the reset fuse button properly
Expand Down
19 changes: 13 additions & 6 deletions js/model/Inductor.js → js/model/Inductor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,39 @@
import NumberProperty from '../../../axon/js/NumberProperty.js';
import Range from '../../../dot/js/Range.js';
import merge from '../../../phet-core/js/merge.js';
import Tandem from '../../../tandem/js/Tandem.js';
import CCKCConstants from '../CCKCConstants.js';
import CCKCQueryParameters from '../CCKCQueryParameters.js';
import circuitConstructionKitCommon from '../circuitConstructionKitCommon.js';
import DynamicCircuitElement from './DynamicCircuitElement.js';
import DynamicCircuitElement, {DynamicCircuitElementOptions} from './DynamicCircuitElement.js';
import Vertex from './Vertex.js';

// constants
const INDUCTOR_LENGTH = CCKCConstants.INDUCTOR_LENGTH;

type InductorOptions = {
inductance: number
} & DynamicCircuitElementOptions;

class Inductor extends DynamicCircuitElement {
inductanceProperty: NumberProperty;

/**
* @param {Vertex} startVertex
* @param {Vertex} endVertex
* @param {Tandem} tandem
* @param {Object} [options]
*/
constructor( startVertex, endVertex, tandem, options ) {
options = merge( {
constructor( startVertex: Vertex, endVertex: Vertex, tandem: Tandem, options?: Partial<InductorOptions> ) {
const filledOptions = merge( {
inductance: CCKCQueryParameters.inductanceDefault,
numberOfDecimalPlaces: CCKCQueryParameters.inductorNumberDecimalPlaces
}, options );
}, options ) as InductorOptions;

super( startVertex, endVertex, INDUCTOR_LENGTH, tandem, options );
super( startVertex, endVertex, INDUCTOR_LENGTH, tandem, filledOptions );

// @public {Property.<number>} the inductance in Henries
this.inductanceProperty = new NumberProperty( options.inductance, {
this.inductanceProperty = new NumberProperty( filledOptions.inductance, {
range: new Range( CCKCQueryParameters.inductanceMin, CCKCQueryParameters.inductanceMax ),
tandem: tandem.createTandem( 'inductanceProperty' )
} );
Expand Down
8 changes: 7 additions & 1 deletion js/model/Meter.js → js/model/Meter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,21 @@ import Emitter from '../../../axon/js/Emitter.js';
import Bounds2 from '../../../dot/js/Bounds2.js';
import Vector2 from '../../../dot/js/Vector2.js';
import Vector2Property from '../../../dot/js/Vector2Property.js';
import Tandem from '../../../tandem/js/Tandem.js';
import circuitConstructionKitCommon from '../circuitConstructionKitCommon.js';

class Meter {
phetioIndex: number;
visibleProperty: BooleanProperty;
bodyPositionProperty: Vector2Property;
draggingProbesWithBodyProperty: BooleanProperty;
droppedEmitter: Emitter<[]>;

/**
* @param {Tandem} tandem
* @param {number} phetioIndex - for assigning corresponding tandems
*/
constructor( tandem, phetioIndex ) {
constructor( tandem: Tandem, phetioIndex: number ) {

// @public (read-only) {number}
this.phetioIndex = phetioIndex;
Expand Down
Loading

0 comments on commit a4262a4

Please sign in to comment.