1: # The LearningOnline Network with CAPA
2: # mutliple choice style responses
3: #
4: # $Id: radiobuttonresponse.pm,v 1.153.6.6 2012/01/25 11:37:32 foxr Exp $
5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: #
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27:
28: package Apache::radiobuttonresponse;
29: use strict;
30: use HTML::Entities();
31: use Apache::lonlocal;
32: use Apache::lonnet;
33: use Apache::response;
34: use Apache::caparesponse;
35:
36: my $default_bubbles_per_line = 10;
37: my @alphabet = ( 'A' .. 'Z' ); # Foil labels.
38:
39:
40:
41: BEGIN {
42: &Apache::lonxml::register( 'Apache::radiobuttonresponse',
43: ('radiobuttonresponse') );
44: }
45:
46: sub bubble_line_count {
47: my ( $numfoils, $bubbles_per_line ) = @_;
48: my $bubble_lines;
49: $bubble_lines = int( $numfoils / $bubbles_per_line );
50: if ( ( $numfoils % $bubbles_per_line ) != 0 ) {
51: $bubble_lines++;
52: }
53: return $bubble_lines;
54:
55: }
56:
57: sub start_radiobuttonresponse {
58: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
59: @_;
60: my $result;
61:
62: #when in a radiobutton response use these
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 );
67:
68: %Apache::hint::radiobutton = ();
69: undef(%Apache::response::foilnames);
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: }
125:
126: }
127: elsif ( $target eq 'analyze' ) {
128: my $part_id = "$Apache::inputtags::part.$id";
129: $Apache::lonhomework::analyze{"$part_id.type"} = 'radiobuttonresponse';
130: push( @{ $Apache::lonhomework::analyze{"parts"} }, $part_id );
131: }
132: return $result;
133: }
134:
135: sub end_radiobuttonresponse {
136: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
137: @_;
138: my $result;
139: if ( $target eq 'edit' ) { $result = &Apache::edit::end_table(); }
140:
141: &Apache::response::end_response;
142: pop @Apache::lonxml::namespace;
143: &Apache::lonxml::deregister( 'Apache::radiobuttonresponse',
144: ( 'foilgroup', 'foil', 'conceptgroup' ) );
145: undef(%Apache::response::foilnames);
146: return $result;
147: }
148:
149: %Apache::response::foilgroup = ();
150:
151: sub start_foilgroup {
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 );
157: return;
158: }
159:
160: sub storesurvey {
161: my ($style) = @_;
162: if ( !&Apache::response::submitted() ) { return ''; }
163: my $response = $env{ 'form.HWVAL_' . $Apache::inputtags::response['-1'] };
164: &Apache::lonxml::debug("Here I am!:$response:");
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'} };
169: my %responsehash;
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 );
176: my $ad;
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';
193: }
194: &Apache::response::handle_previous( \%previous, $ad );
195: &Apache::lonxml::debug("submitted a $response<br />\n");
196: return '';
197: }
198:
199: sub grade_response {
200: my ( $answer, $whichfoils, $bubbles_per_line ) = @_;
201:
202: if ( !&Apache::response::submitted() ) { return; }
203: my $response;
204:
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'] };
214: }
215:
216: if ( $response !~ /[0-9]+/ ) { return; }
217: my $part = $Apache::inputtags::part;
218: my $id = $Apache::inputtags::response['-1'];
219: my %responsehash;
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;
226: &Apache::lonxml::debug("submitted a $response<br />\n");
227: my $ad;
228:
229: if ( $response == $answer ) {
230: $ad = 'EXACT_ANS';
231: }
232: else {
233: $ad = 'INCORRECT';
234: }
235: $Apache::lonhomework::results{"resource.$part.$id.awarddetail"} = $ad;
236: &Apache::response::handle_previous( \%previous, $ad );
237: }
238:
239: sub end_foilgroup {
240: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
241: @_;
242:
243: my $result;
244: my $bubble_lines;
245: my $answer_count;
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: );
315:
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 ] );
323: }
324: &Apache::response::poprandomnumber();
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();
329: }
330: return $result;
331: }
332:
333: sub getbubblesnum {
334: my ( $part, $id ) = @_;
335: my $bubbles_per_line;
336: my $default_numbubbles = $default_bubbles_per_line;
337: if ( ( $env{'form.bubbles_per_row'} =~ /^\d+$/ )
338: && ( $env{'form.bubbles_per_row'} > 0 ) )
339: {
340: $default_numbubbles = $env{'form.bubbles_per_row'};
341: }
342: $bubbles_per_line = &Apache::response::get_response_param( $part . "_$id",
343: 'numbubbles', $default_numbubbles );
344: return $bubbles_per_line;
345: }
346:
347: sub getfoilcounts {
348: my @names;
349: my $truecnt = 0;
350: my $falsecnt = 0;
351: my $name;
352: if ( $Apache::response::foilgroup{'names'} ) {
353: @names = @{ $Apache::response::foilgroup{'names'} };
354: }
355: foreach $name (@names) {
356: if ( $Apache::response::foilgroup{ $name . '.value' } eq 'true' ) {
357: $truecnt++;
358: }
359: elsif ( $Apache::response::foilgroup{ $name . '.value' } eq 'false' ) {
360: $falsecnt++;
361: }
362: }
363: return ( $truecnt, $falsecnt );
364: }
365:
366: sub format_prior_answer {
367: my ( $mode, $answer, $other_data ) = @_;
368: my $foil_data = $other_data->[0];
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>';
375:
376: }
377:
378: ##
379: sub displayallfoils{
380: my ( $direction, $target ) = @_;
381: my $result;
382: &Apache::lonxml::debug("survey style display");
383: my @names;
384: if ( $Apache::response::foilgroup{'names'} ) {
385: @names = @{ $Apache::response::foilgroup{'names'} };
386: }
387:
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:
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: {
432: $newvariation = 1;
433: }
434: }
435: $showanswer = &Apache::response::show_answer();
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"};
451: }
452: if ( $direction eq 'horizontal' ) { $result .= '<table><tr>'; }
453: my %lastresponse = &Apache::lonnet::str2hash($lastresponse);
454: if ($showanswer) {
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 {
514: $result .= '\item \vskip -2mm ';
515: }
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
535: onchange=\"javascript:setSubmittedPart('$part');\"
536: type=\"radio\"
537: name=\"HWVAL_$Apache::inputtags::response['-1']\"
538: value=\"$temp\"";
539:
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>';
564: }
565:
566: # Close tex bracketing:
567:
568: if ($target eq 'tex') {
569: $result .= $end_environment;
570: }
571: return $result;
572: }
573:
574:
575:
576: sub whichfoils {
577: my ( $max, $randomize ) = @_;
578:
579: my @truelist;
580: my @falselist;
581: my @whichfalse = ();
582: my ( $truecnt, $falsecnt ) = &getfoilcounts();
583: my $count = 0;
584:
585: # we will add in 1 of the true statements
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) );
589: &Apache::lonxml::debug("Count is $count, $answer is $answer");
590: my @names;
591: if ( $Apache::response::foilgroup{'names'} ) {
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: }
635: }
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 ) {
763: my $inc = 1;
764: if ( ( $bottomcount > 0 )
765: && ( $Apache::lonhomework::type ne 'exam' ) )
766: {
767: $inc = 2;
768: }
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: }
788: }
789: &Apache::lonxml::debug("Answer is $answer");
790: return ( $answer, @whichfalse );
791: }
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:
811: ##
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: }
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: }
880:
881: ##
882: # Display foils in html rendition.:
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 {
951: $result .= '<br />'; # end line prior to foilgroup:
952:
953: # Not showing the answers, we need to generate the HTML appropriate
954: # to allowing the student to respond.
955:
956: my $item_pretext;
957: my $item_posttext;
958: my $lastresponse = &get_last_response($part);
959:
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: }
983: }
984:
985: return $result;
986: }
987: ##
988: # Display foils in exam mode for latex
989: #
990: # @param $whichfoils - Reference to an array that contains the foil names to display
991: # @param $bubbles_per_line - Number of bubbles on a line.
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.
995: #
996: # @return string
997: # @return the latex rendering of the exam problem.
998: #
999: #
1000: sub display_latex_exam {
1001: my ($whichfoils, $bubbles_per_line, $direction, $vbegin, $vend) = @_;
1002: my $result;
1003: my $numlines;
1004: my $bubble_number = 0;
1005: my $line = 0;
1006: my $i = 0;
1007:
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:
1014: my @foil_texts = &get_foil_texts($whichfoils);
1015: $result .= &Apache::caparesponse::make_horizontal_latex_bubbles(
1016: $whichfoils, \@foil_texts, '$\bigcirc$');
1017:
1018:
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;
1033: }
1034: if ( $numlines > 1 ) {
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} \\\\';
1046: }
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
1075:
1076: }
1077:
1078: return $result;
1079:
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:
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.
1102:
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: }
1113:
1114: $result .= $vend;
1115: }
1116: return $result;
1117: }
1118:
1119:
1120: ##
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.
1174:
1175: sub displayfoils {
1176: my ( $target, $answer, $whichfoils, $direction, $bubbles_per_line ) = @_;
1177: my $result;
1178:
1179: my $part = $Apache::inputtags::part;
1180: my $solved = $Apache::lonhomework::history{"resource.$part.solved"};
1181:
1182: # Show answers html.
1183:
1184: if ( ( $target ne 'tex' )
1185: && &Apache::response::show_answer() )
1186: {
1187:
1188: $result = &display_foils_html(
1189: $whichfoils, $target, $direction, $part, $solved, 1);
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 {
1198:
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:
1206:
1207:
1208: my $numlines;
1209:
1210: # Decide how to bracket the list of foils:
1211:
1212: my $begin_environment;
1213: my $end_environment;
1214:
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: {
1230: $result .= &display_latex_exam(
1231: $whichfoils, $bubbles_per_line, $direction, $begin_environment,
1232: $end_environment);
1233:
1234: $result .= '\vskip 0mm ';
1235:
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'))
1244: {
1245: $result .= $begin_environment;
1246: $result .= &display_pdf_form($whichfoils, $direction);
1247: $result .= $end_environment;
1248: } else {
1249: $result .= &display_latex(
1250: $whichfoils, $direction, $begin_environment, $end_environment
1251: );
1252: }
1253: $result .= '\vskip 0 mm ';
1254:
1255: }
1256:
1257:
1258: }
1259: return $result;
1260: }
1261:
1262: sub displayallanswers {
1263: my @names;
1264: if ( $Apache::response::foilgroup{'names'} ) {
1265: @names = @{ $Apache::response::foilgroup{'names'} };
1266: }
1267: my $result = &Apache::response::answer_header('radiobuttonresponse');
1268: foreach my $name (@names) {
1269: $result .=
1270: &Apache::response::answer_part( 'radiobuttonresponse',
1271: $Apache::response::foilgroup{ $name . '.value' } );
1272: }
1273: $result .= &Apache::response::answer_footer('radiobuttonresponse');
1274: return $result;
1275: }
1276:
1277: sub displayanswers {
1278: my ( $answer, $whichopt, $bubbles_per_line ) = @_;
1279: my $result;
1280:
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' } );
1296: }
1297: $result .= &Apache::response::answer_footer('radiobuttonresponse');
1298: return $result;
1299: }
1300:
1301: sub start_conceptgroup {
1302: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
1303: @_;
1304: $Apache::radiobuttonresponse::conceptgroup = 1;
1305: %Apache::response::conceptgroup = ();
1306: my $result;
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); }
1319: }
1320: return $result;
1321: }
1322:
1323: sub end_conceptgroup {
1324: my ( $target, $token, $tagstack, $parstack, $parser, $safeeval, $style ) =
1325: @_;
1326: $Apache::radiobuttonresponse::conceptgroup = 0;
1327: my $result;
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();
1340: }
1341: return $result;
1342: }
1343:
1344: sub insert_conceptgroup {
1345: my $result =
1346: "\n\t\t<conceptgroup concept=\"\">"
1347: . &insert_foil()
1348: . "\n\t\t</conceptgroup>\n";
1349: return $result;
1350: }
1351:
1352: sub start_foil {
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: }
1386: return $result;
1387: }
1388:
1389: sub end_foil {
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: }
1440: }
1441: return '';
1442: }
1443:
1444: sub insert_foil {
1445: return '
1446: <foil name="" value="unused">
1447: <startouttext />
1448: <endouttext />
1449: </foil>';
1450: }
1451:
1452: 1;
1453: __END__
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
1537:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>