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