Skip to content

Commit

Permalink
add screen-specific default nuclide count query parameters, #101
Browse files Browse the repository at this point in the history
# Conflicts:
#	js/common/view/BANScreenView.ts
  • Loading branch information
zepumph committed Aug 17, 2023
1 parent af3038d commit dfa7067
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 44 deletions.
19 changes: 0 additions & 19 deletions js/build-a-nucleus-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ import simLauncher from '../../joist/js/simLauncher.js';
import BuildANucleusStrings from './BuildANucleusStrings.js';
import DecayScreen from './decay/DecayScreen.js';
import ChartIntroScreen from './chart-intro/ChartIntroScreen.js';
import BANQueryParameters from './common/BANQueryParameters.js';
import AtomIdentifier from '../../shred/js/AtomIdentifier.js';
import BANConstants from './common/BANConstants.js';

const buildANucleusTitleStringProperty = BuildANucleusStrings[ 'build-a-nucleus' ].titleStringProperty;

Expand All @@ -34,22 +31,6 @@ const simOptions: SimOptions = {
// until the images are fully loaded, see https://github.com/phetsims/coulombs-law/issues/70
simLauncher.launch( () => {

// check if a nuclide with the given query parameters exists and reset to default values if not
if ( !AtomIdentifier.doesExist( BANQueryParameters.protons, BANQueryParameters.neutrons ) ) {
const errorMessage = `A nuclide with ${BANQueryParameters.protons} protons and ${BANQueryParameters.neutrons} neutrons does not exist`;

// add a warning if the protons or neutrons query parameter was part of an invalid combo
// there may have already been a warning added if the query parameter value is outside the valid range, so check first
if ( !_.some( QueryStringMachine.warnings, warning => warning.key === 'protons' ) && QueryStringMachine.containsKey( 'protons' ) ) {
QueryStringMachine.addWarning( 'protons', BANQueryParameters.protons, errorMessage );
}
if ( !_.some( QueryStringMachine.warnings, warning => warning.key === 'neutrons' ) && QueryStringMachine.containsKey( 'neutrons' ) ) {
QueryStringMachine.addWarning( 'neutrons', BANQueryParameters.neutrons, errorMessage );
}
BANQueryParameters.protons = BANConstants.DEFAULT_INITIAL_PROTON_NUMBER;
BANQueryParameters.neutrons = BANConstants.DEFAULT_INITIAL_NEUTRON_NUMBER;
}

const sim = new Sim( buildANucleusTitleStringProperty, [
new DecayScreen(),
new ChartIntroScreen()
Expand Down
5 changes: 5 additions & 0 deletions js/chart-intro/view/ChartIntroScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import FullChartDialog from './FullChartDialog.js';
import TextPushButton from '../../../../sun/js/buttons/TextPushButton.js';
import BackgroundNode from '../../../../scenery-phet/js/BackgroundNode.js';
import AlphaParticle from '../../common/model/AlphaParticle.js';
import BANQueryParameters from '../../common/BANQueryParameters.js';

// types
export type NuclideChartIntroScreenViewOptions = BANScreenViewOptions;
Expand Down Expand Up @@ -256,6 +257,10 @@ class ChartIntroScreenView extends BANScreenView<ChartIntroModel> {
showMagicNumbersCheckbox,
fullChartTextButton
] );

phet.joist.sim.isConstructionCompleteProperty.link( ( complete: boolean ) => {
complete && this.populateAtom( BANQueryParameters.chartIntroScreenProtons, BANQueryParameters.chartIntroScreenNeutrons );
} );
}

/**
Expand Down
66 changes: 59 additions & 7 deletions js/common/BANQueryParameters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,78 @@

import buildANucleus from '../buildANucleus.js';
import BANConstants from './BANConstants.js';
import AtomIdentifier from '../../../shred/js/AtomIdentifier.js';
import StrictOmit from '../../../phet-core/js/types/StrictOmit.js';

// Acceptable nucleon counts should be an integer greater than zero, and less than the available max per screen
const getValidationFunctionForMaximum = ( max: number ) => {
return ( value: number ) => Number.isInteger( value ) && value >= 0 && value <= max;
};

const BANQueryParameters = QueryStringMachine.getAll( {

// the number of neutrons in the atom that the sim starts up with
neutrons: {
// The number of neutrons in the atom on the Decay Screen that the sim starts up with.
decayScreenNeutrons: {
public: true,
type: 'number',
defaultValue: BANConstants.DEFAULT_INITIAL_NEUTRON_NUMBER,
isValidValue: ( number: number ) => Number.isInteger( number ) && number >= 0 && number <= BANConstants.DECAY_MAX_NUMBER_OF_NEUTRONS
isValidValue: getValidationFunctionForMaximum( BANConstants.DECAY_MAX_NUMBER_OF_NEUTRONS )
},

// the number of protons in the atom that the sim starts up with
protons: {
// The number of protons in the atom on the Decay Screen that the sim starts up with.
decayScreenProtons: {
public: true,
type: 'number',
defaultValue: BANConstants.DEFAULT_INITIAL_PROTON_NUMBER,
isValidValue: ( number: number ) => Number.isInteger( number ) && number >= 0 && number <= BANConstants.DECAY_MAX_NUMBER_OF_PROTONS
}
isValidValue: getValidationFunctionForMaximum( BANConstants.DECAY_MAX_NUMBER_OF_NEUTRONS )
},

// The number of neutrons in the atom on the Chart Intro Screen that the sim starts up with.
chartIntroScreenNeutrons: {
public: true,
type: 'number',
defaultValue: BANConstants.DEFAULT_INITIAL_NEUTRON_NUMBER,
isValidValue: getValidationFunctionForMaximum( BANConstants.CHART_MAX_NUMBER_OF_PROTONS )
},

// The number of protons in the atom on the Chart Intro Screen that the sim starts up with.
chartIntroScreenProtons: {
public: true,
type: 'number',
defaultValue: BANConstants.DEFAULT_INITIAL_PROTON_NUMBER,
isValidValue: getValidationFunctionForMaximum( BANConstants.CHART_MAX_NUMBER_OF_PROTONS )
}
} );

type QueryParamsWeCareAbout = keyof StrictOmit<typeof BANQueryParameters, 'SCHEMA_MAP'>;

// use QSM's warning logic for these public parameters if trying to create an Atom that doesn't exist.
function warnForNonExistentAtom( protonsKeyString: QueryParamsWeCareAbout, neutronsKeyString: QueryParamsWeCareAbout ): void {

// check if a nuclide with the given query parameters exists and reset to default values if not
const numberOfNeutrons = BANQueryParameters[ neutronsKeyString ];
const numberOfProtons = BANQueryParameters[ protonsKeyString ];

if ( !AtomIdentifier.doesExist( numberOfProtons, numberOfNeutrons ) ) {
const errorMessage = `A nuclide with ${numberOfProtons} protons and ${numberOfNeutrons} neutrons does not exist`;

// add a warning if the protons or neutrons query parameter was part of an invalid combo (atom doesn't exist)
// there may have already been a warning added if the query parameter value is outside the valid range, so check first
if ( QueryStringMachine.containsKey( protonsKeyString ) &&
!_.some( QueryStringMachine.warnings, warning => warning.key === protonsKeyString ) ) {
QueryStringMachine.addWarning( protonsKeyString, numberOfProtons, errorMessage );
}
if ( QueryStringMachine.containsKey( neutronsKeyString ) &&
!_.some( QueryStringMachine.warnings, warning => warning.key === neutronsKeyString ) ) {
QueryStringMachine.addWarning( neutronsKeyString, numberOfNeutrons, errorMessage );
}
BANQueryParameters[ protonsKeyString ] = BANConstants.DEFAULT_INITIAL_PROTON_NUMBER;
BANQueryParameters[ neutronsKeyString ] = BANConstants.DEFAULT_INITIAL_NEUTRON_NUMBER;
}
}

warnForNonExistentAtom( 'decayScreenProtons', 'decayScreenNeutrons' );
warnForNonExistentAtom( 'chartIntroScreenProtons', 'chartIntroScreenNeutrons' );

buildANucleus.register( 'BANQueryParameters', BANQueryParameters );
export default BANQueryParameters;
38 changes: 20 additions & 18 deletions js/common/view/BANScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import ParticleAtom from '../../../../shred/js/model/ParticleAtom.js';
import Vector2 from '../../../../dot/js/Vector2.js';
import DerivedProperty from '../../../../axon/js/DerivedProperty.js';
import arrayRemove from '../../../../phet-core/js/arrayRemove.js';
import BANQueryParameters from '../BANQueryParameters.js';
import ParticleNucleus from '../../chart-intro/model/ParticleNucleus.js';
import ParticleAtomNode from './ParticleAtomNode.js';
import DecayType from '../model/DecayType.js';
Expand Down Expand Up @@ -535,22 +534,6 @@ abstract class BANScreenView<M extends BANModel<ParticleAtom | ParticleNucleus>>
this.particleAtomNode.emptyAtomCircle.visible = ( protonNumber + neutronNumber ) === 0;
} );

phet.joist.sim.isConstructionCompleteProperty.link( ( complete: boolean ) => {
if ( complete ) {
// add initial neutrons and protons specified by the query parameters to the atom
_.times( Math.max( BANQueryParameters.neutrons, BANQueryParameters.protons ), () => {
if ( this.model.particleAtom.neutronCountProperty.value < BANQueryParameters.neutrons &&
this.model.particleAtom.neutronCountProperty.value < this.model.neutronNumberRange.max ) {
this.addNucleonImmediatelyToAtom( ParticleType.NEUTRON );
}
if ( this.model.particleAtom.protonCountProperty.value < BANQueryParameters.protons &&
this.model.particleAtom.protonCountProperty.value < this.model.protonNumberRange.max ) {
this.addNucleonImmediatelyToAtom( ParticleType.PROTON );
}
} );
}
} );

this.pdomPlayAreaNode.pdomOrder = [
protonArrowButtons,
doubleArrowButtons,
Expand Down Expand Up @@ -618,7 +601,8 @@ abstract class BANScreenView<M extends BANModel<ParticleAtom | ParticleNucleus>>
}

/**
* Create and add a nucleon of particleType immediately to the particleAtom.
* Create and add a nucleon of particleType immediately to the particleAtom. Will set the position to the position of
* the particleAtom.
*/
public addNucleonImmediatelyToAtom( particleType: ParticleType ): void {
const particle = new BANParticle( particleType.particleTypeString, {
Expand All @@ -631,6 +615,24 @@ abstract class BANScreenView<M extends BANModel<ParticleAtom | ParticleNucleus>>
this.model.particleAtom.addParticle( particle );
}

/**
* Populate the ParticleAtom with the desired number of nucleons.
*/
public populateAtom( numberOfProtons: number, numberOfNeutrons: number ): void {

// add initial neutrons and protons specified by the query parameters to the atom
_.times( Math.max( numberOfNeutrons, numberOfProtons ), () => {
if ( this.model.particleAtom.neutronCountProperty.value < numberOfNeutrons &&
this.model.particleAtom.neutronCountProperty.value < this.model.neutronNumberRange.max ) {
this.addNucleonImmediatelyToAtom( ParticleType.NEUTRON );
}
if ( this.model.particleAtom.protonCountProperty.value < numberOfProtons &&
this.model.particleAtom.protonCountProperty.value < this.model.protonNumberRange.max ) {
this.addNucleonImmediatelyToAtom( ParticleType.PROTON );
}
} );
}

/**
* Set the input enabled and visibility of a creator node.
*/
Expand Down
5 changes: 5 additions & 0 deletions js/decay/view/DecayScreenView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Multilink from '../../../../axon/js/Multilink.js';
import DecayType from '../../common/model/DecayType.js';
import AlphaParticle from '../../common/model/AlphaParticle.js';
import ReturnButton from '../../../../scenery-phet/js/buttons/ReturnButton.js';
import BANQueryParameters from '../../common/BANQueryParameters.js';

// constants
const NUCLEON_CAPTURE_RADIUS = 100;
Expand Down Expand Up @@ -260,6 +261,10 @@ class DecayScreenView extends BANScreenView<DecayModel> {
availableDecaysPanel
] );
this.pdomControlAreaNode.pdomOrder = [ showElectronCloudCheckbox, ...this.pdomControlAreaNode.pdomOrder! ];

phet.joist.sim.isConstructionCompleteProperty.link( ( complete: boolean ) => {
complete && this.populateAtom( BANQueryParameters.decayScreenProtons, BANQueryParameters.decayScreenNeutrons );
} );
}

public getRandomExternalModelPosition(): Vector2 {
Expand Down

0 comments on commit dfa7067

Please sign in to comment.