diff --git a/js/chart-intro/model/ParticleNucleus.ts b/js/chart-intro/model/ParticleNucleus.ts index 2f16fc5..c2bb829 100644 --- a/js/chart-intro/model/ParticleNucleus.ts +++ b/js/chart-intro/model/ParticleNucleus.ts @@ -27,6 +27,8 @@ export type ParticleShellPosition = { }; // constants +export const FIRST_LEVEL_CAPACITY = 2; // Number of particles available on the first energy level of a nucleus. +export const SECOND_LEVEL_CAPACITY = 6; // Number of particles available on the second and third energy levels of a nucleus. // row is yPosition, number is xPosition const ALLOWED_PARTICLE_POSITIONS = [ @@ -34,6 +36,9 @@ const ALLOWED_PARTICLE_POSITIONS = [ [ 0, 1, 2, 3, 4, 5 ], [ 0, 1, 2, 3, 4, 5 ] ]; +assert && assert( ALLOWED_PARTICLE_POSITIONS[ 1 ].length === SECOND_LEVEL_CAPACITY, 'second level spots check' ); +assert && assert( ALLOWED_PARTICLE_POSITIONS[ 2 ].length === SECOND_LEVEL_CAPACITY, 'third level spots check' ); +assert && assert( ALLOWED_PARTICLE_POSITIONS[ 0 ].length === FIRST_LEVEL_CAPACITY, 'first level spots check' ); class ParticleNucleus extends ParticleAtom { @@ -78,10 +83,10 @@ class ParticleNucleus extends ParticleAtom { // update bound levels based on nucleon counts this.protonCountProperty.link( protonCount => { - if ( protonCount >= 9 ) { + if ( protonCount >= FIRST_LEVEL_CAPACITY + SECOND_LEVEL_CAPACITY ) { this.protonsLevelProperty.value = EnergyLevelType.SECOND; } - else if ( protonCount >= 3 ) { + else if ( protonCount > FIRST_LEVEL_CAPACITY ) { this.protonsLevelProperty.value = EnergyLevelType.FIRST; } else { @@ -89,10 +94,10 @@ class ParticleNucleus extends ParticleAtom { } } ); this.neutronCountProperty.link( neutronCount => { - if ( neutronCount >= 9 ) { + if ( neutronCount >= FIRST_LEVEL_CAPACITY + SECOND_LEVEL_CAPACITY ) { this.neutronsLevelProperty.value = EnergyLevelType.SECOND; } - else if ( neutronCount >= 3 ) { + else if ( neutronCount > FIRST_LEVEL_CAPACITY ) { this.neutronsLevelProperty.value = EnergyLevelType.FIRST; } else { diff --git a/js/chart-intro/view/NucleonShellView.ts b/js/chart-intro/view/NucleonShellView.ts index 2187520..59348da 100644 --- a/js/chart-intro/view/NucleonShellView.ts +++ b/js/chart-intro/view/NucleonShellView.ts @@ -15,44 +15,13 @@ import TReadOnlyProperty from '../../../../axon/js/TReadOnlyProperty.js'; import ParticleType from '../../common/model/ParticleType.js'; import Vector2 from '../../../../dot/js/Vector2.js'; import optionize from '../../../../phet-core/js/optionize.js'; -import { ParticleShellPosition } from '../model/ParticleNucleus.js'; +import { FIRST_LEVEL_CAPACITY, ParticleShellPosition, SECOND_LEVEL_CAPACITY } from '../model/ParticleNucleus.js'; type SelfOptions = { xOffset?: number; }; type EnergyLevelNodeOptions = SelfOptions & NodeOptions; -// TODO: Remove color arrays, instead https://github.com/phetsims/build-a-nucleus/issues/85. -// nucleon number to energy level stroke color -const neutronNumberToColorLowerLevel = [ - BANColors.zeroNucleonsEnergyLevelColorProperty, // 0 - Color.interpolateRGBA( BANColors.zeroNucleonsEnergyLevelColorProperty.value, BANColors.neutronColorProperty.value, 0.5 ), // 1 - BANColors.neutronColorProperty // 2 -]; -const neutronNumberToColorUpperLevel = [ - BANColors.zeroNucleonsEnergyLevelColorProperty, // 0 - new Color( 21, 21, 21 ), // 1 - new Color( 43, 43, 43 ), // 2 - new Color( 64, 64, 64 ), // 3 - new Color( 85, 85, 85 ), // 4 - new Color( 107, 107, 107 ), // 5 - BANColors.neutronColorProperty // 6 -]; -const protonNumberToColorLowerLevel = [ - BANColors.zeroNucleonsEnergyLevelColorProperty, // 0 - Color.interpolateRGBA( BANColors.zeroNucleonsEnergyLevelColorProperty.value, BANColors.neutronColorProperty.value, 0.5 ), // 1 - BANColors.protonColorProperty // 2 -]; -const protonNumberToColorUpperLevel = [ - BANColors.zeroNucleonsEnergyLevelColorProperty, // 0 - new Color( 43, 14, 0 ), // 1 - new Color( 85, 28, 0 ), // 2 - new Color( 128, 43, 0 ), // 3 - new Color( 170, 57, 0 ), // 4 - new Color( 213, 71, 0 ), // 5 - BANColors.protonColorProperty // 6 -]; - class NucleonShellView extends Node { private modelViewTransform: ModelViewTransform2; @@ -60,6 +29,9 @@ class NucleonShellView extends Node { nucleonCountProperty: TReadOnlyProperty, particleViewPositionVector: Vector2, providedOptions?: EnergyLevelNodeOptions ) { + assert && assert( particleType === ParticleType.NEUTRON || particleType === ParticleType.PROTON, + 'only protons and neutrons supported in NucleonShellView' ); + const options = optionize()( { xOffset: 0 }, providedOptions ); @@ -70,6 +42,14 @@ class NucleonShellView extends Node { this.modelViewTransform = BANConstants.NUCLEON_ENERGY_LEVEL_ARRAY_MVT; + // Color when the layer is completely empty + const emptyLayerColor = BANColors.zeroNucleonsEnergyLevelColorProperty.value; + + // Color when the layer is completely full + const fullLayerColor = particleType === ParticleType.NEUTRON ? + BANColors.neutronColorProperty.value : + BANColors.protonColorProperty.value; + // create and add the nucleon energy levels const energyLevels: Line[] = []; nucleonShellPositions.forEach( ( particleShellRow, energyLevel ) => { @@ -93,28 +73,27 @@ class NucleonShellView extends Node { // update the stroke color and width of the respective energy levels as the nucleon count changes const boldEnergyLevelWidth = 4; const defaultEnergyLevelWidth = 1; - const nucleonCountToColorLowerLevel = particleType === ParticleType.PROTON ? protonNumberToColorLowerLevel : - neutronNumberToColorLowerLevel; - const nucleonCountToColorUpperLevel = particleType === ParticleType.PROTON ? protonNumberToColorUpperLevel : - neutronNumberToColorUpperLevel; nucleonCountProperty.link( nucleonCount => { - if ( nucleonCount <= 2 ) { - energyLevels[ 0 ].stroke = nucleonCountToColorLowerLevel[ nucleonCount ]; + if ( nucleonCount <= FIRST_LEVEL_CAPACITY ) { + energyLevels[ 0 ].stroke = Color.interpolateRGBA( emptyLayerColor, fullLayerColor, nucleonCount / FIRST_LEVEL_CAPACITY ); // if the energy level is full (2 particles on the lower energy level), double the lineWidth - energyLevels[ 0 ].lineWidth = nucleonCount === 2 ? boldEnergyLevelWidth : defaultEnergyLevelWidth; + energyLevels[ 0 ].lineWidth = nucleonCount === FIRST_LEVEL_CAPACITY ? boldEnergyLevelWidth : defaultEnergyLevelWidth; } else { let energyLevelNumber = 1; - if ( nucleonCount > 8 ) { - nucleonCount -= 6; - energyLevelNumber = 2; + if ( nucleonCount > SECOND_LEVEL_CAPACITY + FIRST_LEVEL_CAPACITY ) { + nucleonCount -= SECOND_LEVEL_CAPACITY; + energyLevelNumber = FIRST_LEVEL_CAPACITY; } - nucleonCount -= 2; - energyLevels[ energyLevelNumber ].stroke = nucleonCountToColorUpperLevel[ nucleonCount ]; + nucleonCount -= FIRST_LEVEL_CAPACITY; // REVIEW: instead of mutating the listener variable, it is better to name a new one (less confusing that way) + const stroke = Color.interpolateRGBA( emptyLayerColor, fullLayerColor, nucleonCount / SECOND_LEVEL_CAPACITY ); + + console.log( nucleonCount / SECOND_LEVEL_CAPACITY ); + energyLevels[ energyLevelNumber ].stroke = stroke; // if the energy level is full (6 particles on the upper and middle energy levels), double the lineWidth - energyLevels[ energyLevelNumber ].lineWidth = nucleonCount === 6 ? boldEnergyLevelWidth : defaultEnergyLevelWidth; + energyLevels[ energyLevelNumber ].lineWidth = nucleonCount === SECOND_LEVEL_CAPACITY ? boldEnergyLevelWidth : defaultEnergyLevelWidth; } } ); } diff --git a/js/common/BANColors.ts b/js/common/BANColors.ts index 6a0ca3c..970b0f0 100644 --- a/js/common/BANColors.ts +++ b/js/common/BANColors.ts @@ -8,7 +8,7 @@ import { Color, ProfileColorProperty } from '../../../scenery/js/imports.js'; import buildANucleus from '../buildANucleus.js'; -import PhetColorScheme from '../../../scenery-phet/js/PhetColorScheme.js'; +import { PARTICLE_COLORS } from '../../../shred/js/model/Particle.js'; const BANColors = { @@ -19,16 +19,16 @@ const BANColors = { // particle colors protonColorProperty: new ProfileColorProperty( buildANucleus, 'protonColor', { - default: PhetColorScheme.RED_COLORBLIND + default: PARTICLE_COLORS.proton } ), neutronColorProperty: new ProfileColorProperty( buildANucleus, 'neutronColor', { - default: Color.GRAY + default: PARTICLE_COLORS.neutron } ), electronColorProperty: new ProfileColorProperty( buildANucleus, 'electronColor', { - default: Color.BLUE + default: PARTICLE_COLORS.electron } ), positronColorProperty: new ProfileColorProperty( buildANucleus, 'positronColor', { - default: new Color( 53, 182, 74 ) + default: PARTICLE_COLORS.positron } ), // decay colors diff --git a/js/common/view/BANScreenView.ts b/js/common/view/BANScreenView.ts index 64cc678..3f33e69 100644 --- a/js/common/view/BANScreenView.ts +++ b/js/common/view/BANScreenView.ts @@ -747,6 +747,7 @@ abstract class BANScreenView> particle.dispose(); } } + /** * Add a particle to the model and immediately start dragging it with the provided event. */