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