diff --git a/js/common/model/BaseContainer.ts b/js/common/model/BaseContainer.ts index 7a984c58..567ef520 100644 --- a/js/common/model/BaseContainer.ts +++ b/js/common/model/BaseContainer.ts @@ -107,7 +107,7 @@ export default class BaseContainer extends PhetioObject { this.leftWallVelocity = new Vector2( 0, 0 ); this.userIsAdjustingWidthProperty = new BooleanProperty( false, { - tandem: options.widthRange.getLength() === 0 ? Tandem.OPT_OUT : options.tandem.createTandem( 'userIsAdjustingWidthProperty' ), + tandem: this.isFixedWidth ? Tandem.OPT_OUT : options.tandem.createTandem( 'userIsAdjustingWidthProperty' ), phetioReadOnly: true, phetioDocumentation: 'For internal use only.' } ); @@ -122,6 +122,13 @@ export default class BaseContainer extends PhetioObject { */ public get width(): number { return this.widthProperty.value; } + /** + * Does the container have a fixed width? + */ + public get isFixedWidth(): boolean { + return this.widthProperty.range.getLength() === 0; + } + /** * Convenience getter for inside bounds, in pm. */ diff --git a/js/common/model/IdealGasLawContainer.ts b/js/common/model/IdealGasLawContainer.ts index 0f545dbf..d33a1e48 100644 --- a/js/common/model/IdealGasLawContainer.ts +++ b/js/common/model/IdealGasLawContainer.ts @@ -15,11 +15,12 @@ import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; import Utils from '../../../../dot/js/Utils.js'; import Vector2 from '../../../../dot/js/Vector2.js'; import optionize from '../../../../phet-core/js/optionize.js'; -import PickRequired from '../../../../phet-core/js/types/PickRequired.js'; import gasProperties from '../../gasProperties.js'; import GasPropertiesQueryParameters from '../GasPropertiesQueryParameters.js'; import BaseContainer, { BaseContainerOptions } from './BaseContainer.js'; import BooleanIO from '../../../../tandem/js/types/BooleanIO.js'; +import WithRequired from '../../../../phet-core/js/types/WithRequired.js'; +import Tandem from '../../../../tandem/js/Tandem.js'; // constants @@ -30,7 +31,7 @@ type SelfOptions = { leftWallDoesWork?: boolean; // true if the left wall does work on particles, as in the Explore screen }; -type IdealGasLawContainerOptions = SelfOptions & PickRequired; +export type IdealGasLawContainerOptions = SelfOptions & WithRequired; export default class IdealGasLawContainer extends BaseContainer { @@ -107,14 +108,14 @@ export default class IdealGasLawContainer extends BaseContainer { this.desiredWidthProperty = new NumberProperty( this.widthProperty.value, { units: 'pm', - tandem: options.tandem.createTandem( 'desiredWidthProperty' ), + tandem: this.isFixedWidth ? Tandem.OPT_OUT : options.tandem.createTandem( 'desiredWidthProperty' ), phetioReadOnly: true, phetioDocumentation: 'For internal use only.' } ); this.previousLeftProperty = new NumberProperty( this.left, { units: 'pm', - tandem: options.tandem.createTandem( 'previousLeftProperty' ), + tandem: this.isFixedWidth ? Tandem.OPT_OUT : options.tandem.createTandem( 'previousLeftProperty' ), phetioReadOnly: true, phetioDocumentation: 'For internal use only.' } ); diff --git a/js/common/model/IdealGasLawModel.ts b/js/common/model/IdealGasLawModel.ts index 9a4d091d..9270a67d 100644 --- a/js/common/model/IdealGasLawModel.ts +++ b/js/common/model/IdealGasLawModel.ts @@ -22,7 +22,7 @@ import StringUnionProperty from '../../../../axon/js/StringUnionProperty.js'; import Range from '../../../../dot/js/Range.js'; import Utils from '../../../../dot/js/Utils.js'; import Vector2 from '../../../../dot/js/Vector2.js'; -import optionize from '../../../../phet-core/js/optionize.js'; +import optionize, { combineOptions } from '../../../../phet-core/js/optionize.js'; import Tandem from '../../../../tandem/js/Tandem.js'; import gasProperties from '../../gasProperties.js'; import GasPropertiesConstants from '../GasPropertiesConstants.js'; @@ -31,17 +31,16 @@ import BaseModel, { BaseModelOptions } from './BaseModel.js'; import CollisionCounter from './CollisionCounter.js'; import CollisionDetector from './CollisionDetector.js'; import { HoldConstant, HoldConstantValues } from './HoldConstant.js'; -import IdealGasLawContainer from './IdealGasLawContainer.js'; +import IdealGasLawContainer, { IdealGasLawContainerOptions } from './IdealGasLawContainer.js'; import ParticleSystem from './ParticleSystem.js'; import PressureGauge from './PressureGauge.js'; import PressureModel from './PressureModel.js'; import TemperatureModel from './TemperatureModel.js'; +import PickOptional from '../../../../phet-core/js/types/PickOptional.js'; +import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; type SelfOptions = { - // Does the container's left wall do work on particles? - leftWallDoesWork?: boolean; - // Whether the screen has a collision counter. hasCollisionCounter?: boolean; @@ -50,6 +49,9 @@ type SelfOptions = { // Initial value for holdConstantProperty. holdConstant?: HoldConstant; + + // Passed to IdealGasLawContainer. + containerOptions?: PickOptional; }; export type IdealGasLawModelOptions = SelfOptions & BaseModelOptions; @@ -110,10 +112,9 @@ export default class IdealGasLawModel extends BaseModel { public constructor( providedOptions: IdealGasLawModelOptions ) { - const options = optionize()( { + const options = optionize, BaseModelOptions>()( { // SelfOptions - leftWallDoesWork: false, hasCollisionCounter: true, hasHoldConstantFeature: false, holdConstant: 'nothing' @@ -141,10 +142,9 @@ export default class IdealGasLawModel extends BaseModel { phetioDocumentation: 'Determines whether collisions between particles are enabled.' } ); - this.container = new IdealGasLawContainer( { - leftWallDoesWork: options.leftWallDoesWork, + this.container = new IdealGasLawContainer( combineOptions( { tandem: options.tandem.createTandem( 'container' ) - } ); + }, options.containerOptions ) ); this.particleSystem = new ParticleSystem( () => this.temperatureModel.getInitialTemperature(), diff --git a/js/energy/model/EnergyModel.ts b/js/energy/model/EnergyModel.ts index 269576c7..9bc81dc7 100644 --- a/js/energy/model/EnergyModel.ts +++ b/js/energy/model/EnergyModel.ts @@ -11,9 +11,10 @@ import IdealGasLawModel from '../../common/model/IdealGasLawModel.js'; import gasProperties from '../../gasProperties.js'; import AverageSpeedModel from './AverageSpeedModel.js'; import HistogramsModel from './HistogramsModel.js'; +import RangeWithValue from '../../../../dot/js/RangeWithValue.js'; -// constants const SAMPLE_PERIOD = 1; // sample period for Average Speed and histograms, in ps +const CONTAINER_WIDTH = 10000; // pm export default class EnergyModel extends IdealGasLawModel { @@ -25,6 +26,9 @@ export default class EnergyModel extends IdealGasLawModel { super( { holdConstant: 'volume', hasCollisionCounter: false, + containerOptions: { + widthRange: new RangeWithValue( CONTAINER_WIDTH, CONTAINER_WIDTH, CONTAINER_WIDTH ) + }, tandem: tandem } ); @@ -33,11 +37,6 @@ export default class EnergyModel extends IdealGasLawModel { throw new Error( 'holdConstant is fixed in the Energy screen' ); } ); - // In case clients attempt to use this feature of the base class - this.container.widthProperty.lazyLink( width => { - throw new Error( 'container width is fixed in the Energy screen' ); - } ); - this.histogramsModel = new HistogramsModel( this.particleSystem, this.isPlayingProperty, SAMPLE_PERIOD, { tandem: tandem.createTandem( 'histogramsModel' ) } ); diff --git a/js/explore/model/ExploreModel.ts b/js/explore/model/ExploreModel.ts index 2fa358db..cdb89d8f 100644 --- a/js/explore/model/ExploreModel.ts +++ b/js/explore/model/ExploreModel.ts @@ -16,7 +16,9 @@ export default class ExploreModel extends IdealGasLawModel { super( { holdConstant: 'nothing', - leftWallDoesWork: true, // moving the left wall does work on particles + containerOptions: { + leftWallDoesWork: true // moving the left wall does work on particles + }, tandem: tandem } );