Annotation of loncom/homework/matchresponse.pm, revision 1.49
1.1 albertel 1: # The LearningOnline Network with CAPA
2: # Full matching style response
3: #
1.49 ! albertel 4: # $Id: matchresponse.pm,v 1.48 2004/12/04 00:41:26 albertel Exp $
1.1 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
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28:
29: package Apache::matchresponse;
30: use strict;
31: use HTML::Entities();
32: use Math::Random();
1.37 albertel 33: use Apache::optionresponse();
34: use Apache::lonlocal;
1.6 sakharuk 35:
1.1 albertel 36: BEGIN {
37: &Apache::lonxml::register('Apache::matchresponse',('matchresponse'));
38: }
39:
40: sub start_matchresponse {
41: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
42: my $result;
43: #when in a matchresponse use these
44: &Apache::lonxml::register('Apache::matchresponse',
45: ('foilgroup','foil','conceptgroup','item',
46: 'itemgroup'));
47: push (@Apache::lonxml::namespace,'matchresponse');
48: my $id = &Apache::response::start_response($parstack,$safeeval);
49: %Apache::hint::match=();
1.37 albertel 50: undef(%Apache::response::foilnames);
1.1 albertel 51: if ($target eq 'meta') {
52: $result=&Apache::response::meta_package_write('matchresponse');
53: } elsif ($target eq 'edit' ) {
54: $result.=&Apache::edit::start_table($token).
55: '<tr><td>'.&Apache::lonxml::description($token)."</td><td>Delete:".
56: &Apache::edit::deletelist($target,$token)
57: ."</td><td> ".&Apache::edit::end_row()
58: .&Apache::edit::start_spanning_row();
59:
60: $result.=
61: &Apache::edit::text_arg('Max Number Of Shown Foils:','max',$token,'4').
62: &Apache::edit::select_arg('Randomize Foil Order','randomize',
63: ['yes','no'],$token).
64: &Apache::edit::end_row().&Apache::edit::start_spanning_row()."\n";
65: } elsif ($target eq 'modified') {
66: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
67: $safeeval,'max',
68: 'randomize');
69: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1.28 albertel 70: } elsif ($target eq 'analyze') {
71: my $part_id="$Apache::inputtags::part.$id";
72: push (@{ $Apache::lonhomework::analyze{"parts"} },$part_id);
1.1 albertel 73: }
74: return $result;
75: }
76:
77: sub end_matchresponse {
78: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
79: my $result;
80: if ($target eq 'edit') { $result=&Apache::edit::end_table(); }
81: &Apache::response::end_response;
82: pop @Apache::lonxml::namespace;
83: &Apache::lonxml::deregister('Apache::matchresponse',
84: ('foilgroup','foil','conceptgroup'));
1.37 albertel 85: undef(%Apache::response::foilnames);
1.1 albertel 86: return $result;
87: }
88:
89: %Apache::response::itemgroup=();
90: sub start_itemgroup {
91: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
92: my $result;
93: %Apache::response::itemgroup=();
1.4 albertel 94: %Apache::matchresponse::itemtable=();
1.15 albertel 95:
1.1 albertel 96: if ($target eq 'edit') {
97: $result=&Apache::edit::tag_start($target,$token);
98: $result.=&Apache::edit::select_arg('Randomize Order:','randomize',
99: ['yes','no'],$token);
1.4 albertel 100: $result.=&Apache::edit::select_arg('Items Display Location:',
101: 'location',
102: ['top','bottom','left','right'],
103: $token);
1.1 albertel 104: $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
1.4 albertel 105: } elsif ($target eq 'modified') {
106: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
107: $safeeval,'randomize',
108: 'location');
109: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1.21 sakharuk 110: } elsif ($target eq 'web' or $target eq 'tex') {
1.4 albertel 111: $Apache::matchresponse::itemtable{'location'}=
112: &Apache::lonxml::get_param('location',$parstack,$safeeval);
1.43 sakharuk 113: $Apache::matchresponse::TeXitemgroupwidth=&Apache::lonxml::get_param('TeXitemgroupwidth',$parstack,$safeeval,undef,0);
1.1 albertel 114: }
115: return $result;
116: }
117:
118: sub end_itemgroup {
119: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
120: my $result;
121:
1.17 albertel 122: if ($target eq 'edit') { $result=&Apache::edit::end_table(); }
1.1 albertel 123: if (!defined(@{ $Apache::response::itemgroup{'names'} })) { return; }
124: my @names=@{ $Apache::response::itemgroup{'names'} };
125: my $randomize =&Apache::lonxml::get_param('randomize',$parstack,$safeeval);
1.2 albertel 126: if ($randomize ne 'no' ) {
1.18 albertel 127: @names=&Apache::response::whichorder($#names+1,$randomize,0,
128: \%Apache::response::itemgroup);
1.1 albertel 129: }
1.30 albertel 130: if ($target eq 'analyze') {
131: my $partid="$Apache::inputtags::part.$Apache::inputtags::response[-1]";
132: push (@{ $Apache::lonhomework::analyze{"$partid.items"} }, @names);
133: }
1.1 albertel 134: my %letter_name_map;
135: my %name_letter_map;
136: my @alphabet=('A'..'Z');
137: my $i=0;
138: foreach my $name (@names) {
139: $letter_name_map{$alphabet[$i]}=$name;
140: $name_letter_map{$name}=$alphabet[$i];
141: $i++;
142: }
1.15 albertel 143: $Apache::response::itemgroup{'letter_name_map'}=\%letter_name_map;
1.1 albertel 144: $Apache::response::itemgroup{'name_letter_map'}=\%name_letter_map;
145: if ($target eq 'web') {
1.4 albertel 146: my $table='<table>';
1.1 albertel 147: my $i=0;
148: foreach my $name (@names) {
1.4 albertel 149: $table.='<tr><td>'.$alphabet[$i].'</td><td>'.
1.1 albertel 150: $Apache::response::itemgroup{$name.'.text'}.
151: '</td></tr>';
152: $i++;
153: }
1.4 albertel 154: $table.='</table>';
155: $Apache::matchresponse::itemtable{'display'}=$table;
1.5 sakharuk 156: } elsif ($target eq 'tex') {
1.39 sakharuk 157: my $table=' \begin{description}\setlength{\leftmargin}{2em}\setlength{\labelwidth}{1em}\setlength{\itemsep}{0.5pt plus1pt minus2pt}\setlength{\listparindent}{0em} ';
1.5 sakharuk 158: my $i=0;
159: foreach my $name (@names) {
1.11 sakharuk 160: $Apache::response::itemgroup{$name.'.text'}=~s/\$\$/\$/g;
1.19 sakharuk 161: $table.='\item['.$alphabet[$i].'] '.
1.21 sakharuk 162: $Apache::response::itemgroup{$name.'.text'};
1.5 sakharuk 163: $i++;
164: }
1.40 sakharuk 165: $table.=' \end{description} \strut ';
166: if ($Apache::lonhomework::type eq 'exam') {$table.='\vskip -13 mm \strut ';}
1.5 sakharuk 167: $Apache::matchresponse::itemtable{'display'}=$table;
1.17 albertel 168: }
1.1 albertel 169: return $result;
170: }
171:
172: sub start_item {
173: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
174: my $result='';
1.30 albertel 175: if ($target eq 'web' || $target eq 'tex' || $target eq 'analyze') {
1.1 albertel 176: &Apache::lonxml::startredirection;
177: } elsif ($target eq 'edit') {
1.3 albertel 178: my $randomize=&Apache::lonxml::get_param('randomize',$parstack,
179: $safeeval,'-2');
1.1 albertel 180: $result=&Apache::edit::tag_start($target,$token,"Item");
181: $result.=&Apache::edit::text_arg('Name:','name',$token);
1.3 albertel 182: if ($randomize ne 'no') {
183: $result.=&Apache::edit::select_arg('Location:','location',
184: ['random','top','bottom'],
185: $token);
186: }
187: $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
1.1 albertel 188: } elsif ($target eq 'modified') {
189: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
1.3 albertel 190: $safeeval,'name',
191: 'location');
1.1 albertel 192: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
193: }
194: return $result;
195: }
196:
197: sub end_item {
198: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
199: my $text ='';
200: my $result = '';
1.30 albertel 201: if ($target eq 'web' || $target eq 'tex' || $target eq 'analyze') {
1.1 albertel 202: $text=&Apache::lonxml::endredirection;
203: }
204: if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' ||
1.30 albertel 205: $target eq 'edit' || $target eq 'tex' || $target eq 'analyze') {
1.1 albertel 206: my $name = &Apache::lonxml::get_param('name',$parstack,$safeeval);
1.3 albertel 207: my $location=&Apache::lonxml::get_param('location',$parstack,
208: $safeeval);
1.1 albertel 209: &Apache::lonxml::debug("Got a name of :$name:");
210: if (!$name) { $name=$Apache::lonxml::curdepth; }
211: &Apache::lonxml::debug("Using a name of :$name:");
212: push @{ $Apache::response::itemgroup{'names'} }, $name;
213: $Apache::response::itemgroup{"$name.text"} = $text;
1.3 albertel 214: $Apache::response::itemgroup{"$name.location"} = $location;
1.1 albertel 215: }
216: if ($target eq 'edit') {
217: $result.= &Apache::edit::tag_end($target,$token,'');
218: }
219: return $result;
220: }
221:
222: sub insert_item {
223: return '
224: <item name="">
225: <startouttext />
226: <endouttext />
227: </item>';
228: }
229:
230: %Apache::response::foilgroup=();
231: sub start_foilgroup {
232: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
233: my $result;
234: %Apache::response::foilgroup=();
235: $Apache::matchresponse::conceptgroup=0;
1.41 albertel 236: &Apache::response::pushrandomnumber();
1.1 albertel 237: if ($target eq 'edit') {
238: $result.=&Apache::edit::start_table($token)
239: ."<tr><td>Collection Of Foils</td><td>Delete:"
240: .&Apache::edit::deletelist($target,$token)
241: ."</td><td> ".&Apache::edit::end_row()
242: .&Apache::edit::start_spanning_row()."\n";
243: }
244: return $result;
245: }
246:
247: sub end_foilgroup {
248: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
249: my $result;
1.28 albertel 250: if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' || $target eq 'tex' || $target eq 'analyze') {
1.1 albertel 251: my $max = &Apache::lonxml::get_param('max',$parstack,$safeeval,'-2');
252: my $randomize = &Apache::lonxml::get_param('randomize',$parstack,
253: $safeeval,'-2');
1.5 sakharuk 254: if ($target eq 'web' || $target eq 'tex') {
1.1 albertel 255: $result=&displayfoils($target,$max,$randomize);
256: } elsif ($target eq 'answer' ) {
257: $result=&displayanswers($max,$randomize);
258: } elsif ( $target eq 'grade') {
259: &grade_response($max,$randomize);
1.28 albertel 260: } elsif ( $target eq 'analyze') {
261: my @shown=&whichfoils($max,$randomize);
262: &Apache::response::analyze_store_foilgroup(\@shown,
1.29 albertel 263: ['text','value','location']);
1.28 albertel 264: #FIXME need to store options in some way
1.1 albertel 265: }
1.20 sakharuk 266: &Apache::lonxml::increment_counter(&getfoilcounts($max));
1.1 albertel 267: } elsif ($target eq 'edit') {
268: $result=&Apache::edit::end_table();
269: }
1.41 albertel 270: &Apache::response::poprandomnumber();
1.1 albertel 271: return $result;
1.29 albertel 272: }
273:
274: sub whichfoils {
275: my ($max,$randomize)=@_;
276: return &Apache::response::whichorder(&getfoilcounts($max),
277: $randomize,
278: &Apache::response::showallfoils(),
279: \%Apache::response::foilgroup);
1.1 albertel 280: }
281:
282: sub displayanswers {
283: my ($max,$randomize,@opt)=@_;
284: if (!defined(@{ $Apache::response::foilgroup{'names'} })) { return; }
285: my @names = @{ $Apache::response::foilgroup{'names'} };
1.18 albertel 286: my @whichfoils = &Apache::response::whichorder(&getfoilcounts($max),
287: $randomize,
288: &Apache::response::showallfoils(),
289: \%Apache::response::foilgroup);
1.1 albertel 290: my $result=&Apache::response::answer_header('matchresponse');
291: my %name_letter_map;
292: if (defined(%{ $Apache::response::itemgroup{'name_letter_map'} })) {
293: %name_letter_map=
294: %{ $Apache::response::itemgroup{'name_letter_map'} };
295: }
296: foreach my $name (@whichfoils) {
297: my $value_name=$Apache::response::foilgroup{$name.'.value'};
298: my $letter=$name_letter_map{$value_name};
299: $result.=&Apache::response::answer_part('matchresponse',$letter);
300: }
301: $result.=&Apache::response::answer_footer('matchresponse');
302: return $result;
303: }
304:
305:
306: sub grade_response {
307: my ($max,$randomize)=@_;
1.18 albertel 308: my (@whichfoils)=&Apache::response::whichorder(&getfoilcounts($max),
309: $randomize,
310: &Apache::response::showallfoils(),
311: \%Apache::response::foilgroup);
1.1 albertel 312: if (!defined($ENV{'form.submitted'})) { return; }
313: my %responsehash;
314: my %grade;
1.33 albertel 315: my ($temp,$right,$wrong,$ignored)=(1,0,0,0);
1.1 albertel 316: my %letter_name_map;
317: if (defined(%{ $Apache::response::itemgroup{'letter_name_map'} })) {
318: %letter_name_map=
319: %{ $Apache::response::itemgroup{'letter_name_map'} };
320: }
1.30 albertel 321: my @items;
1.1 albertel 322: foreach my $name (@whichfoils) {
1.34 albertel 323: my $response = &Apache::response::getresponse($temp,'letter');
1.30 albertel 324: push(@items,$response);
1.1 albertel 325: my $responsename = $letter_name_map{$response};
326: my $value=$Apache::response::foilgroup{$name.'.value'};
327: if ( $response =~ /[^\s]/) {
1.31 albertel 328: $responsehash{$name}=$responsename;
1.33 albertel 329: &Apache::lonxml::debug("submitted a $response($responsename) for $value<br />\n");
1.1 albertel 330: if ($value eq $responsename) {
331: $grade{$name}='1'; $right++;
332: } else {
333: $grade{$name}='0'; $wrong++;
334: }
335: } else {
336: $ignored++;
337: }
338: $temp++;
339: }
340: my $part=$Apache::inputtags::part;
341: my $id = $Apache::inputtags::response['-1'];
342: my $responsestr=&Apache::lonnet::hash2str(%responsehash);
1.30 albertel 343: my $itemstr =&Apache::lonnet::array2str(@items);
1.1 albertel 344: my $gradestr =&Apache::lonnet::hash2str(%grade);
1.30 albertel 345: my %previous=&Apache::response::check_for_previous($responsestr,$part,$id);
1.1 albertel 346: &Apache::lonxml::debug("Got $right right and $wrong wrong, and $ignored were ignored ");
347: $Apache::lonhomework::results{"resource.$part.$id.submission"}=
348: $responsestr;
1.30 albertel 349: $Apache::lonhomework::results{"resource.$part.$id.submissionitems"}=
350: $itemstr;
1.1 albertel 351: $Apache::lonhomework::results{"resource.$part.$id.submissiongrading"}=
352: $gradestr;
1.47 albertel 353: if ($Apache::lonhomework::type eq 'survey') {
354: if ($ignored == 0) {
355: my $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='SUBMITTED';
356: &Apache::response::handle_previous(\%previous,$ad);
357: } elsif ($wrong==0 && $right==0) {
358: } else {
359: my $ad=$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}='MISSING_ANSWER';
360: &Apache::response::handle_previous(\%previous,$ad);
361: }
362: } elsif (!$Apache::lonhomework::scantronmode) {
1.34 albertel 363: my $ad;
364: if ($wrong==0 && $ignored==0) {
365: $ad='EXACT_ANS';
366: } elsif ($wrong==0 && $right==0) {
367: #nothing submitted
368: } else {
369: if ($ignored==0) {
370: $ad='INCORRECT';
371: } else {
372: $ad='MISSING_ANSWER';
373: }
374: }
375: $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
376: &Apache::response::handle_previous(\%previous,$ad);
377: } else {
378: my $ad;
379: if ($wrong==0 && $right==0) {
380: #nothing submitted
381: } else {
382: $ad='ASSIGNED_SCORE';
383: $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=
384: $ad;
385: $Apache::lonhomework::results{"resource.$part.$id.awarded"}=
1.35 albertel 386: $right/(scalar(@whichfoils));
1.34 albertel 387: $Apache::lonhomework::results{"resource.$part.$id.numfoils"}=
1.35 albertel 388: scalar(@whichfoils);
1.34 albertel 389: }
390: }
1.1 albertel 391: }
392:
1.4 albertel 393: sub itemdisplay {
394: my ($location)=@_;
395: if ($location eq 'top' &&
396: !defined($Apache::matchresponse::itemtable{'location'})) {
397: return $Apache::matchresponse::itemtable{'display'};
398: }
399: if ($Apache::matchresponse::itemtable{'location'} eq $location) {
400: return $Apache::matchresponse::itemtable{'display'};
401: }
402: return undef;
403: }
1.1 albertel 404: sub displayfoils {
405: my ($target,$max,$randomize)=@_;
406: my $result;
1.4 albertel 407: my $question;
1.18 albertel 408: my (@whichfoils)=&Apache::response::whichorder(&getfoilcounts($max),
409: $randomize,
410: &Apache::response::showallfoils(),
411: \%Apache::response::foilgroup);
1.1 albertel 412: my $part=$Apache::inputtags::part;
413: my $solved=$Apache::lonhomework::history{"resource.$part.solved"};
414: my %letter_name_map;
415: if (defined(%{ $Apache::response::itemgroup{'letter_name_map'} })) {
416: %letter_name_map=
417: %{ $Apache::response::itemgroup{'letter_name_map'} };
418: }
419: my %name_letter_map;
420: if (defined(%{ $Apache::response::itemgroup{'name_letter_map'} })) {
421: %name_letter_map=
422: %{ $Apache::response::itemgroup{'name_letter_map'} };
423: }
1.25 albertel 424: if ( &Apache::response::show_answer() && ($target ne 'tex')) {
1.1 albertel 425: foreach my $name (@whichfoils) {
426: my $text=$Apache::response::foilgroup{$name.'.text'};
427: my $value=$Apache::response::foilgroup{$name.'.value'};
428: my $letter=$name_letter_map{$value};
1.5 sakharuk 429: if ($target eq 'tex') {
430: $question.=' \\\\ '.$letter.':'.$text;
431: } else {
432: $question.='<br />'.$letter.':'.$text;
433: }
1.1 albertel 434: }
435: } else {
436: my $i = 0;
1.36 albertel 437: my $temp=1;
1.1 albertel 438: my $id=$Apache::inputtags::response[-1];
439: my $part=$Apache::inputtags::part;
440: my $lastresponse=$Apache::lonhomework::history{"resource.$part.$id.submission"};
1.9 sakharuk 441: my %lastresponse=&Apache::lonnet::str2hash($lastresponse);
442: my @alphabet=('A'..'Z');
1.15 albertel 443: my @used_letters=sort(keys(%letter_name_map));
1.20 sakharuk 444: my $internal_counter=$Apache::lonxml::counter;
1.1 albertel 445: foreach my $name (@whichfoils) {
446: my $lastopt=$lastresponse{$name};
447: my $last_letter=$name_letter_map{$lastopt};
1.5 sakharuk 448: my $optionlist = '';
1.7 sakharuk 449: if ($target ne 'tex') {
450: $optionlist="<option></option>\n";
451: } else {
452: if ($Apache::lonhomework::type ne 'exam') {
453: $optionlist='\framebox[5 mm][s]{\tiny\strut}';
454: }
455: }
1.1 albertel 456: my $option;
1.15 albertel 457: foreach $option (@used_letters) {
1.1 albertel 458: if ($option eq $last_letter) {
1.6 sakharuk 459: if ($target ne 'tex') {$optionlist.="<option selected=\"on\">$option</option>\n";}
1.1 albertel 460: } else {
1.6 sakharuk 461: if ($target ne 'tex') {$optionlist.="<option>$option</option>\n";}
1.1 albertel 462: }
463: }
1.19 sakharuk 464: if ($target ne 'tex' && $Apache::lonhomework::type ne 'exam') {
1.5 sakharuk 465: $optionlist='<select name="HWVAL_'.
466: $Apache::inputtags::response[-1].':'.$temp.'">'.
467: $optionlist."</select>\n";
468: }
1.1 albertel 469: my $text=$Apache::response::foilgroup{$name.'.text'};
1.5 sakharuk 470: if ($target ne 'tex') {
1.19 sakharuk 471: if ($Apache::lonhomework::type ne 'exam') {
1.45 albertel 472: $question.="<br />\n".$optionlist.$text;
1.19 sakharuk 473: } else {
1.45 albertel 474: $question.="<br />\n".$text;
1.19 sakharuk 475: }
1.6 sakharuk 476: if ($Apache::lonhomework::type eq 'exam') {
1.42 albertel 477: my @blank;
478: $question.=&Apache::optionresponse::webbubbles(\@used_letters,\@blank,$temp,$last_letter);
1.6 sakharuk 479: }
480: } else {
481: if ($Apache::lonhomework::type eq 'exam') {
482: $question.=' '.$optionlist.$text."\n";
1.13 sakharuk 483: my @emptyItems = ();
1.16 albertel 484: for (my $i=0;$i<=$#used_letters;$i++) {push @emptyItems, ' ';}
1.40 sakharuk 485: $question.='\vskip -1 mm\noindent\begin{enumerate}\item[\textbf{'.$internal_counter.'}.]'.&Apache::optionresponse::bubbles(\@used_letters,\@emptyItems).'\end{enumerate} \vskip -8 mm \strut ';
1.20 sakharuk 486: $internal_counter++;
1.6 sakharuk 487: } else {
1.22 sakharuk 488: $question.=' '.$optionlist.$text.'\strut\\\\\strut '."\n";
1.6 sakharuk 489: }
1.5 sakharuk 490: }
1.1 albertel 491: $temp++;
492: }
1.4 albertel 493: }
494: if ($result=&itemdisplay('top')) {
495: $result.=$question;
496: } elsif ($result=&itemdisplay('bottom')) {
497: $result=$question.$result;
498: } elsif ($result=&itemdisplay('right')) {
1.32 sakharuk 499: if ($target ne 'tex') {
1.45 albertel 500: #remove the first <br />
501: $question=~s|<br />||;
502: $result='<table><tr><td valign="top">'.$question.
503: '</td><td valign="top">'.$result.'</td></tr></table>';
1.32 sakharuk 504: } else {
1.39 sakharuk 505: my $tabsize=&Apache::londefdef::recalc($ENV{'form.textwidth'});
1.43 sakharuk 506: my ($lefttabsize,$righttabsize)=(0,0);
507: if ($Apache::matchresponse::TeXitemgroupwidth ne '') {
508: $Apache::matchresponse::TeXitemgroupwidth=~/(\d*.?\d*)/;
509: $lefttabsize=$tabsize*$1/100;
510: $righttabsize=0.95*($tabsize-$lefttabsize);
511: } else {
512: $tabsize=~/(\d+\.?\d*)/;
513: $lefttabsize=$1/2.1;
514: $righttabsize=0.95*($1-$lefttabsize);
515: }
516: $lefttabsize.=' mm ';
517: $righttabsize.=' mm ';
518: $result='\setlength{\tabcolsep}{1 mm}\begin{tabular}{p{'.$righttabsize.'}p{'.$lefttabsize.'}}\begin{minipage}{'.$righttabsize.'}'.$question.'\end{minipage}&\begin{minipage}{'.$lefttabsize.'}'.$result.'\end{minipage}\end{tabular}';
1.32 sakharuk 519: }
1.4 albertel 520: } elsif ($result=&itemdisplay('left')) {
1.32 sakharuk 521: if ($target ne 'tex') {
1.45 albertel 522: #remove the first <br />
523: $question=~s|<br />||;
524: $result='<table><tr><td valign="top">'.$result.
525: '</td><td valign="top">'.$question.'</td></tr></table>';
1.32 sakharuk 526: } else {
1.39 sakharuk 527: my $tabsize=&Apache::londefdef::recalc($ENV{'form.textwidth'});
1.43 sakharuk 528: my ($lefttabsize,$righttabsize)=(0,0);
529: if ($Apache::matchresponse::TeXitemgroupwidth ne '') {
530: $Apache::matchresponse::TeXitemgroupwidth=~/(\d*.?\d*)/;
531: $lefttabsize=$tabsize*$1/100;
532: $righttabsize=0.95*($tabsize-$lefttabsize);
533: } else {
534: $tabsize=~/(\d+\.?\d*)/;
1.44 sakharuk 535: $lefttabsize=$1/2.1;
1.43 sakharuk 536: $righttabsize=0.95*($1-$lefttabsize);
537: }
538: $lefttabsize.=' mm ';
539: $righttabsize.=' mm ';
540: $result='\setlength{\tabcolsep}{1 mm}\begin{tabular}{p{'.$lefttabsize.'}p{'.$righttabsize.'}}\begin{minipage}{'.$lefttabsize.'}'.$result.'\end{minipage}&\begin{minipage}{'.$righttabsize.'}'.$question.'\end{minipage}\end{tabular}';
1.32 sakharuk 541: }
1.1 albertel 542: }
1.5 sakharuk 543: if ($target ne 'tex') {$result.="<br />";} else {$result.=' \\\\ ';}
1.1 albertel 544: return $result;
545: }
546:
547: sub getfoilcounts {
548: my ($max)=@_;
549: # +1 since instructors will count from 1
550: my $count = $#{ $Apache::response::foilgroup{'names'} }+1;
551: if (&Apache::response::showallfoils()) { $max=$count; }
552: if ($count>$max) { $count=$max }
553: &Apache::lonxml::debug("Count is $count from $max");
554: return $count;
555: }
556:
557:
558: sub start_conceptgroup {
559: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
560: $Apache::matchresponse::conceptgroup=1;
561: %Apache::response::conceptgroup=();
562: my $result;
563: if ($target eq 'edit') {
564: $result.=&Apache::edit::tag_start($target,$token,
565: "Concept Grouped Foils");
566: $result.=&Apache::edit::text_arg('Concept:','concept',$token,'50').
567: &Apache::edit::end_row().&Apache::edit::start_spanning_row();
568: }
569: if ($target eq 'modified') {
570: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
571: $safeeval,'concept');
572: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
573: }
574: return $result;
575: }
576:
577: sub end_conceptgroup {
578: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
579: $Apache::matchresponse::conceptgroup=0;
580: my $result='';
1.28 albertel 581: if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' ||
582: $target eq 'tex' || $target eq 'analyze') {
583: &Apache::response::pick_foil_for_concept($target,
584: ['value','text','location'],
585: \%Apache::hint::match,
586: $parstack,$safeeval);
1.1 albertel 587: } elsif ($target eq 'edit') {
588: $result=&Apache::edit::end_table();
589: }
590: return $result;
591: }
592:
593: sub insert_conceptgroup {
594: my $result="\n\t\t<conceptgroup concept=\"\">".&insert_foil()."\n\t\t</conceptgroup>\n";
595: return $result;
596: }
597:
598: sub start_foil {
599: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
600: my $result='';
1.28 albertel 601: if ($target eq 'web' || $target eq 'tex' || $target eq 'analyze') {
1.1 albertel 602: &Apache::lonxml::startredirection;
1.46 albertel 603: if ($target eq 'analyze') {
604: &Apache::response::check_if_computed($token,$parstack,$safeeval,'value');
605: }
1.1 albertel 606: } elsif ($target eq 'edit') {
607: $result=&Apache::edit::tag_start($target,$token,"Foil");
608: my $level='-2';
609: if ($$tagstack[-2] eq 'conceptgroup') { $level = '-3'; }
610: $result.=&Apache::edit::text_arg('Name:','name',$token);
611: my @names;
612: if (defined(@{ $Apache::response::itemgroup{'names'} })) {
613: @names=@{ $Apache::response::itemgroup{'names'} };
614: }
615: $result.= &Apache::edit::select_or_text_arg('Correct Option:','value',['unused',@names],$token,'15');
616: my $randomize=&Apache::lonxml::get_param('randomize',$parstack,
617: $safeeval,'-3');
618: if ($randomize ne 'no') {
619: $result.=&Apache::edit::select_arg('Location:','location',
620: ['random','top','bottom'],$token);
621: }
622: $result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
623: } elsif ($target eq 'modified') {
624: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
625: $safeeval,'value',
626: 'name','location');
627: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
628: }
629: return $result;
630: }
631:
632: sub end_foil {
633: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
634: my $text ='';
635: my $result = '';
1.28 albertel 636: if ($target eq 'web' || $target eq 'tex' || $target eq 'analyze') {
1.1 albertel 637: $text=&Apache::lonxml::endredirection;
638: }
1.48 albertel 639:
1.28 albertel 640: if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' ||
641: $target eq 'tex' || $target eq 'analyze') {
1.48 albertel 642: if ($target eq 'tex' && $Apache::lonhomework::type eq 'exam') {
643: $text='\vskip 5mm $\triangleright$ '.$text;
644: }
1.1 albertel 645: my $value = &Apache::lonxml::get_param('value',$parstack,$safeeval);
646: if ($value ne 'unused') {
647: my $name = &Apache::lonxml::get_param('name',$parstack,$safeeval);
648: &Apache::lonxml::debug("Got a name of :$name:");
1.49 ! albertel 649: if (!$name) {
! 650: &Apache::lonxml::error("Foils without names exist. This can cause problems to malfunction.");
! 651: $name=$Apache::lonxml::curdepth;
! 652: }
1.1 albertel 653: &Apache::lonxml::debug("Using a name of :$name:");
1.37 albertel 654: if (defined($Apache::response::foilnames{$name})) {
655: &Apache::lonxml::error(&mt("Foil name <b><tt>[_1]</tt></b> appears more than once. Foil names need to be unique.",$name));
656: }
1.38 albertel 657: $Apache::response::foilnames{$name}++;
1.37 albertel 658: my $location =&Apache::lonxml::get_param('location',$parstack,
659: $safeeval);
1.1 albertel 660: if ( $Apache::matchresponse::conceptgroup
661: && !&Apache::response::showallfoils() ) {
662: push @{ $Apache::response::conceptgroup{'names'} }, $name;
663: $Apache::response::conceptgroup{"$name.value"} = $value;
1.48 albertel 664: $Apache::response::conceptgroup{"$name.text"} = $text;
1.1 albertel 665: $Apache::response::conceptgroup{"$name.location"} = $location;
666: } else {
667: push @{ $Apache::response::foilgroup{'names'} }, $name;
668: $Apache::response::foilgroup{"$name.value"} = $value;
1.48 albertel 669: $Apache::response::foilgroup{"$name.text"} = $text;
1.1 albertel 670: $Apache::response::foilgroup{"$name.location"} = $location;
671: }
672: }
673: }
674: if ($target eq 'edit') {
675: $result.= &Apache::edit::tag_end($target,$token,'');
676: }
677: return $result;
678: }
679:
680: sub insert_foil {
681: return '
682: <foil name="" value="unused">
683: <startouttext />
684: <endouttext />
685: </foil>';
686: }
687: 1;
688: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>