Forums

Search results: 163

Hi,

Where images are stored in WeBWorK depends on how you set things up.  Place the cursor over the image and look at the path to the image.  If you see webwork2_files, that is the directory /opt/webwork/webwork2/htdocs.  If you see something else (e.g. wwtmp), your should know where you put that (maybe /var/www/wwtmp or /var/www/html/wwtmp).  

Arnie
I looked up forcing reload and tried a couple of those - last one for chrome was ctrl/shft/del and clearing images. I tried a ctrl/R and ctrl/F5 for firefox. I've zero'ed out one of my graphs but this still doesn't show. Where are the dynamic graphics stored in webwork? or do they exist only in the browser chache? 
I can't get the webwork to refresh the dynamic graph. I have set 
$refreshCachedImages = 1;

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"AnswerFormatHelp.pl",
"PGgraphmacros.pl",
"unionTables.pl",
"PGanswermacros.pl",
"PGchoicemacros.pl",
 "PGgraphmacros.pl",
  "extraAnswerEvaluators.pl",
 "parserCustomization.pl"
);

TEXT(beginproblem());

Context(Complex)->variables->are(t=>"Real",F=>"Real",a=>"Real",w=>"Real");


$showPartialCorrectAnswers = 1;
$a = random(1,9,1);
$b = random(2,1,9);   
$w_max = 10;              

$func = Formula("$a*j*w/($b + (j*w)**2)"); 

@eq = ("\( y=-2f(-t) \)",
       "\( y=2f(-t) \)",
       "\( y=-2f(t) \)",
       "\( y=-f \left( - \frac{1}{2} t \right) \)",
       "\( y=-\frac{1}{2} f(-t) \)",
       "\( y=f \left( \frac{1}{2} t \right) \)"     );

@descript = ("is a reflection about both the \(t\)-axis and \(y\)-axis as well as a vertical stretch by a factor of 2.",
"is a horizontal reflection about the \(y\)-axis as well as a vertical stretch by a factor of 2.",
"is a vertical reflection about the \(t\)-axis as well as a vertical stretch by a factor of 2.",
"is a reflection about both the \(t\)-axis and \(y\)-axis as well as a horizontal stretch by a factor of 2.");

$p1[0] = FEQ("sin(t)  for t in <-1,10> using color:blue and weight:2");
$p2[0] = FEQ("cos(t) for t in <-1,10> using color:blue and weight:2");
$p3[0] = FEQ("exp(t) for t in <-1,10> using color:blue and weight:2");
$p4[0] = FEQ("sin(t+1)  for t in <-1,10> using color:blue and weight:2");
$p1[1] = FEQ(qq! sin(t)- cos(t-2) for t in <-1,10> using color:blue and weight:2!);


##$graphf = init_graph(@opts);
##    (plot_functions($graphf,"$f for x in <-$dom,$dom> using color:blue"))[0]->steps(250);
## $labelf = new Label(@gr_lab, 'y = f(x)', 'blue' , 'center', 'center');
##    $graphf->lb($labelf);

$gr = init_graph(-1,$w_max,10,4,'axes'=>[0,0],'ticks'=>[10,6] );
$gr->lb('reset');
for ($i = -1; $i <= $wmax; $i++) { if ($i != 0) {
  $gr->lb(new Label(-.1,$i,$i,'black','right','middle')) }};
for ($i = -1; $i <= 5; $i++) {
  $gr->lb(new Label(2*$i,-.2,2*$i,'black','center','top')) };
$gr->lb(new Label(-.2,4.5,"y",'black','right','top'));
$gr->lb(new Label(9.5,-.2,"t",'black','right','top'));
$gr->lb(new Label(3.5,4,"s(t)",'black','left','bottom'));
## parentheses in ($fn1) are necessary
($f1n) = plot_functions( $gr, $p1[1] );
$f1n->steps(200);

$orig = image(insertGraph($gr),width => 400,height => 300,tex_size => 600);

$F = random(1,5,1);

$g[0] = "abs($a*j*w/($b + (j*w)**2)) for w in <0,$w_max> using color:blue and weight:2";
$g[1] = "abs(2*$a*j*w/($b + (j*w)**2)) for w in <0,$w_max> using color:blue and weight:2";
$g[2] = "abs($a*j*w/($b - (j*w)**2)) for w in <0,$w_max> using color:blue and weight:2";
$g[4] = "abs($a*j*w/($b + 10*(j*w)**2)) for w in <0,$w_max> using color:blue and weight:2";
$g[3] = "abs($a*j*w/($b + (j*w))) for w in <0,$w_max> using color:blue and weight:2";
$g[5] = "abs($a*j*w/(($b + (j*w))**2)) for w in <0,$w_max> using color:blue and weight:2";

for ($j = 0; $j <=5; $j++) {
$graph[$j] = init_graph(0,-1,$w_max,2,'axes'=>[0,0],'ticks'=>[8,8] );
};

for ($j = 0; $j <=5; $j++) {
$graph[$j]->lb('reset');
$graph[$j]->lb(new Label(-.07,-1,-1,'black','right','middle'));
$graph[$j]->lb(new Label(-.07,1,1,'black','right','middle'));
for ($i = -3; $i <= 3; $i++) { if ($i != 0) {
    $graph[$j]->lb(new Label(0.25*$i,-.2,0.25*$i,'black','center','top')) }};
$graph[$j]->lb(new Label(-.05,1.9,"|H|",'black','right','top'));
$graph[$j]->lb(new Label(0.95,0.1,"w",'black','right','bottom'));
plot_functions( $graph[$j], $g[$j]);
$fig[$j] = image(insertGraph($graph[$j]),width => 240,height => 180,tex_size => 200); 
};


# $pick = random(0,3,1);

# if ( $pick != 0 ) { $temp_eq = $eqn[0];
#                    $temp_gr = $fig[0];
#                    $eq[0] = $eq[$pick];
#                    $fig[0] = $fig[$pick];
#                    $eq[$pick] = $temp_eq;
#                    $fig[$pick] = $temp_gr};

$mc = new_multiple_choice();
$mc->qa('On a separate piece of paper, sketch an accurate graph of the magnitude of this function, \( |H(w)| \), for \( w \) and \( w \in [0, $w_max] \).  Which (if any) of the graphs below matches the graph you drew?','$fig[0]');
$mc->extra('$fig[1] $BR $BITALIC(click on image to enlarge)$EITALIC',
'$fig[2] $BR $BITALIC(click on image to enlarge)$EITALIC',
'$fig[3] $BR $BITALIC(click on image to enlarge)$EITALIC',
'$fig[4] $BR $BITALIC(click on image to enlarge)$EITALIC',
'$fig[5] $BR $BITALIC(click on image to enlarge)$EITALIC');

$mc->makeLast('None of the above');

## force a refresh of the image after changes

$refreshCachedImages = 1;

Context()->texStrings;
BEGIN_TEXT
Plotting graphs of complex functions
$PAR
Consider the complex valued function 
$BR
$BR
\( H(w) = $func \).
$BR

\{ $mc->print_q() \} $BR
\{ $mc->print_a() \}

END_TEXT
Context()->normalStrings;

ANS(radio_cmp($mc->correct_ans));
## force a refresh of the image after changes
$refreshCachedImages = 1;

Context()->texStrings;
SOLUTION(EV3(<<'END_SOLUTION'));
$PAR
$BBOLD  SOLUTION $EBOLD
$PAR
Setting \( F = $F \) gives the function \( y = \sin(2 \pi $F t) \). This has $F cycles in one unit of time. It starts at zero at t = 0, since it is a sine and is positive for the first values greater than zero. Therefore the correct graph is
$PAR
$BCENTER
$fig[0]
$ECENTER
$BR
which is answer \{ $mc->correct_ans \}.

END_SOLUTION
Context()->normalStrings;


ENDDOCUMENT();  

Installation -> upgraded Ubuntu

by Chrissy Safranski -
Sorry if this doesn't make a ton of sense - I'm posting for our administrator who doesn't have a forum account yet, and my vocabulary is lacking.  

We've been running an installation of WebWork 2.7 since January.  That was sucessfully upgraded to 2.9 at the end of June.  Then recently, there was some message that a part of Ubuntu, I forget which part, needed to be updated, so our administrator upgraded to the newest version of Ubuntu, 14 something.  

After that, Apache, Ubuntu and WebWork were not working together, and the WebWork webpage wouldn't load at all.  Our administrator read the wiki and got it fixed and working, but there seem to be a few lingering issues signalling that something isn't configured quite right, and we'd like any advice that you have.  

The most frequently occurring problem occurs when trying to edit a problem.  The buttons at the bottom, View, Update, New Version will appear different, in darker-filled boxes instead of light colored tabs, and clicking on them won't do anything.  Instead, the bottom of the browser shows: javascript:void(null);  Fortunately, because they look different than normal, we can see the problem before making edits that would be lost, and most of the time, reloading the page then makes it work as normal.  Sometimes we need to refresh the page more than once.  

Thank you for any ideas!
Hello everybody,

I am a newbie in WeBWork from Puerto Rico. I installed it (http://webwork.uprm.edu) in a CentOS server using ww_install python script (https://github.com/aubreyja/ww_install), it is running so well. 

Thank you very much to all who have contributed and contributes in this powerful tool.

I am coding some problems, I want restrict scientific notation like 3.25E3 in students solution. Of course, the problem is convert from scientific notation to standard.

I include the full code, it is in spanish, I hope this is not a problem. Maybe I'm not quite right encoding, suggestions are welcome.
#  DESCRIPTION
#
#  Tipo: respuesta corta
#  Pasar de notación científica a normal
#
#  Problema WebWork escrito por Edwin Florez,
#  edwin.florez at uprm dot edu
#  Adaptado desde el sistema quiz.uprm.edu del archivo
#  pedro_prebasica/notacion_cientifica/notacion_cientifica.db
#
#  ENDDESCRIPTION

## DBsubject(Prebasica)
## DBchapter(Sistemas numéricos)
## DBsection(Notación científica)
## Level(1)
## KEYWORDS('notacion', 'cientifica')
## Author(Edwin Florez)
## Institution(UPRM)
## Language(es)

DOCUMENT();

loadMacros(
"PGstandard.pl",
"MathObjects.pl",
"PGgraphmacros.pl",
"AnswerFormatHelp.pl",
"problemRandomize.pl"
);

TEXT(beginproblem());
#$refreshCachedImages = 1;

#  Allow for the user to try another version of the problem once they get it correct.
ProblemRandomize(when=>"Correct",XonlyAfterDue=>0);

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

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

Context("Numeric");

#Number's parts: a.b x 10^n
$a = random(1,9);
$b = random(1,99);
$n = non_zero_random(-6,6);
$abs_n = abs($n);

#Used in the solution
#string of zeros with length n for padding
$zeros = '0'x($abs_n);

if ( $n > 0 ){
  $simbolo = ">";
  $direccion = "derecha";
  $cadena_tmp = "$a.$b".$zeros;
}else{
 $simbolo = "<";
 $direccion = "izquierda";
 $cadena_tmp = $zeros."$a.$b";
}


#number in scientific notation like a string
$numero_nota_cient = "$a."."$b\times 10^{$n}";

#Building from a, b and n the answer
if ($b > 9){
 $rp = 100*$a + $b;
 $r = $rp*(10**($n-2));
}else{
 $rp = 10*$a + $b;
 $r = $rp*(10**($n-1));
}

$answer = Compute($r);

Context()->texStrings;
BEGIN_TEXT
Eliminar los productos y potencias del número
\[
 $numero_nota_cient
\]
$PAR
Contestación: \{ans_rule(10)\} \{ AnswerFormatHelp("number") \}
END_TEXT
Context()->normalStrings;


ANS( $answer->cmp() );

Context()->texStrings;
SOLUTION(EV3(<<'END_SOLUTION'));
$BBOLD Paso 1:$EBOLD Escribir el número
\[
$a.$b
\]
$PAR
$BBOLD Paso 2:$EBOLD Como \( n $simbolo 0 \) se añade $abs_n cero(s) a la $direccion
\[
$cadena_tmp
\]
y luego se mueve el punto decimal $abs_n unidad(es) a la $direccion y se obtiene:
\[
 $numero_nota_cient = $answer,
\]
por lo tanto, la solución es: \( $answer \).
END_SOLUTION
Context()->normalStrings;


ENDDOCUMENT();

I read from another post that this is useful,

Page generated at 07/15/2014 at 02:22pm AST

Thanks, 

 Edwin F.
In fact, here is a version that uses PopUp's in the way that I think you are suggesting:

DOCUMENT();

loadMacros(
  "AnswerFormatHelp.pl",
  "MathObjects.pl",
  "PeriodicRerandomization.pl",
  "PGgraphmacros.pl",
  "PGstandard.pl",
  "parserMultiAnswer.pl",
	"parserPopUp.pl",
);

TEXT(beginproblem());
PeriodicRerandomization("3");
$refreshCachedImages = 1;
$showPartialCorrectAnswers = 1;


#################################################################
# setup contexts and variables 
#################################################################
Context("Numeric");
Context()->strings->add("even"=>{}, "e"=>{alias=>"even"},
"odd"=>{}, "o"=>{alias=>"odd"},
"positive"=>{}, "pos"=>{alias=>"positive"}, "p"=>{alias=>"positive"},
"negative"=>{}, "neg"=>{alias=>"negative"}, "n"=>{alias=>"negative"});
Context()->{error}{msg}{"Operands of '*' can't be words"} = " ";
#Context()->{error}{msg}{"Can't convert an Empty Value to a Real Number"} = " ";
$numzeros = random(2,5);
do {
  # posszeros = possible zeros?
  @posszeros = (-10..10);
  # zeros = actual zeros?
  @zeros = (1..$numzeros);
  for ($i = 0; $i < $numzeros; $i++) {
    $zeros[$i] = list_random(@posszeros);
    if ($numzeros == 2 || $numzeros == 3) {
      $powers[$i] = random(2,3);
    } else {
      $powers[$i] = random(1,2);
    } 
    $removed = 0;
    $count = 0;
    do {
      if ($posszeros[$count] == $zeros[$i]) {
        $tmp = $posszeros[$count];
        $posszeros[$count] = $posszeros[scalar(@posszeros)-1];
        $posszeros[scalar(@posszeros)-1] = $tmp;
        pop(@posszeros);
        $removed = 1;
      }
      $count++;
    } until ($removed || $count == scalar(@posszeros));
    $removed = 0;
    $count = 0;
    do {
      if ($posszeros[$count] == $zeros[$i]-1) {
        $tmp = $posszeros[$count];
        $posszeros[$count] = $posszeros[scalar(@posszeros)-1];
        $posszeros[scalar(@posszeros)-1] = $tmp;
        pop(@posszeros);
        $removed = 1;
      }
      $count++;
    } until ($removed || $count == scalar(@posszeros));
    $removed = 0;
    $count = 0;
    do {
      if ($posszeros[$count] == $zeros[$i]+1) {
        $tmp = $posszeros[$count];
        $posszeros[$count] = $posszeros[scalar(@posszeros)-1];
        $posszeros[scalar(@posszeros)-1] = $tmp;
        pop(@posszeros);
        $removed = 1;
      }
      $count++;
    } until ($removed || $count == scalar(@posszeros));
  }

  $yint = 1;
  for ($i = 0; $i < $numzeros; $i++) {
    $yint = $yint*((-$zeros[$i])**$powers[$i]);
  }

  # this sub routine represents what is to be the graphed polynomial
  sub poly {
    my $x = shift();  
    $prod = 1;
    for ($i = 0; $i < $numzeros; $i++) {
      $prod = $prod*(($x - $zeros[$i])**$powers[$i]);
    }
    return $prod;
  };

  # sort zeros from low to high;
  $swapped = 1;
  $count = 0;
  while ($swapped) {
    $swapped = 0;
    $count++;
    for ($i = 0; $i < $numzeros - $count; $i++) {
      if ($zeros[$i] > $zeros[$i+1]) {
        $tmp = $zeros[$i];
        $zeros[$i] = $zeros[$i+1];
        $zeros[$i+1] = $tmp;
        $swapped = 1;
      }
    }
  }

  # this next bit is to be sure that the gap between the low or high point 
  # between zeros and the x-axis is not too small
  for ($i = 0; $i < $numzeros-1; $i++) {
    $maxs[$i] = 0;
  }

  for ($j = 0; $j < $numzeros-1; $j++) {
    $steps = 100;
    $stepsize = ($zeros[$j+1] - $zeros[$j])/$steps;
    for ($k = 0; $k < $steps; $k++) {
      $tmp = abs(poly($zeros[$j]+$k*$stepsize));
      if ($tmp > $maxs[$j]) {
        $maxs[$j] = $tmp; 
      } 
    }
  }

  $min = min(@maxs);
  $max = max(@maxs);
  $scale = random(5,9);
  $a = random(-1,1,2)*$scale/max($max);
  $tmp1 = abs($min*$a);
  $tmp2 = abs($max*$a);
} until (abs($tmp2/$tmp1) < 3*$scale/2);

$expn = sub {
  my $x = shift();  
  $prod = $a;
  for ($i = 0; $i < $numzeros; $i++) {
    $prod = $prod*(($x - $zeros[$i])**$powers[$i]);
  }
  return $prod;
};

$minx = min($zeros[0],0)-3;
$miny = -10;
$maxx = max($zeros[$numzeros-1],0)+3;
$maxy = 10;
$gsize = 400;

$graph = init_graph($minx, $miny, $maxx, $maxy, size=>[$gsize,$gsize]);
for ($i = $minx; $i <= $maxx; $i++) {
  $graph->moveTo($i,$miny);
  $graph->lineTo($i,$maxy,'gray',1);
}
for ($i = $miny; $i <= $maxy; $i++) {
  $graph->moveTo($minx,$i);
  $graph->lineTo($maxx,$i,'gray',1);
}
$graph->moveTo($minx, 0);
$graph->arrowTo($maxx, 0, 'black', 2);
$graph->arrowTo($minx, 0, 'black', 2);
$graph->moveTo(0, $miny);
$graph->arrowTo(0, $maxy, 'black', 2);
$graph->arrowTo(0, $miny, 'black', 2);
$graph->lb(new Label($maxx-0.1, 0.4, 'x', 'black', 'bottom', 'right'));
$graph->lb(new Label(0.4, $maxy-0.1, 'y', 'black', 'top', 'left'));

for ($i = $minx+1; $i < $maxx; $i++) {
  if ($i != 0 && $i % 5 == 0 || $i == 1) {
    $graph->lb(new Label($i,-0.1,$i, 'black', 'top','center'));
  }
}

for ($i = $miny+1; $i < $maxy; $i++) {
  if ($i != 0 && $i % 5 == 0 || $i == 1) {
    $graph->lb(new Label(-0.1,$i,$i, 'black', 'middle', 'right'));
  }
}

for ($i = 0; $i < $numzeros; $i++) {
  $graph->stamps(closed_circle($zeros[$i],0,'blue'));
}

$fun = new Fun($expn, $graph);
$fun->steps(1500);
$fun->domain($minx,$maxx);

$zerosans = List(@zeros);

for ($i = 0; $i < $numzeros; $i++) {
  if ($powers[$i] % 2 == 0) {
    $mltpy[$i] = "even";
  } else {
    $mltpy[$i] = "odd";
  }
}

for ($i = 0; $i < $numzeros; $i++) {
  $answers[2*$i] = $zeros[$i];
  $answers[2*$i+1] = PopUp([" ","even","odd"],$mltpy[$i]);
}

$ma = MultiAnswer(@answers)->with(
  singleResult => 0,
  allowBlankAnswers => 1,
  checker => sub {
    $num = scalar(@answers);
    my ($correct, $student, $self) = @_;
    my @ac = @{$correct};
    my @st = @{$student};
    my @ans = (0..scalar(@ac)/2);
    for ($i = 0; $i < $num; $i++) {
      $returnans[$i] = 0;
    }
    for ($i = 0; $i < $num/2; $i++) {
      $hasbeenused[$i] = 0;
    }
    for ($i = 0; $i < scalar(@ac)/2; $i++) {
      $ans[$i] = [$ac[2*$i],$ac[2*$i+1]];
    }
    for ($i = 0; $i < scalar(@ac)/2; $i++) {
      for ($j = 0; $j < scalar(@ac)/2; $j++) {
        if ($ans[$i][0] == $st[2*$j] && $ans[$i][1] == $st[2*$j+1] && $hasbeenused[$i] != 1) {
          $returnans[0][2*$j] = 1;
          $returnans[0][2*$j+1] = 1;
          $hasbeenused[$i] = 1;
        }
      }
    }
    for ($i = 0; $i < $num; $i++) {
      $reans[0][$i] = $returnans[0][$i]; 
    }
    return @reans;
  }
);

$degree = $powers[0];
for ($i = 1; $i < $numzeros; $i++) {
  $degree = $degree + $powers[$i];
}
if ($degree % 2 == 0) {
  $degreeans = "even";
} else {
  $degreeans = "odd";
}

if ($a < 0) {
  $leadcoeffans = "negative";
} else {
  $leadcoeffans = "positive";
}

$dispzeros = "$zeros[0]";
$dispmults = "$mltpy[0]";
for ($i = 1; $i < $numzeros; $i++) {
  $dispzeros = ($dispzeros).", ".($zeros[$i]);
  $dispmults = ($dispmults).", ".($mltpy[$i]);
}

$degree = PopUp([" ","even", "odd"], "$degreeans");
$lead_coef_sgn = PopUp([" ","positive", "negative"], "$leadcoeffans");

#################################################################
# state the problem 
#################################################################

Context()->texStrings;
BEGIN_TEXT

$PAR
$BCENTER
\{ image(insertGraph($graph), width=>$gsize, height=>$gsize, tex_size=>300 ); \}
$ECENTER 
$PAR

Find the following information pertaining to the polynomial, \(f(x)\), graphed above. 
$PAR
(a) The zeros of \(f(x)\) are \(x = \) \{ans_rule(15)\} (separate by commas) and 
END_TEXT

for ($i = 0; $i < $numzeros; $i++) {
  if ($i == $numzeros-2) {
    BEGIN_TEXT
    $PAR
    $SPACE $SPACE $SPACE $SPACE  the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity and,
    $PAR
    END_TEXT
  } elsif ($i == $numzeros-1) {
    BEGIN_TEXT
    $PAR
    $SPACE $SPACE $SPACE $SPACE  the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity.
    $PAR
    END_TEXT
  } else {
    BEGIN_TEXT
    $PAR
    $SPACE $SPACE $SPACE $SPACE  the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity,
    $PAR
    END_TEXT
  }
}

BEGIN_TEXT
$PAR
(b) The degree of \(f(x)\) is \{$degree->menu()\}.
$PAR
(c) The leading coefficient of \(f(x)\) is \{$lead_coef_sgn->menu()\}.
END_TEXT


#################################################################
# check the answer  
#################################################################
ANS(Compute($zerosans)->cmp());
ANS($ma->cmp());
ANS($degree->cmp());
ANS($lead_coef_sgn->cmp());


#################################################################
# use PeriodicRerandomization to write the answer and generate a new
# version of the problem
#################################################################
if ($attempts_modp == 0 && $actualAttempts != 0) {
  BEGIN_TEXT
  $PAR
  ${BBOLD}Answer:${EBOLD}
  $PAR
  (a) The zeros are \(x = $dispzeros\) with $dispmults multiplicity, respectively.
  $PAR
  (b) The degree is $degreeans.
  $PAR
  (c) The leading coefficient is $leadcoeffans.
  $PAR
  END_TEXT
} else {
  BEGIN_TEXT
  $PAR
  ${BBOLD}Help:${EBOLD} Type ${BBOLD}even${EBOLD} or
  ${BBOLD}odd${EBOLD} for multiplicities and the degree. 
  Type ${BBOLD}pos${EBOLD} for positive or ${BBOLD}neg${EBOLD}
  for negative for the leading coefficient. You must have the
  corresponding multiplicity correct for each zero in order to
  receive credit!
  $BR
  END_TEXT
}
Context()->normalStrings;
PeriodicStatus(); 


ENDDOCUMENT();
I was wondering if there was a way to combine PopUpLists with MultiAnswer choices? The problem we're working on goes like this: the student is presented with a graph of a polynomial and they have to find the value and multiplicity of each zero. They can enter the zero's in any order they please. We would like the multiplicity choice for each zero to be a PopUpList containing either "even" or "odd". I've attached a photo of part of the problem to this message. 

I thought about switching to the unorderedAnswers.pl helper functions but I didn't know how to group the pairs of solutions togethers.

I've also included the code we've been using below.

Thank you!
Patrick Spencer
University of Missouri

DOCUMENT();
loadMacros(
  "AnswerFormatHelp.pl",
  "MathObjects.pl",
  "PeriodicRerandomization.pl",
  "PGgraphmacros.pl",
  "PGstandard.pl",
  "parserMultiAnswer.pl",
"parserPopUp.pl",
);

TEXT(beginproblem());
PeriodicRerandomization("3");
$refreshCachedImages = 1;
$showPartialCorrectAnswers = 1;


#################################################################
# setup contexts and variables 
#################################################################
Context("Numeric");
Context()->strings->add("even"=>{}, "e"=>{alias=>"even"},
"odd"=>{}, "o"=>{alias=>"odd"},
"positive"=>{}, "pos"=>{alias=>"positive"}, "p"=>{alias=>"positive"},
"negative"=>{}, "neg"=>{alias=>"negative"}, "n"=>{alias=>"negative"});
Context()->{error}{msg}{"Operands of '*' can't be words"} = " ";
#Context()->{error}{msg}{"Can't convert an Empty Value to a Real Number"} = " ";
$numzeros = random(2,5);
do {
  # posszeros = possible zeros?
  @posszeros = (-10..10);
  # zeros = actual zeros?
  @zeros = (1..$numzeros);
  for ($i = 0; $i < $numzeros; $i++) {
    $zeros[$i] = list_random(@posszeros);
    if ($numzeros == 2 || $numzeros == 3) {
      $powers[$i] = random(2,3);
    } else {
      $powers[$i] = random(1,2);
    } 
    $removed = 0;
    $count = 0;
    do {
      if ($posszeros[$count] == $zeros[$i]) {
        $tmp = $posszeros[$count];
        $posszeros[$count] = $posszeros[scalar(@posszeros)-1];
        $posszeros[scalar(@posszeros)-1] = $tmp;
        pop(@posszeros);
        $removed = 1;
      }
      $count++;
    } until ($removed || $count == scalar(@posszeros));
    $removed = 0;
    $count = 0;
    do {
      if ($posszeros[$count] == $zeros[$i]-1) {
        $tmp = $posszeros[$count];
        $posszeros[$count] = $posszeros[scalar(@posszeros)-1];
        $posszeros[scalar(@posszeros)-1] = $tmp;
        pop(@posszeros);
        $removed = 1;
      }
      $count++;
    } until ($removed || $count == scalar(@posszeros));
    $removed = 0;
    $count = 0;
    do {
      if ($posszeros[$count] == $zeros[$i]+1) {
        $tmp = $posszeros[$count];
        $posszeros[$count] = $posszeros[scalar(@posszeros)-1];
        $posszeros[scalar(@posszeros)-1] = $tmp;
        pop(@posszeros);
        $removed = 1;
      }
      $count++;
    } until ($removed || $count == scalar(@posszeros));
  }

  $yint = 1;
  for ($i = 0; $i < $numzeros; $i++) {
    $yint = $yint*((-$zeros[$i])**$powers[$i]);
  }

  # this sub routine represents what is to be the graphed polynomial
  sub poly {
    my $x = shift();  
    $prod = 1;
    for ($i = 0; $i < $numzeros; $i++) {
      $prod = $prod*(($x - $zeros[$i])**$powers[$i]);
    }
    return $prod;
  };

  # sort zeros from low to high;
  $swapped = 1;
  $count = 0;
  while ($swapped) {
    $swapped = 0;
    $count++;
    for ($i = 0; $i < $numzeros - $count; $i++) {
      if ($zeros[$i] > $zeros[$i+1]) {
        $tmp = $zeros[$i];
        $zeros[$i] = $zeros[$i+1];
        $zeros[$i+1] = $tmp;
        $swapped = 1;
      }
    }
  }

  # this next bit is to be sure that the gap between the low or high point 
  # between zeros and the x-axis is not too small
  for ($i = 0; $i < $numzeros-1; $i++) {
    $maxs[$i] = 0;
  }

  for ($j = 0; $j < $numzeros-1; $j++) {
    $steps = 100;
    $stepsize = ($zeros[$j+1] - $zeros[$j])/$steps;
    for ($k = 0; $k < $steps; $k++) {
      $tmp = abs(poly($zeros[$j]+$k*$stepsize));
      if ($tmp > $maxs[$j]) {
        $maxs[$j] = $tmp; 
      } 
    }
  }

  $min = min(@maxs);
  $max = max(@maxs);
  $scale = random(5,9);
  $a = random(-1,1,2)*$scale/max($max);
  $tmp1 = abs($min*$a);
  $tmp2 = abs($max*$a);
} until (abs($tmp2/$tmp1) < 3*$scale/2);

$expn = sub {
  my $x = shift();  
  $prod = $a;
  for ($i = 0; $i < $numzeros; $i++) {
    $prod = $prod*(($x - $zeros[$i])**$powers[$i]);
  }
  return $prod;
};

$minx = min($zeros[0],0)-3;
$miny = -10;
$maxx = max($zeros[$numzeros-1],0)+3;
$maxy = 10;
$gsize = 400;

$graph = init_graph($minx, $miny, $maxx, $maxy, size=>[$gsize,$gsize]);
for ($i = $minx; $i <= $maxx; $i++) {
  $graph->moveTo($i,$miny);
  $graph->lineTo($i,$maxy,'gray',1);
}
for ($i = $miny; $i <= $maxy; $i++) {
  $graph->moveTo($minx,$i);
  $graph->lineTo($maxx,$i,'gray',1);
}
$graph->moveTo($minx, 0);
$graph->arrowTo($maxx, 0, 'black', 2);
$graph->arrowTo($minx, 0, 'black', 2);
$graph->moveTo(0, $miny);
$graph->arrowTo(0, $maxy, 'black', 2);
$graph->arrowTo(0, $miny, 'black', 2);
$graph->lb(new Label($maxx-0.1, 0.4, 'x', 'black', 'bottom', 'right'));
$graph->lb(new Label(0.4, $maxy-0.1, 'y', 'black', 'top', 'left'));

for ($i = $minx+1; $i < $maxx; $i++) {
  if ($i != 0 && $i % 5 == 0 || $i == 1) {
    $graph->lb(new Label($i,-0.1,$i, 'black', 'top','center'));
  }
}

for ($i = $miny+1; $i < $maxy; $i++) {
  if ($i != 0 && $i % 5 == 0 || $i == 1) {
    $graph->lb(new Label(-0.1,$i,$i, 'black', 'middle', 'right'));
  }
}

for ($i = 0; $i < $numzeros; $i++) {
  $graph->stamps(closed_circle($zeros[$i],0,'blue'));
}

$fun = new Fun($expn, $graph);
$fun->steps(1500);
$fun->domain($minx,$maxx);

$zerosans = List(@zeros);

for ($i = 0; $i < $numzeros; $i++) {
  if ($powers[$i] % 2 == 0) {
    $mltpy[$i] = "even";
  } else {
    $mltpy[$i] = "odd";
  }
}

for ($i = 0; $i < $numzeros; $i++) {
  $answers[2*$i] = $zeros[$i];
  $answers[2*$i+1] = $mltpy[$i]
}

$ma = MultiAnswer(@answers)->with(
  singleResult => 0,
  allowBlankAnswers => 1,
  checker => sub {
    $num = scalar(@answers);
    my ($correct, $student, $self) = @_;
    my @ac = @{$correct};
    my @st = @{$student};
    my @ans = (0..scalar(@ac)/2);
    for ($i = 0; $i < $num; $i++) {
      $returnans[$i] = 0;
    }
    for ($i = 0; $i < $num/2; $i++) {
      $hasbeenused[$i] = 0;
    }
    for ($i = 0; $i < scalar(@ac)/2; $i++) {
      $ans[$i] = [$ac[2*$i],$ac[2*$i+1]];
    }
    for ($i = 0; $i < scalar(@ac)/2; $i++) {
      for ($j = 0; $j < scalar(@ac)/2; $j++) {
        if ($ans[$i][0] == $st[2*$j] && $ans[$i][1] == $st[2*$j+1] && $hasbeenused[$i] != 1) {
          $returnans[0][2*$j] = 1;
          $returnans[0][2*$j+1] = 1;
          $hasbeenused[$i] = 1;
        }
      }
    }
    for ($i = 0; $i < $num; $i++) {
      $reans[0][$i] = $returnans[0][$i]; 
    }
    return @reans;
  }
);

$degree = $powers[0];
for ($i = 1; $i < $numzeros; $i++) {
  $degree = $degree + $powers[$i];
}
if ($degree % 2 == 0) {
  $degreeans = "even";
} else {
  $degreeans = "odd";
}

if ($a < 0) {
  $leadcoeffans = "negative";
} else {
  $leadcoeffans = "positive";
}

$dispzeros = "$zeros[0]";
$dispmults = "$mltpy[0]";
for ($i = 1; $i < $numzeros; $i++) {
  $dispzeros = ($dispzeros).", ".($zeros[$i]);
  $dispmults = ($dispmults).", ".($mltpy[$i]);
}

$degree = PopUp([" ","even", "odd"], "$degreeans");
$lead_coef_sgn = PopUp([" ","positive", "negative"], "$leadcoeffans");

#################################################################
# state the problem 
#################################################################

Context()->texStrings;
BEGIN_TEXT

$PAR
$BCENTER
\{ image(insertGraph($graph), width=>$gsize, height=>$gsize, tex_size=>300 ); \}
$ECENTER 
$PAR

Find the following information pertaining to the polynomial, \(f(x)\), graphed above. 
$PAR
(a) The zeros of \(f(x)\) are \(x = \) \{ans_rule(15)\} (separate by commas) and 
END_TEXT

for ($i = 0; $i < $numzeros; $i++) {
  if ($i == $numzeros-2) {
    BEGIN_TEXT
    $PAR
    $SPACE $SPACE $SPACE $SPACE  the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity and,
    $PAR
    END_TEXT
  } elsif ($i == $numzeros-1) {
    BEGIN_TEXT
    $PAR
    $SPACE $SPACE $SPACE $SPACE  the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity.
    $PAR
    END_TEXT
  } else {
    BEGIN_TEXT
    $PAR
    $SPACE $SPACE $SPACE $SPACE  the zero \(x = \) \{$ma->ans_rule(5)\} has \{$ma->ans_rule(5)\} multiplicity,
    $PAR
    END_TEXT
  }
}

BEGIN_TEXT
$PAR
(b) The degree of \(f(x)\) is \{$degree->menu()\}.
$PAR
(c) The leading coefficient of \(f(x)\) is \{$lead_coef_sgn->menu()\}.
END_TEXT


#################################################################
# check the answer  
#################################################################
ANS(Compute($zerosans)->cmp());
ANS($ma->cmp());
ANS($degree->cmp());
ANS($lead_coef_sgn->cmp());


#################################################################
# use PeriodicRerandomization to write the answer and generate a new
# version of the problem
#################################################################
if ($attempts_modp == 0 && $actualAttempts != 0) {
  BEGIN_TEXT
  $PAR
  ${BBOLD}Answer:${EBOLD}
  $PAR
  (a) The zeros are \(x = $dispzeros\) with $dispmults multiplicity, respectively.
  $PAR
  (b) The degree is $degreeans.
  $PAR
  (c) The leading coefficient is $leadcoeffans.
  $PAR
  END_TEXT
} else {
  BEGIN_TEXT
  $PAR
  ${BBOLD}Help:${EBOLD} Type ${BBOLD}even${EBOLD} or ${BBOLD}odd${EBOLD} for multiplicities and the degree. Type ${BBOLD}pos${EBOLD} for positive or ${BBOLD}neg${EBOLD} for negative for the leading coefficient. You must have the corresponding multiplicity correct for each zero in order to receive credit!
  $BR
  END_TEXT
}
Context()->normalStrings;
PeriodicStatus(); 


ENDDOCUMENT();

Attachment graph.png