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