WeBWorK Main Forum

using student answers to generate output

using student answers to generate output

by Joel Trussell -
Number of replies: 4
I"m going to try this one again. I asked about this in 2014. I'd still like to do this. I read about Scaffolding but didn't see a way to use it. I had only one response previously and that to use a custom answer checker. I tried variations on this but the output of the checker didn't show up in the latter part of the questions - not surprising since the entire question is formatted before the student enters an answer. Is it possible to use Sage/Python to let the student enter answers that I can use for subsequent computation. My toy example is

part 1 - student chooses a frequency F for a sinusoid (1<= F <= 10). I'll accept any answer as correct if it is in the interval [1,10]. part 2 - I draw a graph using the student's frequency F + dF, a random number and ask the student if this is the correct graph. If dF = 0, it is, if dF != 0 it is not. this is not the complex problem that I'd use but it illustrates the concepts I'm after.

thanks!!
In reply to Joel Trussell

Re: using student answers to generate output

by Paul Pearson -
Hi Joel,

The first pg problem below uses PGML and scaffold.pl
  • http://webwork.maa.org/wiki/Scaffolding2
  • https://github.com/openwebwork/pg/blob/master/macros/scaffold.pl
and harvests the student's first answer using

$inputs_ref->{ANS_NUM_TO_NAME(1)}

The second pg problem below uses only BEGIN_TEXT / END_TEXT and recycles some code from the CompoundProblems that came before scaffold.pl
  • http://webwork.maa.org/wiki/CompoundProblems
and harvests the student's score and answer from the answer hash via

$ans_hash1 = $answer1->cmp()->evaluate( $inputs_ref->{ANS_NUM_TO_NAME(1)} );
$answer1_score = $ans_hash1->{score};
$answer1_student = $ans_hash1->{original_student_ans};

You can also use the listEnvironmentVariables() subroutine in PGinfo.pl to view the environment variables, such as what's stored in $inputs_ref. 

Best regards,

Paul Pearson

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

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"scaffold.pl",
"PGcourse.pl",
"PGgraphmacros.pl",
"PGinfo.pl",
);

TEXT(beginproblem());

Context("Numeric");

$answer1 = Compute("sin(x)");

Scaffold::Begin(
  can_open => "when_previous_correct",
  is_open  => "first_incorrect"
);
 
Section::Begin("Part 1: The first part");
BEGIN_PGML
Enter [` \sin(x) `] [________]{$answer1}
END_PGML
Section::End();

$answer1_student = $inputs_ref->{ANS_NUM_TO_NAME(1)}; # alternate, perhaps more direct method

$gr = init_graph(-4,-1,4,1,
axes=>[0,0],
grid=>[8,2],
size=>[400,400]
);

add_functions($gr, "$answer1_student for x in <-4,4> using color:blue and weight:2");

Section::Begin("Part 2: The second part");
BEGIN_PGML
The student's first answer was [$answer1_student].  Here's a graph of the student's answer:

[@ image( insertGraph($gr), width=>200,height=>200,tex_size=>800 ) @]*
END_PGML
Section::End();

Scaffold::End();

ENDDOCUMENT();

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

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"scaffold.pl",
"PGcourse.pl",
"PGgraphmacros.pl",
"PGinfo.pl",
);

TEXT(beginproblem());

Context("Numeric");

$answer1 = Compute("sin(x)");


BEGIN_TEXT
Enter \( \sin(x) \) \{ $answer1->ans_rule(10) \}
END_TEXT

ANS( $answer1->cmp );

$ans_hash1 = $answer1->cmp()->evaluate( $inputs_ref->{ANS_NUM_TO_NAME(1)} );
$answer1_score = $ans_hash1->{score};
$answer1_student = $ans_hash1->{original_student_ans};

# $answer1_student = $inputs_ref->{ANS_NUM_TO_NAME(1)}; # alternate, perhaps more direct method


$gr = init_graph(-4,-1,4,1,
axes=>[0,0],
grid=>[8,2],
size=>[400,400]
);

add_functions($gr, "$answer1_student for x in <-4,4> using color:blue and weight:2");


if ( $ans_hash1->{score} == 1 ) {
BEGIN_TEXT
The student's first answer was $answer1_student.  Here's a graph of the student's answer:

\{ image( insertGraph($gr), width=>200,height=>200,tex_size=>800 ) \}
END_TEXT
}

BEGIN_TEXT
$PAR
\{ 
listEnvironmentVariables() 
\}
END_TEXT
ENDDOCUMENT();
In reply to Paul Pearson

Re: using student answers to generate output

by Joel Trussell -
I changed x to t and changed all occurrences I see. I intentionally gave the wrong answer to verify that the code generated the graph that goes with the student input. (I have a commented piece where I generated the graph using cos(t) DIRECTLY. )  I'm not seeing a graph
code follows screen shot  ( I can't insert screenshot into this window - so only code is here - screenshot is attached)

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"scaffold.pl",
"PGcourse.pl",
"PGgraphmacros.pl",
"PGinfo.pl",
);

TEXT(beginproblem());

Context("Numeric");
Context()->variables->are(t=>'Real');
$answer1 = Compute("sin(t)");

Scaffold::Begin(
  can_open => "when_previous_correct",
  is_open  => "first_incorrect"
);
 
Section::Begin("Part 1: The first part");
BEGIN_PGML
Enter [` \sin(t) `] [________]{$answer1}
END_PGML
Section::End();

$answer1_student = $inputs_ref->{ANS_NUM_TO_NAME(1)}; # alternate, perhaps more direct method

$gr = init_graph(-4,-1,4,1,
axes=>[0,0],
grid=>[8,2],
size=>[400,400]
);

#$V_out = Formula("cos(t )");
#$G0 = FEQ(qq! $V_out for t in <-4,4> using color:blue and weight:2!);
#($f1n) = plot_functions( $gr, $G0 );
add_functions($gr, "$answer1_student for t in <-4,4> using color:blue and weight:2");

Section::Begin("Part 2: The second part");
BEGIN_PGML
The student's first answer was [$answer1_student].  Here's a graph of the student's answer:

[@ image( insertGraph($gr), width=>200,height=>200,tex_size=>800 ) @]*
END_PGML
Section::End();

Scaffold::End();

ENDDOCUMENT();
Attachment Capture_01.PNG
In reply to Joel Trussell

Re: using student answers to generate output

by Joel Trussell -
I tried the second code and kept the x. I changed the test so it would graph a wrong answer. I still see a sin(x)
DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"scaffold.pl",
"PGcourse.pl",
"PGgraphmacros.pl",
"PGinfo.pl",
);

TEXT(beginproblem());

Context("Numeric");

$answer1 = Compute("sin(x)");


BEGIN_TEXT
Enter \( \sin(x) \) \{ $answer1->ans_rule(10) \}
END_TEXT

ANS( $answer1->cmp );

$ans_hash1 = $answer1->cmp()->evaluate( $inputs_ref->{ANS_NUM_TO_NAME(1)} );
$answer1_score = $ans_hash1->{score};
$answer1_student = $ans_hash1->{original_student_ans};

# $answer1_student = $inputs_ref->{ANS_NUM_TO_NAME(1)}; # alternate, perhaps more direct method


$gr = init_graph(-4,-1,4,1,
axes=>[0,0],
grid=>[8,2],
size=>[400,400]
);

add_functions($gr, "$answer1_student for x in <-4,4> using color:blue and weight:2");


if ( $ans_hash1->{score} != 2 ) {
BEGIN_TEXT
The student's first answer was $answer1_student.  Here's a graph of the student's answer:

\{ image( insertGraph($gr), width=>200,height=>200,tex_size=>800 ) \}
END_TEXT
}

#BEGIN_TEXT
#$PAR
#\{ 
#listEnvironmentVariables() 
#\}
#END_TEXT
ENDDOCUMENT();
screen shot is capture_02

Attachment Capture_02.PNG
In reply to Joel Trussell

Re: using student answers to generate output

by Michael Gage -
Hi Joel,

The image has a caching problem.  First the server is caching the image
so that the image is created only once.  This is usually what you want.
It can be turned off by: 
$refreshCachedImages =1;

But that is not enough because the browser is also caching the image. And I'm not sure how to turn that off easily.  You can see the true image using shift-reload which makes the browser request the image again instead of using the cache -- but that is annoying and hard to explain to students.

The best solution seems to be to add a time stamp to the image name -- so that every image is different.  I checked StackOverflow and this is at least one answer.  The downside is that stale images will pile up on your server so you might want to delete them from the tmp directory on a regular basis. 

Others may have cleverer ways to fool the browser into refreshing the image.

Anyway here is some code which works for me:

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGML.pl",
"scaffold.pl",
"PGcourse.pl",
"PGgraphmacros.pl",
"PGinfo.pl",
);
#$refreshCachedImages=1;
# the above line is not needed if we are adding random numbers to the image name

TEXT(beginproblem());

Context("Numeric");
Context()->variables->are(t=>'Real');
$answer1 = Compute("sin(t)");

Scaffold::Begin(
  can_open => "when_previous_correct",
  is_open  => "first_incorrect"
);

Section::Begin("Part 1: The first part");
BEGIN_PGML
Enter [` \sin(t) `] [________]{$answer1}
END_PGML
Section::End();

$answer1_student = $inputs_ref->{ANS_NUM_TO_NAME(1)}; # alternate, perhaps more direct method

$gr = init_graph(-4,-1,4,1,
axes=>[0,0],
grid=>[8,2],
size=>[400,400]
);
$gr->imageName($gr->imageName."-".time);
#TEXT( "graph name ", $gr->imageName);
#$V_out = Formula("cos(t )");
#$G0 = FEQ(qq! $V_out for t in <-4,4> using color:blue and weight:2!);
#($f1n) = plot_functions( $gr, $G0 );
add_functions($gr, "$answer1_student for t in <-4,4> using color:blue and weight:2");

Section::Begin("Part 2: The second part");
BEGIN_PGML
The student's first answer was [$answer1_student].  
Here's a graph of the student's answer:

[@ image( insertGraph($gr), width=>200,height=>200,tex_size=>800 ) @]*
END_PGML

Section::End();

Scaffold::End();

ENDDOCUMENT();