diff --git a/js/common/view/GasPropertiesIconFactory.ts b/js/common/view/GasPropertiesIconFactory.ts index 35567030..914a98ef 100644 --- a/js/common/view/GasPropertiesIconFactory.ts +++ b/js/common/view/GasPropertiesIconFactory.ts @@ -318,14 +318,14 @@ const GasPropertiesIconFactory = { * Creates an icon for particle type 1 in the Diffusion screen. */ createDiffusionParticle1Icon( modelViewTransform: ModelViewTransform2, options?: ParticleNodeOptions ): Node { - return createParticleIcon( new DiffusionParticle1(), modelViewTransform, options ); + return createParticleIcon( DiffusionParticle1.withDefaults(), modelViewTransform, options ); }, /** * Creates an icon for particle type 2 in the Diffusion screen. */ createDiffusionParticle2Icon( modelViewTransform: ModelViewTransform2, options?: ParticleNodeOptions ): Node { - return createParticleIcon( new DiffusionParticle2(), modelViewTransform, options ); + return createParticleIcon( DiffusionParticle2.withDefaults(), modelViewTransform, options ); }, /** diff --git a/js/diffusion/model/DiffusionData.ts b/js/diffusion/model/DiffusionData.ts index d7948624..15c1f8d5 100644 --- a/js/diffusion/model/DiffusionData.ts +++ b/js/diffusion/model/DiffusionData.ts @@ -87,6 +87,7 @@ export default class DiffusionData { * Updates Properties based on the contents of the particle arrays. */ public update(): void { + assert && this.particleSystem.verify(); let numberOfParticles1 = 0; let numberOfParticles2 = 0; diff --git a/js/diffusion/model/DiffusionParticle.ts b/js/diffusion/model/DiffusionParticle.ts index 58503da0..dacb880d 100644 --- a/js/diffusion/model/DiffusionParticle.ts +++ b/js/diffusion/model/DiffusionParticle.ts @@ -6,25 +6,20 @@ * @author Chris Malley (PixelZoom, Inc.) */ -import optionize, { EmptySelfOptions } from '../../../../phet-core/js/optionize.js'; +import { EmptySelfOptions } from '../../../../phet-core/js/optionize.js'; import Particle, { ParticleOptions } from '../../common/model/Particle.js'; -import GasPropertiesConstants from '../../common/GasPropertiesConstants.js'; import gasProperties from '../../gasProperties.js'; -import WithOptional from '../../../../phet-core/js/types/WithOptional.js'; +import WithRequired from '../../../../phet-core/js/types/WithRequired.js'; type SelfOptions = EmptySelfOptions; -export type DiffusionParticleOptions = SelfOptions & WithOptional; +export type DiffusionParticleOptions = SelfOptions & + WithRequired; export default class DiffusionParticle extends Particle { protected constructor( providedOptions: DiffusionParticleOptions ) { - super( optionize()( { - - // ParticleOptions - mass: GasPropertiesConstants.DIFFUSION_MASS_RANGE.defaultValue, - radius: GasPropertiesConstants.DIFFUSION_RADIUS_RANGE.defaultValue - }, providedOptions ) ); + super( providedOptions ); } /** diff --git a/js/diffusion/model/DiffusionParticle1.ts b/js/diffusion/model/DiffusionParticle1.ts index 062864d8..86650c27 100644 --- a/js/diffusion/model/DiffusionParticle1.ts +++ b/js/diffusion/model/DiffusionParticle1.ts @@ -15,6 +15,7 @@ import gasProperties from '../../gasProperties.js'; import DiffusionParticle, { DiffusionParticleOptions } from './DiffusionParticle.js'; import { ParticleStateObject } from '../../common/model/Particle.js'; import IOType from '../../../../tandem/js/types/IOType.js'; +import GasPropertiesConstants from '../../common/GasPropertiesConstants.js'; type SelfOptions = EmptySelfOptions; @@ -25,7 +26,7 @@ export type DiffusionParticle1StateObject = ParticleStateObject; export default class DiffusionParticle1 extends DiffusionParticle { - public constructor( providedOptions?: DiffusionParticle1Options ) { + public constructor( providedOptions: DiffusionParticle1Options ) { super( optionize()( { // DiffusionParticleOptions @@ -34,6 +35,16 @@ export default class DiffusionParticle1 extends DiffusionParticle { }, providedOptions ) ); } + /** + * Creates a DiffusionParticle1 with default configuration. This is used for creating icons. + */ + public static withDefaults(): DiffusionParticle1 { + return new DiffusionParticle1( { + mass: GasPropertiesConstants.DIFFUSION_MASS_RANGE.defaultValue, + radius: GasPropertiesConstants.DIFFUSION_RADIUS_RANGE.defaultValue + } ); + } + /** * Deserializes an instance of DiffusionParticle1. */ @@ -44,7 +55,9 @@ export default class DiffusionParticle1 extends DiffusionParticle { previousX: stateObject._previousX, previousY: stateObject._previousY, vx: stateObject.vx, - vy: stateObject.vy + vy: stateObject.vy, + mass: stateObject.mass, + radius: stateObject.radius } ); } diff --git a/js/diffusion/model/DiffusionParticle2.ts b/js/diffusion/model/DiffusionParticle2.ts index ffea9ec3..096a594d 100644 --- a/js/diffusion/model/DiffusionParticle2.ts +++ b/js/diffusion/model/DiffusionParticle2.ts @@ -15,6 +15,7 @@ import gasProperties from '../../gasProperties.js'; import DiffusionParticle, { DiffusionParticleOptions } from './DiffusionParticle.js'; import { ParticleStateObject } from '../../common/model/Particle.js'; import IOType from '../../../../tandem/js/types/IOType.js'; +import GasPropertiesConstants from '../../common/GasPropertiesConstants.js'; type SelfOptions = EmptySelfOptions; @@ -25,7 +26,7 @@ export type DiffusionParticle2StateObject = ParticleStateObject; export default class DiffusionParticle2 extends DiffusionParticle { - public constructor( providedOptions?: DiffusionParticle2Options ) { + public constructor( providedOptions: DiffusionParticle2Options ) { super( optionize()( { // ParticleOptions @@ -34,6 +35,16 @@ export default class DiffusionParticle2 extends DiffusionParticle { }, providedOptions ) ); } + /** + * Creates a DiffusionParticle2 with default configuration. This is used for creating icons. + */ + public static withDefaults(): DiffusionParticle2 { + return new DiffusionParticle2( { + mass: GasPropertiesConstants.DIFFUSION_MASS_RANGE.defaultValue, + radius: GasPropertiesConstants.DIFFUSION_RADIUS_RANGE.defaultValue + } ); + } + /** * Deserializes an instance of DiffusionParticle1. */ @@ -44,7 +55,9 @@ export default class DiffusionParticle2 extends DiffusionParticle { previousX: stateObject._previousX, previousY: stateObject._previousY, vx: stateObject.vx, - vy: stateObject.vy + vy: stateObject.vy, + mass: stateObject.mass, + radius: stateObject.radius } ); } diff --git a/js/diffusion/model/DiffusionParticleSystem.ts b/js/diffusion/model/DiffusionParticleSystem.ts index 30eda3b4..f9001e48 100644 --- a/js/diffusion/model/DiffusionParticleSystem.ts +++ b/js/diffusion/model/DiffusionParticleSystem.ts @@ -244,6 +244,26 @@ export default class DiffusionParticleSystem extends PhetioObject { this.centerOfMass2Property.value = ParticleUtils.getCenterXOfMass( this.particles2, this.container.width / 2 ); } + /** + * Verifies that the particles system is in a consistent state. + */ + public verify(): void { + this.verifyParticles( this.particles1, this.particle1Settings ); + this.verifyParticles( this.particles2, this.particle2Settings ); + } + + /** + * Verifies that all particles of the same type have the same mass and radius. + */ + private verifyParticles( particles: DiffusionParticle[], settings: DiffusionSettings ): void { + if ( particles.length > 0 ) { + assert && assert( _.every( particles, particle => ( particle.mass === settings.massProperty.value ) ), + 'Particles do not have consistent mass.' ); + assert && assert( _.every( particles, particle => ( particle.radius === settings.radiusProperty.value ) ), + 'Particles do not have consistent radius.' ); + } + } + /** * DiffusionParticleSystemIO handles serialization of the particle arrays. It implements reference-type serialization, * as described in https://github.com/phetsims/phet-io/blob/main/doc/phet-io-instrumentation-technical-guide.md#serialization. diff --git a/js/diffusion/view/DiffusionParticleSystemNode.ts b/js/diffusion/view/DiffusionParticleSystemNode.ts index 611083fa..d4a46608 100644 --- a/js/diffusion/view/DiffusionParticleSystemNode.ts +++ b/js/diffusion/view/DiffusionParticleSystemNode.ts @@ -27,14 +27,14 @@ export default class DiffusionParticleSystemNode extends ParticlesNode { // generated canvas for DiffusionParticle1 species const particle1CanvasProperty = new DiffusionParticleCanvasProperty( - new DiffusionParticle1(), + DiffusionParticle1.withDefaults(), model.modelViewTransform, model.particleSystem.particle1Settings.radiusProperty ); // generated canvas for DiffusionParticle2 species const particle2CanvasProperty = new DiffusionParticleCanvasProperty( - new DiffusionParticle2(), + DiffusionParticle2.withDefaults(), model.modelViewTransform, model.particleSystem.particle2Settings.radiusProperty );