phetsims / projectile-data-lab

"Projectile Data Lab" is an educational simulation in HTML5, by PhET Interactive Simulations.
GNU General Public License v3.0
0 stars 0 forks source link

Add 'mean tone' to end of histogram sound #179

Closed matthew-blackman closed 6 months ago

matthew-blackman commented 6 months ago

In the 2/22 sound design meeting, @emily-phet and @Ashton-Morris agreed that it would be a good idea to add a 'mean tone' to the end of the histogram sonification, to show the center of the data set. We also want to highlight the mean indicator when this tone plays. This should only occur on the Measures screen if the 'mean' is checked.

samreid commented 6 months ago

Patch from collaboration with @matthew-blackman

```diff Subject: [PATCH] Remove redundant eslint overrides, see https://github.com/phetsims/projectile-data-lab/issues/200 --- Index: js/measures/view/DataMeasuresOverlay.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/measures/view/DataMeasuresOverlay.ts b/js/measures/view/DataMeasuresOverlay.ts --- a/js/measures/view/DataMeasuresOverlay.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/measures/view/DataMeasuresOverlay.ts (date 1709069760209) @@ -28,6 +28,8 @@ import ProjectileDataLabStrings from '../../ProjectileDataLabStrings.js'; import PDLConstants, { IS_CURRENTLY_AUTO_GENERATING_DATA_PROPERTY } from '../../common/PDLConstants.js'; import { PDLPanel } from '../../common/view/PDLPanel.js'; +import { stepTimer, TReadOnlyProperty } from '../../../../axon/js/imports.js'; +import PDLColors from '../../common/PDLColors.js'; type SelfOptions = { context: 'histogram' | 'field' | 'icon'; @@ -53,6 +55,7 @@ isStandardDeviationDisplayedProperty: BooleanProperty, isValuesDisplayedProperty: BooleanProperty, totalHeight: number, + sonifiedBinProperty: TReadOnlyProperty | null, providedOptions: DataMeasuresFieldOverlayOptions ) { const origin = modelViewTransform.modelToViewPosition( Vector2.ZERO ); @@ -149,6 +152,19 @@ yMargin: 0 } ); + sonifiedBinProperty && sonifiedBinProperty.lazyLink( ( sonifiedBin, oldValue ) => { + + console.log( sonifiedBin, oldValue ); + if ( oldValue === 'mean' && sonifiedBin === null ) { + console.log( 'pink' ); + meanIndicator.fill = 'pink'; + + stepTimer.setTimeout( () => { + meanIndicator.fill = PDLColors.meanMarkerFillProperty; + }, 500 ); + } + } ); + const sdPatternStringProperty = new PatternStringProperty( ProjectileDataLabStrings.standardDeviationMPatternStringProperty, { standardDeviation: roundedStringProperty( standardDeviationDistanceProperty ) } ); Index: js/measures/model/MeasuresModel.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/measures/model/MeasuresModel.ts b/js/measures/model/MeasuresModel.ts --- a/js/measures/model/MeasuresModel.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/measures/model/MeasuresModel.ts (date 1709068895400) @@ -23,6 +23,7 @@ import SMModel, { SMModelOptions } from '../../common-sm/model/SMModel.js'; import StrictOmit from '../../../../phet-core/js/types/StrictOmit.js'; import WithRequired from '../../../../phet-core/js/types/WithRequired.js'; +import { MeanTone } from '../../common/model/MeanTone.js'; type SelfOptions = EmptySelfOptions; @@ -176,6 +177,16 @@ this.intervalTool.changedEmitter.addListener( updateIntervalToolDataPercentage ); } + public override playMeanTone(): void { + console.log( 'hello' ); + + MeanTone.playMean( this.meanDistanceProperty.value! ); + } + + public override shouldPlayMeanTone(): boolean { + return this.isMeanVisibleProperty.value && this.meanDistanceProperty.value !== null; + } + public override reset(): void { super.reset(); Index: js/measures/view/MeasuresHistogramNode.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/measures/view/MeasuresHistogramNode.ts b/js/measures/view/MeasuresHistogramNode.ts --- a/js/measures/view/MeasuresHistogramNode.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/measures/view/MeasuresHistogramNode.ts (date 1709069495006) @@ -125,7 +125,9 @@ // The numbers on the data measures overlay are not shown in the histogram new BooleanProperty( false ), - this.chartTransform.viewHeight, { + + this.chartTransform.viewHeight, + histogram.histogramSonifier.sonifiedBinProperty, { context: 'histogram', tandem: options.tandem.createTandem( 'dataMeasuresChartOverlay' ) } ); Index: js/common/view/MeanIndicatorNode.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/view/MeanIndicatorNode.ts b/js/common/view/MeanIndicatorNode.ts --- a/js/common/view/MeanIndicatorNode.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/common/view/MeanIndicatorNode.ts (date 1709069632216) @@ -26,6 +26,8 @@ }, providedOptions ); super( Shape.regularPolygon( 3, radius ), options ); + + // this.fill = 'pink'; } } Index: js/common/model/HistogramSonifier.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/model/HistogramSonifier.ts b/js/common/model/HistogramSonifier.ts --- a/js/common/model/HistogramSonifier.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/common/model/HistogramSonifier.ts (date 1709070155592) @@ -21,7 +21,7 @@ export default class HistogramSonifier { // The bin that is currently being sonified - public readonly sonifiedBinProperty: Property = new Property( null ); + public readonly sonifiedBinProperty: Property = new Property( null ); // The sorted data from the left to the rightmost bin private binnedData = new Map(); @@ -35,7 +35,11 @@ // The time remaining for sonifying the current bin private timeRemainingInCurrentBin = 0; - public constructor( private binWidthProperty: TReadOnlyProperty ) { + public constructor( + private readonly playMeanTone: () => void, + private readonly shouldPlayMeanTone: () => boolean, + private binWidthProperty: TReadOnlyProperty + ) { // When the bin width changes, stop playing the sound binWidthProperty.link( () => { @@ -44,7 +48,7 @@ // This plays a tone for each bin, with the pitch corresponding to the number of projectiles in the bin this.sonifiedBinProperty.link( sonifiedBin => { - if ( sonifiedBin !== null ) { + if ( typeof sonifiedBin === 'number' ) { const sonifiedBinData = this.binnedData.get( sonifiedBin )!; const binHeight = sonifiedBinData.length; @@ -117,16 +121,36 @@ if ( this.timeRemainingInCurrentBin <= 0 ) { - this.currentBinIndex++; + if ( this.sonifiedBinProperty.value === 'mean' ) { + this.playMeanTone(); + + this.timeRemainingInCurrentBin = 0.5; + this.sonifiedBinProperty.value = 'highlightingMean'; + } + else if ( this.sonifiedBinProperty.value === 'highlightingMean' ) { + + this.sonifiedBinProperty.value = null; + } + else { + this.currentBinIndex++; - this.timeRemainingInCurrentBin = this.getSoundDelayForCurrentBin(); + this.timeRemainingInCurrentBin = this.getSoundDelayForCurrentBin(); - // If we went past the edge of the bins, stop playing - if ( this.currentBinIndex >= this.binnedData.size ) { - this.sonifiedBinProperty.value = null; - } - else { - this.sonifiedBinProperty.value = this.sortedBins[ this.currentBinIndex ]; + // If we went past the edge of the bins, stop playing + if ( this.currentBinIndex >= this.binnedData.size ) { + + if ( this.shouldPlayMeanTone() ) { + + this.timeRemainingInCurrentBin = 0.5; + this.sonifiedBinProperty.value = 'mean'; + } + else { + this.sonifiedBinProperty.value = null; + } + } + else { + this.sonifiedBinProperty.value = this.sortedBins[ this.currentBinIndex ]; + } } } } Index: js/common/model/PDLModel.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/model/PDLModel.ts b/js/common/model/PDLModel.ts --- a/js/common/model/PDLModel.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/common/model/PDLModel.ts (date 1709069036243) @@ -114,7 +114,7 @@ phetioReadOnly: providedOptions.isFieldPropertyPhetioReadonly } ); - this.histogram = new Histogram( { tandem: providedOptions.tandem.createTandem( 'histogram' ) } ); + this.histogram = new Histogram( () => this.playMeanTone(), () => this.shouldPlayMeanTone(), { tandem: providedOptions.tandem.createTandem( 'histogram' ) } ); this.singleOrContinuousProperty = new Property( 'single', { validValues: SingleOrContinuousValues, @@ -185,6 +185,14 @@ } ); } + public playMeanTone(): void { +//nothing to do here + } + + public shouldPlayMeanTone(): boolean { + return false; + } + /** * This method is called when the launch button is pressed. The launch button has multi-modal behaviors where its behavior * differs depending on the current state of the simulation. Index: js/common/model/Histogram.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/common/model/Histogram.ts b/js/common/model/Histogram.ts --- a/js/common/model/Histogram.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/common/model/Histogram.ts (date 1709068627494) @@ -81,7 +81,7 @@ public readonly histogramSonifier: HistogramSonifier; - public constructor( providedOptions: HistogramOptions ) { + public constructor( playMeanTone: () => void, shouldPlayMeanTone: () => boolean, providedOptions: HistogramOptions ) { this.selectedBinWidthProperty = new Property( 1, { validValues: [ 0.5, 1, 2, 5, 10 ], tandem: providedOptions.tandem.createTandem( 'selectedBinWidthProperty' ), @@ -119,7 +119,7 @@ phetioDocumentation: 'This property indicates whether the histogram is showing bars (one per bin) or blocks (one per projectile).' } ); - this.histogramSonifier = new HistogramSonifier( this.binWidthProperty ); + this.histogramSonifier = new HistogramSonifier( playMeanTone, shouldPlayMeanTone, this.binWidthProperty ); } public step( dt: number ): void { Index: js/measures/view/MeasuresStaticToolPanel.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/measures/view/MeasuresStaticToolPanel.ts b/js/measures/view/MeasuresStaticToolPanel.ts --- a/js/measures/view/MeasuresStaticToolPanel.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/measures/view/MeasuresStaticToolPanel.ts (date 1709069473015) @@ -39,7 +39,8 @@ new BooleanProperty( showMean ), new BooleanProperty( showStandardDeviation ), new BooleanProperty( false ), - ICON_WIDTH, { + ICON_WIDTH, + null, { context: 'icon' } ) .rasterized( { Index: js/measures/view/MeasuresScreenView.ts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/js/measures/view/MeasuresScreenView.ts b/js/measures/view/MeasuresScreenView.ts --- a/js/measures/view/MeasuresScreenView.ts (revision 663d49a7b29cf504549bcc2fee8c4788560824ce) +++ b/js/measures/view/MeasuresScreenView.ts (date 1709069473019) @@ -105,7 +105,8 @@ model.isMeanVisibleProperty, model.isStandardDeviationVisibleProperty, model.isValuesVisibleProperty, - 62, { + 62, + null,{ context: 'field', tandem: options.tandem.createTandem( 'dataMeasuresFieldOverlay' ) } ); ```
samreid commented 6 months ago

I think @matthew-blackman labeled this as ready for review for @catherinecarter to comment on the design. But for @matthew-blackman and myself, keep in mind there are 7 TODOs to address before closing.

samreid commented 6 months ago

The TODOs have been addressed. Self-unassigning.

catherinecarter commented 6 months ago

I played with the sim a bit with the mean sound, and here are my initial thoughts:

Likes

Curiosities/Noticings

matthew-blackman commented 6 months ago

Thanks for the feedback @catherinecarter! I made the following changes:

@catherinecarter back to you!

matthew-blackman commented 6 months ago

I reviewed this with @catherinecarter and all is good here as of the most recent commits. Closing.