Annotation of loncom/homework/radiobuttonresponse.pm, revision 1.153.6.5
1.22 albertel 1: # The LearningOnline Network with CAPA
2: # mutliple choice style responses
1.31 albertel 3: #
1.153.6.5! foxr 4: # $Id: radiobuttonresponse.pm,v 1.153.6.4 2012/01/23 12:00:13 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 foxr 452: if ( $direction eq 'horizontal' ) { $result .= '<table><tr>'; }
453: my %lastresponse = &Apache::lonnet::str2hash($lastresponse);
1.147 raeburn 454: if ($showanswer) {
1.153 foxr 455: foreach my $name (@names) {
456: if ( $Apache::response::foilgroup{ $name . '.value' } ne 'unused' )
457: {
458: if ( ( $direction eq 'horizontal' ) && ( $target ne 'tex' ) ) {
459: $result .= "<td>";
460: }
461: else {
462: if ( $target eq 'tex' ) {
463: $result .= '\item \vskip -2mm ';
464: }
465: else {
466: $result .= "<br />";
467: }
468: }
469: if ( defined( $lastresponse{$name} ) ) {
470: if ( $target eq 'tex' ) {
471: $result .= '}';
472: }
473: else {
474: $result .= '<b>';
475: }
476: }
477: $result .= $Apache::response::foilgroup{ $name . '.text' };
478: if ( defined( $lastresponse{$name} ) && ( $target ne 'tex' ) ) {
479: $result .= '</b>';
480: }
481: if ( ( $direction eq 'horizontal' ) && ( $target ne 'tex' ) ) {
482: $result .= "</td>";
483: }
484: }
485: }
486: }
487: else {
488: foreach my $name (@names) {
489: if ( $Apache::response::foilgroup{ $name . '.value' } ne 'unused' )
490: {
491: if ( $direction eq 'horizontal' ) {
492: $result .= "<td>";
493: }
494: else {
495: if ( $target eq 'tex' ) {
496: if ( $env{'form.pdfFormFields'} eq 'yes'
497: && $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
498: {
499: my $fieldname =
500: $env{'request.symb'}
501: . '&part_'
502: . $Apache::inputtags::part
503: . '&radiobuttonresponse'
504: . '&HWVAL_'
505: . $Apache::inputtags::response['-1'];
506: $result .= '\item[{'
507: . &Apache::lonxml::print_pdf_radiobutton(
508: $fieldname, $temp )
509: . '}]'
510: . $Apache::response::foilgroup{ $name . '.text' }
511: . "\n";
512: }
513: else {
1.135 onken 514: $result .= '\item \vskip -2mm ';
515: }
1.153 foxr 516: }
517: else {
518: $result .= "<br />";
519: }
520: }
521: if ( $target eq 'tex' ) {
522: if ( $env{'form.pdfFormFields'} ne 'yes'
523: or $Apache::inputtags::status[-1] ne 'CAN_ANSWER' )
524: {
525: $result .=
526: '$\bigcirc$'
527: . $Apache::response::foilgroup{ $name . '.text' }
528: . '\\\\'; #' stupid emacs
529: }
530: $i++;
531: }
532: else {
533: $result .= '<label>';
534: $result .= "<input
1.113 albertel 535: onchange=\"javascript:setSubmittedPart('$part');\"
536: type=\"radio\"
537: name=\"HWVAL_$Apache::inputtags::response['-1']\"
1.142 bisitz 538: value=\"$temp\"";
1.147 raeburn 539:
1.153 foxr 540: if ( defined( $lastresponse{$name} ) ) {
541: $result .= ' checked="checked"';
542: }
543: $result .= ' />'
544: . $Apache::response::foilgroup{ $name . '.text' }
545: . '</label>';
546: }
547: $temp++;
548: if ( $target ne 'tex' ) {
549: if ( ( $direction eq 'horizontal' )
550: && ( $target ne 'tex' ) )
551: {
552: $result .= "</td>";
553: }
554: }
555: else {
556: $result .= '\vskip 0 mm ';
557: }
558: }
559: }
560: }
561:
562: if ( ( $direction eq 'horizontal' ) && ( $target ne 'tex' ) ) {
563: $result .= '</tr></table>';
1.45 albertel 564: }
1.153.6.5! foxr 565:
! 566: # Close tex bracketing:
! 567:
! 568: if ($target eq 'tex') {
! 569: $result .= $end_environment;
! 570: }
1.83 albertel 571: return $result;
1.15 albertel 572: }
573:
1.28 albertel 574: sub whichfoils {
1.153 foxr 575: my ( $max, $randomize ) = @_;
1.28 albertel 576:
1.83 albertel 577: my @truelist;
578: my @falselist;
1.153 foxr 579: my @whichfalse = ();
580: my ( $truecnt, $falsecnt ) = &getfoilcounts();
581: my $count = 0;
582:
1.83 albertel 583: # we will add in 1 of the true statements
1.153 foxr 584: if ( $max > 0 && ( $falsecnt + 1 ) > $max ) { $count = $max }
585: else { $count = $falsecnt + 1; $max = $count; }
586: my $answer = int( &Math::Random::random_uniform() * ($count) );
1.83 albertel 587: &Apache::lonxml::debug("Count is $count, $answer is $answer");
588: my @names;
589: if ( $Apache::response::foilgroup{'names'} ) {
1.153 foxr 590: @names = @{ $Apache::response::foilgroup{'names'} };
591: }
592: if ( &Apache::response::showallfoils() ) {
593: @whichfalse = @names;
594: }
595: elsif ( $randomize eq 'no' ) {
596: &Apache::lonxml::debug("No randomization");
597: my $havetrue = 0;
598: foreach my $name (@names) {
599: if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
600: if ( !$havetrue ) {
601: push( @whichfalse, $name );
602: $havetrue++;
603: $answer = $#whichfalse;
604: }
605: }
606: elsif (
607: $Apache::response::foilgroup{ $name . '.value' } eq 'false' )
608: {
609: push( @whichfalse, $name );
610: }
611: elsif (
612: $Apache::response::foilgroup{ $name . '.value' } eq 'unused' )
613: {
614: }
615: else {
616: &Apache::lonxml::error(
617: &HTML::Entities::encode(
618: "No valid value assigned ($Apache::response::foilgroup{$name.'.value'}) for foil $name in <foilgroup>",
619: '<>&"'
620: )
621: );
622: }
623: }
624: if ( ( !$havetrue )
625: && ( $Apache::lonhomework::type ne 'survey' )
626: && ( $Apache::lonhomework::type ne 'surveycred' )
627: && ( $Apache::lonhomework::type ne 'anonsurvey' )
628: && ( $Apache::lonhomework::type ne 'anonsurveycred' ) )
629: {
630: &Apache::lonxml::error(
631: &mt('There are no true statements available.') . '<br />' );
632: }
1.83 albertel 633: }
1.153 foxr 634: else {
635: my $current = 0;
636: &Apache::lonhomework::showhash(%Apache::response::foilgroup);
637: my ( %top, %bottom );
638:
639: #first find out where everyone wants to be
640: foreach my $name (@names) {
641: $current++;
642: if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
643: push( @truelist, $name );
644: if ( $Apache::response::foilgroup{ $name . '.location' } eq
645: 'top' )
646: {
647: $top{$name} = $current;
648: }
649: elsif ( $Apache::response::foilgroup{ $name . '.location' } eq
650: 'bottom' )
651: {
652: $bottom{$name} = $current;
653: }
654: }
655: elsif (
656: $Apache::response::foilgroup{ $name . '.value' } eq 'false' )
657: {
658: push( @falselist, $name );
659: if ( $Apache::response::foilgroup{ $name . '.location' } eq
660: 'top' )
661: {
662: $top{$name} = $current;
663: }
664: elsif ( $Apache::response::foilgroup{ $name . '.location' } eq
665: 'bottom' )
666: {
667: $bottom{$name} = $current;
668: }
669: }
670: elsif (
671: $Apache::response::foilgroup{ $name . '.value' } eq 'unused' )
672: {
673: }
674: else {
675: &Apache::lonxml::error(
676: &HTML::Entities::encode(
677: "No valid value assigned ($Apache::response::foilgroup{$name.'.value'}) for foil $name in <foilgroup>",
678: '<>&"'
679: )
680: );
681: }
682: }
683:
684: #pick a true statement
685: my $notrue = 0;
686: if ( scalar(@truelist) == 0 ) { $notrue = 1; }
687: my $whichtrue =
688: int( &Math::Random::random_uniform() * ( $#truelist + 1 ) );
689: &Apache::lonxml::debug(
690: "Max is $max, From $#truelist elms, picking $whichtrue");
691: my ( @toplist, @bottomlist );
692: my $topcount = 0;
693: my $bottomcount = 0;
694:
695: # assign everyone to either toplist/bottomlist or whichfalse
696: # which false is randomized, toplist bottomlist are in order
697: while (( ( $#whichfalse + $topcount + $bottomcount ) < $max - 2 )
698: && ( $#falselist > -1 ) )
699: {
700: &Apache::lonxml::debug("Have $#whichfalse max is $max");
701: my $afalse =
702: int( &Math::Random::random_uniform() * ( $#falselist + 1 ) );
703: &Apache::lonxml::debug("From $#falselist elms, picking $afalse");
704: $afalse = splice( @falselist, $afalse, 1 );
705: &Apache::lonxml::debug("Picked $afalse");
706: &Apache::lonhomework::showhash( ( 'names' => \@names ) );
707: &Apache::lonhomework::showhash(%top);
708: if ( $top{$afalse} ) {
709: $toplist[ $top{$afalse} ] = $afalse;
710: $topcount++;
711: }
712: elsif ( $bottom{$afalse} ) {
713: $bottomlist[ $bottom{$afalse} ] = $afalse;
714: $bottomcount++;
715: }
716: else {
717: push( @whichfalse, $afalse );
718: }
719: }
720: &Apache::lonxml::debug("Answer wants $answer");
721: my $truename = $truelist[$whichtrue];
722: my $dosplice = 1;
723: if ( ($notrue)
724: && ( $Apache::lonhomework::type ne 'survey' )
725: && ( $Apache::lonhomework::type ne 'surveycred' )
726: && ( $Apache::lonhomework::type ne 'anonsurvey' )
727: && ( $Apache::lonhomework::type ne 'anonsurveycred' ) )
728: {
729: $dosplice = 0;
730: &Apache::lonxml::error(
731: &mt('There are no true statements available.') . '<br />' );
732: }
733:
734: #insert the true statement, keeping track of where it wants to be
735: if ( $Apache::response::foilgroup{ $truename . '.location' } eq 'top'
736: && $dosplice )
737: {
738: $toplist[ $top{$truename} ] = $truename;
739: $answer = -1;
740: foreach my $top ( reverse(@toplist) ) {
741: if ($top) { $answer++; }
742: if ( $top eq $truename ) { last; }
743: }
744: $dosplice = 0;
745: }
746: elsif (
747: $Apache::response::foilgroup{ $truename . '.location' } eq 'bottom'
748: && $dosplice )
749: {
750: $bottomlist[ $bottom{$truename} ] = $truename;
751: $answer = -1;
752: foreach my $bot (@bottomlist) {
753: if ($bot) { $answer++; }
754: if ( $bot eq $truename ) { last; }
755: }
756: $answer += $topcount + $#whichfalse + 1;
757: $dosplice = 0;
758: }
759: else {
760: if ( $topcount > 0 || $bottomcount > 0 ) {
1.150 raeburn 761: my $inc = 1;
1.153 foxr 762: if ( ( $bottomcount > 0 )
763: && ( $Apache::lonhomework::type ne 'exam' ) )
764: {
1.150 raeburn 765: $inc = 2;
766: }
1.153 foxr 767: $answer = int(
768: &Math::Random::random_uniform() * ( $#whichfalse + $inc ) )
769: + $topcount;
770: }
771: }
772: &Apache::lonxml::debug("Answer now wants $answer");
773:
774: #add the top items to the top, bottom items to the bottom
775: for ( my $i = 0 ; $i <= $#toplist ; $i++ ) {
776: if ( $toplist[$i] ) { unshift( @whichfalse, $toplist[$i] ) }
777: }
778: for ( my $i = 0 ; $i <= $#bottomlist ; $i++ ) {
779: if ( $bottomlist[$i] ) { push( @whichfalse, $bottomlist[$i] ) }
780: }
781:
782: #if the true statement is randomized insert it into the list
783: if ($dosplice) {
784: splice( @whichfalse, $answer, 0, $truelist[$whichtrue] );
785: }
1.49 albertel 786: }
1.83 albertel 787: &Apache::lonxml::debug("Answer is $answer");
1.153 foxr 788: return ( $answer, @whichfalse );
1.28 albertel 789: }
1.153.6.1 foxr 790: ##
1.153.6.2 foxr 791: # Generate the HTML for a single html foil.
792: # @param $part - The part for which the response is being generated.
793: # @param $fieldname - The basename of the radiobutton field
794: # @param $name - The foilname.
795: # @param $last_responses - Reference to a hash that holds the most recent
796: # responses.
797: # @param $value - radiobutton value.
798: #
799: # @return text
800: # @retval The generated html.
801: #
802: sub html_radiobutton {
803: my ($part, $fieldname, $name, $last_responses, $value) = @_;
804:
805: my $result='<label>';
806:
807: $result .= '<input type="radio"
808: onchange="javascript:setSubmittedPart(' . "'$part');\""
809: . 'name="HWVAL_' . $fieldname . '"'
810: . "value='$value'";
811:
812: if (defined($last_responses->{$name})) {
813: $result .= ' checked="checked" ';
814: }
815: $result .= ' />';
816: $result .= $Apache::response::foilgroup{$name . '.text'};
817: $result .= '</label>';
818:
819: return $result;
820:
821: }
1.153.6.3 foxr 822: ##
823: # Return a reference to the last response hash. This hash has exactly
824: # one or zero entries. The one entry is keyed by the foil 'name' of
825: # the prior response
826: #
827: # @param $part - Number of the problem part.
828: #
829: # @return reference to a hash.
830: # @retval see above.
831: #
832: sub get_last_response {
833: my ($part) = @_;
834:
835: my $id = $Apache::inputtags::response['-1'];
836: my ( $lastresponse, $newvariation );
837:
838: if ((( $Apache::lonhomework::history{"resource.$part.type"} eq 'randomizetry')
839: || ( $Apache::lonhomework::type eq 'randomizetry' )
840: )
841: && ( $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
842: )
843: {
844:
845: if ( $env{ 'form.' . $part . '.rndseed' } ne
846: $Apache::lonhomework::history{"resource.$part.rndseed"} )
847: {
848: $newvariation = 1;
849: }
850: }
851: unless ($newvariation) {
852: $lastresponse =
853: $Apache::lonhomework::history{"resource.$part.$id.submission"};
854: }
855: my %lastresponse = &Apache::lonnet::str2hash($lastresponse);
856:
857: return \%lastresponse;
858: }
1.153.6.2 foxr 859:
860: ##
1.153.6.3 foxr 861: # Display foils in html rendition.:
1.153.6.1 foxr 862: #
863: # @param $whichfoils - Set of foils to display.
864: # @param $target - Rendition target...there are several html targets.
865: # @param $direction - 'horizontal' if layout is horizontal.
866: # @param $part - Part of the problem that's being displayed.
867: # @param $solved - Solution state of the problem.
868: # @param $show_answer- True if answers should be shown.
869: #
870: # @return string
871: # @retval generated html.
872: #
873: sub display_foils_html {
874: my ($whichfoils, $target, $direction, $part, $solved, $show_answer) = @_;
875: my $result;
876:
877: # if the answers get shown, we need to label each item as correct or
878: # incorrect.
879:
880: if ($show_answer) {
881: my $item_pretext = '<br />'; # html prior to each item
882: my $item_posttext = ''; # html after each item.
883: my $finalclose = ''; # html to close off the whole shebang
884:
885:
886: # Horizontal layout is a table with each foil in a cell
887:
888: if ($direction eq 'horizontal') {
889: $result = '<table><tr>';
890: $item_pretext = '<td>' . $item_pretext;
891: $item_posttext = '</td>';
892: $finalclose = '</tr></table>';
893: }
894:
895: foreach my $name (@{$whichfoils}) {
896:
897: # If the item gets further surrounded by tags, this
898: # holds the closures for those tages.
899:
900: my $item_closetag = '';
901:
902: $result .= $item_pretext;
903:
904: # Label each foil as correct or incorrect:
905:
906: if ($Apache::response::foilgroup{$name . '.value'} eq 'true') {
907: $result .= &mt('Correct:') . '<b>';
908: $item_closetag .= '</b>';
909:
910: } else {
911: $result .= &mt('Incorrect');
912: }
913:
914: # Web rendition encloses the
915: # item text in a label tag as well:
916:
917: if ($target eq 'web') {
918: $result .= '<label>';
919: $item_closetag = '</label>' . $item_closetag;
920: }
921: $result .= $Apache::response::foilgroup{$name . '.text'};
922: $result .= $item_closetag;
923: $result .= $item_posttext;
924: $result .= "\n"; # make the html a bit more readable.
925: }
926:
927: $result .= $finalclose;
928:
929: } else {
1.153.6.3 foxr 930: $result .= '<br />'; # end line prior to foilgroup:
931:
1.153.6.1 foxr 932: # Not showing the answers, we need to generate the HTML appropriate
933: # to allowing the student to respond.
934:
1.153.6.3 foxr 935: my $item_pretext;
936: my $item_posttext;
937: my $lastresponse = &get_last_response($part);
1.153.6.1 foxr 938:
1.153.6.3 foxr 939: if ( $direction eq 'horizontal' ) {
940: $item_pretext = '<td>';
941: $item_posttext = '</td>';
942: }
943: else {
944: $item_pretext = '<br/>';
945: }
946: my $item_no = 0;
947: foreach my $name (@{$whichfoils}) {
948: $result .= $item_pretext;
949: $result .= &html_radiobutton(
950: $part, $Apache::inputtags::response[-1],
951: $name, $lastresponse, $item_no
952: );
953: $result .= $item_posttext;
954: $item_no++;
955: }
956:
957: if ($direction eq 'horizontal' ) {
958: $result .= "</tr></table>";
959: } else {
960: $result .= "<br />";
961: }
1.153.6.1 foxr 962: }
963:
964: return $result;
965: }
1.153.6.4 foxr 966: ##
967: # Display foils in exam mode for latex
968: #
1.153.6.5! foxr 969: # @param $whichfoils - Reference to an array that contains the foil names to display
1.153.6.4 foxr 970: # @param $bubbles_per_line - Number of bubbles on a line.
1.153.6.5! foxr 971: # @param $direction - Rendering direction 'horizontal' is what we're looking for.
! 972: # @param $vbegin - Start latex fragment in vertical rendering.
! 973: # @param $vend - End latex fragmentin vertical rendering.
1.153.6.4 foxr 974: #
975: # @return string
976: # @return the latex rendering of the exam problem.
977: #
978: #
979: sub display_latex_exam {
1.153.6.5! foxr 980: my ($whichfoils, $bubbles_per_line, $direction, $vbegin, $vend) = @_;
1.153.6.4 foxr 981: my $result;
982: my $numlines;
983: my $bubble_number = 0;
984: my $line = 0;
985: my $i = 0;
986:
1.153.6.5! foxr 987: &Apache::lonnet::logthis("LaTeX exam: $direction $vbegin $vend");
! 988:
! 989: if ($direction eq 'horizontal') {
! 990:
! 991: # Marshall the display text for each foil and turn things over to
! 992: # Apache::response::make_horizontal_bubbles:
! 993:
! 994: my @foil_texts;
! 995: foreach my $name (@{$whichfoils}) {
! 996: push(@foil_texts, $Apache::response::foilgroup{$name . '.text'});
1.153.6.4 foxr 997: }
1.153.6.5! foxr 998: $result .= &Apache::caparesponse::make_horizontal_latex_bubbles(
! 999: $whichfoils, \@foil_texts, '$\bigcirc$');
1.153.6.4 foxr 1000:
1001:
1.153.6.5! foxr 1002: } else {
! 1003: $result .= $vbegin;
! 1004:
! 1005: # This section puts out the prefix that tells the user
! 1006: # (if necessary) to only choose one bubble in the next n lines
! 1007: # for problems with more than one line worth of bubbles in the grid sheet:
! 1008:
! 1009: my $numitems = scalar( @{$whichfoils} );
! 1010: $numlines = int( $numitems / $bubbles_per_line );
! 1011: if ( ( $numitems % $bubbles_per_line ) != 0 ) {
! 1012: $numlines++;
! 1013: }
! 1014: if ( $numlines < 1 ) {
! 1015: $numlines = 1;
1.153.6.4 foxr 1016: }
1017: if ( $numlines > 1 ) {
1.153.6.5! foxr 1018: my $linetext;
! 1019: for ( my $i = 0 ; $i < $numlines ; $i++ ) {
! 1020: $linetext .= $Apache::lonxml::counter + $i . ', ';
! 1021: }
! 1022: $linetext =~ s/,\s$//;
! 1023: $result .=
! 1024: '\item[\small {\textbf{'
! 1025: . $linetext . '}}]'
! 1026: . ' {\footnotesize '
! 1027: . &mt( '(Bubble once in [_1] lines)', $numlines )
! 1028: . '} \hspace*{\fill} \\\\';
1.153.6.4 foxr 1029: }
1.153.6.5! foxr 1030: else {
! 1031: $result .= '\item[\textbf{' . $Apache::lonxml::counter . '}.]';
! 1032: }
! 1033:
! 1034: # Now output the bubbles themselves:
! 1035:
! 1036: foreach my $name (@{$whichfoils}) {
! 1037: if ( $bubble_number >= $bubbles_per_line ) {
! 1038: $line++;
! 1039: $i = 0;
! 1040: $bubble_number = 0;
! 1041: }
! 1042: my $identifier;
! 1043: if ( $numlines > 1 ) {
! 1044: $identifier = $Apache::lonxml::counter + $line;
! 1045: }
! 1046: $result .=
! 1047: '{\small \textbf{'
! 1048: . $identifier
! 1049: . $alphabet[$i]
! 1050: . '}}$\bigcirc$'
! 1051: . $Apache::response::foilgroup{ $name . '.text' }
! 1052: . '\\\\'; #' stupid emacs -- it thinks it needs that apostrophe to close the quote
! 1053:
! 1054: $i++;
! 1055: $bubble_number++;
! 1056: }
! 1057: $result .= $vend
1.153.6.4 foxr 1058:
1.153.6.5! foxr 1059: }
1.153.6.4 foxr 1060:
1.153.6.5! foxr 1061: return $result;
! 1062:
1.153.6.4 foxr 1063: }
1064:
1065: ##
1066: # Display latex when exam mode is not on.
1067: #
1068: # @param $whichfoils - The foils to display
1069: # @param $direction - Display direction ('horizontal' is what matters to us).
1070: # @param $vbegin - Begin the vertical environment being used.
1071: # @param $vend - End the vertical environment being used.
1072: #
1073: # @return string
1074: # @retval - The LaTeX rendering of the resource.'
1075: #
1076: sub display_latex {
1077: my ($whichfoils, $direction, $vbegin, $vend) = @_;
1078: my $result;
1079:
1080: $result .= $vbegin;
1081: foreach my $name (@{$whichfoils}) {
1082: $result .= '\vspace*{-2 mm}\item '
1083: . $Apache::response::foilgroup{ $name . '.text' };
1084: }
1085:
1086: $result .= $vend;
1087:
1088: return $result;
1089: }
1.153.6.1 foxr 1090:
1091:
1092: ##
1.153.6.5! foxr 1093: # Render foils for a PDF form. This is a variant of tex rednering that provides
! 1094: # sufficient markup that the final PDF is a form that can be filled in online,
! 1095: # or offline.
! 1096: #
! 1097: # @param $whichfoils - References an array of foils to display in the order in which
! 1098: # they should be displayed.
! 1099: # @param $direction - Rendering direction. 'horiztonal' means inputs are laid out
! 1100: # horizontally otherwise they are stacked vertically.
! 1101: #
! 1102: # @return string
! 1103: # @retval String containing the rendering of the resource.
! 1104: #
! 1105: sub display_pdf_form {
! 1106: my ($whichfoils) = @_;
! 1107: my $temp = 0;
! 1108: my $result;
! 1109:
! 1110: foreach my $name ( @{$whichfoils} ) {
! 1111:
! 1112: my $fieldname =
! 1113: $env{'request.symb'}
! 1114: . '&part_'
! 1115: . $Apache::inputtags::part
! 1116: . '&radiobuttonresponse'
! 1117: . '&HWVAL_'
! 1118: . $Apache::inputtags::response['-1'];
! 1119: $result .= '\item[{'
! 1120: . &Apache::lonxml::print_pdf_radiobutton( $fieldname,
! 1121: $temp )
! 1122: . '}]'
! 1123: . $Apache::response::foilgroup{ $name . '.text' }
! 1124: . "\n";
! 1125:
! 1126: $temp++;
! 1127: }
! 1128:
! 1129: return $result;
! 1130: }
! 1131:
! 1132:
! 1133: ##
! 1134: # Display selected foils: This is really just a dispatchter to appropriate renderers
! 1135: #
! 1136: # @param $target - Target (e.g. 'tex'...).
! 1137: # @param $answer - True if answers should be shown.
! 1138: # @param $whichfoils - Array of foil selectors that indicate which foils shouild be
! 1139: # rendered, in rendering order.
! 1140: # @param $direction- Rendering direction ('horizontal' is the one we look for,
! 1141: # otherwise foils are rendered one per line vertically.
! 1142: # @param $bubbles_per_line - number of exam bubbles per line.
! 1143: #
! 1144: # @return string
! 1145: # @retval The rendered problem.
1.28 albertel 1146:
1147: sub displayfoils {
1.153 foxr 1148: my ( $target, $answer, $whichfoils, $direction, $bubbles_per_line ) = @_;
1.83 albertel 1149: my $result;
1.28 albertel 1150:
1.153 foxr 1151: my $part = $Apache::inputtags::part;
1152: my $solved = $Apache::lonhomework::history{"resource.$part.solved"};
1.153.6.4 foxr 1153:
1154: # Show answers html.
1155:
1.153 foxr 1156: if ( ( $target ne 'tex' )
1157: && &Apache::response::show_answer() )
1158: {
1.153.6.1 foxr 1159:
1160: $result = &display_foils_html(
1161: $whichfoils, $target, $direction, $part, $solved, 1);
1.153.6.4 foxr 1162:
1163: # other html
1164: } elsif ($target ne 'tex') {
1165: $result = &display_foils_html($whichfoils, $target, $direction, $part,
1166: 0, 0);
1167:
1168: # LaTeX rendering:
1169: } else {
1.153.6.1 foxr 1170:
1.153 foxr 1171: my $i = 0;
1172: my $bubble_number = 0;
1173: my $line = 0;
1174: my $temp = 0;
1175: my $id = $Apache::inputtags::response['-1'];
1176: my $part = $Apache::inputtags::part;
1177:
1.153.6.4 foxr 1178:
1179:
1180: my $numlines;
1181:
1182: # Decide how to bracket the list of foils:
1.153.6.3 foxr 1183:
1.153.6.4 foxr 1184: my $begin_environment;
1185: my $end_environment;
1.153.6.3 foxr 1186:
1.153.6.4 foxr 1187: if ( $env{'form.pdfFormFields'} eq 'yes'
1188: && $Apache::inputtags::status[-1] eq 'CAN_ANSWER' )
1189: {
1190: $begin_environment = '\begin{itemize}';
1191: $end_environment = '\end{itemize}';
1192: }
1193: else {
1194: $begin_environment = '\begin{enumerate}';
1195: $end_environment = '\end{enumerate}';
1196: }
1197:
1198: # Rendering for latex exams.
1199:
1200: if ( ( $Apache::lonhomework::type eq 'exam' ) )
1201: {
1.153.6.5! foxr 1202: $result .= &display_latex_exam(
! 1203: $whichfoils, $bubbles_per_line, $direction, $begin_environment,
! 1204: $end_environment);
! 1205:
1.153.6.4 foxr 1206: $result .= '\vskip 0mm ';
1.153.6.3 foxr 1207:
1.153.6.4 foxr 1208: } else {
1209:
1210: # Different rendering for PDF form than for a
1211: # 'regular' answer direction is honored in both of those
1212: #
1213:
1214: if ( ($env{'form.pdfFormFields'} eq 'yes')
1215: && ($Apache::inputtags::status[-1] eq 'CAN_ANSWER'))
1.153.6.3 foxr 1216: {
1.153.6.4 foxr 1217: $result .= $begin_environment;
1.153.6.5! foxr 1218: $result .= &display_pdf_form($whichfoils, $direction);
1.153.6.4 foxr 1219: $result .= $end_environment;
1220: } else {
1221: $result .= &display_latex(
1222: $whichfoils, $direction, $begin_environment, $end_environment
1223: );
1.153.6.2 foxr 1224: }
1.153.6.4 foxr 1225: $result .= '\vskip 0 mm ';
1226:
1.153.6.2 foxr 1227: }
1.153.6.4 foxr 1228:
1229:
1.83 albertel 1230: }
1231: return $result;
1.81 albertel 1232: }
1233:
1234: sub displayallanswers {
1.106 albertel 1235: my @names;
1236: if ( $Apache::response::foilgroup{'names'} ) {
1.153 foxr 1237: @names = @{ $Apache::response::foilgroup{'names'} };
1.106 albertel 1238: }
1.153 foxr 1239: my $result = &Apache::response::answer_header('radiobuttonresponse');
1.81 albertel 1240: foreach my $name (@names) {
1.153 foxr 1241: $result .=
1242: &Apache::response::answer_part( 'radiobuttonresponse',
1243: $Apache::response::foilgroup{ $name . '.value' } );
1.81 albertel 1244: }
1.153 foxr 1245: $result .= &Apache::response::answer_footer('radiobuttonresponse');
1.81 albertel 1246: return $result;
1.14 albertel 1247: }
1248:
1.28 albertel 1249: sub displayanswers {
1.153 foxr 1250: my ( $answer, $whichopt, $bubbles_per_line ) = @_;
1.124 albertel 1251: my $result;
1252:
1.153 foxr 1253: if ( $Apache::lonhomework::type eq 'exam' ) {
1254: my $line = int( $answer / $bubbles_per_line );
1255: my $correct = ( 'A' .. 'Z' )[ $answer % $bubbles_per_line ];
1256: $result .=
1257: &Apache::response::answer_header( 'radiobuttonresponse', $line );
1258: $result .=
1259: &Apache::response::answer_part( 'radiobuttonresponse', $correct );
1260: }
1261: else {
1262: $result .= &Apache::response::answer_header('radiobuttonresponse');
1263: }
1264: foreach my $name ( @{$whichopt} ) {
1265: $result .=
1266: &Apache::response::answer_part( 'radiobuttonresponse',
1267: $Apache::response::foilgroup{ $name . '.value' } );
1.105 albertel 1268: }
1.153 foxr 1269: $result .= &Apache::response::answer_footer('radiobuttonresponse');
1.83 albertel 1270: return $result;
1.28 albertel 1271: }
1272:
1.14 albertel 1273: sub start_conceptgroup {
1.153 foxr 1274: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
1275: @_;
1276: $Apache::radiobuttonresponse::conceptgroup = 1;
1277: %Apache::response::conceptgroup = ();
1.83 albertel 1278: my $result;
1.153 foxr 1279: if ( $target eq 'edit' ) {
1280: $result .= &Apache::edit::tag_start( $target, $token );
1281: $result .=
1282: &Apache::edit::text_arg( 'Concept:', 'concept', $token, '50' )
1283: . &Apache::edit::end_row()
1284: . &Apache::edit::start_spanning_row();
1285: }
1286: elsif ( $target eq 'modified' ) {
1287: my $constructtag =
1288: &Apache::edit::get_new_args( $token, $parstack, $safeeval,
1289: 'concept' );
1290: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1.83 albertel 1291: }
1292: return $result;
1.14 albertel 1293: }
1294:
1295: sub end_conceptgroup {
1.153 foxr 1296: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
1297: @_;
1298: $Apache::radiobuttonresponse::conceptgroup = 0;
1.83 albertel 1299: my $result;
1.153 foxr 1300: if ( $target eq 'web'
1301: || $target eq 'grade'
1302: || $target eq 'answer'
1303: || $target eq 'tex'
1304: || $target eq 'analyze' )
1305: {
1306: &Apache::response::pick_foil_for_concept( $target,
1307: [ 'value', 'text', 'location' ],
1308: \%Apache::hint::radiobutton, $parstack, $safeeval );
1309: }
1310: elsif ( $target eq 'edit' ) {
1311: $result = &Apache::edit::end_table();
1.83 albertel 1312: }
1313: return $result;
1.26 albertel 1314: }
1315:
1316: sub insert_conceptgroup {
1.153 foxr 1317: my $result =
1318: "\n\t\t<conceptgroup concept=\"\">"
1319: . &insert_foil()
1320: . "\n\t\t</conceptgroup>\n";
1.83 albertel 1321: return $result;
1.1 albertel 1322: }
1323:
1324: sub start_foil {
1.153 foxr 1325: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
1326: @_;
1327: my $result = '';
1328: if ( $target eq 'web' || $target eq 'tex' || $target eq 'analyze' ) {
1329: &Apache::lonxml::startredirection;
1330: if ( $target eq 'analyze' ) {
1331: &Apache::response::check_if_computed( $token, $parstack, $safeeval,
1332: 'value' );
1333: }
1334: }
1335: elsif ( $target eq 'edit' ) {
1336: $result = &Apache::edit::tag_start( $target, $token );
1337: $result .= &Apache::edit::text_arg( 'Name:', 'name', $token );
1338: $result .= &Apache::edit::select_or_text_arg(
1339: 'Correct Option:', 'value',
1340: [ 'unused', 'true', 'false' ], $token
1341: );
1342: my $randomize =
1343: &Apache::lonxml::get_param( 'randomize', $parstack, $safeeval, '-3' );
1344: if ( $randomize ne 'no' ) {
1345: $result .=
1346: &Apache::edit::select_arg( 'Location:', 'location',
1347: [ 'random', 'top', 'bottom' ], $token );
1348: }
1349: $result .=
1350: &Apache::edit::end_row() . &Apache::edit::start_spanning_row();
1351: }
1352: elsif ( $target eq 'modified' ) {
1353: my $constructtag =
1354: &Apache::edit::get_new_args( $token, $parstack, $safeeval, 'value',
1355: 'name', 'location' );
1356: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1357: }
1.83 albertel 1358: return $result;
1.1 albertel 1359: }
1360:
1361: sub end_foil {
1.153 foxr 1362: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
1363: @_;
1364: my $text = '';
1365: if ( $target eq 'web' || $target eq 'tex' || $target eq 'analyze' ) {
1366: $text = &Apache::lonxml::endredirection;
1367: }
1368: if ( $target eq 'web'
1369: || $target eq 'grade'
1370: || $target eq 'answer'
1371: || $target eq 'tex'
1372: || $target eq 'analyze' )
1373: {
1374: my $value = &Apache::lonxml::get_param( 'value', $parstack, $safeeval );
1375: if ( $value ne 'unused' ) {
1376: my $name =
1377: &Apache::lonxml::get_param( 'name', $parstack, $safeeval );
1378: if ( $name eq "" ) {
1379: &Apache::lonxml::warning(
1380: &mt(
1381: 'Foils without names exist. This can cause problems to malfunction.'
1382: )
1383: );
1384: $name = $Apache::lonxml::curdepth;
1385: }
1386: if ( defined( $Apache::response::foilnames{$name} ) ) {
1387: &Apache::lonxml::error(
1388: &mt(
1389: 'Foil name [_1] appears more than once. Foil names need to be unique.',
1390: '<b><tt>' . $name . '</tt></b>'
1391: )
1392: );
1393: }
1394: $Apache::response::foilnames{$name}++;
1395: my $location =
1396: &Apache::lonxml::get_param( 'location', $parstack, $safeeval );
1397: if ( $Apache::radiobuttonresponse::conceptgroup
1398: && !&Apache::response::showallfoils() )
1399: {
1400: push @{ $Apache::response::conceptgroup{'names'} }, $name;
1401: $Apache::response::conceptgroup{"$name.value"} = $value;
1402: $Apache::response::conceptgroup{"$name.text"} = $text;
1403: $Apache::response::conceptgroup{"$name.location"} = $location;
1404: }
1405: else {
1406: push @{ $Apache::response::foilgroup{'names'} }, $name;
1407: $Apache::response::foilgroup{"$name.value"} = $value;
1408: $Apache::response::foilgroup{"$name.text"} = $text;
1409: $Apache::response::foilgroup{"$name.location"} = $location;
1410: }
1411: }
1.18 albertel 1412: }
1.83 albertel 1413: return '';
1.1 albertel 1414: }
1415:
1.27 albertel 1416: sub insert_foil {
1.83 albertel 1417: return '
1.27 albertel 1418: <foil name="" value="unused">
1419: <startouttext />
1420: <endouttext />
1421: </foil>';
1422: }
1.151 raeburn 1423:
1.1 albertel 1424: 1;
1425: __END__
1.139 jms 1426:
1427:
1428:
1429: =head1 NAME
1430:
1431: Apache::radiobuttonresponse
1432:
1433: =head1 SYNOPSIS
1434:
1435: Handles multiple-choice style responses.
1436:
1437: This is part of the LearningOnline Network with CAPA project
1438: described at http://www.lon-capa.org.
1439:
1440: =head1 SUBROUTINES
1441:
1442: =over
1443:
1444: =item start_radiobuttonresponse()
1445:
1446: =item bubble_line_count()
1447:
1448: =item end_radiobuttonresponse()
1449:
1450: =item start_foilgroup()
1451:
1452: =item storesurvey()
1453:
1454: =item grade_response()
1455:
1456: =item end_foilgroup()
1457:
1458: =item getfoilcounts()
1459:
1460: =item format_prior_answer()
1461:
1462: =item displayallfoils()
1463:
1464: =item &whichfoils($max,$randomize)
1465:
1466: Randomizes the list of foils.
1467: Respects
1468: - each foils desire to be randomized
1469: - the existance of Concept groups of foils (select 1 foil from each)
1470: - and selects a single correct statement from all possilble true statments
1471: - and limits it to a toal of $max foils
1472:
1473: WARNING: this routine uses the random number generator, it should only
1474: be called once per target, otherwise it can cause randomness changes in
1475: homework problems.
1476:
1477: Arguments
1478: $max - maximum number of foils to select (including the true one)
1479: (so a max of 5 is: 1 true, 4 false)
1480:
1481: $randomize - whether to randomize the listing of foils, by default
1482: will randomize, only if randomize is 'no' will it not
1483:
1484: Returns
1485: $answer - location in the array of the correct answer
1486: @foils - array of foil names in to display order
1487:
1488: =item displayfoils()
1489:
1490: =item displayallanswers()
1491:
1492: =item displayanswers()
1493:
1494: =item start_conceptgroup()
1495:
1496: =item end_conceptgroup()
1497:
1498: =item insert_conceptgroup()
1499:
1500: =item start_foil()
1501:
1502: =item end_foil()
1503:
1504: =item insert_foil()
1505:
1506: =back
1507:
1508: =cut
1.1 albertel 1509:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>