<taskModel about="urn:cetask.wpi.edu:examples:Inquiry" xmlns="http://ce.org/cea-2018">

 <!-- 
      Mike Sao Pedro
      mikesp@wpi.edu
      
      Main task: perform all parts of the scientific method.      
  -->
  <task id="PerformExperiment">
    <input name="userGenerateHypothesis" type="string"/>
    <output name="hypothesis" type="Hypothesis"/>
    
  	<!-- 
  	   Have student perform all parts of the scientific method. 
  	   Here the student will be asked to fill in specific tests.
  	-->
  	<subtasks id="allScientificMethod">
  	
  	   <step name="formHypothesis" task="FormHypothesis"/>
  	   <step name="runExperiments" task="RunExperiments"/>
  	   <step name="formConclusions" task="FormConclusions"/>
  	   <step name="promptCongrats" task="PromptCongrats"/>
  	   
  	   <!-- The experiments are geared towards the hypothesis selected -->
  	   <binding slot="$this.hypothesis" value="$formHypothesis.hypothesis"/>
  	   <binding slot="$formHypothesis.userGenerateHypothesis" value="$this.userGenerateHypothesis"/>
  	   
  	   <binding slot="$runExperiments.hypothesis" value="$this.hypothesis"/>
  	            
  	   <binding slot="$formConclusions.trial1" 
  	            value="$runExperiments.trial1"/>
  	   <binding slot="$formConclusions.trial2" 
  	            value="$runExperiments.trial2"/>
  	   <binding slot="$formConclusions.hypothesis"
  	            value="$formHypothesis.hypothesis"/>
  	</subtasks>
  </task>


  <task id="PromptCongrats">
     <script/>
  </task>
  
  <task id="PromptTryAgain">
     <script/>
  </task>
  
<!-- ********************************************************************** -->
<!-- ********************************************************************** -->

  
  <!-- 
      Given a simulation specification, make a student fill in
      a hypothesis. Forming a hypothesis consists of seeing how
      and independent variable affects an outcome variable.
      
   -->
  <task id="FormHypothesis">
    <input name="userGenerateHypothesis" type="string"/>
  	<output name="independentVarValue" type="string"/>
  	<output name="comparatorValue" type="string"/>
  	<output name="outcomeVarValue" type="string"/>
  	<output name="hypothesis" type="Hypothesis"/>

  	<subtasks id="userFillHypothesisTemplate" ordered="false">
  	   <step name="independentVar" task="SelectIndependentVar"/>
  	   <step name="outcomeVar" task="SelectOutcomeVar"/>
  	   <step name="comparator" task="SelectComparator"/>
  	   <step name="buildHypothesis" task="BuildHypothesis" requires="independentVar comparator outcomeVar"/>
  	   <step name="prompt" task="PromptGoodFilledHypothesis" requires="buildHypothesis"/>
  	   
  	   <applicable>
  	      $this.userGenerateHypothesis == 'yes'
  	   </applicable>
  	   
  	   <!-- input bindings: indep/dep vars come from simulation def. -->
  	   <binding slot="$this.comparatorValue" value="$comparator.selection"/>
  	   <binding slot="$this.independentVarValue" value="$independentVar.selection"/>
  	   <binding slot="$this.outcomeVarValue" value="$outcomeVar.selection"/>
  	   <binding slot="$buildHypothesis.comparator" value="$comparator.selection"/>
  	   <binding slot="$buildHypothesis.target" value="$independentVar.selection"/>
  	   <binding slot="$buildHypothesis.outcome" value="$outcomeVar.selection"/>
  	   <binding slot="$this.hypothesis" value="$buildHypothesis.hypothesis"/>
  	   <binding slot="$independentVar.external" value="true"/>
  	   <binding slot="$outcomeVar.external" value="true"/>
  	   <binding slot="$comparator.external" value="true"/>
  	</subtasks>

  	<subtasks id="agentFillHypothesisTemplate" ordered="false">
  	   <step name="prompt" task="PromptFillingHypothesis"/>
  	   <step name="independentVar" task="SelectIndependentVar" requires="prompt"/>
  	   <step name="outcomeVar" task="SelectOutcomeVar" requires="prompt"/>
  	   <step name="comparator" task="SelectComparator" requires="prompt"/>
  	   <step name="buildHypothesis" task="BuildHypothesis" requires="independentVar comparator outcomeVar"/>

  	   <applicable>
  	      $this.userGenerateHypothesis != 'yes'
  	   </applicable>
  	   
  	   <!-- input bindings: indep/dep vars come from simulation def. -->
  	   <binding slot="$this.comparatorValue" value="$comparator.selection"/>
  	   <binding slot="$this.independentVarValue" value="$independentVar.selection"/>
  	   <binding slot="$this.outcomeVarValue" value="$outcomeVar.selection"/>
  	   <binding slot="$buildHypothesis.comparator" value="$comparator.selection"/>
  	   <binding slot="$buildHypothesis.target" value="$independentVar.selection"/>
  	   <binding slot="$buildHypothesis.outcome" value="$outcomeVar.selection"/>
  	   <binding slot="$this.hypothesis" value="$buildHypothesis.hypothesis"/>
  	   <binding slot="$independentVar.external" value="false"/>
  	   <binding slot="$outcomeVar.external" value="false"/>
  	   <binding slot="$comparator.external" value="false"/>
  	</subtasks>
  	
  </task>

  <task id="PromptGoodFilledHypothesis">
     <script/>
  </task>

  <task id="PromptFillingHypothesis">
     <script/>
  </task>
  
  <!-- Choose the target IndependentVariable from the list. Can be done by user or sw agent. -->
  <task id="SelectIndependentVar">
  	<output name="selection" type="string"/>
  	
  	<postcondition>
  	  $this.selection != undefined &amp;&amp;
  	  contains(independentVariableNames, $this.selection);
  	</postcondition>
  	
  	<!-- 
  	   If user can't do the step for whatever reason, this script will do it.
  	   This enables the task to be done by the pedagogical agent instead of the user
  	   (maybe if it's in a demonstration mode) 
  	 -->
  	<script>  	  
   	  $this.selection = random_selection(independentVariableNames);
   	  
   	  // --- Get the distance and time from the GUI
  	  importClass(Packages.edu.assistment.experiments.pedagogy.PedagogicalAgent);
      PedagogicalAgent.hypothesisTarget.setSelectedItem($this.selection);
  	</script>
  </task>
  
  <!-- Choose an OutcomeVariable from the list. Can be done by user or sw agent. -->
  <task id="SelectOutcomeVar">
  	<output name="selection" type="string"/>
  	
  	<postcondition>
  	  $this.selection != undefined &amp;&amp;
  	  contains(outcomeVariableNames, $this.selection);
  	</postcondition>
  	
  	<script>
  	  $this.selection = random_selection(outcomeVariableNames);

   	  // --- Get the distance and time from the GUI
  	  importClass(Packages.edu.assistment.experiments.pedagogy.PedagogicalAgent);
      PedagogicalAgent.hypothesisOutcome.setSelectedItem($this.selection);
  	</script>	
  </task>
  
  <!-- Choose a comparator from the list. Can be done by user or sw agent. -->
  <task id="SelectComparator">
  	<output name="selection" type="string"/>
  	
  	<postcondition>
  	  $this.selection != undefined &amp;&amp;
  	  contains(comparators, $this.selection);
  	</postcondition>
  	
  	<script>
  	  $this.selection = random_selection(comparators);
  	  
   	  // --- Get the distance and time from the GUI
  	  importClass(Packages.edu.assistment.experiments.pedagogy.PedagogicalAgent);
      PedagogicalAgent.hypothesisComparator.setSelectedItem($this.selection);  	  
  	</script>
  	
  </task>
  
  <!-- 
      Have the sw agent construct the Hypothesis object.
      Call 'execute'. 
    -->
  <task id="BuildHypothesis">
     <input name="target" type="string"/>
     <input name="comparator" type="string"/>
     <input name="outcome" type="string"/>
     <output name="hypothesis" type="Hypothesis"/>
     
     <precondition>
        $this.target != undefined &amp;&amp;
        $this.comparator != undefined &amp;&amp;
        $this.outcome != undefined;
     </precondition>
     
     <postcondition>
        $this.hypothesis != undefined &amp;&amp;
        $this.hypothesis != null;
     </postcondition>
     
     <script>
         $this.hypothesis = new Hypothesis($this.target, $this.outcome, $this.comparator);
     </script>
  </task>
  
  
<!-- ********************************************************************** -->
<!-- ********************************************************************** -->
  
  <!-- 
     The "meat": how will a student set up their experiments?
     For now, I am assuming they will run TWO experiments to do CVS .
     
     Setup2 is the more important one since it must be compared to Setup1
     
   -->
  <task id="RunExperiments">
    <input name="hypothesis" type="Hypothesis"/>
    <output name="trial1" type="Trial"/>
    <output name="trial2" type="Trial"/>
    
    <!-- May need tail recursion on SetupTrialCheckCVS instead? -->
    <subtasks id="fillInTrials">
       <step name="setup1" task="SetupTrial"/>
       <step name="press" task="ResetRamp"/>
       <step name="outcome1" task="RecordOutcome"/>
       <step name="buildtrial1" task="BuildTrial"/>
       <step name="incrementtrial1" task="IncrementTrial"/>
       <step name="setup2" task="SetupTrialCheckCVS"/>
       <step name="outcome2" task="RecordOutcome"/>
       <step name="buildtrial2" task="BuildTrial"/>
       <step name="incrementtrial2" task="IncrementTrial"/>
       <step name="prompt" task="PromptGoodRunExperiments"/>
       
	   <!-- Binding to ensure CVS works -->
       <binding slot="$setup2.hypothesis" value="$this.hypothesis"/>
       <binding slot="$setup2.checkVars" value="$buildtrial1.indepvars"/>

       <!-- outcome bindings -->
       <binding slot="$outcome1.leftRampAngle" value="$setup1.leftRampAngle"/>
       <binding slot="$outcome1.ballStartPosition" value="$setup1.ballStartPosition"/>
       <binding slot="$outcome1.leftRampFriction" value="$setup1.leftRampFriction"/>
       <binding slot="$outcome1.ballType" value="$setup1.ballType"/>
       <binding slot="$outcome2.leftRampAngle" value="$setup2.leftRampAngle"/>
       <binding slot="$outcome2.ballStartPosition" value="$setup2.ballStartPosition"/>
       <binding slot="$outcome2.leftRampFriction" value="$setup2.leftRampFriction"/>
       <binding slot="$outcome2.ballType" value="$setup2.ballType"/>
       
       <!-- Trial object binding -->
       <binding slot="$buildtrial1.leftRampAngle" value="$setup1.leftRampAngle"/>
       <binding slot="$buildtrial1.ballStartPosition" value="$setup1.ballStartPosition"/>
       <binding slot="$buildtrial1.leftRampFriction" value="$setup1.leftRampFriction"/>
       <binding slot="$buildtrial1.ballType" value="$setup1.ballType"/>
       <binding slot="$buildtrial1.distance" value="$outcome1.distance"/>
       <binding slot="$buildtrial1.time" value="$outcome1.time"/>
       <binding slot="$buildtrial2.leftRampAngle" value="$setup2.leftRampAngle"/>
       <binding slot="$buildtrial2.ballStartPosition" value="$setup2.ballStartPosition"/>
       <binding slot="$buildtrial2.leftRampFriction" value="$setup2.leftRampFriction"/>
       <binding slot="$buildtrial2.ballType" value="$setup2.ballType"/>
       <binding slot="$buildtrial2.distance" value="$outcome2.distance"/>
       <binding slot="$buildtrial2.time" value="$outcome2.time"/>
       
       <!-- Prompt binding -->
       <binding slot="$prompt.hypothesis" value="$this.hypothesis"/>
       <binding slot="$press.external" value="true"/>
       
	   <!-- Final binding to trials -->
       <binding slot="$this.trial1" value="$buildtrial1.trial"/>
       <binding slot="$this.trial2" value="$buildtrial2.trial"/>
    </subtasks>    
  </task>
  
  <!-- 
     Each of these will be set by the GUI elements
     For convenience, aggregate all the variables at the end for other tasks to use 
   -->
  <task id="SetupTrial">
    <output name="leftRampAngle" type="string"/>
    <output name="ballStartPosition" type="string"/>
    <output name="leftRampFriction" type="string"/>
    <output name="ballType" type="string"/>
    
    <postcondition>
       $this.leftRampAngle != undefined &amp;&amp;
       $this.ballStartPosition != undefined &amp;&amp;
       $this.leftRampFriction != undefined &amp;&amp;
       $this.ballType != undefined;
    </postcondition>
  </task>
  
  <!-- 
     Record the results of running an experiment. The system always does this.
     For convenience, aggregate all the variables at the end for other tasks to use
     
     This task is capable of automatically recording the data to the graphical table.       
   -->
  <task id="RecordOutcome">
    <input name="leftRampAngle" type="string"/>
    <input name="ballStartPosition" type="string"/>
    <input name="leftRampFriction" type="string"/>
    <input name="ballType" type="string"/>
  	<output name="distance" type="number"/>
  	<output name="time" type="number"/>
  	
  	<precondition>
  	   $this.leftRampAngle != undefined &amp;&amp;
  	   $this.ballStartPosition != undefined &amp;&amp;
  	   $this.leftRampFriction != undefined &amp;&amp;
  	   $this.ballType != undefined;
  	</precondition>
  	
  	<postcondition>
  	   $this.distance != undefined &amp;&amp;
  	   $this.time != undefined;
  	</postcondition>
  	
  	<script>
  	   // --- Get the distance and time from the GUI
  	   importClass(Packages.edu.assistment.experiments.pedagogy.PedagogicalAgent);
  	   
  	   // --- Nasty; wait for the simulation thread to stop (yielding results)
  	   // while(!PedagogicalAgent.simController.resultsAvailable());
  	   
  	   // --- Get the results
  	   $this.distance = PedagogicalAgent.simModel.getDistanceRolledFromIncline();
  	   $this.time = PedagogicalAgent.simModel.getCurrentTime();
  	   
  	   // --- Put them in the table 
  	   PedagogicalAgent.trialTable.getModel().setValueAt($this.leftRampAngle, trial-1, 1);
  	   PedagogicalAgent.trialTable.getModel().setValueAt($this.leftRampFriction, trial-1, 2);
  	   PedagogicalAgent.trialTable.getModel().setValueAt($this.ballType, trial-1, 3);
  	   PedagogicalAgent.trialTable.getModel().setValueAt($this.ballStartPosition, trial-1, 4);  	   
  	   PedagogicalAgent.trialTable.getModel().setValueAt($this.distance, trial-1, 5);
  	   PedagogicalAgent.trialTable.getModel().setValueAt($this.time, trial-1, 6);
  	</script>	

  </task>
  
  
  <!-- Have sw agent keep track of current trial # -->
  <task id="IncrementTrial">
  	<script>
        trial++;  	     	   
  	</script>
  </task>
  
  <!-- Wait for user to press 'reset ramp' button -->
  <task id="ResetRamp">
  </task>
  
  <!-- Have sw build the trial object -->
  <task id="BuildTrial">
    <input name="leftRampAngle" type="string"/>
    <input name="ballStartPosition" type="string"/>
    <input name="leftRampFriction" type="string"/>
    <input name="ballType" type="string"/>
  	<input name="distance" type="number"/>
  	<input name="time" type="number"/>
  	<output name="trial" type="Trial"/>
  	<output name="indepvars" type="VariableCollection"/>
  	<output name="outcomevars" type="VariableCollection"/>
  	
  	<script>
  	     // --- Indep vars
         var leftRampAngleVar = new IndependentVariable("steepness", $this.leftRampAngle);
         var ballStartPositionVar = new IndependentVariable("run length", $this.ballStartPosition);
         var leftRampFrictionVar = new IndependentVariable("surface type", $this.leftRampFriction);
         var ballTypeVar = new IndependentVariable("ball type", $this.ballType);
         $this.indepvars = new VariableCollection([leftRampAngleVar, ballStartPositionVar, leftRampFrictionVar, ballTypeVar]);

         // --- Outcome vars
  		 var distanceVar = new OutcomeVariable("distance", $this.distance);
  		 var timeVar = new OutcomeVariable("time", $this.time);
         $this.outcomevars = new VariableCollection([distanceVar, timeVar]);
         
         $this.trial = new Trial($this.indepvars, $this.outcomevars);
  	</script>
     
  </task>
  
  <!-- If CVS strategy satisfied, this task will not be needed -->
  <task id="SetupTrialCheckCVS">
     <input name="hypothesis" type="Hypothesis"/>
     <input name="checkVars" type="VariableCollection"/>
     <output name="leftRampAngle" type="string"/>
     <output name="ballStartPosition" type="string"/>
     <output name="leftRampFriction" type="string"/>
     <output name="ballType" type="string"/>
     
     <subtasks id="performAndCheck">
     	<step name="setup" task="SetupTrial"/>
        <step name="press" task="ResetRamp"/>
     	<step name="buildVarCollection" task="BuildVariableCollection"/>
     	<step name="clearHighlights" task="ClearHighlights"/>
     	<step name="check" task="CheckCVS"/>
     	
     	<binding slot="$this.leftRampAngle" value="$setup.leftRampAngle"/>
     	<binding slot="$this.ballStartPosition" value="$setup.ballStartPosition"/>
     	<binding slot="$this.leftRampFriction" value="$setup.leftRampFriction"/>
     	<binding slot="$this.ballType" value="$setup.ballType"/>
     	<binding slot="$buildVarCollection.leftRampAngle" value="$setup.leftRampAngle"/>
     	<binding slot="$buildVarCollection.ballStartPosition" value="$setup.ballStartPosition"/>
     	<binding slot="$buildVarCollection.leftRampFriction" value="$setup.leftRampFriction"/>
     	<binding slot="$buildVarCollection.ballType" value="$setup.ballType"/>
     	
     	<binding slot="$check.hypothesis" value="$this.hypothesis"/>
     	<binding slot="$check.checkVars" value="$this.checkVars"/>
     	<binding slot="$check.setupVars" value="$buildVarCollection.variables"/>

        <binding slot="$press.external" value="true"/>
     </subtasks>
     
     <!-- If the first check failed, try again -->
     <subtasks id="retry">
        <step name="again" task="SetupTrialCheckCVS"/>
        
        <applicable> 
           $this.success == false;
        </applicable>
        
        <binding slot="$again.hypothesis" value="$this.hypothesis"/>
        <binding slot="$again.checkVars" value="$this.checkVars"/>
        <binding slot="$this.leftRampAngle" value="$again.leftRampAngle"/>
        <binding slot="$this.ballStartPosition" value="$again.ballStartPosition"/>
        <binding slot="$this.leftRampFriction" value="$again.leftRampFriction"/>
        <binding slot="$this.ballType" value="$again.ballType"/>        
     </subtasks>     
  </task>

  <!-- Construct the variable collection used in CVS comparison -->
  <task id="BuildVariableCollection">
     <input name="leftRampAngle" type="string"/>
     <input name="ballStartPosition" type="string"/>
     <input name="leftRampFriction" type="string"/>
     <input name="ballType" type="string"/>
     <output name="variables" type="VariableCollection"/>
  
     <script>
         var leftRampAngleVar = new IndependentVariable("steepness", $this.leftRampAngle);
         var ballStartPositionVar = new IndependentVariable("run length", $this.ballStartPosition);
         var leftRampFrictionVar = new IndependentVariable("surface type", $this.leftRampFriction);
         var ballTypeVar = new IndependentVariable("ball type", $this.ballType);
         $this.variables = new VariableCollection([leftRampAngleVar, ballStartPositionVar, leftRampFrictionVar, ballTypeVar]);     
     </script>
  </task>
  
  <!-- 
     Clear highlights since we do not know if any of the subsequent tasks will
     highlight anything. 
   -->
  <task id="ClearHighlights">
     <script>
  	     importClass(Packages.edu.assistment.experiments.pedagogy.PedagogicalAgent);     
  	     for(var i=0; i &lt; independentVariableNames.length; i++)
  	     {
  	        PedagogicalAgent.clearHighlight(independentVariableNames[i]);
  	     }
     </script>
  </task>
  
  <!-- 
      Determine if the two experiments the user has set up is correct. 
      Engage in scaffolding if not corrected.
   -->
  <task id="CheckCVS">
  	<input name="hypothesis" type="Hypothesis"/>
  	<input name="checkVars" type="VariableCollection"/>
  	<input name="setupVars" type="VariableCollection"/>

  	<!-- If these properties hold true, CVS has been performed correctly. -->
  	<postcondition sufficient="true">
  	   $this.hypothesis != undefined &amp;&amp;
  	   $this.checkVars != undefined &amp;&amp;
  	   $this.setupVars != undefined &amp;&amp;
       unchangedVariables($this.hypothesis.independentVariable, $this.checkVars.vars, $this.setupVars.vars) &amp;&amp;
  	   changedTarget($this.hypothesis.independentVariable, $this.checkVars.vars, $this.setupVars.vars);         	   
  	</postcondition>
  
    <!-- 
      Scaffolding process
      1. State there's an error
      2. Figure out what kind(s) of errors there are and take action
      3. State to try again
      
      Note that the repair tasks are optional since there may or may not
      be a repair necessary for that criteria. These tasks will only get
      executed if the 'preconditions' for those tasks are valid.
      
      This is actually the result of a refactoring from a decomposition that was required
      since I wanted to prompt and error and a try again message before and
      after the repairing.
     -->
     <subtasks id="repairSequence">
      <step name="promptError" task="PromptSetupError"/>
      <step name="repair1" task="RepairUnchangedHypothesisValue" minOccurs="0"/>
      <step name="repair2" task="RepairVariablesNotControlled" minOccurs="0"/>
      <step name="promptAgain" task="PromptTryAgain"/>
      
  	  <binding slot="$repair1.hypothesis" value="$this.hypothesis"/>
      <binding slot="$repair1.setupVars" value="$this.setupVars"/>
  	  <binding slot="$repair1.checkVars" value="$this.checkVars"/>
  	  <binding slot="$repair2.hypothesis" value="$this.hypothesis"/>
  	  <binding slot="$repair2.setupVars" value="$this.setupVars"/>
  	  <binding slot="$repair2.checkVars" value="$this.checkVars"/>
  	  <binding slot="$promptError.hypothesis" value="$this.hypothesis"/>
    </subtasks>  
  </task>
    
  <!-- 
     If the target variable is unchanged, either
     1. Prompt that something is incorrect
     2. Highlight the error 
    -->  
  <task id="RepairUnchangedHypothesisValue">
     <input name="hypothesis" type="Hypothesis"/>
  	 <input name="checkVars" type="VariableCollection"/>
  	 <input name="setupVars" type="VariableCollection"/>
     
     <precondition>
  		!changedTarget($this.hypothesis.independentVariable, $this.checkVars.vars, $this.setupVars.vars);
     </precondition>
     
    <!-- The other variables not mentioned in the hypothesis were changed -->  	  	
  	<subtasks id="prompting">
  	    <step name="prompt" task="PromptUnchangedHypothesis"/>
        
  		<applicable>
  		   hypothesisUnchangedCtr &lt; 1;
  		</applicable>
  	</subtasks>
  	
  	<subtasks id="highlighting">
  	   <step name="highlight" task="HighlightUnchangedHypothesis"/>
  	   
  	   <applicable>
  		   hypothesisUnchangedCtr &gt;= 1;
  	   </applicable>
  	   
  		<binding slot="$highlight.hypothesis" value="$this.hypothesis"/>
  	</subtasks>
  </task>
  
  <task id="PromptUnchangedHypothesis">
  	<script>
  	  hypothesisUnchangedCtr++;
  	</script>
  </task>
  
  <task id="HighlightUnchangedHypothesis">
    <input name="hypothesis" type="Hypothesis"/>
    <output name="target" type="string"/>
    
    <script>
       hypothesisUnchangedCtr++;
       $this.target = $this.hypothesis.independentVariable;
       
       // --- Highlight the target variable not changed
  	   importClass(Packages.edu.assistment.experiments.pedagogy.PedagogicalAgent);
  	   importClass(Packages.java.awt.Color);
  	   PedagogicalAgent.highlightControl($this.hypothesis.independentVariable, java.awt.Color.BLUE);     
    </script>
  </task>
  
  <!-- 
     Two levels of repair vars not controlled:
     1. Prompt incorrect twice
     2. Show incorrectness
   -->
  <task id="RepairVariablesNotControlled">
  	<input name="hypothesis" type="Hypothesis"/>
  	<input name="checkVars" type="VariableCollection"/>
  	<input name="setupVars" type="VariableCollection"/>

    <precondition>
       !unchangedVariables($this.hypothesis.independentVariable, $this.checkVars.vars, $this.setupVars.vars);
    </precondition>    
    
    <!-- The other variables not mentioned in the hypothesis were changed -->  	  	
  	<subtasks id="prompting">
  	    <step name="prompt" task="PromptVariablesNotControlledIncorrect"/>
        
  		<applicable>
  		   repairVariablesNotControlledCtr &lt; 1;
  		</applicable>
  	</subtasks>
  	
  	<subtasks id="highlighting">
  	   <step name="highlight" task="HighlightVariablesNotControlled"/>
  	   
  	   <applicable>
  		   repairVariablesNotControlledCtr &gt;= 1;
  	   </applicable>
  	   
  		<binding slot="$highlight.hypothesis" value="$this.hypothesis"/>
  		<binding slot="$highlight.setupVars" value="$this.setupVars"/>
  		<binding slot="$highlight.checkVars" value="$this.checkVars"/>
  	</subtasks>
  	
  </task>
  
  <task id="PromptVariablesNotControlledIncorrect">
      <script>
         repairVariablesNotControlledCtr++;
      </script>
  </task>
  
  <task id="HighlightVariablesNotControlled">
  	<input name="hypothesis" type="Hypothesis"/>
  	<input name="checkVars" type="VariableCollection"/>
  	<input name="setupVars" type="VariableCollection"/>
    <output name="uncontrolledVarNames" type="string"/>
      
      <script>
         repairVariablesNotControlledCtr++;
         
         var uncontrolledVars = getChangedVariables($this.hypothesis.independentVariable, $this.checkVars.vars, $this.setupVars.vars);
         $this.uncontrolledVarNames = uncontrolledVars.toString();
         
     	 // --- Highlight all of the controls whose variables are uncontrolled
  	     importClass(Packages.edu.assistment.experiments.pedagogy.PedagogicalAgent);     
    	 importClass(Packages.java.awt.Color);
  	     for(var i=0; i &lt; uncontrolledVars.length; i++)
  	     {
            PedagogicalAgent.highlightControl(uncontrolledVars[i], java.awt.Color.RED);
         }
      </script>
  </task>
  
  <!-- Prompt to the user that they set up a good experiment. -->
  <task id="PromptGoodRunExperiments">
    <input name="hypothesis" type="Hypothesis"/>
    <output name="independentVar" type="string"/>
    <output name="outcomeVar" type="string"/>
    
    <script>
       $this.outcomeVar = $this.hypothesis.outcomeVariable;
       $this.independentVar = $this.hypothesis.independentVariable;
    </script>
  </task>

  <!-- Prompt to the user that they set up an incorrect experiment. -->
  <task id="PromptSetupError">
    <input name="hypothesis" type="Hypothesis"/>
    <output name="independentVar" type="string"/>
    <output name="outcomeVar" type="string"/>
    
    <script>
       $this.outcomeVar = $this.hypothesis.outcomeVariable;
       $this.independentVar = $this.hypothesis.independentVariable;
    </script>
  </task>
  
<!-- ********************************************************************** -->
<!-- ********************************************************************** -->    
  
  
    
  <!-- Repeatedly try to get the student to form the correct conclusions -->
  <task id="FormConclusions">
    <input name="hypothesis" type="Hypothesis"/>
    <input name="trial1" type="Trial"/>
    <input name="trial2" type="Trial"/>
    <output name="conclusions" type="Conclusions"/>
    
    <subtasks id="performAndCheckConclusions" ordered="false">
       <step name="select" task="SelectConclusions"/>
       <step name="build" task="BuildConclusions"/>
       <step name="check" task="CheckConclusions" requires="select build"/>

       <binding slot="$this.conclusions" value="$build.conclusions"/>
       <binding slot="$build.correctness" value="$select.correctness"/>
       <binding slot="$build.outcomeVar" value="$select.outcomeVar"/>
       <binding slot="$build.comparator" value="$select.comparator"/>
       
       <binding slot="$check.hypothesis" value="$this.hypothesis"/>
       <binding slot="$check.trial1" value="$this.trial1"/>
       <binding slot="$check.trial2" value="$this.trial2"/>
       <binding slot="$check.conclusions" value="$build.conclusions"/>
    </subtasks>
    
    <subtasks id="retryConclusions">
       <step name="again" task="FormConclusions"/>
       
       <applicable>
         $this.success == false;
       </applicable>
       
       <binding slot="$again.hypothesis" value="$this.hypothesis"/>
       <binding slot="$again.trial1" value="$this.trial1"/>
       <binding slot="$again.trial2" value="$this.trial2"/>
       <binding slot="$this.conclusions" value="$again.conclusions"/>
    </subtasks>
    
  </task>
  
  <!-- Primitive task for entering in conclusions -->
  <task id="SelectConclusions">
    <input name="correctness" type="string"/>
    <input name="outcomeVar" type="string"/>
    <input name="comparator" type="string"/>
    
    <postcondition>
      $this.correctness != undefined &amp;&amp;
      $this.comparator != undefined &amp;&amp;
      $this.outcomeVar != undefined &amp;&amp;
      contains(outcomeVariableNames, $this.outcomeVar) &amp;&amp;
      contains(comparators, $this.comparator) &amp;&amp;
      contains(["incorrect", "correct"], $this.correctness);
    </postcondition>

  </task>
  
  <!-- Have the sw agent build the Conclusions object -->
  <task id="BuildConclusions">
    <input name="correctness" type="string"/>
    <input name="comparator" type="string"/>
    <input name="outcomeVar" type="string"/>
    <output name="conclusions" type="Conclusions"/>

    <precondition>
      $this.correctness != undefined &amp;&amp;
      $this.comparator != undefined &amp;&amp;
      $this.outcomeVar != undefined;
    </precondition>
    
    <postcondition>
      $this.conclusions != undefined;
    </postcondition>
  
    <script>
       $this.conclusions = new Conclusions($this.correctness, $this.outcomeVar, $this.comparator);
    </script>
    
  </task>
  
  <!--  
     Check to make sure the conclusions are valid and take remedial actions as necessary. 
  -->
  <task id="CheckConclusions">
    <input name="hypothesis" type="Hypothesis"/>
    <input name="trial1" type="Trial"/>
    <input name="trial2" type="Trial"/>
    <input name="conclusions" type="Conclusions"/>

    <postcondition sufficient="true">
       $this.hypothesis != undefined &amp;&amp;
       $this.trial1 != undefined &amp;&amp;
       $this.trial2 != undefined &amp;&amp;
       $this.conclusions != undefined &amp;&amp;
       unchangedOutcome($this.hypothesis, $this.conclusions) &amp;&amp;
       compareTrials($this.hypothesis, $this.conclusions, $this.trial1, $this.trial2) &amp;&amp;
       correctnessCheck($this.hypothesis, $this.conclusions, $this.trial1, $this.trial2);       
    </postcondition>

    <subtasks id="wrongOutcome">
      <step name="prompt" task="PromptConclusionWrongOutcomeVar"/>
      <applicable>
         print("Apply WRONG OUTCOME?");
         $this.conclusions != undefined &amp;&amp;
         !unchangedOutcome($this.hypothesis, $this.conclusions);
      </applicable>
    </subtasks>
    
    <subtasks id="wrongInterpretation">
      <step name="prompt" task="PromptConclusionWrongInterpretation"/>
      <applicable>
         print("Apply WRONG INTERPRETATION?");
         $this.conclusions != undefined &amp;&amp;
         $this.hypothesis != undefined &amp;&amp;
         !compareTrials($this.hypothesis, $this.conclusions, $this.trial1, $this.trial2);
      </applicable>
    </subtasks>
    
    <subtasks id="wrongCorrectness">
      <step name="prompt" task="PromptConclusionWrongCorrectness"/>
      <applicable>
         print("Apply WRONG CORRECTNESS?");
         $this.conclusions != undefined &amp;&amp;
         $this.hypothesis != undefined &amp;&amp;
         !correctnessCheck($this.hypothesis, $this.conclusions, $this.trial1, $this.trial2);       
      </applicable>
    </subtasks>
    
  </task>
    
  <task id="PromptConclusionWrongOutcomeVar">
     <script>
     </script>
  </task>
  
  <task id="PromptConclusionWrongInterpretation">
     <script>
     </script>
  </task>
  
  <task id="PromptConclusionWrongCorrectness">
     <script>
     </script>
  </task>

<!-- ********************************************************************** -->
<!-- ********************************************************************** -->    
<!-- ********************************************************************** -->
<!-- ********************************************************************** -->    
<!-- ********************************************************************** -->
<!-- ********************************************************************** -->    
<!-- ********************************************************************** -->
<!-- ********************************************************************** -->    
  
  <!-- Define all the elements associated with the system -->
  <script init="true">
  
    function IndependentVariable (name, value) 
    {
      this.name = name;
      this.value = value;
    }
    
    function OutcomeVariable (name, value) 
    {
      this.name = name;
      this.value = value;
    }
    
    function Simulation (indepVarsNames, outcomeVarsNames)
    {
      this.independentVariableNames = indepVarsNames;
      this.outcomeVariablesNames = outcomeVarsNames;
    }
    
    function Hypothesis (indepVar, outcomeVar, comp)
    {
      this.comparator = comp;
      this.independentVariable = indepVar;
      this.outcomeVariable = outcomeVar;
    }

    function Conclusions (correctness, outcomeVar, comp)
    {
      this.correct = correctness; 
      this.comparator = comp;
      this.outcomeVariable = outcomeVar;
    }
    
    function Experiment (sim)
    {
      this.simulation = sim;
    }
    
    function Trial (inputVars, outputVars)
    {
      this.inputVariables = inputVars;
      this.outputVariables = outputVars;
      
      this.toString = function()
      {
         return "input vars: " + this.inputVariables + "output vars: " + this.outputVariables;
      }
    }
    
    function TrialSet(trials)
    {
      this.trials = trials;
    }
    
    function VariableCollection(vs)
    {
      this.vars = vs;
    }

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

    //
    // Check to make sure the comparison is valid given the data.
    // Returns true if the comparison is valid; false otherwise.
    function compareTrials(hyp, concl, trial1, trial2)
    {
       //print("compareTrials trial1: " + trial1.toString());
       //print("compareTrials trial2: " + trial2.toString());

       if(hyp == undefined || concl == undefined || trial1 == undefined || trial2 == undefined)
       {
          return false;
       }
       if(trial1.inputVariables == undefined)
       {
          print("ERROR -- Trial 1 inputvars undefined! Returning false");
          return false;
       }
       if(trial2.inputVariables == undefined)
       {
          print("ERROR -- Trial 2 inputvars undefined! Returning false");
          return false;
       }
       
       return doCompareTrials(hyp.independentVariable, concl.outcomeVariable,
                            concl.comparator, trial1, trial2);
    }
    
    // --- Actually perform the "compareTrials" computation
    function doCompareTrials(indepName, outcomeName, comparator, trial1, trial2)
    {
       var t1 = null;
       var t2 = null;
       
       //print("Trial 1 input vars: " + trial1.inputVariables);
       //print("Trial 1 input vars vars: " + trial1.inputVariables.vars);
       //print("Trial 2 input vars: " + trial2.inputVariables);
       //print("Trial 2 input vars vars: " + trial2.inputVariables.vars);
       
       if( findVariableValue(findVariable(indepName, trial1.inputVariables.vars).value) == 1)
       {
         t1 = trial2;
         t2 = trial1;
       } 
       else
       {
         t1 = trial1;
         t2 = trial2;
       }
       
       return comparatorCompare(comparator, findVariable(outcomeName, t1.outputVariables.vars).value,
                                            findVariable(outcomeName, t2.outputVariables.vars).value);
    }
        
    // +comparator: {"increase", "decrease", "stay the same"}
    // +val1: float
    // +val2: float
    // return TRUE on the conditions listed in the code; FALSE otherwise.
    function comparatorCompare(comparator, val1, val2)
    {
       //print("Comparing: " + comparator + "  val1: " + val1 + "  val2:  " + val2);
       
       if(comparator == "increase")
       {
          return val1 &lt; val2;
       }
       if(comparator == "decrease")
       {
          return val1 > val2;
       }
       
       return Math.abs(val1 - val2) &lt; 0.0001;
    }

    // return TRUE if correctness is the string "correct"; FALSE otherwise.
    function correctToBoolean(correctness)
    {
       if(correctness == "correct")
       {
         return true;
       }
       
       return false;
    }

    // correctness check function
    function correctnessCheck(hyp, concl, trial1, trial2)
    {
       if(concl == undefined)
       {
         return false;
       }
       
       //print("main hypoth: " + hyp.comparator);
       //print("main concl: " + concl.comparator);
       //print("main trial1: " + trial1.toString());
       //print("main trial2: " + trial2.toString());
       //print("trial1 input vars: " + trial1.inputVariables);
       
       // --- Hypothesis is passed in twice, because we want to see if the original
       //     hypothesis is correct or not. Conveniently, hypothesis has the same
       //     attribute variables as the Conclusions so this works.
       var compareTrialsResult = 
         compareTrials(hyp, hyp, trial1, trial2);
       var correctResult = correctToBoolean(concl.correct);
       
       //print("Trial comparison: " + compareTrialsResult);
       //print("Correctness result: " + correctResult);
       return compareTrialsResult == correctResult; 
    
    }
            
    // +list: list of elements,
    // +elt: element potentially in list
    //
    // return: true if elt in list, false otherwise.
    function contains (list, elt) 
    {
       //print(list)
       //print(elt)
       if(elt == undefined) return false;
       
       return list.indexOf(elt) != -1;
    }

    // return: random element in the list
    function random_selection(list)
    {
       return list[(Math.floor( Math.random() * (list.length)) % list.length)];
    }
    
    // Return a variable in the list with matching name
    // Return: IndependentVariable
    function findVariable(name, varlist)
    {
       //print('name: ' + name);
       for(i=0; i &lt; varlist.length; i++)
       {
          //print('varlist ' + i + '  name: ' + varlist[i].name);
          if(varlist[i].name == name)
          {
             //print('match!');
             return varlist[i];
          }
       }
       print('ERROR! NO MATCH in findVariable for: ' + name);
    }
    
    // Return the numerical equivalent of a variable's value.
    // Needed for conclusion checking
    //
    // Returns null if failure
    function findVariableValue(name)
    {
       for(i=0; i &lt; variableValues.length; i++)
       {
          if(variableValues[i].name == name)
            return variableValues[i].value;
       }
       
       return null;
    }
    
    function getChangedVariables(name, vars1, vars2)
    {
       //print('changedVariables');
       //print('name: ' + name);
       //print(vars1);
       //print(vars2);
       var changedVars = [];
       var idx=0;
       for(i=0; i &lt; vars1.length; i++)
       {
          // Don't use the hypothesis variable since we DO want that to differ!
          //print(vars1[i].name + " =?= " + name);
          if(vars1[i].name != name)
          {
             matchVar = findVariable(vars1[i].name, vars2);
             //print("*** " + matchVar.value + " =?= " + vars1[i].value);
             if(matchVar.value != vars1[i].value)
             {
                changedVars[idx] = vars1[i].name;
                idx++;
             }
          } 
       }
       
       //print("Changed vars: " + changedVars);
       return changedVars;       
    }
    
    // Check if any values other than the one w/ name given as input have the same values
    // Return: true if no other variables changed, false otherwise
    function unchangedVariables(name, vars1, vars2)
    {
       if (name == undefined || vars1 == undefined || vars2 == undefined)
       {
          return false;
       }

       var changedVars = getChangedVariables(name, vars1, vars2);
       //print("changed Vars: " + changedVars);
       return (changedVars.length) == 0;
    }

    // Return: true if name, vars1, and vars2 are all defined AND the value for
    //         vars1@name == vars2@name. False otherwise.
    function changedTarget(name, vars1, vars2)
    {
       if (name == undefined || vars1 == undefined || vars2 == undefined)
       {
          return false;
       }
       
  	   return findVariable(name, vars1).value != findVariable(name, vars2).value;
    }


    // 
    // Make sure the outcome variable has not changed between the hypothesis
    // and the conclusion.
    //
    // return TRUE if the hypothesis and conclusion have the same outcome variable
    //        FALSE otherwise.
    function unchangedOutcome(hyp, concl)
    {
       if(hyp == undefined || concl == undefined)
       {
          return false;
       }
       
       return hyp.outcomeVariable == concl.outcomeVariable;
    }
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
    
    // ******* WORLD OBJECTS *********
    
    var independentVariableNames = ["steepness", "run length", "ball type", "surface type"];
    var outcomeVariableNames = ["distance", "time"];
    var comparators = ["increase", "decrease", "stay the same"];    
    
    // --- Mapping from variable values to integers. Used by "FormConclusions" computations
    //     to check for correctness.
    var variableValues = [
      { name: "low", value: 0},
      { name: "high", value: 1},
      { name: "smooth", value: 0},
      { name: "rough", value: 1},
      { name: "rubber", value: 0},
      { name: "golf", value: 1},
      { name: "full", value: 0},
      { name: "half", value: 1} ];
                  
    // --- Global counter for trial number
    var trial = 1;
    
    // --- Global counters for #attempts fixing 2nd trial to get
    //     the control of variables strategy (CVS) correct.
    //
    //     These cause prompting/highlighting branches to change.
    repairVariablesNotControlledCtr = 0;
    hypothesisUnchangedCtr = 0;
    
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////


    // test evals:
    // eval compareTrials("steepness", "distance", "increase", trial1, trial2)
    // eval compareTrials("steepness", "time", "increase", trial1, trial2)

  </script>

</taskModel>