File:  [LON-CAPA] / loncom / homework / radiobuttonresponse.pm
Revision 1.153.6.3: download - view: text, annotated - select for diffs
Sat Jan 21 21:40:41 2012 UTC (12 years, 3 months ago) by foxr
Branches: BZ4492-feature_horizontal_radioresponse
Diff to branchpoint 1.153: preferred, unified
BZ4492 - continued refactoring of how this is rendered so this can be done
sensibly.

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

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