File:  [LON-CAPA] / loncom / homework / radiobuttonresponse.pm
Revision 1.153.6.1: download - view: text, annotated - select for diffs
Fri Jan 20 11:41:31 2012 UTC (12 years, 3 months ago) by foxr
Branches: BZ4492-feature_horizontal_radioresponse
Diff to branchpoint 1.153: preferred, unified
BZ 4492 Start refactorying the rendition code so that it's tractable
for modification

    1: # The LearningOnline Network with CAPA
    2: # mutliple choice style responses
    3: #
    4: # $Id: radiobuttonresponse.pm,v 1.153.6.1 2012/01/20 11:41:31 foxr Exp $
    5: #
    6: # Copyright Michigan State University Board of Trustees
    7: #
    8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    9: #
   10: # LON-CAPA is free software; you can redistribute it and/or modify
   11: # it under the terms of the GNU General Public License as published by
   12: # the Free Software Foundation; either version 2 of the License, or
   13: # (at your option) any later version.
   14: #
   15: # LON-CAPA is distributed in the hope that it will be useful,
   16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18: # GNU General Public License for more details.
   19: #
   20: # You should have received a copy of the GNU General Public License
   21: # along with LON-CAPA; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22: #
   23: # /home/httpd/html/adm/gpl.txt
   24: #
   25: # http://www.lon-capa.org/
   26: #
   27: 
   28: package Apache::radiobuttonresponse;
   29: use strict;
   30: use HTML::Entities();
   31: use Apache::lonlocal;
   32: use Apache::lonnet;
   33: use Apache::response;
   34: 
   35: my $default_bubbles_per_line = 10;
   36: 
   37: BEGIN {
   38:     &Apache::lonxml::register( 'Apache::radiobuttonresponse',
   39:         ('radiobuttonresponse') );
   40: }
   41: 
   42: sub bubble_line_count {
   43:     my ( $numfoils, $bubbles_per_line ) = @_;
   44:     my $bubble_lines;
   45:     $bubble_lines = int( $numfoils / $bubbles_per_line );
   46:     if ( ( $numfoils % $bubbles_per_line ) != 0 ) {
   47:         $bubble_lines++;
   48:     }
   49:     return $bubble_lines;
   50: 
   51: }
   52: 
   53: sub start_radiobuttonresponse {
   54:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
   55:       @_;
   56:     my $result;
   57: 
   58:     #when in a radiobutton response use these
   59:     &Apache::lonxml::register( 'Apache::radiobuttonresponse',
   60:         ( 'foilgroup', 'foil', 'conceptgroup' ) );
   61:     push( @Apache::lonxml::namespace, 'radiobuttonresponse' );
   62:     my $id = &Apache::response::start_response( $parstack, $safeeval );
   63: 
   64:     %Apache::hint::radiobutton = ();
   65:     undef(%Apache::response::foilnames);
   66:     if ( $target eq 'meta' ) {
   67:         $result = &Apache::response::meta_package_write('radiobuttonresponse');
   68:     }
   69:     elsif ( $target eq 'edit' ) {
   70:         $result .=
   71:             &Apache::edit::start_table($token)
   72:           . '<tr><td>'
   73:           . &Apache::lonxml::description($token)
   74:           . &Apache::loncommon::help_open_topic('Radio_Response_Problems')
   75:           . '</td>'
   76:           . '<td><span class="LC_nobreak">'
   77:           . &mt('Delete?') . ' '
   78:           . &Apache::edit::deletelist( $target, $token )
   79:           . '</span></td>'
   80:           . '<td>&nbsp;'
   81:           . &Apache::edit::end_row()
   82:           . &Apache::edit::start_spanning_row();
   83:         $result .= &Apache::edit::text_arg( 'Max Number Of Shown Foils:',
   84:             'max', $token, '4' )
   85:           . '&nbsp;' x 3
   86:           . &Apache::edit::select_arg( 'Randomize Foil Order:',
   87:             'randomize', [ 'yes', 'no' ], $token )
   88:           . '&nbsp;' x 3
   89:           . &Apache::edit::select_arg(
   90:             'Display Direction:', 'direction',
   91:             [ 'vertical', 'horizontal' ], $token
   92:           )
   93:           . &Apache::edit::end_row()
   94:           . &Apache::edit::start_spanning_row() . "\n";
   95:     }
   96:     elsif ( $target eq 'modified' ) {
   97:         my $constructtag =
   98:           &Apache::edit::get_new_args( $token, $parstack, $safeeval, 'max',
   99:             'randomize', 'direction' );
  100:         if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
  101:     }
  102:     elsif ( $target eq 'tex' ) {
  103:         my $type =
  104:           &Apache::lonxml::get_param( 'TeXtype', $parstack, $safeeval, undef,
  105:             0 );
  106:         if ( $type eq '1' ) {
  107:             $result .= ' \renewcommand{\labelenumi}{\arabic{enumi}.}';
  108:         }
  109:         elsif ( $type eq 'A' ) {
  110:             $result .= ' \renewcommand{\labelenumi}{\Alph{enumi}.}';
  111:         }
  112:         elsif ( $type eq 'a' ) {
  113:             $result .= ' \renewcommand{\labelenumi}{\alph{enumi}.}';
  114:         }
  115:         elsif ( $type eq 'i' ) {
  116:             $result .= ' \renewcommand{\labelenumi}{\roman{enumi}.}';
  117:         }
  118:         else {
  119:             $result .= ' \renewcommand{\labelenumi}{\Alph{enumi}.}';
  120:         }
  121:         if (   $env{'form.pdfFormFields'} eq 'yes'
  122:             && $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
  123:         {
  124:             $result .= '\begin{itemize}';
  125:         }
  126:         else {
  127:             $result .= '\begin{enumerate}';
  128:         }
  129:     }
  130:     elsif ( $target eq 'analyze' ) {
  131:         my $part_id = "$Apache::inputtags::part.$id";
  132:         $Apache::lonhomework::analyze{"$part_id.type"} = 'radiobuttonresponse';
  133:         push( @{ $Apache::lonhomework::analyze{"parts"} }, $part_id );
  134:     }
  135:     return $result;
  136: }
  137: 
  138: sub end_radiobuttonresponse {
  139:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
  140:       @_;
  141:     my $result;
  142:     if ( $target eq 'edit' ) { $result = &Apache::edit::end_table(); }
  143:     if ( $target eq 'tex' ) {
  144:         if (    $env{'form.pdfFormFields'} eq 'yes'
  145:             and $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
  146:         {
  147:             $result .= '\end{itemize}';
  148:         }
  149:         else {
  150:             $result .= '\end{enumerate}';
  151:         }
  152:     }
  153:     &Apache::response::end_response;
  154:     pop @Apache::lonxml::namespace;
  155:     &Apache::lonxml::deregister( 'Apache::radiobuttonresponse',
  156:         ( 'foilgroup', 'foil', 'conceptgroup' ) );
  157:     undef(%Apache::response::foilnames);
  158:     return $result;
  159: }
  160: 
  161: %Apache::response::foilgroup = ();
  162: 
  163: sub start_foilgroup {
  164:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
  165:       @_;
  166:     %Apache::response::foilgroup               = ();
  167:     $Apache::radiobuttonresponse::conceptgroup = 0;
  168:     &Apache::response::pushrandomnumber( undef, $target );
  169:     return;
  170: }
  171: 
  172: sub storesurvey {
  173:     my ($style) = @_;
  174:     if ( !&Apache::response::submitted() ) { return ''; }
  175:     my $response = $env{ 'form.HWVAL_' . $Apache::inputtags::response['-1'] };
  176:     &Apache::lonxml::debug("Here I am!:$response:");
  177:     if ( $response !~ /[0-9]+/ ) { return ''; }
  178:     my $part       = $Apache::inputtags::part;
  179:     my $id         = $Apache::inputtags::response['-1'];
  180:     my @whichfoils = @{ $Apache::response::foilgroup{'names'} };
  181:     my %responsehash;
  182:     $responsehash{ $whichfoils[$response] } = $response;
  183:     my $responsestr = &Apache::lonnet::hash2str(%responsehash);
  184:     $Apache::lonhomework::results{"resource.$part.$id.submission"} =
  185:       $responsestr;
  186:     my %previous =
  187:       &Apache::response::check_for_previous( $responsestr, $part, $id );
  188:     my $ad;
  189: 
  190:     if ( $style eq 'anonsurvey' ) {
  191:         $ad = $Apache::lonhomework::results{"resource.$part.$id.awarddetail"} =
  192:           'ANONYMOUS';
  193:     }
  194:     elsif ( $style eq 'anonsurveycred' ) {
  195:         $ad = $Apache::lonhomework::results{"resource.$part.$id.awarddetail"} =
  196:           'ANONYMOUS_CREDIT';
  197:     }
  198:     elsif ( $style eq 'surveycred' ) {
  199:         $ad = $Apache::lonhomework::results{"resource.$part.$id.awarddetail"} =
  200:           'SUBMITTED_CREDIT';
  201:     }
  202:     else {
  203:         $ad = $Apache::lonhomework::results{"resource.$part.$id.awarddetail"} =
  204:           'SUBMITTED';
  205:     }
  206:     &Apache::response::handle_previous( \%previous, $ad );
  207:     &Apache::lonxml::debug("submitted a $response<br />\n");
  208:     return '';
  209: }
  210: 
  211: sub grade_response {
  212:     my ( $answer, $whichfoils, $bubbles_per_line ) = @_;
  213: 
  214:     if ( !&Apache::response::submitted() ) { return; }
  215:     my $response;
  216: 
  217:     if ( $env{'form.submitted'} eq 'scantron' ) {
  218:         $response =
  219:           &Apache::response::getresponse( 1, undef,
  220:             &bubble_line_count( scalar( @{$whichfoils} ), $bubbles_per_line ),
  221:             $bubbles_per_line );
  222: 
  223:     }
  224:     else {
  225:         $response = $env{ 'form.HWVAL_' . $Apache::inputtags::response['-1'] };
  226:     }
  227: 
  228:     if ( $response !~ /[0-9]+/ ) { return; }
  229:     my $part = $Apache::inputtags::part;
  230:     my $id   = $Apache::inputtags::response['-1'];
  231:     my %responsehash;
  232:     $responsehash{ $whichfoils->[$response] } = $response;
  233:     my $responsestr = &Apache::lonnet::hash2str(%responsehash);
  234:     my %previous =
  235:       &Apache::response::check_for_previous( $responsestr, $part, $id );
  236:     $Apache::lonhomework::results{"resource.$part.$id.submission"} =
  237:       $responsestr;
  238:     &Apache::lonxml::debug("submitted a $response<br />\n");
  239:     my $ad;
  240: 
  241:     if ( $response == $answer ) {
  242:         $ad = 'EXACT_ANS';
  243:     }
  244:     else {
  245:         $ad = 'INCORRECT';
  246:     }
  247:     $Apache::lonhomework::results{"resource.$part.$id.awarddetail"} = $ad;
  248:     &Apache::response::handle_previous( \%previous, $ad );
  249: }
  250: 
  251: sub end_foilgroup {
  252:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
  253:       @_;
  254: 
  255:     my $result;
  256:     my $bubble_lines;
  257:     my $answer_count;
  258:     my $id               = $Apache::inputtags::response['-1'];
  259:     my $part             = $Apache::inputtags::part;
  260:     my $bubbles_per_line = &getbubblesnum( $part, $id );
  261: 
  262:     if (   $target eq 'grade'
  263:         || $target eq 'web'
  264:         || $target eq 'answer'
  265:         || $target eq 'tex'
  266:         || $target eq 'analyze' )
  267:     {
  268:         my $style = $Apache::lonhomework::type;
  269:         my $direction =
  270:           &Apache::lonxml::get_param( 'direction', $parstack, $safeeval, '-2' );
  271:         if (
  272:             (
  273:                    ( $style eq 'survey' )
  274:                 || ( $style eq 'surveycred' )
  275:                 || ( $style eq 'anonsurvey' )
  276:                 || ( $style eq 'anonsurveycred' )
  277:             )
  278:             && ( $target ne 'analyze' )
  279:           )
  280:         {
  281:             if ( $target eq 'web' || $target eq 'tex' ) {
  282:                 $result = &displayallfoils( $direction, $target );
  283:             }
  284:             elsif ( $target eq 'answer' ) {
  285:                 $result = &displayallanswers();
  286:             }
  287:             elsif ( $target eq 'grade' ) {
  288:                 $result = &storesurvey($style);
  289:             }
  290:             $answer_count =
  291:               scalar( @{ $Apache::response::foilgroup{'names'} } );
  292: 
  293:         }
  294:         else {
  295: 
  296:             my $name;
  297:             my $max =
  298:               &Apache::lonxml::get_param( 'max', $parstack, $safeeval, '-2' );
  299:             my $randomize =
  300:               &Apache::lonxml::get_param( 'randomize', $parstack, $safeeval,
  301:                 '-2' );
  302:             my ( $answer, @shown ) = &whichfoils( $max, $randomize );
  303:             $answer_count = scalar(@shown);
  304: 
  305:             if ( $target eq 'web' || $target eq 'tex' ) {
  306:                 $result =
  307:                   &displayfoils( $target, $answer, \@shown, $direction,
  308:                     $bubbles_per_line );
  309:             }
  310:             elsif ( $target eq 'answer' ) {
  311:                 $result =
  312:                   &displayanswers( $answer, \@shown, $bubbles_per_line );
  313:             }
  314:             elsif ( $target eq 'grade' ) {
  315:                 &grade_response( $answer, \@shown, $bubbles_per_line );
  316:             }
  317:             elsif ( $target eq 'analyze' ) {
  318:                 my $bubble_lines =
  319:                   &bubble_line_count( $answer_count, $bubbles_per_line );
  320:                 &Apache::response::analyze_store_foilgroup( \@shown,
  321:                     [ 'text', 'value', 'location' ] );
  322:                 my $part_id = "$part.$id";
  323:                 push(
  324:                     @{ $Apache::lonhomework::analyze{"$part_id.options"} },
  325:                     ( 'true', 'false' )
  326:                 );
  327: 
  328:             }
  329:         }
  330:         $Apache::lonxml::post_evaluate = 0;
  331:     }
  332:     if ( $target eq 'web' ) {
  333:         &Apache::response::setup_prior_tries_hash( \&format_prior_answer,
  334:             [ \%Apache::response::foilgroup ] );
  335:     }
  336:     &Apache::response::poprandomnumber();
  337:     $bubble_lines = &bubble_line_count( $answer_count, $bubbles_per_line );
  338:     &Apache::lonxml::increment_counter( $bubble_lines, "$part.$id" );
  339:     if ( $target eq 'analyze' ) {
  340:         &Apache::lonhomework::set_bubble_lines();
  341:     }
  342:     return $result;
  343: }
  344: 
  345: sub getbubblesnum {
  346:     my ( $part, $id ) = @_;
  347:     my $bubbles_per_line;
  348:     my $default_numbubbles = $default_bubbles_per_line;
  349:     if (   ( $env{'form.bubbles_per_row'} =~ /^\d+$/ )
  350:         && ( $env{'form.bubbles_per_row'} > 0 ) )
  351:     {
  352:         $default_numbubbles = $env{'form.bubbles_per_row'};
  353:     }
  354:     $bubbles_per_line = &Apache::response::get_response_param( $part . "_$id",
  355:         'numbubbles', $default_numbubbles );
  356:     return $bubbles_per_line;
  357: }
  358: 
  359: sub getfoilcounts {
  360:     my @names;
  361:     my $truecnt  = 0;
  362:     my $falsecnt = 0;
  363:     my $name;
  364:     if ( $Apache::response::foilgroup{'names'} ) {
  365:         @names = @{ $Apache::response::foilgroup{'names'} };
  366:     }
  367:     foreach $name (@names) {
  368:         if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
  369:             $truecnt++;
  370:         }
  371:         elsif ( $Apache::response::foilgroup{ $name . '.value' } eq 'false' ) {
  372:             $falsecnt++;
  373:         }
  374:     }
  375:     return ( $truecnt, $falsecnt );
  376: }
  377: 
  378: sub format_prior_answer {
  379:     my ( $mode, $answer, $other_data ) = @_;
  380:     my $foil_data = $other_data->[0];
  381:     my %response  = &Apache::lonnet::str2hash($answer);
  382:     my ($name)    = keys(%response);
  383:     return
  384:         '<span class="LC_prior_radiobutton">'
  385:       . $foil_data->{ $name . '.text' }
  386:       . '</span>';
  387: 
  388: }
  389: 
  390: ##
  391: sub displayallfoils {
  392:     my ( $direction, $target ) = @_;
  393:     my $result;
  394:     &Apache::lonxml::debug("survey style display");
  395:     my @names;
  396:     if ( $Apache::response::foilgroup{'names'} ) {
  397:         @names = @{ $Apache::response::foilgroup{'names'} };
  398:     }
  399: 
  400:     my $temp = 0;
  401:     my $i    = 0;
  402:     my $id   = $Apache::inputtags::response['-1'];
  403:     my $part = $Apache::inputtags::part;
  404:     my ( $lastresponse, $newvariation, $showanswer );
  405:     if (
  406:         (
  407:             (
  408:                 $Apache::lonhomework::history{"resource.$part.type"} eq
  409:                 'randomizetry'
  410:             )
  411:             || ( $Apache::lonhomework::type eq 'randomizetry' )
  412:         )
  413:         && ( $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
  414:       )
  415:     {
  416:         if ( $env{ 'form.' . $part . '.rndseed' } ne
  417:             $Apache::lonhomework::history{"resource.$part.rndseed"} )
  418:         {
  419:             $newvariation = 1;
  420:         }
  421:     }
  422:     $showanswer = &Apache::response::show_answer();
  423:     unless (
  424:         (
  425:             (
  426:                 $Apache::lonhomework::history{"resource.$part.type"} eq
  427:                 'anonsurvey'
  428:             )
  429:             || ( $Apache::lonhomework::history{"resource.$part.type"} eq
  430:                 'anonsurveycred' )
  431:         )
  432:         && ( defined( $env{'form.grade_symb'} ) )
  433:         || ( $newvariation && !$showanswer )
  434:       )
  435:     {
  436:         $lastresponse =
  437:           $Apache::lonhomework::history{"resource.$part.$id.submission"};
  438:     }
  439:     if ( $direction eq 'horizontal' ) { $result .= '<table><tr>'; }
  440:     my %lastresponse = &Apache::lonnet::str2hash($lastresponse);
  441:     if ($showanswer) {
  442:         foreach my $name (@names) {
  443:             if ( $Apache::response::foilgroup{ $name . '.value' } ne 'unused' )
  444:             {
  445:                 if ( ( $direction eq 'horizontal' ) && ( $target ne 'tex' ) ) {
  446:                     $result .= "<td>";
  447:                 }
  448:                 else {
  449:                     if ( $target eq 'tex' ) {
  450:                         $result .= '\item \vskip -2mm ';
  451:                     }
  452:                     else {
  453:                         $result .= "<br />";
  454:                     }
  455:                 }
  456:                 if ( defined( $lastresponse{$name} ) ) {
  457:                     if ( $target eq 'tex' ) {
  458:                         $result .= '}';
  459:                     }
  460:                     else {
  461:                         $result .= '<b>';
  462:                     }
  463:                 }
  464:                 $result .= $Apache::response::foilgroup{ $name . '.text' };
  465:                 if ( defined( $lastresponse{$name} ) && ( $target ne 'tex' ) ) {
  466:                     $result .= '</b>';
  467:                 }
  468:                 if ( ( $direction eq 'horizontal' ) && ( $target ne 'tex' ) ) {
  469:                     $result .= "</td>";
  470:                 }
  471:             }
  472:         }
  473:     }
  474:     else {
  475:         foreach my $name (@names) {
  476:             if ( $Apache::response::foilgroup{ $name . '.value' } ne 'unused' )
  477:             {
  478:                 if ( $direction eq 'horizontal' ) {
  479:                     $result .= "<td>";
  480:                 }
  481:                 else {
  482:                     if ( $target eq 'tex' ) {
  483:                         if (   $env{'form.pdfFormFields'} eq 'yes'
  484:                             && $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
  485:                         {
  486:                             my $fieldname =
  487:                                 $env{'request.symb'} 
  488:                               . '&part_'
  489:                               . $Apache::inputtags::part
  490:                               . '&radiobuttonresponse'
  491:                               . '&HWVAL_'
  492:                               . $Apache::inputtags::response['-1'];
  493:                             $result .= '\item[{'
  494:                               . &Apache::lonxml::print_pdf_radiobutton(
  495:                                 $fieldname, $temp )
  496:                               . '}]'
  497:                               . $Apache::response::foilgroup{ $name . '.text' }
  498:                               . "\n";
  499:                         }
  500:                         else {
  501:                             $result .= '\item \vskip -2mm ';
  502:                         }
  503:                     }
  504:                     else {
  505:                         $result .= "<br />";
  506:                     }
  507:                 }
  508:                 if ( $target eq 'tex' ) {
  509:                     if (   $env{'form.pdfFormFields'} ne 'yes'
  510:                         or $Apache::inputtags::status[-1] ne 'CAN_ANSWER' )
  511:                     {
  512:                         $result .=
  513:                             '$\bigcirc$'
  514:                           . $Apache::response::foilgroup{ $name . '.text' }
  515:                           . '\\\\';    #' stupid emacs
  516:                     }
  517:                     $i++;
  518:                 }
  519:                 else {
  520:                     $result .= '<label>';
  521:                     $result .= "<input
  522:                        onchange=\"javascript:setSubmittedPart('$part');\"
  523:                        type=\"radio\"
  524:                        name=\"HWVAL_$Apache::inputtags::response['-1']\"
  525:                        value=\"$temp\"";
  526: 
  527:                     if ( defined( $lastresponse{$name} ) ) {
  528:                         $result .= ' checked="checked"';
  529:                     }
  530:                     $result .= ' />'
  531:                       . $Apache::response::foilgroup{ $name . '.text' }
  532:                       . '</label>';
  533:                 }
  534:                 $temp++;
  535:                 if ( $target ne 'tex' ) {
  536:                     if (   ( $direction eq 'horizontal' )
  537:                         && ( $target ne 'tex' ) )
  538:                     {
  539:                         $result .= "</td>";
  540:                     }
  541:                 }
  542:                 else {
  543:                     $result .= '\vskip 0 mm ';
  544:                 }
  545:             }
  546:         }
  547:     }
  548: 
  549:     if ( ( $direction eq 'horizontal' ) && ( $target ne 'tex' ) ) {
  550:         $result .= '</tr></table>';
  551:     }
  552:     return $result;
  553: }
  554: 
  555: sub whichfoils {
  556:     my ( $max, $randomize ) = @_;
  557: 
  558:     my @truelist;
  559:     my @falselist;
  560:     my @whichfalse = ();
  561:     my ( $truecnt, $falsecnt ) = &getfoilcounts();
  562:     my $count = 0;
  563: 
  564:     # we will add in 1 of the true statements
  565:     if ( $max > 0 && ( $falsecnt + 1 ) > $max ) { $count = $max }
  566:     else { $count = $falsecnt + 1; $max = $count; }
  567:     my $answer = int( &Math::Random::random_uniform() * ($count) );
  568:     &Apache::lonxml::debug("Count is $count, $answer is $answer");
  569:     my @names;
  570:     if ( $Apache::response::foilgroup{'names'} ) {
  571:         @names = @{ $Apache::response::foilgroup{'names'} };
  572:     }
  573:     if ( &Apache::response::showallfoils() ) {
  574:         @whichfalse = @names;
  575:     }
  576:     elsif ( $randomize eq 'no' ) {
  577:         &Apache::lonxml::debug("No randomization");
  578:         my $havetrue = 0;
  579:         foreach my $name (@names) {
  580:             if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
  581:                 if ( !$havetrue ) {
  582:                     push( @whichfalse, $name );
  583:                     $havetrue++;
  584:                     $answer = $#whichfalse;
  585:                 }
  586:             }
  587:             elsif (
  588:                 $Apache::response::foilgroup{ $name . '.value' } eq 'false' )
  589:             {
  590:                 push( @whichfalse, $name );
  591:             }
  592:             elsif (
  593:                 $Apache::response::foilgroup{ $name . '.value' } eq 'unused' )
  594:             {
  595:             }
  596:             else {
  597:                 &Apache::lonxml::error(
  598:                     &HTML::Entities::encode(
  599: "No valid value assigned ($Apache::response::foilgroup{$name.'.value'}) for foil $name in <foilgroup>",
  600:                         '<>&"'
  601:                     )
  602:                 );
  603:             }
  604:         }
  605:         if (   ( !$havetrue )
  606:             && ( $Apache::lonhomework::type ne 'survey' )
  607:             && ( $Apache::lonhomework::type ne 'surveycred' )
  608:             && ( $Apache::lonhomework::type ne 'anonsurvey' )
  609:             && ( $Apache::lonhomework::type ne 'anonsurveycred' ) )
  610:         {
  611:             &Apache::lonxml::error(
  612:                 &mt('There are no true statements available.') . '<br />' );
  613:         }
  614:     }
  615:     else {
  616:         my $current = 0;
  617:         &Apache::lonhomework::showhash(%Apache::response::foilgroup);
  618:         my ( %top, %bottom );
  619: 
  620:         #first find out where everyone wants to be
  621:         foreach my $name (@names) {
  622:             $current++;
  623:             if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
  624:                 push( @truelist, $name );
  625:                 if ( $Apache::response::foilgroup{ $name . '.location' } eq
  626:                     'top' )
  627:                 {
  628:                     $top{$name} = $current;
  629:                 }
  630:                 elsif ( $Apache::response::foilgroup{ $name . '.location' } eq
  631:                     'bottom' )
  632:                 {
  633:                     $bottom{$name} = $current;
  634:                 }
  635:             }
  636:             elsif (
  637:                 $Apache::response::foilgroup{ $name . '.value' } eq 'false' )
  638:             {
  639:                 push( @falselist, $name );
  640:                 if ( $Apache::response::foilgroup{ $name . '.location' } eq
  641:                     'top' )
  642:                 {
  643:                     $top{$name} = $current;
  644:                 }
  645:                 elsif ( $Apache::response::foilgroup{ $name . '.location' } eq
  646:                     'bottom' )
  647:                 {
  648:                     $bottom{$name} = $current;
  649:                 }
  650:             }
  651:             elsif (
  652:                 $Apache::response::foilgroup{ $name . '.value' } eq 'unused' )
  653:             {
  654:             }
  655:             else {
  656:                 &Apache::lonxml::error(
  657:                     &HTML::Entities::encode(
  658: "No valid value assigned ($Apache::response::foilgroup{$name.'.value'}) for foil $name in <foilgroup>",
  659:                         '<>&"'
  660:                     )
  661:                 );
  662:             }
  663:         }
  664: 
  665:         #pick a true statement
  666:         my $notrue = 0;
  667:         if ( scalar(@truelist) == 0 ) { $notrue = 1; }
  668:         my $whichtrue =
  669:           int( &Math::Random::random_uniform() * ( $#truelist + 1 ) );
  670:         &Apache::lonxml::debug(
  671:             "Max is $max, From $#truelist elms, picking $whichtrue");
  672:         my ( @toplist, @bottomlist );
  673:         my $topcount    = 0;
  674:         my $bottomcount = 0;
  675: 
  676:         # assign everyone to either toplist/bottomlist or whichfalse
  677:         # which false is randomized, toplist bottomlist are in order
  678:         while (( ( $#whichfalse + $topcount + $bottomcount ) < $max - 2 )
  679:             && ( $#falselist > -1 ) )
  680:         {
  681:             &Apache::lonxml::debug("Have $#whichfalse max is $max");
  682:             my $afalse =
  683:               int( &Math::Random::random_uniform() * ( $#falselist + 1 ) );
  684:             &Apache::lonxml::debug("From $#falselist elms, picking $afalse");
  685:             $afalse = splice( @falselist, $afalse, 1 );
  686:             &Apache::lonxml::debug("Picked $afalse");
  687:             &Apache::lonhomework::showhash( ( 'names' => \@names ) );
  688:             &Apache::lonhomework::showhash(%top);
  689:             if ( $top{$afalse} ) {
  690:                 $toplist[ $top{$afalse} ] = $afalse;
  691:                 $topcount++;
  692:             }
  693:             elsif ( $bottom{$afalse} ) {
  694:                 $bottomlist[ $bottom{$afalse} ] = $afalse;
  695:                 $bottomcount++;
  696:             }
  697:             else {
  698:                 push( @whichfalse, $afalse );
  699:             }
  700:         }
  701:         &Apache::lonxml::debug("Answer wants $answer");
  702:         my $truename = $truelist[$whichtrue];
  703:         my $dosplice = 1;
  704:         if (   ($notrue)
  705:             && ( $Apache::lonhomework::type ne 'survey' )
  706:             && ( $Apache::lonhomework::type ne 'surveycred' )
  707:             && ( $Apache::lonhomework::type ne 'anonsurvey' )
  708:             && ( $Apache::lonhomework::type ne 'anonsurveycred' ) )
  709:         {
  710:             $dosplice = 0;
  711:             &Apache::lonxml::error(
  712:                 &mt('There are no true statements available.') . '<br />' );
  713:         }
  714: 
  715:         #insert the true statement, keeping track of where it wants to be
  716:         if (   $Apache::response::foilgroup{ $truename . '.location' } eq 'top'
  717:             && $dosplice )
  718:         {
  719:             $toplist[ $top{$truename} ] = $truename;
  720:             $answer = -1;
  721:             foreach my $top ( reverse(@toplist) ) {
  722:                 if ($top) { $answer++; }
  723:                 if ( $top eq $truename ) { last; }
  724:             }
  725:             $dosplice = 0;
  726:         }
  727:         elsif (
  728:             $Apache::response::foilgroup{ $truename . '.location' } eq 'bottom'
  729:             && $dosplice )
  730:         {
  731:             $bottomlist[ $bottom{$truename} ] = $truename;
  732:             $answer = -1;
  733:             foreach my $bot (@bottomlist) {
  734:                 if ($bot) { $answer++; }
  735:                 if ( $bot eq $truename ) { last; }
  736:             }
  737:             $answer += $topcount + $#whichfalse + 1;
  738:             $dosplice = 0;
  739:         }
  740:         else {
  741:             if ( $topcount > 0 || $bottomcount > 0 ) {
  742:                 my $inc = 1;
  743:                 if (   ( $bottomcount > 0 )
  744:                     && ( $Apache::lonhomework::type ne 'exam' ) )
  745:                 {
  746:                     $inc = 2;
  747:                 }
  748:                 $answer = int(
  749:                     &Math::Random::random_uniform() * ( $#whichfalse + $inc ) )
  750:                   + $topcount;
  751:             }
  752:         }
  753:         &Apache::lonxml::debug("Answer now wants $answer");
  754: 
  755:         #add the top items to the top, bottom items to the bottom
  756:         for ( my $i = 0 ; $i <= $#toplist ; $i++ ) {
  757:             if ( $toplist[$i] ) { unshift( @whichfalse, $toplist[$i] ) }
  758:         }
  759:         for ( my $i = 0 ; $i <= $#bottomlist ; $i++ ) {
  760:             if ( $bottomlist[$i] ) { push( @whichfalse, $bottomlist[$i] ) }
  761:         }
  762: 
  763:         #if the true statement is randomized insert it into the list
  764:         if ($dosplice) {
  765:             splice( @whichfalse, $answer, 0, $truelist[$whichtrue] );
  766:         }
  767:     }
  768:     &Apache::lonxml::debug("Answer is $answer");
  769:     return ( $answer, @whichfalse );
  770: }
  771: ##
  772: # Display foils in html rendition:
  773: #
  774: # @param $whichfoils - Set of foils to display.
  775: # @param $target     - Rendition target...there are several html targets.
  776: # @param $direction  - 'horizontal' if layout is horizontal.
  777: # @param $part       - Part of the problem that's being displayed.
  778: # @param $solved     - Solution state of the problem.
  779: # @param $show_answer- True if answers should be shown.
  780: #
  781: # @return string
  782: # @retval generated html.
  783: #
  784: sub display_foils_html {
  785:     my ($whichfoils, $target, $direction, $part, $solved, $show_answer) = @_;
  786:     my $result;
  787: 
  788:     # if the answers get shown, we need to label each item as correct or
  789:     # incorrect.
  790: 
  791:     if ($show_answer) {
  792: 	my $item_pretext     = '<br />'; # html prior to each item
  793: 	my $item_posttext    = '';	 # html after each item.
  794: 	my $finalclose       = '';	 # html to close off the whole shebang
  795: 
  796: 
  797: 	# Horizontal layout is a table with each foil in a cell
  798: 
  799: 	if ($direction eq 'horizontal') {
  800: 	    $result        = '<table><tr>';
  801: 	    $item_pretext  = '<td>' . $item_pretext;
  802: 	    $item_posttext = '</td>';
  803: 	    $finalclose    = '</tr></table>';
  804: 	} 
  805: 
  806: 	foreach my $name (@{$whichfoils}) {
  807: 
  808: 	    # If the item gets further surrounded by tags, this 
  809: 	    # holds the closures for those tages.
  810: 
  811: 	    my $item_closetag = '';
  812: 
  813: 	    $result .= $item_pretext;
  814: 
  815: 	    # Label each foil as correct or incorrect:
  816: 
  817: 	    if ($Apache::response::foilgroup{$name . '.value'} eq 'true') {
  818: 		$result .= &mt('Correct:') . '<b>';
  819: 		$item_closetag .= '</b>';
  820: 		
  821: 	    } else {
  822: 		$result .= &mt('Incorrect');
  823: 	    }
  824: 
  825: 	    # Web rendition encloses the 
  826: 	    # item text in a label tag as well:
  827: 
  828: 	    if ($target eq 'web') {
  829: 		$result .= '<label>';
  830: 		$item_closetag = '</label>' . $item_closetag;
  831: 	    }
  832: 	    $result .= $Apache::response::foilgroup{$name . '.text'};
  833: 	    $result .= $item_closetag;
  834: 	    $result .= $item_posttext;
  835: 	    $result .= "\n";	# make the html a bit more readable.
  836: 	}
  837: 
  838: 	$result .= $finalclose;
  839: 
  840:     } else {
  841: 	#  Not showing the answers, we need to generate the HTML appropriate
  842: 	#  to allowing the student to respond.
  843: 	
  844: 
  845:     }
  846: 
  847:     return $result;
  848: }
  849: 
  850: 
  851: ##
  852: 
  853: sub displayfoils {
  854:     my ( $target, $answer, $whichfoils, $direction, $bubbles_per_line ) = @_;
  855:     my $result;
  856: 
  857:     my $part   = $Apache::inputtags::part;
  858:     my $solved = $Apache::lonhomework::history{"resource.$part.solved"};
  859:     if ( ( $target ne 'tex' )
  860:         && &Apache::response::show_answer() )
  861:     {
  862: 
  863: 	$result = &display_foils_html(
  864: 	    $whichfoils, $target, $direction, $part, $solved, 1);
  865: 
  866: #        if ( $direction eq 'horizontal' ) {
  867: #            if ( $target ne 'tex' ) {
  868: #                $result .= '<table><tr>';
  869: #            }
  870: #        }
  871: #        foreach my $name ( @{$whichfoils} ) {
  872: #            if ( $direction eq 'horizontal' ) {
  873: #                if ( $target ne 'tex' ) { $result .= '<td>'; }
  874: #            }
  875: #            if ( $target ne 'tex' ) {
  876: #                $result .= "<br />";
  877: #            }
  878: #            else {
  879: #                $result .= '\item \vskip -2 mm  ';
  880: #            }
  881: #            if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
  882: #                if ( $target ne 'tex' ) {
  883: #                    $result .= &mt('Correct:') . '<b>';
  884: #                }
  885: #                else {
  886: #                    $result .= &mt('Correct:') . ' \textbf{';
  887: #                }
  888: #            }
  889: #            else {
  890: #                $result .= &mt('Incorrect:');
  891: #            }
  892: #            if ( $target eq 'web' ) { $result .= "<label>"; }
  893: #            $result .= $Apache::response::foilgroup{ $name . '.text' };
  894: #            if ( $target eq 'web' ) { $result .= "</label>"; }
  895: #            if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
  896: #                if   ( $target ne 'tex' ) { $result .= '</b>'; }
  897: #                else                      { $result .= '}'; }
  898: #            }
  899: #            if ( $direction eq 'horizontal' ) {
  900: #                if ( $target ne 'tex' ) { $result .= '</td>'; }
  901: #            }
  902: #        }
  903: #        if ( $direction eq 'horizontal' ) {
  904: #            if ( $target ne 'tex' ) {
  905: #                $result .= '</tr></table>';
  906: #            }
  907: #        }
  908:     }
  909:     else {
  910:         my @alphabet      = ( 'A' .. 'Z' );
  911:         my $i             = 0;
  912:         my $bubble_number = 0;
  913:         my $line          = 0;
  914:         my $temp          = 0;
  915:         my $id            = $Apache::inputtags::response['-1'];
  916:         my $part          = $Apache::inputtags::part;
  917:         my ( $lastresponse, $newvariation );
  918: 
  919:         if (
  920:             (
  921:                 (
  922:                     $Apache::lonhomework::history{"resource.$part.type"} eq
  923:                     'randomizetry'
  924:                 )
  925:                 || ( $Apache::lonhomework::type eq 'randomizetry' )
  926:             )
  927:             && ( $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
  928:           )
  929:         {
  930: 
  931:             if ( $env{ 'form.' . $part . '.rndseed' } ne
  932:                 $Apache::lonhomework::history{"resource.$part.rndseed"} )
  933:             {
  934:                 $newvariation = 1;
  935:             }
  936:         }
  937:         unless ($newvariation) {
  938:             $lastresponse =
  939:               $Apache::lonhomework::history{"resource.$part.$id.submission"};
  940:         }
  941:         my %lastresponse = &Apache::lonnet::str2hash($lastresponse);
  942:         if ( $target ne 'tex' && $direction eq 'horizontal' ) {
  943:             $result .= "<table><tr>";
  944:         }
  945:         my $numlines;
  946:         if ( ( $target eq 'tex' ) && ( $Apache::lonhomework::type eq 'exam' ) )
  947:         {
  948:             my $numitems = scalar( @{$whichfoils} );
  949:             $numlines = int( $numitems / $bubbles_per_line );
  950:             if ( ( $numitems % $bubbles_per_line ) != 0 ) {
  951:                 $numlines++;
  952:             }
  953:             if ( $numlines < 1 ) {
  954:                 $numlines = 1;
  955:             }
  956:             if ( $numlines > 1 ) {
  957:                 my $linetext;
  958:                 for ( my $i = 0 ; $i < $numlines ; $i++ ) {
  959:                     $linetext .= $Apache::lonxml::counter + $i . ', ';
  960:                 }
  961:                 $linetext =~ s/,\s$//;
  962:                 $result .=
  963:                     '\item[\small {\textbf{'
  964:                   . $linetext . '}}]'
  965:                   . ' {\footnotesize '
  966:                   . &mt( '(Bubble once in [_1] lines)', $numlines )
  967:                   . '} \hspace*{\fill} \\\\';
  968:             }
  969:             else {
  970:                 $result .= '\item[\textbf{' . $Apache::lonxml::counter . '}.]';
  971:             }
  972:         }
  973:         foreach my $name ( @{$whichfoils} ) {
  974:             if ( $target ne 'tex' ) {
  975:                 if ( $direction eq 'horizontal' ) {
  976:                     $result .= "<td>";
  977:                 }
  978:                 else {
  979:                     $result .= "<br />";
  980:                 }
  981:             }
  982:             if ( $target ne 'tex' ) {
  983:                 $result .= '<label>';
  984:                 $result .= "<input type=\"radio\"
  985:                             onchange=\"javascript:setSubmittedPart('$part');\"
  986:                             name=\"HWVAL_$Apache::inputtags::response['-1']\"
  987:                             value=\"$temp\"";
  988:                 if ( defined( $lastresponse{$name} ) ) {
  989:                     $result .= ' checked="checked"';
  990:                 }
  991:                 $result .= ' />'
  992:                   . $Apache::response::foilgroup{ $name . '.text' }
  993:                   . "</label>";
  994:             }
  995:             else {
  996:                 if ( $Apache::lonhomework::type eq 'exam' ) {
  997:                     if ( $bubble_number >= $bubbles_per_line ) {
  998:                         $line++;
  999:                         $i             = 0;
 1000:                         $bubble_number = 0;
 1001:                     }
 1002:                     my $identifier;
 1003:                     if ( $numlines > 1 ) {
 1004:                         $identifier = $Apache::lonxml::counter + $line;
 1005:                     }
 1006:                     $result .=
 1007:                         '{\small \textbf{'
 1008:                       . $identifier
 1009:                       . $alphabet[$i]
 1010:                       . '}}$\bigcirc$'
 1011:                       . $Apache::response::foilgroup{ $name . '.text' }
 1012:                       . '\\\\';    #' stupid emacs
 1013:                     $i++;
 1014:                     $bubble_number++;
 1015:                 }
 1016:                 else {
 1017:                     if (   $env{'form.pdfFormFields'} eq 'yes'
 1018:                         && $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
 1019:                     {
 1020:                         my $fieldname =
 1021:                             $env{'request.symb'} 
 1022:                           . '&part_'
 1023:                           . $Apache::inputtags::part
 1024:                           . '&radiobuttonresponse'
 1025:                           . '&HWVAL_'
 1026:                           . $Apache::inputtags::response['-1'];
 1027:                         $result .= '\item[{'
 1028:                           . &Apache::lonxml::print_pdf_radiobutton( $fieldname,
 1029:                             $temp )
 1030:                           . '}]'
 1031:                           . $Apache::response::foilgroup{ $name . '.text' }
 1032:                           . "\n";
 1033:                     }
 1034:                     else {
 1035:                         $result .= '\vspace*{-2 mm}\item '
 1036:                           . $Apache::response::foilgroup{ $name . '.text' };
 1037:                     }
 1038:                 }
 1039:             }
 1040:             if ( $target ne 'tex' && $direction eq 'horizontal' ) {
 1041:                 $result .= "</td>";
 1042:             }
 1043:             $temp++;
 1044:         }
 1045:         if ( $target ne 'tex' && $direction eq 'horizontal' ) {
 1046:             $result .= "</tr></table>";
 1047:         }
 1048:     }
 1049:     if ( $target ne 'tex' ) {
 1050:         if ( $direction ne 'horizontal' ) { $result .= "<br />"; }
 1051:     }
 1052:     else { $result .= '\vskip 0 mm '; }
 1053:     return $result;
 1054: }
 1055: 
 1056: sub displayallanswers {
 1057:     my @names;
 1058:     if ( $Apache::response::foilgroup{'names'} ) {
 1059:         @names = @{ $Apache::response::foilgroup{'names'} };
 1060:     }
 1061:     my $result = &Apache::response::answer_header('radiobuttonresponse');
 1062:     foreach my $name (@names) {
 1063:         $result .=
 1064:           &Apache::response::answer_part( 'radiobuttonresponse',
 1065:             $Apache::response::foilgroup{ $name . '.value' } );
 1066:     }
 1067:     $result .= &Apache::response::answer_footer('radiobuttonresponse');
 1068:     return $result;
 1069: }
 1070: 
 1071: sub displayanswers {
 1072:     my ( $answer, $whichopt, $bubbles_per_line ) = @_;
 1073:     my $result;
 1074: 
 1075:     if ( $Apache::lonhomework::type eq 'exam' ) {
 1076:         my $line    = int( $answer / $bubbles_per_line );
 1077:         my $correct = ( 'A' .. 'Z' )[ $answer % $bubbles_per_line ];
 1078:         $result .=
 1079:           &Apache::response::answer_header( 'radiobuttonresponse', $line );
 1080:         $result .=
 1081:           &Apache::response::answer_part( 'radiobuttonresponse', $correct );
 1082:     }
 1083:     else {
 1084:         $result .= &Apache::response::answer_header('radiobuttonresponse');
 1085:     }
 1086:     foreach my $name ( @{$whichopt} ) {
 1087:         $result .=
 1088:           &Apache::response::answer_part( 'radiobuttonresponse',
 1089:             $Apache::response::foilgroup{ $name . '.value' } );
 1090:     }
 1091:     $result .= &Apache::response::answer_footer('radiobuttonresponse');
 1092:     return $result;
 1093: }
 1094: 
 1095: sub start_conceptgroup {
 1096:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
 1097:       @_;
 1098:     $Apache::radiobuttonresponse::conceptgroup = 1;
 1099:     %Apache::response::conceptgroup            = ();
 1100:     my $result;
 1101:     if ( $target eq 'edit' ) {
 1102:         $result .= &Apache::edit::tag_start( $target, $token );
 1103:         $result .=
 1104:             &Apache::edit::text_arg( 'Concept:', 'concept', $token, '50' )
 1105:           . &Apache::edit::end_row()
 1106:           . &Apache::edit::start_spanning_row();
 1107:     }
 1108:     elsif ( $target eq 'modified' ) {
 1109:         my $constructtag =
 1110:           &Apache::edit::get_new_args( $token, $parstack, $safeeval,
 1111:             'concept' );
 1112:         if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
 1113:     }
 1114:     return $result;
 1115: }
 1116: 
 1117: sub end_conceptgroup {
 1118:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
 1119:       @_;
 1120:     $Apache::radiobuttonresponse::conceptgroup = 0;
 1121:     my $result;
 1122:     if (   $target eq 'web'
 1123:         || $target eq 'grade'
 1124:         || $target eq 'answer'
 1125:         || $target eq 'tex'
 1126:         || $target eq 'analyze' )
 1127:     {
 1128:         &Apache::response::pick_foil_for_concept( $target,
 1129:             [ 'value', 'text', 'location' ],
 1130:             \%Apache::hint::radiobutton, $parstack, $safeeval );
 1131:     }
 1132:     elsif ( $target eq 'edit' ) {
 1133:         $result = &Apache::edit::end_table();
 1134:     }
 1135:     return $result;
 1136: }
 1137: 
 1138: sub insert_conceptgroup {
 1139:     my $result =
 1140:         "\n\t\t<conceptgroup concept=\"\">"
 1141:       . &insert_foil()
 1142:       . "\n\t\t</conceptgroup>\n";
 1143:     return $result;
 1144: }
 1145: 
 1146: sub start_foil {
 1147:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
 1148:       @_;
 1149:     my $result = '';
 1150:     if ( $target eq 'web' || $target eq 'tex' || $target eq 'analyze' ) {
 1151:         &Apache::lonxml::startredirection;
 1152:         if ( $target eq 'analyze' ) {
 1153:             &Apache::response::check_if_computed( $token, $parstack, $safeeval,
 1154:                 'value' );
 1155:         }
 1156:     }
 1157:     elsif ( $target eq 'edit' ) {
 1158:         $result = &Apache::edit::tag_start( $target, $token );
 1159:         $result .= &Apache::edit::text_arg( 'Name:', 'name', $token );
 1160:         $result .= &Apache::edit::select_or_text_arg(
 1161:             'Correct Option:', 'value',
 1162:             [ 'unused', 'true', 'false' ], $token
 1163:         );
 1164:         my $randomize =
 1165:           &Apache::lonxml::get_param( 'randomize', $parstack, $safeeval, '-3' );
 1166:         if ( $randomize ne 'no' ) {
 1167:             $result .=
 1168:               &Apache::edit::select_arg( 'Location:', 'location',
 1169:                 [ 'random', 'top', 'bottom' ], $token );
 1170:         }
 1171:         $result .=
 1172:           &Apache::edit::end_row() . &Apache::edit::start_spanning_row();
 1173:     }
 1174:     elsif ( $target eq 'modified' ) {
 1175:         my $constructtag =
 1176:           &Apache::edit::get_new_args( $token, $parstack, $safeeval, 'value',
 1177:             'name', 'location' );
 1178:         if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
 1179:     }
 1180:     return $result;
 1181: }
 1182: 
 1183: sub end_foil {
 1184:     my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
 1185:       @_;
 1186:     my $text = '';
 1187:     if ( $target eq 'web' || $target eq 'tex' || $target eq 'analyze' ) {
 1188:         $text = &Apache::lonxml::endredirection;
 1189:     }
 1190:     if (   $target eq 'web'
 1191:         || $target eq 'grade'
 1192:         || $target eq 'answer'
 1193:         || $target eq 'tex'
 1194:         || $target eq 'analyze' )
 1195:     {
 1196:         my $value = &Apache::lonxml::get_param( 'value', $parstack, $safeeval );
 1197:         if ( $value ne 'unused' ) {
 1198:             my $name =
 1199:               &Apache::lonxml::get_param( 'name', $parstack, $safeeval );
 1200:             if ( $name eq "" ) {
 1201:                 &Apache::lonxml::warning(
 1202:                     &mt(
 1203: 'Foils without names exist. This can cause problems to malfunction.'
 1204:                     )
 1205:                 );
 1206:                 $name = $Apache::lonxml::curdepth;
 1207:             }
 1208:             if ( defined( $Apache::response::foilnames{$name} ) ) {
 1209:                 &Apache::lonxml::error(
 1210:                     &mt(
 1211: 'Foil name [_1] appears more than once. Foil names need to be unique.',
 1212:                         '<b><tt>' . $name . '</tt></b>'
 1213:                     )
 1214:                 );
 1215:             }
 1216:             $Apache::response::foilnames{$name}++;
 1217:             my $location =
 1218:               &Apache::lonxml::get_param( 'location', $parstack, $safeeval );
 1219:             if ( $Apache::radiobuttonresponse::conceptgroup
 1220:                 && !&Apache::response::showallfoils() )
 1221:             {
 1222:                 push @{ $Apache::response::conceptgroup{'names'} }, $name;
 1223:                 $Apache::response::conceptgroup{"$name.value"}    = $value;
 1224:                 $Apache::response::conceptgroup{"$name.text"}     = $text;
 1225:                 $Apache::response::conceptgroup{"$name.location"} = $location;
 1226:             }
 1227:             else {
 1228:                 push @{ $Apache::response::foilgroup{'names'} }, $name;
 1229:                 $Apache::response::foilgroup{"$name.value"}    = $value;
 1230:                 $Apache::response::foilgroup{"$name.text"}     = $text;
 1231:                 $Apache::response::foilgroup{"$name.location"} = $location;
 1232:             }
 1233:         }
 1234:     }
 1235:     return '';
 1236: }
 1237: 
 1238: sub insert_foil {
 1239:     return '
 1240: <foil name="" value="unused">
 1241: <startouttext />
 1242: <endouttext />
 1243: </foil>';
 1244: }
 1245: 
 1246: 1;
 1247: __END__
 1248: 
 1249: 
 1250: 
 1251: =head1 NAME
 1252: 
 1253: Apache::radiobuttonresponse
 1254: 
 1255: =head1 SYNOPSIS
 1256: 
 1257: Handles multiple-choice style responses.
 1258: 
 1259: This is part of the LearningOnline Network with CAPA project
 1260: described at http://www.lon-capa.org.
 1261: 
 1262: =head1 SUBROUTINES
 1263: 
 1264: =over
 1265: 
 1266: =item start_radiobuttonresponse()
 1267: 
 1268: =item bubble_line_count()
 1269: 
 1270: =item end_radiobuttonresponse()
 1271: 
 1272: =item start_foilgroup()
 1273: 
 1274: =item storesurvey()
 1275: 
 1276: =item grade_response()
 1277: 
 1278: =item end_foilgroup()
 1279: 
 1280: =item getfoilcounts()
 1281: 
 1282: =item format_prior_answer()
 1283: 
 1284: =item displayallfoils()
 1285: 
 1286: =item &whichfoils($max,$randomize)
 1287: 
 1288: Randomizes the list of foils.
 1289: Respects
 1290:   - each foils desire to be randomized
 1291:   - the existance of Concept groups of foils (select 1 foil from each)
 1292:   - and selects a single correct statement from all possilble true statments
 1293:   - and limits it to a toal of $max foils
 1294: 
 1295: WARNING: this routine uses the random number generator, it should only
 1296: be called once per target, otherwise it can cause randomness changes in
 1297: homework problems.
 1298: 
 1299: Arguments
 1300:   $max - maximum number of foils to select (including the true one)
 1301:          (so a max of 5 is: 1 true, 4 false)
 1302: 
 1303:   $randomize - whether to randomize the listing of foils, by default
 1304:                will randomize, only if randomize is 'no' will it not
 1305: 
 1306: Returns
 1307:   $answer - location in the array of the correct answer
 1308:   @foils  - array of foil names in to display order
 1309: 
 1310: =item displayfoils()
 1311: 
 1312: =item displayallanswers()
 1313: 
 1314: =item displayanswers()
 1315: 
 1316: =item start_conceptgroup()
 1317: 
 1318: =item end_conceptgroup()
 1319: 
 1320: =item insert_conceptgroup()
 1321: 
 1322: =item start_foil()
 1323: 
 1324: =item end_foil()
 1325: 
 1326: =item insert_foil()
 1327: 
 1328: =back
 1329: 
 1330: =cut
 1331:  

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>