Fundamental Theorem of Calculus: storing answers, the eval method for formulas and eval-or-do blocks.

From WeBWorK_wiki
Revision as of 17:35, 7 May 2022 by Rhcpkole (talk | contribs) (Created page with "It is very often that we want to give partial credit to a student based on a previous answer. This example goes over this. <nowiki># Created by Nikola Kuzmanovski # In this...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

It is very often that we want to give partial credit to a student based on a previous answer. This example goes over this.

# Created by Nikola Kuzmanovski
# In this problem we ask the student to find the anti-derivative of a function.
# The +C is included at the end, so the student need not insert it.
# However, if the student enters an answer with a concrete constant we will still count this as correct.
# For example both x^4 and x^4+3 would be valid answers if the correct answer is x^4.
# We then ask the student to find the definite integral of the same function with certain bounds.
# We will award partial credit for the second part of the problem based on the students input for the first part.

########################################################################

DOCUMENT();      

loadMacros(
   "PGstandard.pl",     		# Standard macros for PG language
   "MathObjects.pl",			# Standard objects like real numbers, functions etc.	
);

# Print problem number and point value (weight) for the problem
TEXT(beginproblem());

# Show which answers are correct and which ones are incorrect
$showPartialCorrectAnswers = 1;

##############################################################
#
#  Setup
#
#


Context("Numeric");	# Contains almost everything you need for real variable calculus

# The function to be integrated.
$f = Formula("x^4");


# The anti-derivative
$antiDiv = Formula("x^5/5");

# The limits of integration for the definite integral
$lowerLimit = 4;
$upperLimit = 10;

# The correct value for the definite integral
$area = $antiDiv->eval(x => $upperLimit) - $antiDiv->eval(x => $lowerLimit);

##############################################################
#
#  Text
#
#

Context()->texStrings;
BEGIN_TEXT
The is a problem on integration.
For the first part you need to find an anti-derivative.
Note that we have included that \(+ C\) at the end, so you need not worry about it.
In the second part you need to compute a definite integral.
$BR

One has
$BCENTER
\(\displaystyle \int  $f = \) \{ans_rule\} + \(C\).
$ECENTER

So, then we get
$BCENTER
\(\displaystyle \int_{$lowerLimit}^{$upperLimit}  $f = \) \{ans_rule\}.
$ECENTER


END_TEXT
Context()->normalStrings;

##############################################################
#
#  Answers
#
#

# We are going to store the answer and score for the first answer that the student provides.
$ans1 = Formula("");
$score1  = 0.0;

# Subroutine that will check the first answer and store the answer and score.
$checkAntiDiv = sub{
	my ($correctFunc, $studentFunc, $ansHash) = @_;	# Get correct answer, student answer and the answer hash.
	
	# Store the first answer.
	$ans1 = $studentFunc;
	
	# Check if the student got the correct answer.
	if($correctFunc == $studentFunc){
		# The student got the correct answer.
		# Store the score the student got.
		$score1 = 1.0;
		
		# Return the score and exit.
		return $score1;
	}
	
	# The student didn't get any credit.
	return $score1;
};

# Check the first answer.
# We make sure that if the student answer differs by a constant that it is still accepted.
ANS($antiDiv->cmp(upToConstant => 1, checker => $checkAntiDiv));

# Subroutine that will check if the computed the definite integral correctly.
$checkArea= sub {
	my ($correctArea, $studentAreaInput, $ansHash) = @_;	# Get correct answer, student answer and the answer hash.
	
	# Check if the student got everything correct.
	if($score1 && $correctArea == $studentAreaInput){
		# The student got everything correct.
		#Give full points and exit.
		return 1.0;
	} 
	
	# The student didn't get the first part correct.
	# However, we will give them points if they used the Fundamental Theorem of Calculus correctly.
	
	# The score to be given to the student.
	# Currently 0 because they haven't earned any credit.
	my $score = 0.0;
	
	# Try to compute the definite integral based on the first answer.
	eval{
		# Compute the definite integral
		my $studentAreaEval = $ans1->eval(x => $upperLimit) - $ans1->eval(x => $lowerLimit);
		
		# Check if the definite integral from the first answer and the input for the second answer match.
		if ($studentAreaEval == $studentAreaInput){
			# They match.
			# Give the student full points for the second part.
			$score = 1.0;
			# Tell the student why they got points.
			$ansHash->{ans_message} = "You didn't get the first part right. However, you used the Fundamental Theorem of Calculus correctly.";
		}
		
		# Report that there were no errors.
		1;
	} or do{
		# An error occurred when using formula->eval above.
		# Tell the student to double check things.
		$ansHash->{ans_message} = "It seems that the answer you gave for the antiderivative doesn't evaluate at the limit points for the second part of the problem.";
		$ansHash->{ans_message} = $ansHash->{ans_message} . " Try double checking your work for the first part and try again.";
		$ansHash->{ans_message} = $ansHash->{ans_message} . " Check for things like divison by 0 or negatives under a square root.";
	};
	
	# Give partial credit points to the student.
	return $score;
};


ANS($area->cmp(checker => $checkArea));


ENDDOCUMENT();        

Exercises:

  1. Input 1/(x+10) for the first answer blank. What happens?
  2. Remove the 1; in the eval block. What happens and why? Try inputting x for the first answer and 3 for the second answer.
  3. Modify the problem above to give partial credit when the student flips the limits of integration.
  4. Modify the problem from exercise two to give partial credit in at least four other situations.
  5. Modify the problem above to use parserMultiAnswer.pl.
    1. Try inputting 1/(x+10) for the first answer blank. If your program fails, fix it.
    2. Try Inputting x^5/5 for the first answer blank and the string blabla for the second answer blank. If the problem doesn't award full points for the first part then fix it. Look at PreFilter. A multi answer object is an array, the first things that it points to (when you check the answers) is the student input.
    3. Try inputting x^5/5 in the first answer blank and (0,0) in the second. What happens?
    4. Discuss design decisions between storing answers and parserMultiAnswer.pl.