diff --git a/js/gravity-force-lab/view/GravityForceLabScreenSummaryNode.js b/js/gravity-force-lab/view/GravityForceLabScreenSummaryNode.js index 8163cc20..72e4590f 100644 --- a/js/gravity-force-lab/view/GravityForceLabScreenSummaryNode.js +++ b/js/gravity-force-lab/view/GravityForceLabScreenSummaryNode.js @@ -12,6 +12,7 @@ define( require => { // modules const gravityForceLab = require( 'GRAVITY_FORCE_LAB/gravityForceLab' ); const GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' ); + const GravityForceLabForceDescriber = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/describers/GravityForceLabForceDescriber' ); const Node = require( 'SCENERY/nodes/Node' ); const Property = require( 'AXON/Property' ); @@ -36,6 +37,7 @@ define( require => { // super( _.omit( options, 'summaryOptions' ) ); super( {} ); this.stringManager = stringManager; + this.describer = GravityForceLabForceDescriber.getDescriber(); var mainSummaryDescriptionNode = new Node( { tagName: 'p', innerContent: options.mainDescriptionContent } ); var secondSummaryDescriptionNode = new Node( { tagName: 'p', innerContent: options.secondaryDecriptionContent } ); @@ -102,7 +104,7 @@ define( require => { } updateForceVectorSummary() { - this.forceVectorsSummaryItem.innerContent = this.stringManager.getForceVectorsSummaryText(); + this.forceVectorsSummaryItem.innerContent = this.describer.getForceVectorsSummaryText(); } updateObjectDistanceSummary() { diff --git a/js/gravity-force-lab/view/GravityForceLabScreenView.js b/js/gravity-force-lab/view/GravityForceLabScreenView.js index 3782c34b..43f0ca30 100644 --- a/js/gravity-force-lab/view/GravityForceLabScreenView.js +++ b/js/gravity-force-lab/view/GravityForceLabScreenView.js @@ -11,15 +11,13 @@ define( function( require ) { 'use strict'; // modules - // var GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' ); - // var Node = require( 'SCENERY/nodes/Node' ); - // var ParameterControlPanel = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/ParameterControlPanel' ); var Bounds2 = require( 'DOT/Bounds2' ); var ControlAreaNode = require( 'SCENERY_PHET/accessibility/nodes/ControlAreaNode' ); var gravityForceLab = require( 'GRAVITY_FORCE_LAB/gravityForceLab' ); var GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' ); var GravityForceLabAlertManager = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/GravityForceLabAlertManager' ); var GravityForceLabConstants = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabConstants' ); + var GravityForceLabForceDescriber = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/describers/GravityForceLabForceDescriber' ); var GravityForceLabScreenSummaryNode = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/GravityForceLabScreenSummaryNode' ); var GravityForceLabStringManager = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/GravityForceLabStringManager' ); var inherit = require( 'PHET_CORE/inherit' ); @@ -74,6 +72,9 @@ define( function( require ) { addScreenSummaryNode: true, tandem: tandem } ); + // force text isn't retrieved direclty in the screenview, we simply initialize and access it in various nodes + GravityForceLabForceDescriber.initialize( model, mass1AbbreviatedString, mass2AbbreviatedString ); + var stringManager = new GravityForceLabStringManager( model, mass1AbbreviatedString, mass2AbbreviatedString ); var alertManager = new GravityForceLabAlertManager( model, stringManager ); var summaryNode = new GravityForceLabScreenSummaryNode( model, stringManager ); diff --git a/js/gravity-force-lab/view/GravityForceLabStringManager.js b/js/gravity-force-lab/view/GravityForceLabStringManager.js index ef93b2b9..ed9197c2 100644 --- a/js/gravity-force-lab/view/GravityForceLabStringManager.js +++ b/js/gravity-force-lab/view/GravityForceLabStringManager.js @@ -304,26 +304,6 @@ define( require => { // NOTE: these are pure functions, so it may be possible to pass them into the supertype constructor // as a config object - getPositionRegionChanged( newDistance, oldDistance ) { - if ( newDistance === oldDistance ) { - return false; - } - - var min = Math.min( newDistance, oldDistance ); - var max = Math.max( newDistance, oldDistance ); - // TODO: Move to constants - var regionBoundaries = [ - 8.2, 6.7, 5.2, 3.7, 2.2, 0.9 - ]; - - for ( let i = 0; i < regionBoundaries.length; i++ ) { - const boundary = regionBoundaries[ i ]; - if ( min < boundary && boundary <= max ) { - return true; - } - } - } - getForceVectorIndex( force ) { const convertedForce = Math.abs( force ) * MICRO_CONVERSION_FACTOR; if ( convertedForce < 0.041713 ) { diff --git a/js/gravity-force-lab/view/MassPDOMNode.js b/js/gravity-force-lab/view/MassPDOMNode.js index c0b8a518..fc22fc4c 100644 --- a/js/gravity-force-lab/view/MassPDOMNode.js +++ b/js/gravity-force-lab/view/MassPDOMNode.js @@ -6,6 +6,7 @@ define( require => { // modules const gravityForceLab = require( 'GRAVITY_FORCE_LAB/gravityForceLab' ); // const GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' ); + const GravityForceLabForceDescriber = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/view/describers/GravityForceLabForceDescriber' ); const ISLCObjectPDOMNode = require( 'INVERSE_SQUARE_LAW_COMMON/view/ISLCObjectPDOMNode' ); const Node = require( 'SCENERY/nodes/Node' ); @@ -17,17 +18,22 @@ define( require => { constructor( model, objectEnum, stringManager, options ) { - // const labelContent = objectEnum === ISLCObjectEnum.OBJECT_ONE ? mass1BlueSphereString : mass2RedSphereString; const labelContent = stringManager.getMassSphereString( objectEnum ); options.a11yOptions = { labelContent }; super( model, objectEnum, stringManager, options ); + const describer = GravityForceLabForceDescriber.getDescriber(); this.massAndPositionNode = new Node( { tagName: 'li' } ); this.addChild( this.massAndPositionNode ); this.linkToForceProperty( force => { + const forceBetweenContent = describer.getForceBetweenAndVectorText( this.thisObjectLabel, this.otherObjectLabel ); + const forceMagnitudeContent = describer.getForceVectorMagnitudeText(); const newContent = stringManager.getSizeAndPositionItemText( this.thisObjectLabel ); + + this.forceBetweenAndVectorNode.innerContent = forceBetweenContent; + this.forceVectorMagnitudeItemNode.innerContent = forceMagnitudeContent; this.massAndPositionNode.innerContent = newContent; } ); diff --git a/js/gravity-force-lab/view/describers/GravityForceLabForceDescriber.js b/js/gravity-force-lab/view/describers/GravityForceLabForceDescriber.js new file mode 100644 index 00000000..c293ab8a --- /dev/null +++ b/js/gravity-force-lab/view/describers/GravityForceLabForceDescriber.js @@ -0,0 +1,127 @@ +// Copyright 2018, University of Colorado Boulder + +define( require => { + 'use strict'; + + // modules + const gravityForceLab = require( 'GRAVITY_FORCE_LAB/gravityForceLab' ); + const ForceDescriber = require( 'INVERSE_SQUARE_LAW_COMMON/view/describers/ForceDescriber' ); + const GravityForceLabA11yStrings = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabA11yStrings' ); + const Util = require( 'DOT/Util' ); + const GravityForceLabConstants = require( 'GRAVITY_FORCE_LAB/gravity-force-lab/GravityForceLabConstants' ); + const LinearFunction = require( 'DOT/LinearFunction' ); + + // strings + const unitsNewtonsString = require( 'string!INVERSE_SQUARE_LAW_COMMON/units.newtons' ); + + // a11y strings + const micronewtonsString = GravityForceLabA11yStrings.micronewtons.value; + + // constants + const MICRO_CONVERSION_FACTOR = 1e6; + const { min, max } = GravityForceLabConstants.PULL_FORCE_RANGE; + const forceToPullIndex = new LinearFunction( min, max, 6, 0, true ); + + let describer = null; + + class GravityForceLabForceDescriber extends ForceDescriber { + + constructor( model, object1Label, object2Label ) { + const options = { + units: micronewtonsString, + + convertForce: force => { + if ( !this.forceInScientificNotation ) { + return GravityForceLabForceDescriber.convertForceToMicronewtons( force ); + } + return force; + }, + + forceValueToString: convertedForce => { + if ( this.forceInScientificNotation ) { + return ForceDescriber.getForceInScientificNotation( convertedForce, 2 ); + } + return convertedForce + ''; + } + }; + + super( model, object1Label, object2Label, options ); + + model.scientificNotationProperty.link( showScientificNotation => { + this.units = showScientificNotation ? micronewtonsString : unitsNewtonsString; + } ); + } + + get forceInScientificNotation() { + return this.model.scientificNotationProperty.get(); + } + + /** + * Returns the mapped index based on the given force value. Force values in ISLC sims range from piconewtons to + * newtons, so it's necessary for sim-specific subtypes to specify this logic. + * + * @override + * @param {Number} force + * @return {Integer} + */ + getForceVectorIndex( force ) { + const convertedForce = GravityForceLabForceDescriber.convertForceToMicronewtons( force ); + if ( convertedForce < 0.041713 ) { + return 0; + } + if ( convertedForce < 0.074155 ) { + return 1; + } + if ( convertedForce < 0.260698 ) { + return 2; + } + if ( convertedForce < 0.789805 ) { + return 3; + } + if ( convertedForce < 1.564182 ) { + return 4; + } + if ( convertedForce < 2.309288 ) { + return 5; + } + if ( convertedForce >= 2.309288 ) { + return 6; + } + throw new Error( 'Invalid force value' ); + } + + /** + * Returns the mapped puller index based on the provided force. + * + * @override + * @param {Number} force + * @return {Integer} + */ + getEffortIndex( force ) { + return Util.roundSymmetric( forceToPullIndex( force ) ); + } + + /** + * Uses the singleton pattern to keep one instance of this describer for the entire lifetime of the sim. + * @returns {ForceDescriber} + */ + static getDescriber() { + assert && assert( describer, 'describer has not yet been initialized' ); + return describer; + } + + /** + * Initialize the describer singleton + * @throws Error + */ + static initialize( model, object1Label, object2Label ) { + describer = new GravityForceLabForceDescriber( model, object1Label, object2Label ); + } + + static convertForceToMicronewtons( force ) { + return Util.toFixedNumber( force * MICRO_CONVERSION_FACTOR, 6 ); + } + } + + return gravityForceLab.register( 'GravityForceLabForceDescriber', GravityForceLabForceDescriber ); +} ); \ No newline at end of file