1: # The LearningOnline Network with CAPA
2: # implements the tags that control the hints
3: #
4: # $Id: hint.pm,v 1.79 2024/09/29 01:58:43 raeburn 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 me&aree 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:
30:
31: package Apache::hinttags;
32:
33: use strict;
34: use Apache::lonnet();
35: use capa;
36: use Apache::caparesponse();
37: use Apache::lonmaxima();
38: use Apache::lonr();
39: use Apache::chemresponse();
40: use Apache::response();
41: use Apache::lonlocal;
42: use Storable qw(dclone);
43:
44: BEGIN {
45: &Apache::lonxml::register('Apache::hinttags',('hintgroup','hintpart','numericalhint','stringhint','formulahint','optionhint','radiobuttonhint','mathhint','customhint','reactionhint','organichint'));
46: }
47:
48:
49: @Apache::hint::which=();
50: sub start_hintgroup {
51: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
52: my $skiptoend='0';
53: my $result;
54:
55: if ($target eq 'web') {
56: my $id=$Apache::inputtags::part;
57: my $numtries=$Apache::lonhomework::history{"resource.$id.tries"};
58: if ( $numtries eq '') { $numtries = 0; }
59: my $hinttries=&Apache::response::get_response_param($id,"hinttries",1);
60: &Apache::lonxml::debug("found :$id:$numtries:$hinttries:");
61: my $gradestatus=
62: $Apache::lonhomework::history{"resource.$id.solved"};
63: my $showoncorrect=lc(&Apache::lonxml::get_param('showoncorrect',$parstack,$safeeval));
64: &Apache::lonxml::debug("onc orrect $showoncorrect, $gradestatus");
65: if ( ($showoncorrect ne 'yes' && &Apache::response::show_answer()) ||
66: ( $numtries < $hinttries) ) {
67: &Apache::lonxml::debug("Grabbin all");
68: &Apache::lonxml::get_all_text("/hintgroup",$parser,$style);
69: }
70: &Apache::lonxml::startredirection;
71: } elsif ($target eq 'tex') {
72: $result .= '\keephidden{';
73: } elsif ($target eq 'edit') {
74: $result.=&Apache::edit::tag_start($target,$token);
75: $result.=&Apache::edit::select_arg('Show hint even if problem Correct:','showoncorrect',['no','yes'],$token);
76: $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
77: } elsif ($target eq 'modified') {
78: my $constructtag=&Apache::edit::get_new_args($token,$parstack,$safeeval,'showoncorrect');
79: if ($constructtag) {
80: $result =&Apache::edit::rebuild_tag($token);
81: }
82: }
83: @Apache::hint::which=();
84: if (($#Apache::functionplotresponse::failedrules>=0) && ($target eq 'web')) {
85: @Apache::hint::which=@Apache::functionplotresponse::failedrules;
86: undef @Apache::functionplotresponse::failedrules;
87: }
88: return $result;
89: }
90:
91: sub end_hintgroup {
92: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
93: my $result;
94:
95: if ($target eq 'web') {
96: my $id=$Apache::inputtags::part;
97: my $numtries=$Apache::lonhomework::history{"resource.$id.tries"};
98: if ( $numtries eq '') { $numtries = 0; }
99: my $hinttries=&Apache::response::get_response_param($id,"hinttries",1);
100: &Apache::lonxml::debug("found :$id:$numtries:$hinttries:");
101: my $hinttext=&Apache::lonxml::endredirection;
102: if ($Apache::lonhomework::type ne 'exam' &&
103: $numtries >= $hinttries && $hinttext =~/\S/) {
104: $result='<table bgcolor="#dddddd"><tr><td>'.
105: $hinttext.'</td></tr></table>';
106: }
107: } elsif ($target eq 'edit') {
108: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
109: } elsif ($target eq 'tex') {
110: $result .= '}';
111: }
112: @Apache::hint::which=();
113: return $result;
114: }
115:
116: sub start_numericalhint {
117: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
118: #do everything in end, so intervening <responseparams> work
119: &Apache::response::start_hintresponse($parstack,$safeeval);
120: &Apache::caparesponse::push_answer();
121: my $result;
122: if ($target eq 'edit') {
123: $result.=&Apache::edit::tag_start($target,$token);
124: $result.=&Apache::edit::text_arg('Name:','name',$token);
125: $result.=&Apache::edit::text_arg('Answer:','answer',$token);
126: if ($token->[1] eq 'numericalhint') {
127: $result.=&Apache::edit::text_arg('Unit:','unit',$token,5).
128: &Apache::loncommon::help_open_topic('Physical_Units');
129: $result.=&Apache::edit::text_arg('Format:','format',$token,4).
130: &Apache::loncommon::help_open_topic('Numerical_Response_Format');
131: } elsif ($token->[1] eq 'formulahint') {
132: $result.=&Apache::edit::text_arg('Sample Points:','samples',
133: $token,40).
134: &Apache::loncommon::help_open_topic('Formula_Response_Sampling');
135: }
136: $result.=&Apache::edit::text_arg('Pre-Processor Subroutine:','preprocess',
137: $token,10);
138: $result.=&Apache::edit::end_row();
139: $result.=&Apache::edit::start_spanning_row();
140: } elsif ($target eq 'modified') {
141: my $constructtag;
142: if ($token->[1] eq 'numericalhint') {
143: $constructtag=&Apache::edit::get_new_args($token,$parstack,
144: $safeeval,'name',
145: 'answer','unit','format','preprocess');
146: } elsif ($token->[1] eq 'formulahint') {
147: $constructtag=&Apache::edit::get_new_args($token,$parstack,
148: $safeeval,'name','answer',
149: 'samples','preprocess');
150: }
151: if ($constructtag) {
152: $result = &Apache::edit::rebuild_tag($token);
153: }
154: } elsif ($target eq 'web') {
155: &Apache::response::reset_params();
156: }
157: return $result;
158: }
159:
160: sub end_numericalhint {
161: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
162: my $result;
163: if ($target eq 'web') {
164: if (!$Apache::lonxml::default_homework_loaded) {
165: &Apache::lonxml::default_homework_load($safeeval);
166: }
167: $safeeval->share_from('capa',['&caparesponse_capa_check_answer']);
168: my $hint_name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
169: &Apache::response::setup_params('numericalhint',$safeeval);
170:
171: my $partid=$Apache::inputtags::part;
172: my $id=$Apache::inputtags::hint[-1];
173: #id submissions occurred under
174: my $submitid=$Apache::inputtags::response[-1];
175:
176: my $response = $Apache::lonhomework::history{
177: "resource.$partid.$submitid.submission"};
178: &Apache::lonxml::debug("hintgroup is using $response<br />\n");
179:
180: my @args = ('type','tol','sig','ans_fmt','unit','calc','samples');
181: my $args_ref =
182: &Apache::caparesponse::setup_capa_args($safeeval,$parstack,
183: \@args,$response);
184:
185: my $hideunit=&Apache::response::get_response_param($partid.'_'.$submitid,'turnoffunit');
186: if (lc($hideunit) eq "yes") { delete($$args_ref{'unit'}); }
187:
188: my $stringify;
189: if ($$tagstack[-1] eq 'formulahint') {
190: if ($$args_ref{'samples'}) {
191: $$args_ref{'type'}='fml';
192: $stringify = 1;
193: } else {
194: $$args_ref{'type'}='math';
195: }
196: } elsif ($$tagstack[-1] eq 'numericalhint') {
197: $$args_ref{'type'}='float';
198: $stringify = 1;
199: }
200: &Apache::caparesponse::add_in_tag_answer($parstack,$safeeval,$stringify);
201: my %answer = &Apache::caparesponse::get_answer();
202: my (@final_awards,@final_msgs,@ans_names);
203: foreach my $ans_name (keys(%answer)) {
204: &Apache::lonxml::debug(" doing $ans_name with ".join(':',@{ $answer{$ans_name}{'answers'} }));
205:
206: ${$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=
207: dclone($answer{$ans_name});
208: &Apache::caparesponse::setup_capa_response($args_ref,$response);
209: my ($result,@msgs) =
210: &Apache::run::run("&caparesponse_check_list()",$safeeval);
211: &Apache::lonxml::debug("checking $ans_name $result with $response");
212: &Apache::lonxml::debug('msgs are '.join(':',@msgs));
213: my ($awards)=split(/:/,$result);
214: my @awards= split(/,/,$awards);
215: my ($ad, $msg) =
216: &Apache::inputtags::finalizeawards(\@awards,\@msgs);
217: push(@final_awards,$ad);
218: push(@final_msgs,$msg);
219: push(@ans_names,$ans_name);
220: }
221: my ($ad, $msg, $ans_name) =
222: &Apache::inputtags::finalizeawards(\@final_awards,
223: \@final_msgs,
224: \@ans_names,1);
225: if ($ad eq 'EXACT_ANS' || $ad eq 'APPROX_ANS') {
226: push(@Apache::hint::which,$hint_name);
227: }
228: $result='';
229: } elsif ($target eq 'meta') {
230: $result=&Apache::response::meta_package_write($token->[1]);
231: } elsif ($target eq 'edit') {
232: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
233: }
234: &Apache::caparesponse::pop_answer();
235: &Apache::response::end_hintresponse();
236: return $result;
237: }
238:
239: sub start_formulahint {
240: return &start_numericalhint(@_);
241: }
242:
243: sub end_formulahint {
244: return &end_numericalhint(@_);
245: }
246:
247: sub start_mathhint {
248: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
249: #do everything in end, so intervening <responseparams> and <answer> work
250: &Apache::response::start_hintresponse($parstack,$safeeval);
251: &Apache::lonxml::register('Apache::response',('answer'));
252: my $result;
253: if ($target eq 'edit') {
254: $result.=&Apache::edit::tag_start($target,$token);
255: $result.=&Apache::edit::text_arg('Name:','name',$token);
256: $result.=&Apache::edit::select_arg('Algebra System:',
257: 'cas',
258: ['maxima','R'],
259: $token);
260: $result.=&Apache::edit::text_arg('Argument Array:',
261: 'args',$token);
262: $result.=&Apache::edit::end_row();
263: $result.=&Apache::edit::start_spanning_row();
264: } elsif ($target eq 'modified') {
265: my $constructtag;
266: $constructtag=&Apache::edit::get_new_args($token,$parstack,
267: $safeeval,'name','cas',
268: 'args');
269: $result = &Apache::edit::rebuild_tag($token);
270: } elsif ($target eq 'web') {
271: &Apache::response::reset_params();
272: }
273: return $result;
274: }
275:
276: sub end_mathhint {
277: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
278: my $result;
279: if ($target eq 'web') {
280: if (!$Apache::lonxml::default_homework_loaded) {
281: &Apache::lonxml::default_homework_load($safeeval);
282: }
283: my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
284: &Apache::response::setup_params('mathhint',$safeeval);
285: my $partid=$Apache::inputtags::part;
286: my $submitid=$Apache::inputtags::response[-1];
287: my $response = $Apache::lonhomework::history{
288: "resource.$partid.$submitid.submission"};
289:
290: my $cas = &Apache::lonxml::get_param('cas',$parstack,$safeeval);
291: my $award;
292: if ($cas eq 'maxima') {
293: my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)];
294: $award=&Apache::lonmaxima::maxima_run($Apache::response::custom_answer[-1],$response,$args);
295: }
296: if ($cas eq 'R') {
297: my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)];
298: $award=&Apache::lonr::r_run($Apache::response::custom_answer[-1],$response,$args);
299: }
300: if ($award eq 'EXACT_ANS' || $award eq 'APPROX_ANS') {
301: push (@Apache::hint::which,$name);
302: }
303: $result='';
304: } elsif ($target eq 'meta') {
305: $result=&Apache::response::meta_package_write($token->[1]);
306: } elsif ($target eq 'edit') {
307: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
308: }
309: pop(@Apache::response::custom_answer);
310: pop(@Apache::response::custom_answer_type);
311: &Apache::response::end_hintresponse();
312: return $result;
313: }
314:
315: sub start_customhint {
316: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
317: #do everything in end, so intervening <responseparams> and <answer> work
318: &Apache::response::start_hintresponse($parstack,$safeeval);
319: &Apache::lonxml::register('Apache::response',('answer'));
320: my $result;
321: if ($target eq 'edit') {
322: $result.=&Apache::edit::tag_start($target,$token);
323: $result.=&Apache::edit::text_arg('Name:','name',$token);
324: $result.=&Apache::edit::end_row();
325: $result.=&Apache::edit::start_spanning_row();
326: } elsif ($target eq 'modified') {
327: my $constructtag;
328: $constructtag=&Apache::edit::get_new_args($token,$parstack,
329: $safeeval,'name');
330: $result = &Apache::edit::rebuild_tag($token);
331: } elsif ($target eq 'web') {
332: &Apache::response::reset_params();
333: }
334: return $result;
335: }
336:
337: sub end_customhint {
338: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
339: my $result;
340: if ($target eq 'web') {
341: if (!$Apache::lonxml::default_homework_loaded) {
342: &Apache::lonxml::default_homework_load($safeeval);
343: }
344: my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
345: &Apache::response::setup_params('customhint',$safeeval);
346: my $partid=$Apache::inputtags::part;
347: my $submitid=$Apache::inputtags::response[-1];
348: my $response = $Apache::lonhomework::history{
349: "resource.$partid.$submitid.submission"};
350: my $award;
351: if ( $response =~ /[^\s]/ &&
352: $Apache::response::custom_answer_type[-1] eq 'loncapa/perl') {
353: if (!$Apache::lonxml::default_homework_loaded) {
354: &Apache::lonxml::default_homework_load($safeeval);
355: }
356: ${$safeeval->varglob('LONCAPA::customresponse_submission')}=
357: $response;
358:
359: $award = &Apache::run::run('{ my $submission=$LONCAPA::customresponse_submission;'.$Apache::response::custom_answer[-1].'}',$safeeval);
360: }
361: if ($award eq 'EXACT_ANS' || $award eq 'APPROX_ANS') {
362: push (@Apache::hint::which,$name);
363: }
364: $result='';
365: } elsif ($target eq 'meta') {
366: $result=&Apache::response::meta_package_write($token->[1]);
367: } elsif ($target eq 'edit') {
368: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
369: }
370: pop(@Apache::response::custom_answer);
371: pop(@Apache::response::custom_answer_type);
372: &Apache::response::end_hintresponse();
373: return $result;
374: }
375:
376: sub start_stringhint {
377: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
378: #do everything in end, so intervening <responseparams> work
379: &Apache::response::start_hintresponse($parstack,$safeeval);
380: my $result;
381: if ($target eq 'edit') {
382: $result.=&Apache::edit::tag_start($target,$token);
383: $result.=&Apache::edit::text_arg('Name:','name',$token);
384: $result.=&Apache::edit::text_arg('Answer:','answer',$token);
385: $result.=&Apache::edit::select_arg('Type:','type',
386: [['cs','Case Sensitive'],['ci','Case Insensitive'],
387: ['mc','Case Insensitive, Any Order'],
388: ['re','Regular Expression']],$token);
389: $result.=&Apache::edit::text_arg('Pre-Processor Subroutine:','preprocess',
390: $token,10);
391: $result.=&Apache::edit::end_row();
392: $result.=&Apache::edit::start_spanning_row();
393: } elsif ($target eq 'modified') {
394: my $constructtag;
395: $constructtag=&Apache::edit::get_new_args($token,$parstack,
396: $safeeval,'name','answer',
397: 'type','preprocess');
398: $result = &Apache::edit::rebuild_tag($token);
399: } elsif ($target eq 'web') {
400: &Apache::response::reset_params();
401: }
402: return $result;
403: }
404:
405: sub end_stringhint {
406: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
407: my $result;
408: if ($target eq 'web') {
409: if (!$Apache::lonxml::default_homework_loaded) {
410: &Apache::lonxml::default_homework_load($safeeval);
411: }
412: $safeeval->share_from('capa',['&caparesponse_capa_check_answer']);
413: my $hint_name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
414: &Apache::response::setup_params('stringhint',$safeeval);
415: my $partid=$Apache::inputtags::part;
416: my $id=$Apache::inputtags::hint[-1];
417: #id submissions occurred under
418: my $submitid=$Apache::inputtags::response[-1];
419: my $response = $Apache::lonhomework::history{
420: "resource.$partid.$submitid.submission"};
421: &Apache::lonxml::debug("hintgroup is using $response<br />\n");
422: my $type = &Apache::lonxml::get_param('type',$parstack,$safeeval);
423: my ($ad,$msg);
424: if ($type eq 're' ) {
425: my $answer=&Apache::lonxml::get_param('answer',$parstack,
426: $safeeval);
427: ${$safeeval->varglob('LONCAPA::response')}=$response;
428: my $compare='=';
429: if ($answer=~/^\s*NOT\s*/) {
430: $answer=~s/^\s*NOT\s*//;
431: $compare='!';
432: }
433: my $test='$LONCAPA::response'.$compare.'~m'.$answer;
434: &Apache::lonxml::debug("test $test");
435: $result = &Apache::run::run("return $test",$safeeval);
436: &Apache::lonxml::debug("current $response");
437: &Apache::lonxml::debug("current $answer");
438: $ad = ($result) ? 'APPROX_ANS' : 'INCORRECT';
439: } else {
440: my @args = ('type');
441: my $args_ref =
442: &Apache::caparesponse::setup_capa_args($safeeval,$parstack,
443: \@args,$response);
444: if ($$args_ref{'type'} eq '') {
445: $$args_ref{'type'} = 'ci';
446: }
447: my $stringify;
448: if ($$args_ref{'type'} ne 're') {
449: $stringify = 1;
450: }
451: &Apache::caparesponse::add_in_tag_answer($parstack,$safeeval,$stringify);
452: my (@final_awards,@final_msgs,@ans_names);
453: my %answer = &Apache::caparesponse::get_answer();
454: foreach my $ans_name (keys(%answer)) {
455: &Apache::lonxml::debug(" doing $ans_name with ".join(':',@{ $answer{$ans_name}{'answers'} }));
456: ${$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=dclone($answer{$ans_name});
457: my ($result, @msgs)=&Apache::run::run("&caparesponse_check_list()",$safeeval);
458: &Apache::lonxml::debug('msgs are'.join(':',@msgs));
459: my ($awards) = split(/:/,$result);
460: my (@awards) = split(/,/,$awards);
461: ($ad,$msg) =
462: &Apache::inputtags::finalizeawards(\@awards,\@msgs);
463: push(@final_awards,$ad);
464: push(@final_msgs,$msg);
465: push(@ans_names,$ans_name);
466: &Apache::lonxml::debug("\n<br>result:$result:$Apache::lonxml::curdepth<br>\n");
467: }
468: my ($ad, $msg, $ans_name) =
469: &Apache::inputtags::finalizeawards(\@final_awards,
470: \@final_msgs,
471: \@ans_names,1);
472: }
473: if ($ad eq 'EXACT_ANS' || $ad eq 'APPROX_ANS') {
474: push(@Apache::hint::which,$hint_name);
475: }
476: $result='';
477: } elsif ($target eq 'meta') {
478: $result=&Apache::response::meta_package_write($token->[1]);
479: } elsif ($target eq 'edit') {
480: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
481: }
482: &Apache::response::end_hintresponse();
483: return $result;
484: }
485:
486: # reactionhint
487:
488: sub start_reactionhint {
489: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
490: #do everything in end, so intervening <responseparams> work
491: &Apache::response::start_hintresponse($parstack,$safeeval);
492: my $result;
493: if ($target eq 'edit') {
494: $result.=&Apache::edit::tag_start($target,$token);
495: $result.=&Apache::edit::text_arg('Name:','name',$token);
496: $result.=&Apache::edit::text_arg('Answer:','answer',$token);
497: $result.=&Apache::edit::end_row();
498: $result.=&Apache::edit::start_spanning_row();
499: } elsif ($target eq 'modified') {
500: my $constructtag;
501: $constructtag=&Apache::edit::get_new_args($token,$parstack,
502: $safeeval,'name','answer',
503: );
504: $result = &Apache::edit::rebuild_tag($token);
505: } elsif ($target eq 'web') {
506: &Apache::response::reset_params();
507: }
508: return $result;
509: }
510:
511: sub end_reactionhint {
512: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
513: my $result;
514: if ($target eq 'web') {
515: if (!$Apache::lonxml::default_homework_loaded) {
516: &Apache::lonxml::default_homework_load($safeeval);
517: }
518: my $hint_name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
519: &Apache::response::setup_params('reactionhint',$safeeval);
520: my $partid=$Apache::inputtags::part;
521: my $id=$Apache::inputtags::hint[-1];
522: #id submissions occurred under
523: my $submitid=$Apache::inputtags::response[-1];
524: my $response = $Apache::lonhomework::history{
525: "resource.$partid.$submitid.submission"};
526: &Apache::lonxml::debug("hintgroup is using $response<br />\n");
527: my $answer=&Apache::lonxml::get_param('answer',$parstack,
528: $safeeval);
529: &Apache::lonxml::debug("current $response");
530: &Apache::lonxml::debug("current $answer");
531: if (&Apache::chemresponse::chem_standard_order($response) eq
532: &Apache::chemresponse::chem_standard_order($answer)) {
533: push(@Apache::hint::which,$hint_name);
534: }
535: $result='';
536: } elsif ($target eq 'meta') {
537: $result=&Apache::response::meta_package_write($token->[1]);
538: } elsif ($target eq 'edit') {
539: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
540: }
541: &Apache::response::end_hintresponse();
542: return $result;
543: }
544:
545: # organichint
546:
547: sub start_organichint {
548: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
549: #do everything in end, so intervening <responseparams> work
550: &Apache::response::start_hintresponse($parstack,$safeeval);
551: my $result;
552: if ($target eq 'edit') {
553: $result.=&Apache::edit::tag_start($target,$token);
554: $result.=&Apache::edit::text_arg('Name:','name',$token);
555: $result.=&Apache::edit::text_arg('Answer:','answer',$token);
556: $result.=&Apache::edit::end_row();
557: $result.=&Apache::edit::start_spanning_row();
558: } elsif ($target eq 'modified') {
559: my $constructtag;
560: $constructtag=&Apache::edit::get_new_args($token,$parstack,
561: $safeeval,'name','answer',
562: );
563: $result = &Apache::edit::rebuild_tag($token);
564: } elsif ($target eq 'web') {
565: &Apache::response::reset_params();
566: }
567: return $result;
568: }
569:
570: sub end_organichint {
571: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
572: my $result;
573: if ($target eq 'web') {
574: if (!$Apache::lonxml::default_homework_loaded) {
575: &Apache::lonxml::default_homework_load($safeeval);
576: }
577: my $hint_name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
578: &Apache::response::setup_params('organichint',$safeeval);
579: my $partid=$Apache::inputtags::part;
580: my $id=$Apache::inputtags::hint[-1];
581: #id submissions occurred under
582: my $submitid=$Apache::inputtags::response[-1];
583: my $response = $Apache::lonhomework::history{
584: "resource.$partid.$submitid.submission"};
585: &Apache::lonxml::debug("hintgroup is using $response<br />\n");
586: my (@answers)=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval);
587: my %previous = &Apache::response::check_for_previous($response,$partid,$id);
588: foreach my $answer (@answers) {
589: &Apache::lonxml::debug("submitted a $response for $answer<br \>\n");
590: if ($response eq $answer) {
591: push(@Apache::hint::which,$hint_name);
592: last;
593: }
594: }
595: $result='';
596: } elsif ($target eq 'meta') {
597: $result=&Apache::response::meta_package_write($token->[1]);
598: } elsif ($target eq 'edit') {
599: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
600: }
601: &Apache::response::end_hintresponse();
602: return $result;
603: }
604:
605:
606: # a part shows if it is on, if no specific parts are on, then default shows
607: sub start_hintpart {
608: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
609:
610: my $show ='0';
611: my $result = '';
612: if ($target eq 'web') {
613: my $on= &Apache::lonxml::get_param('on',$parstack,$safeeval);
614: &Apache::lonxml::debug("hintpart sees $on and ,$#Apache::hint::which");
615: if ( $on eq 'default' && $#Apache::hint::which == '-1') {
616: $show=1;
617: } else {
618: my $which;
619: foreach $which (@Apache::hint::which) { if ($which eq $on) { $show = 1; last } }
620: }
621: if (!$show) {
622: &Apache::lonxml::get_all_text("/hintpart",$parser,$style);
623: }
624: } elsif ($target eq 'grade') {
625: &Apache::lonxml::get_all_text("/hintpart",$parser,$style);
626: } elsif ($target eq 'edit') {
627: $result.= &Apache::edit::tag_start($target,$token);
628: $result.= &Apache::edit::text_arg('On:','on',$token);
629: $result.= &Apache::edit::end_row();
630: $result.= &Apache::edit::start_spanning_row();
631: } elsif ($target eq 'modified') {
632: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
633: $safeeval,'on');
634: if ($constructtag) {
635: $result = &Apache::edit::rebuild_tag($token);
636: }
637: }
638: return $result;
639: }
640:
641: sub end_hintpart {
642: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
643: my $result;
644: if ($target eq 'edit') {
645: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
646: }
647: return $result;
648: }
649:
650: sub start_optionhint {
651: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
652: my $result;
653: &Apache::response::start_hintresponse($parstack,$safeeval);
654: if ($target eq 'edit') {
655: $result.=&Apache::edit::tag_start($target,$token);
656: $result.=&Apache::edit::text_arg('Name:','name',$token);
657: $result.=&Apache::edit::text_arg('Answer:','answer',$token,40);
658: $result.=&Apache::edit::text_arg('Concept:','concept',$token,50);
659: } elsif ($target eq 'modified') {
660: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
661: $safeeval,'name',
662: 'answer','concept');
663: if ($constructtag) {
664: $result = &Apache::edit::rebuild_tag($token);
665: }
666: } elsif ($target eq 'meta') {
667: $result=&Apache::response::meta_package_write('numericalhint');
668: }
669: return $result;
670: }
671:
672: sub end_optionhint {
673: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
674: my $result;
675: if ($target eq 'web') {
676: my ($foilmatch,$conceptmatch)=(-1,-1);
677: my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
678: my $partid=$Apache::inputtags::part;
679: #id submissions occurred under
680: my $submitid=$Apache::inputtags::response[-1];
681: my $part_id="$partid.$submitid";
682: my %answer;
683: my $answer=&Apache::lonxml::get_param('answer',$parstack,$safeeval);
684: if ($answer) {
685: eval('%answer ='.$answer);
686: &Apache::lonxml::debug("answwer hash");
687: &Apache::lonhomework::showhash(%answer);
688: my $response = $Apache::lonhomework::history{
689: "resource.$part_id.submission"};
690: my %response=&Apache::lonnet::str2hash($response);
691: &Apache::lonhomework::showhash(%response);
692: foreach my $foil (keys(%answer)) {
693: $foilmatch=1;
694: if ($answer{$foil} ne $response{$foil}) {$foilmatch=0;last;}
695: }
696: }
697: my %concept;
698: my $constr=&Apache::lonxml::get_param('concept',$parstack,$safeeval);
699: if ( $constr ) { eval('%concept ='.$constr); }
700: my $response = $Apache::lonhomework::history{
701: "resource.$part_id.submissiongrading"};
702: my %response=&Apache::lonnet::str2hash($response);
703: foreach my $concept (keys(%concept)) {
704: my $compare;
705: if ($concept{$concept} eq 'correct') {$compare=1}else{$compare=0}
706: $conceptmatch=1;
707: if (ref($Apache::hint::option{"$part_id.concepts"})) {
708: foreach my $foil (@{ $Apache::hint::option{"$part_id.concept.$concept"} }) {
709: &Apache::lonxml::debug("compare -$foil- -$response{$foil}-$compare-");
710: if ( exists($response{$foil}) &&
711: $response{$foil} ne $compare) {$conceptmatch=0;last;}
712: }
713: } else {
714: $conceptmatch=0;
715: }
716: if ($conceptmatch eq '0') { last; }
717: }
718: if ( ($conceptmatch eq '-1' || $conceptmatch eq '1') &&
719: ($foilmatch eq '-1' || $foilmatch eq '1') ) {
720: push(@Apache::hint::which,$name);
721: }
722: } elsif ($target eq 'edit') {
723: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
724: }
725: &Apache::response::end_hintresponse();
726: return $result;
727: }
728:
729: sub start_radiobuttonhint {
730: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
731: my $result;
732: &Apache::response::start_hintresponse($parstack,$safeeval);
733: if ($target eq 'edit') {
734: $result.=&Apache::edit::tag_start($target,$token);
735: $result.=&Apache::edit::text_arg('Name:','name',$token);
736: $result.=&Apache::edit::text_arg('Answer:','answer',$token);
737: } elsif ($target eq 'modified') {
738: my $constructtag=&Apache::edit::get_new_args($token,$parstack,
739: $safeeval,'name',
740: 'answer');
741: if ($constructtag) {
742: $result = &Apache::edit::rebuild_tag($token);
743: }
744: } elsif ($target eq 'meta') {
745: $result=&Apache::response::meta_package_write('numericalhint');
746: }
747: return $result;
748: }
749:
750: sub end_radiobuttonhint {
751: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
752: my $result;
753: if ($target eq 'web') {
754: my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
755: my @answer;
756: my $answer=&Apache::lonxml::get_param('answer',$parstack,$safeeval);
757: eval('@answer ='.$answer);
758: my $partid=$Apache::inputtags::part;
759: #id submissions occurred under
760: my $submitid=$Apache::inputtags::response[-1];
761: my $part_id="$partid.$submitid";
762: my $response = $Apache::lonhomework::history{
763: "resource.$part_id.submission"};
764: ($response)=&Apache::lonnet::str2hash($response);
765: &Apache::lonxml::debug("response is $response");
766:
767: if ($answer[0] eq 'foil') {
768: shift(@answer);
769: foreach my $answer (@answer) {
770: if ($response eq $answer) {
771: push (@Apache::hint::which,$name);
772: last;
773: }
774: }
775: } elsif ($answer[0] eq 'concept') {
776: shift(@answer);
777: foreach my $answer (@answer) {
778: if (ref($Apache::hint::radiobutton{"$part_id.concept.".$answer})) {
779: my @names=@{ $Apache::hint::radiobutton{"$part_id.concept.".$answer} };
780: if (grep(/^\Q$response\E$/,@names)) {
781: push(@Apache::hint::which,$name);
782: last;
783: }
784: }
785: }
786: }
787: } elsif ($target eq 'edit') {
788: $result.=&Apache::edit::end_row().&Apache::edit::end_table();
789: }
790: &Apache::response::end_hintresponse();
791: return $result;
792: }
793: 1;
794: __END__
795:
796:
797: =head1 NAME
798:
799: Apache::hinttags
800:
801: =head1 SYNOPSIS
802:
803: This handler coordinates the delivery of hints to students working on LON-CAPA problems and assignments.
804:
805: This is part of the LearningOnline Network with CAPA project
806: described at http://www.lon-capa.org.
807:
808: =head1 SUBROUTINES
809:
810: =over
811:
812: =item start_hintgroup()
813:
814: =item end_hintgroup()
815:
816: =item start_numericalhint()
817:
818: =item end_numericalhint()
819:
820: =item start_formulahint()
821:
822: =item end_formulahint()
823:
824: =item start_mathhint()
825:
826: =item end_mathhint()
827:
828: =item start_customhint()
829:
830: =item end_customhint()
831:
832: =item start_stringhint()
833:
834: =item end_stringhint()
835:
836: =item start_hintpart()
837:
838: =item end_hintpart()
839:
840: =item start_optionhint()
841:
842: =item end_optionhint()
843:
844: =item start_radiobuttonhint()
845:
846: =item end_radiobuttonhint()
847:
848: =back
849:
850: =cut
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>