Skip to content

Commit

Permalink
Merge branch 'together'
Browse files Browse the repository at this point in the history
  • Loading branch information
samreid committed Mar 25, 2015
2 parents f5e646c + c1ca425 commit 893a140
Show file tree
Hide file tree
Showing 18 changed files with 152 additions and 46 deletions.
8 changes: 6 additions & 2 deletions js/common/model/Movable.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,14 @@ define( function( require ) {
* Constructor
* @param {Vector2} location
* @param {Bounds2} dragBounds
* @param {object} [options]
* @constructor
*/
function Movable( location, dragBounds ) {
this.locationProperty = new Property( location );
function Movable( location, dragBounds, options ) {
options = _.extend( {
locationComponentID: null
}, options );
this.locationProperty = new Property( location, { componentID: options.locationComponentID } );
this.dragBounds = dragBounds;
}

Expand Down
4 changes: 2 additions & 2 deletions js/concentration/model/ConcentrationMeter.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ define( function( require ) {
*/
function ConcentrationMeter( bodyLocation, bodyDragBounds, probeLocation, probeDragBounds ) {
this.value = new Property( NaN ); // NaN if the meter is not reading a value
this.body = new Movable( bodyLocation, bodyDragBounds );
this.probe = new Movable( probeLocation, probeDragBounds );
this.body = new Movable( bodyLocation, bodyDragBounds, { locationComponentID: 'concentrationScreen.concentrationMeter.bodyLocation' } );
this.probe = new Movable( probeLocation, probeDragBounds, { locationComponentID: 'concentrationScreen.concentrationMeter.probeLocation' } );
}

return inherit( Object, ConcentrationMeter, {
Expand Down
22 changes: 20 additions & 2 deletions js/concentration/model/ConcentrationModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,33 @@ define( function( require ) {

// model elements
thisModel.solute = new Property( thisModel.solutes[ 0 ] );

// The Public API for this simulation provides a simplified name for the selected solute
// Here, we perform 2-way binding between the solute name and the solute instance
// This means we can get the value of the solute by name, and set it back by name,
// which enables save/load/record/playback/configuration through query parameters/etc.
var soluteAPINameProperty = new Property( thisModel.solute.value.apiName, { componentID: 'concentrationScreen.solute' } );
soluteAPINameProperty.link( function( soluteAPIName ) {
for ( var i = 0; i < thisModel.solutes.length; i++ ) {
var solute = thisModel.solutes[ i ];
if ( solute.apiName === soluteAPIName ) {
thisModel.solute.value = solute;
}
}
} );
thisModel.solute.link( function( solute ) {
soluteAPINameProperty.value = solute.apiName;
} );

thisModel.solution = new ConcentrationSolution( thisModel.solute, DEFAULT_SOLUTE_AMOUNT, SOLUTION_VOLUME_RANGE.defaultValue );
thisModel.beaker = new Beaker( new Vector2( 400, 550 ), new Dimension2( 600, 300 ), 1 );
thisModel.precipitate = new Precipitate( thisModel.solution, thisModel.beaker );
thisModel.shaker = new Shaker( new Vector2( thisModel.beaker.location.x, 170 ), new Bounds2( 225, 50, 625, 210 ), 0.75 * Math.PI, thisModel.solute, SHAKER_MAX_DISPENSING_RATE, true );
thisModel.shakerParticles = new ShakerParticles( thisModel.shaker, thisModel.solution, thisModel.beaker );
thisModel.dropper = new Dropper( new Vector2( thisModel.beaker.location.x, 225 ), new Bounds2( 250, 225, 570, 225 ), thisModel.solute, DROPPER_FLOW_RATE, false );
thisModel.evaporator = new Evaporator( MAX_EVAPORATION_RATE, thisModel.solution );
thisModel.solventFaucet = new Faucet( new Vector2( 155, 220 ), -400, 45, MAX_INPUT_FLOW_RATE );
thisModel.drainFaucet = new Faucet( new Vector2( 800, 630 ), thisModel.beaker.getRight(), 45, MAX_OUTPUT_FLOW_RATE );
thisModel.solventFaucet = new Faucet( new Vector2( 155, 220 ), -400, 45, MAX_INPUT_FLOW_RATE, { flowRateComponentID: 'concentrationScreen.solventFaucet.flowRate' } );
thisModel.drainFaucet = new Faucet( new Vector2( 800, 630 ), thisModel.beaker.getRight(), 45, MAX_OUTPUT_FLOW_RATE, { flowRateComponentID: 'concentrationScreen.drainFaucet.flowRate' } );
thisModel.concentrationMeter = new ConcentrationMeter( new Vector2( 785, 210 ), new Bounds2( 10, 150, 835, 680 ),
new Vector2( 750, 370 ), new Bounds2( 30, 150, 966, 680 ) );

Expand Down
8 changes: 4 additions & 4 deletions js/concentration/model/ConcentrationSolution.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ define( function( require ) {

thisSolution.solvent = Solvent.WATER;
thisSolution.solute = solute;
thisSolution.soluteAmount = new Property( soluteAmount );
thisSolution.volume = new Property( volume );
thisSolution.soluteAmount = new Property( soluteAmount, { componentID: 'concentrationScreen.solution.soluteAmount' } );
thisSolution.volume = new Property( volume, { componentID: 'concentrationScreen.solution.volume' } );

// derive amount of precipitate (moles)
thisSolution.precipitateAmount = new Property( 0 );
thisSolution.concentration = new Property( 0 );
thisSolution.precipitateAmount = new Property( 0, { componentID: 'concentrationScreen.solution.precipitateAmount' } );
thisSolution.concentration = new Property( 0, { componentID: 'concentrationScreen.solution.concentration' } );
var updatePrecipitateAmount = function() {

var volume = thisSolution.volume.get();
Expand Down
12 changes: 7 additions & 5 deletions js/concentration/model/Dropper.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ define( function( require ) {
function Dropper( location, dragBounds, solute, maxFlowRate, visible ) {

var thisDropper = this;
Movable.call( thisDropper, location, dragBounds );
Movable.call( thisDropper, location, dragBounds, { locationComponentID: 'concentrationScreen.dropper.location' } );

thisDropper.solute = solute;
thisDropper.visible = new Property( visible );
thisDropper.on = new Property( false ); // true if the dropper is dispensing solution
thisDropper.visible = new Property( visible, { componentID: 'concentrationScreen.dropper.visible' } );
thisDropper.on = new Property( false, { componentID: 'concentrationScreen.dropper.on' } ); // true if the dropper is dispensing solution
thisDropper.enabled = new Property( true );
thisDropper.empty = new Property( false );
thisDropper.flowRate = new Property( 0 ); // L/sec
thisDropper.empty = new Property( false, { componentID: 'concentrationScreen.dropper.empty' } );
thisDropper.flowRate = new Property( 0, { componentID: 'concentrationScreen.dropper.flowRate' } ); // L/sec

// Turn off the dropper when it's disabled.
thisDropper.enabled.link( function( enabled ) {
Expand All @@ -51,6 +51,8 @@ define( function( require ) {
thisDropper.enabled.set( false );
}
} );

//together && together.addComponent( 'concentrationScreen.dropper.location', thisDropper.locationProperty );
}

return inherit( Movable, Dropper, {
Expand Down
4 changes: 2 additions & 2 deletions js/concentration/model/Evaporator.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ define( function( require ) {
var thisEvaporator = this;

thisEvaporator.maxEvaporationRate = maxEvaporationRate; // L/sec
thisEvaporator.evaporationRate = new Property( 0 ); // L/sec
thisEvaporator.enabled = new Property( true );
thisEvaporator.evaporationRate = new Property( 0, { componentID: 'concentrationScreen.evaporationRate' } ); // L/sec
thisEvaporator.enabled = new Property( true, { componentID: 'concentrationScreen.evaporationEnabled' } );

// disable when the volume gets to zero
solution.volume.link( function( volume ) {
Expand Down
7 changes: 5 additions & 2 deletions js/concentration/model/Faucet.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ define( function( require ) {
* @param {number} maxFlowRate L/sec
* @constructor
*/
function Faucet( location, pipeMinX, spoutWidth, maxFlowRate ) {
function Faucet( location, pipeMinX, spoutWidth, maxFlowRate, options ) {

options = _.extend( {
flowRateComponentID: null
}, options );
assert && assert( pipeMinX < location.x ); // pipe enters the faucet from the left

var thisFaucet = this;
Expand All @@ -30,7 +33,7 @@ define( function( require ) {
thisFaucet.pipeMinX = pipeMinX;
thisFaucet.spoutWidth = spoutWidth;
thisFaucet.maxFlowRate = maxFlowRate;
thisFaucet.flowRate = new Property( 0 );
thisFaucet.flowRate = new Property( 0, { componentID: options.flowRateComponentID } );
thisFaucet.enabled = new Property( true );

// when disabled, turn off the faucet.
Expand Down
2 changes: 1 addition & 1 deletion js/concentration/model/Shaker.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ define( function( require ) {
function Shaker( location, dragBounds, orientation, solute, maxDispensingRate, visible ) {

var thisShaker = this;
Movable.call( thisShaker, location, dragBounds );
Movable.call( thisShaker, location, dragBounds, { locationComponentID: 'concentrationScreen.shaker.location' } );

thisShaker.orientation = orientation;
thisShaker.solute = solute;
Expand Down
21 changes: 20 additions & 1 deletion js/concentration/model/Solute.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,19 @@ define( function( require ) {
* Constructor.
* @param {string} name
* @param {string} formula
* @param {string} apiName - A non-internationalized unique identifier that can be used to access the solute
* @param {number} stockSolutionConcentration
* @param {SoluteColorScheme} colorScheme
* @param {Color|undefined} particleColor
* @param {Number|undefined} particleSize
* @param {Number|undefined} particlesPerMole
* @constructor
*/
function Solute( name, formula, stockSolutionConcentration, colorScheme, particleColor, particleSize, particlesPerMole ) {
function Solute( name, formula, apiName, listItemComponentID, stockSolutionConcentration, colorScheme, particleColor, particleSize, particlesPerMole ) {
this.name = name;
this.formula = formula;
this.apiName = apiName;
this.listItemComponentID = listItemComponentID;
this.stockSolutionConcentration = stockSolutionConcentration;
this.colorScheme = colorScheme;
this.particleColor = particleColor || colorScheme.maxColor;
Expand All @@ -58,6 +61,8 @@ define( function( require ) {
Solute.DRINK_MIX = new Solute(
drinkMixString,
drinkMixString,
'drinkMix',
'concentrationScreen.soluteComboBox.drinkMixButton',
5.5,
new SoluteColorScheme( 0, new Color( 224, 255, 255 ),
0.05, new Color( 255, 225, 225 ),
Expand All @@ -66,6 +71,8 @@ define( function( require ) {
Solute.COBALT_II_NITRATE = new Solute(
cobaltIINitrateString,
BLLSymbols.COBALT_II_NITRATE,
'cobaltIINitrate',
'concentrationScreen.soluteComboBox.cobaltIINitrateButton',
5.0,
new SoluteColorScheme( 0, Solvent.WATER_COLOR,
0.05, new Color( 255, 225, 225 ),
Expand All @@ -74,6 +81,8 @@ define( function( require ) {
Solute.COBALT_CHLORIDE = new Solute(
cobaltChlorideString,
BLLSymbols.COBALT_CHLORIDE,
'cobaltChloride',
'concentrationScreen.soluteComboBox.cobaltChlorideButton',
4.0,
new SoluteColorScheme( 0, Solvent.WATER_COLOR,
0.05, new Color( 255, 242, 242 ),
Expand All @@ -82,6 +91,8 @@ define( function( require ) {
Solute.POTASSIUM_DICHROMATE = new Solute(
potassiumDichromateString,
BLLSymbols.POTASSIUM_DICHROMATE,
'potassiumDichromate',
'concentrationScreen.soluteComboBox.potassiumDichromateButton',
0.5,
new SoluteColorScheme( 0, Solvent.WATER_COLOR,
0.01, new Color( 255, 204, 153 ),
Expand All @@ -90,6 +101,8 @@ define( function( require ) {
Solute.POTASSIUM_CHROMATE = new Solute(
potassiumChromateString,
BLLSymbols.POTASSIUM_CHROMATE,
'potassiumChromate',
'concentrationScreen.soluteComboBox.potassiumChromateButton',
3.0,
new SoluteColorScheme( 0, Solvent.WATER_COLOR,
0.05, new Color( 255, 255, 153 ),
Expand All @@ -98,6 +111,8 @@ define( function( require ) {
Solute.NICKEL_II_CHLORIDE = new Solute(
nickelIIChlorideString,
BLLSymbols.NICKEL_II_CHLORIDE,
'nickelIIChloride',
'concentrationScreen.soluteComboBox.nickelIIChlorideButton',
5.0,
new SoluteColorScheme( 0, Solvent.WATER_COLOR,
0.2, new Color( 170, 255, 170 ),
Expand All @@ -106,6 +121,8 @@ define( function( require ) {
Solute.COPPER_SULFATE = new Solute(
copperSulfateString,
BLLSymbols.COPPER_SULFATE,
'copperSulfate',
'concentrationScreen.soluteComboBox.copperSulfateButton',
1.0,
new SoluteColorScheme( 0, Solvent.WATER_COLOR,
0.2, new Color( 200, 225, 255 ),
Expand All @@ -114,6 +131,8 @@ define( function( require ) {
Solute.POTASSIUM_PERMANGANATE = new Solute(
potassiumPermanganateString,
BLLSymbols.POTASSIUM_PERMANGANATE,
'potassiumPermanganate',
'concentrationScreen.soluteComboBox.potassiumPermanganateButton',
0.4,
new SoluteColorScheme( 0, Solvent.WATER_COLOR,
0.01, new Color( 255, 0, 255 ),
Expand Down
17 changes: 12 additions & 5 deletions js/concentration/view/BLLDropperNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ define( function( require ) {
EyeDropperNode.call( thisNode, {
onProperty: dropper.on,
enabledProperty: dropper.enabled,
emptyProperty: dropper.empty
emptyProperty: dropper.empty,
componentID: 'concentrationScreen.dropper',
buttonComponentID: 'concentrationScreen.dropperButton'
} );

// label background, so the label shows up on various fluid colors
Expand All @@ -43,7 +45,10 @@ define( function( require ) {
thisNode.addChild( labelBackground );

// label
var label = new SubSupText( dropper.solute.formula, { font: new PhetFont( { size: 18, weight: 'bold' } ), fill: 'black' } );
var label = new SubSupText( dropper.solute.formula, {
font: new PhetFont( { size: 18, weight: 'bold' } ),
fill: 'black'
} );
thisNode.addChild( label );

// location
Expand Down Expand Up @@ -83,10 +88,12 @@ define( function( require ) {
thisNode.touchArea = thisNode.localBounds.dilatedX( 0.25 * thisNode.width );

// move the dropper
thisNode.addInputListener( new MovableDragHandler( dropper.locationProperty, {
this.movableDragHandler = new MovableDragHandler( dropper.locationProperty, {
dragBounds: dropper.dragBounds,
modelViewTransform: modelViewTransform
} ) );
modelViewTransform: modelViewTransform,
componentID: thisNode.componentID
} );
thisNode.addInputListener( this.movableDragHandler );
}

return inherit( EyeDropperNode, BLLDropperNode );
Expand Down
8 changes: 6 additions & 2 deletions js/concentration/view/BLLFaucetNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ define( function( require ) {
* @param {ModelViewTransform2} modelViewTransform
* @constructor
*/
function BLLFaucetNode( faucet, modelViewTransform ) {
function BLLFaucetNode( faucet, modelViewTransform, options ) {
var scale = 0.75;
var horizontalPipeLength = modelViewTransform.modelToViewX( faucet.location.x - faucet.pipeMinX ) / scale;
FaucetNode.call( this, faucet.maxFlowRate, faucet.flowRate, faucet.enabled, { horizontalPipeLength: horizontalPipeLength, scale: scale } );
options = _.extend( {
horizontalPipeLength: horizontalPipeLength,
scale: scale
}, options );
FaucetNode.call( this, faucet.maxFlowRate, faucet.flowRate, faucet.enabled, options );
this.translation = modelViewTransform.modelToViewPosition( faucet.location );
}

Expand Down
15 changes: 13 additions & 2 deletions js/concentration/view/ConcentrationMeterNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ define( function( require ) {
var Text = require( 'SCENERY/nodes/Text' );
var Util = require( 'DOT/Util' );
var Vector2 = require( 'DOT/Vector2' );
var Property = require( 'AXON/Property' );

// strings
var concentrationString = require( 'string!BEERS_LAW_LAB/concentration' );
Expand Down Expand Up @@ -108,7 +109,8 @@ define( function( require ) {
if ( BODY_IS_DRAGGABLE ) {
thisNode.addInputListener( new MovableDragHandler( meter.body.locationProperty, {
dragBounds: meter.body.dragBounds,
modelViewTransform: modelViewTransform
modelViewTransform: modelViewTransform,
componentID: 'concentrationScreen.concentrationMeterBody'
} ) );
}

Expand All @@ -118,6 +120,7 @@ define( function( require ) {
} );

// displayed value
var displayedTextProperty = new Property( NO_VALUE, { componentID: 'concentrationScreen.concentrationMeter.readout' } );
meter.value.link( function( value ) {
if ( isNaN( value ) ) {
valueNode.setText( NO_VALUE );
Expand All @@ -127,6 +130,9 @@ define( function( require ) {
valueNode.setText( value.toFixed( VALUE_DECIMALS ) );
valueNode.right = valueBackgroundNode.right - VALUE_X_MARGIN; // right justified
}

// Output the data in the arch data stream
displayedTextProperty.set( valueNode.getText() );
} );
}

Expand All @@ -149,6 +155,8 @@ define( function( require ) {
cursor: 'pointer'
} );

this.componentID = 'concentrationScreen.concentrationMeterProbe';

var imageNode = new Image( probeImage );
thisNode.addChild( imageNode );
var radius = imageNode.height / 2; // assumes that image height defines the radius
Expand All @@ -168,7 +176,8 @@ define( function( require ) {
// drag handler
thisNode.addInputListener( new MovableDragHandler( probe.locationProperty, {
dragBounds: probe.dragBounds,
modelViewTransform: modelViewTransform
modelViewTransform: modelViewTransform,
componentID: thisNode.componentID
} ) );

var isInNode = function( node ) {
Expand All @@ -193,6 +202,8 @@ define( function( require ) {
thisNode.isInStockSolution = function() {
return isInNode( stockSolutionNode );
};

together && together.addComponent( this );
}

inherit( Node, ProbeNode );
Expand Down
14 changes: 7 additions & 7 deletions js/concentration/view/ConcentrationView.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ define( function( require ) {
var stockSolutionNode = new StockSolutionNode( model.solution.solvent, model.solute, model.dropper, model.beaker, dropperNode.TIP_WIDTH - 1, modelViewTransform );

// faucets
var solventFaucetNode = new BLLFaucetNode( model.solventFaucet, modelViewTransform );
var drainFaucetNode = new BLLFaucetNode( model.drainFaucet, modelViewTransform );
var solventFaucetNode = new BLLFaucetNode( model.solventFaucet, modelViewTransform, { componentID: 'concentrationScreen.solventFaucet' } );
var drainFaucetNode = new BLLFaucetNode( model.drainFaucet, modelViewTransform, { componentID: 'concentrationScreen.drainFaucet' } );
var SOLVENT_FLUID_HEIGHT = model.beaker.location.y - model.solventFaucet.location.y;
var DRAIN_FLUID_HEIGHT = 1000; // tall enough that resizing the play area is unlikely to show bottom of fluid
var solventFluidNode = new FaucetFluidNode( model.solventFaucet, model.solution.solvent, SOLVENT_FLUID_HEIGHT, modelViewTransform );
Expand All @@ -83,11 +83,11 @@ define( function( require ) {
var removeSoluteButton = new RemoveSoluteButton( model.solution, model.shakerParticles );

// Reset All button
var resetAllButton = new ResetAllButton(
{
listener: function() { model.reset(); },
scale: 1.32
} );
var resetAllButton = new ResetAllButton( {
listener: function() { model.reset(); },
scale: 1.32,
componentID: 'concentrationScreen.resetAllButton'
} );

// Rendering order
thisView.addChild( solventFluidNode );
Expand Down
Loading

0 comments on commit 893a140

Please sign in to comment.