1: # The LearningOnline Network with CAPA
2: # definition of tags that give a structure to a document
3: # 2/19 Guy
4: # 6/26/2001 fixed extra web display at end of <web></web> tags
5: # 8/17,8/18,8/20 Gerd Kortemeyer
6:
7: package Apache::structuretags;
8:
9: use strict;
10: use Apache::lonnet;
11:
12: sub BEGIN {
13: &Apache::lonxml::register('Apache::structuretags',('block','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','startouttext','endouttext'));
14: # &Apache::lonxml::register_insert('problem','',('part','postanswerdate','preduedate'))
15: }
16:
17: sub start_web {
18: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
19: my $bodytext=&Apache::lonxml::get_all_text("/web",$$parser[$#$parser]);
20: if ($target eq 'web') {
21: return $bodytext;
22: }
23: return '';
24: }
25:
26: sub end_web {
27: return '';
28: }
29:
30: sub start_tex {
31: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
32: my $bodytext=&Apache::lonxml::get_all_text("/tex",$$parser[$#$parser]);
33: if ($target eq 'tex') {
34: return $bodytext
35: }
36: return '';
37: }
38:
39: sub end_tex {
40: return '';
41: }
42:
43: sub page_start {
44: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
45: my $result=&Apache::londefdef::start_html($target,$token,$tagstack,$parstack,$parser,$safeeval);
46: my $head_tag_start='<head>'.&Apache::lonxml::registerurl();
47: my $body_tag_start='<body onLoad="'.&Apache::lonxml::loadevents().'" '.
48: 'onUnload="'.&Apache::lonxml::unloadevents().'" ';
49: my $background=&Apache::lonxml::get_param('background',$parstack,$safeeval);
50: if ($background) {
51: $Apache::lonxml::extlinks[$#Apache::lonxml::extlinks+1]=
52: $background;
53: $body_tag_start.='background="'.$background.'" ';
54: } else {
55: my $bgcolor=&Apache::lonxml::get_param('bgcolor',$parstack,$safeeval);
56: if ($bgcolor) {
57: $body_tag_start.='bgcolor="'.$bgcolor.'" ';
58: } else {
59: $body_tag_start.='bgcolor="#ffffff"';
60: }
61: }
62: $body_tag_start.='>';
63: return ($result,$head_tag_start,$body_tag_start);
64: }
65:
66: sub initialize_storage {
67: %Apache::lonhomework::results=();
68: my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser();
69: %Apache::lonhomework::history=
70: &Apache::lonnet::restore($symb,$courseid,$domain,$name);
71: #ignore error conditions
72: my ($temp)=keys %Apache::lonhomework::history ;
73: if ($temp =~ m/^error:.*/) { %Apache::lonhomework::history=(); }
74: }
75:
76: # -------------------------------------------------------------finalize_storage
77: # Stores away the result has to a student's environment
78: # checks form.grade_ for specific values, other wises stores
79: # to the running users environment
80: sub finalize_storage {
81: my $result;
82: my ($temp) = keys %Apache::lonhomework::results;
83: if ( $temp ne '' ) {
84: my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser();
85: $result=&Apache::lonnet::cstore(\%Apache::lonhomework::results,
86: $symb,$courseid,$domain,$name);
87: &Apache::lonxml::debug("Store return message:".$result);
88: }
89: return $result;
90: }
91:
92: sub checkout_msg {
93: return (<<ENDCHECKOUT);
94: <h2>The resource needs to be checked out</h2>
95: As a resource gets checked out, a unique timestamped ID is given to it, and a
96: permanent record is left in the system.<p />
97: <font color=red>
98: Checking out resources is subject to course policies, and may exclude future
99: credit even if done erroneously.<p />
100: </font>
101: <form method=post>
102: <input type=button name="doescheckout"
103: value="Check out Exam for Viewing"
104: onClick="if (confirm('Check out Exam?')) { this.form.submit(); }" />
105: </form>
106: ENDCHECKOUT
107: }
108:
109: sub start_problem {
110: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
111:
112: #intialize globals
113: $Apache::inputtags::part='0';
114: @Apache::inputtags::responselist = ();
115: @Apache::inputtags::previous=();
116: &initialize_storage();
117: $Apache::lonhomework::type=&Apache::lonnet::EXT('resource.0.type');
118: &Apache::lonxml::debug("Found this to be of type :$Apache::lonhomework::type:");
119: if ($Apache::lonhomework::type eq '') {
120: my $uri=$ENV{'request.uri'};
121: if ($uri=~/\.(\w+)$/) {
122: $Apache::lonhomework::type=$1;
123: &Apache::lonxml::debug("Using type of $1");
124: } else {
125: $Apache::lonhomework::type='problem';
126: &Apache::lonxml::debug("Using default type, problem, :$uri:");
127: }
128: }
129:
130: #added vars to the scripting enviroment
131: my $expression='$external::part='.$Apache::inputtags::part.';';
132: &Apache::run::run($expression,$safeeval);
133: my $status;
134: my $accessmsg;
135:
136: #should get back a <html> or the neccesary stuff to start XML/MathML
137: my ($result,$head_tag_start,$body_tag_start)=
138: &page_start($target,$token,$tagstack,$parstack,$parser,$safeeval);
139:
140: if ($Apache::lonhomework::type eq 'exam') {
141: if ($target eq 'web') {
142: my $token=$Apache::lonhomework::history{"resource.0.outtoken"};
143: if (($ENV{'form.doescheckout'}) && (!$token)) {
144: $token=&Apache::lonxml::maketoken();
145: $Apache::lonhomework::history{"resource.0.outtoken"}=$token;
146: }
147: $body_tag_start.=&Apache::lonxml::printtokenheader($target,$token);
148: }
149: }
150: if ($target eq 'web' || $target eq 'grade') {
151: ($status,$accessmsg) = &Apache::lonhomework::check_access('0');
152: push (@Apache::inputtags::status,$status);
153: my $expression='$external::datestatus="'.$status.'";';
154: $expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.0.solved"}.'";';
155: &Apache::run::run($expression,$safeeval);
156: if (( $status eq 'CLOSED' ) ||
157: ( $status eq 'UNCHECKEDOUT') ||
158: ( $status eq 'BANNED')) {
159: my $bodytext=&Apache::lonxml::get_all_text("/problem",$$parser[$#$parser]);
160: if ( $target eq "web" ) {
161: $result.= $head_tag_start.'</head>';
162: my $msg=$body_tag_start.
163: '<h1>Not open to be viewed</h1>';
164: if ($status eq 'CLOSED') {
165: $msg.='The problem '.$accessmsg;
166: } elsif ($status eq 'UNCHECKEDOUT') {
167: $msg.=&checkout_msg;
168: }
169: return $result.$msg.'<br />';
170: }
171: }
172: }
173: if ($target eq 'web') {
174: my $name= &Apache::lonxml::get_param('name',$parstack,$safeeval);
175: if ($name eq '') {
176: $name=&Apache::lonnet::EXT('resource.title');
177: if ($name eq 'con_lost') { $name = ''; }
178: }
179: $Apache::lonhomework::name=$name;
180: if ($status eq 'CAN_ANSWER') {
181: # create a page header and exit
182: $result.="$head_tag_start<title>$name</title></head>\n
183: $body_tag_start\n
184: <form name=\"lonhomework\" method=\"POST\" action=\"".$ENV{'request.uri'}."\">".
185: '<input type="hidden" name="submitted" value="yes" />';
186: if ($ENV{'request.state'} eq "construct") {
187: $result.='<input type="hidden" name="problemmode" value="View" />
188: <input type="submit" name="problemmode" value="Edit" /><hr />';
189: }
190: # if we are viewing someone else preserve that info
191: if (defined $ENV{'form.grade_symb'}) {
192: foreach my $field ('symb','courseid','domain','username') {
193: $result .= '<input type="hidden" name="grade_'.$field.
194: '" value="'.$ENV{"form.grade_$field"}.'" />'."\n";
195: }
196: }
197: return $result;
198: } elsif ($status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER' || $status eq 'CLOSED') {
199: return $result.$head_tag_start."<title>$name</title></head>\n$body_tag_start\n";
200: }
201: }
202: if ($target eq 'edit') {
203: $result.=$head_tag_start."</head>".$body_tag_start.
204: '<form name="lonhomework" method="POST" action="'.$ENV{'request.uri'}.'">
205: <input type="hidden" name="submitted" value="edit" />
206: <input type="hidden" name="problemmode" value="Edit" />
207: <input type="submit" name="problemmode" value="View" />
208: <input type="submit" name="Undo" value="undo" /> <hr />
209: <input type="submit" name="submit" value="Submit Changes" /><br />
210: ';
211: my $temp=&Apache::edit::insertlist($target,$token);
212: $result.=$temp;
213: return $result;
214: }
215: if ($target eq 'modified') {
216: $result=$token->[4];
217: $result.=&Apache::edit::handle_insert();
218: return $result;
219: }
220: return '';
221: }
222:
223: sub end_problem {
224: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
225: my $result='';
226: my $status=$Apache::inputtags::status['-1'];
227: if ($target eq 'grade' || $target eq 'web' ) {
228: if ( $target eq 'grade' && $Apache::inputtags::part eq '0' &&
229: $status eq 'CAN_ANSWER') {
230: # if part is zero, no <part>s existed, so we need to the grading
231: &Apache::inputtags::grade;
232: } elsif ($Apache::inputtags::part eq '0') {
233: # if part is zero, no <part>s existed, so we need show the current
234: # grading status
235: $result.= &Apache::inputtags::gradestatus($Apache::inputtags::part);
236: }
237: if ($target eq 'web') {
238: if ($status eq 'CAN_ANSWER') {
239: $result.="</form></body>\n";
240: } elsif ($status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER') {
241: $result.="</body>\n";
242: }
243: $result.=&Apache::lonxml::xmlend();
244: }
245: if ($target eq 'grade') {
246: &Apache::lonhomework::showhash(%Apache::lonhomework::results);
247: &finalize_storage();
248: }
249: } elsif ($target eq 'meta') {
250: if ($Apache::inputtags::part eq '0') {
251: $result=&Apache::response::mandatory_part_meta;
252: }
253: } elsif ($target eq 'edit') {
254: &Apache::lonxml::debug("in end_problem with $target, edit");
255: $result='<br /><input type="submit" name="submit" value="Submit Changes" />';
256: }
257: return $result;
258: }
259:
260: sub start_library {
261: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
262: my ($result,$head_tag_start,$body_tag_start)=
263: &page_start($target,$token,$tagstack,$parstack,$parser,$safeeval);
264: if ($target eq 'edit') {
265: $result.=$head_tag_start."</head>".$body_tag_start.
266: '<form name="lonhomework" method="POST" action="'.$ENV{'request.uri'}.'">
267: <input type="hidden" name="submitted" value="edit" />
268: <input type="hidden" name="problemmode" value="Edit" />
269: <input type="submit" name="problemmode" value="View" />
270: <input type="submit" name="Undo" value="undo" /> <hr />
271: ';
272: my $temp=&Apache::edit::insertlist($target,$token);
273: $result.=$temp;
274: return $result;
275: }
276: if ($target eq 'modified') {
277: $result=$token->[4];
278: $result.=&Apache::edit::handle_insert();
279: return $result;
280: }
281: return '';
282: }
283:
284: sub end_library {
285: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
286: my $result='';
287: if ($target eq 'edit') {
288: $result='<br /><input type="submit" name="submit" value="Submit Changes" />';
289: }
290: return $result;
291: }
292:
293: sub start_block {
294: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
295:
296: if ($target eq 'web' || $target eq 'grade') {
297: my $code = @$parstack[$#$parstack];
298: $code =~ s/\"//g;
299: $code .=';return $condition;';
300: # print "<br />$code<br />";
301: my $result = &Apache::run::run($code,$safeeval);
302: &Apache::lonxml::debug("block :$code: returned :$result:");
303: if ( ! $result ) {
304: my $skip=&Apache::lonxml::get_all_text("/block",$$parser[$#$parser]);
305: &Apache::lonxml::debug("skipping ahead :$skip: $$parser[$#$parser]");
306: }
307: }
308: return "";
309: }
310:
311: sub end_block {
312: return '';
313: }
314:
315: sub start_while {
316: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
317:
318: my $code = @$parstack[$#$parstack];
319: $code =~ s/\"//g;
320: $code .=';return $condition;';
321:
322: push( @Apache::structuretags::whileconds, $code);
323: my $result = &Apache::run::run($code,$safeeval);
324: my $bodytext=$$parser[$#$parser]->get_text("/while");
325: push( @Apache::structuretags::whilebody, $bodytext);
326: if ( $result ) {
327: &Apache::lonxml::newparser($parser,\$bodytext);
328: }
329: return "";
330: }
331:
332: sub end_while {
333: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
334: my $code = pop @Apache::structuretags::whileconds;
335: my $bodytext = pop @Apache::structuretags::whilebody;
336: my $result = &Apache::run::run($code,$safeeval);
337: if ( $result ) {
338: &Apache::lonxml::newparser($parser,\$bodytext);
339: }
340: return "";
341: }
342:
343: # <randomlist>
344: # <tag1>..</tag1>
345: # <tag2>..</tag2>
346: # <tag3>..</tag3>
347: # ...
348: # </randomlist>
349: sub start_randomlist {
350: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
351: my $body= &Apache::lonxml::get_all_text("/randomlist",$$parser[$#$parser]);
352: my $b_parser= HTML::TokeParser->new(\$body);
353: my $b_tok;
354: my @randomlist;
355: my $list_item;
356:
357: while($b_tok = $b_parser->get_token() ) {
358: if($b_tok->[0] eq 'S') { # start tag
359: # get content of the tag until matching end tag
360: # get all text upto the matching tag
361: # and push the content into @randomlist
362: $list_item = &Apache::lonxml::get_all_text('/'.$b_tok->[1],$b_parser);
363: $list_item = "$b_tok->[4]"."$list_item"."</$b_tok->[1]>";
364: push(@randomlist,$list_item);
365: # print "<br /><b>START-TAG $b_tok->[1], $b_tok->[4], $list_item</b>";
366: }
367: if($b_tok->[0] eq 'T') { # text
368: # what to do with text in between tags?
369: # print "<b>TEXT $b_tok->[1]</b><br />";
370: }
371: # if($b_tok->[0] eq 'E') { # end tag, should not happen
372: # print "<b>END-TAG $b_tok->[1]</b><br />";
373: # }
374: }
375: my @idx_arr = (0 .. $#randomlist);
376: &Apache::structuretags::shuffle(\@idx_arr);
377: my $bodytext = '';
378: for(0 .. $#randomlist) {
379: $bodytext .= "$randomlist[ $idx_arr[$_] ]";
380: }
381:
382: &Apache::lonxml::newparser($parser,\$bodytext);
383: return "";
384: }
385:
386: sub shuffle {
387: my $a=shift;
388: my $i;
389: &Apache::response::setrandomnumber();
390: for($i=@$a;--$i;) {
391: my $j=int rand($i+1);
392: next if $i == $j;
393: @$a[$i,$j] = @$a[$j,$i];
394: }
395: }
396:
397: sub end_randomlist {
398: return '';
399: }
400:
401: sub start_part {
402: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
403: my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval);
404: if ($id eq '') { $id = $Apache::lonxml::curdepth; }
405: $Apache::inputtags::part=$id;
406: @Apache::inputtags::responselist = ();
407: @Apache::inputtags::previous=();
408: if ($target eq 'meta') {
409: return &Apache::response::mandatory_part_meta;
410: } elsif ($target eq 'web' || $target eq 'grade') {
411: my ($status,$accessmsg) = &Apache::lonhomework::check_access($id);
412: push (@Apache::inputtags::status,$status);
413: my $expression='$external::datestatus="'.$status.'";';
414: $expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.$id.solved"}.'";';
415: &Apache::run::run($expression,$safeeval);
416: if ( $status eq 'CLOSED' ) {
417: my $bodytext=&Apache::lonxml::get_all_text("/part",$$parser[$#$parser]);
418: if ( $target eq "web" ) {
419: return "<br />Part is not open to be viewed. It $accessmsg<br />";
420: }
421: }
422: }
423: return '';
424: }
425:
426: sub end_part {
427: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
428: &Apache::lonxml::debug("in end_part $target ");
429: my $status=$Apache::inputtags::status['-1'];
430: pop @Apache::inputtags::status;
431: if ( $target eq 'meta' ) { return ''; }
432: if ( $target eq 'grade' && $status eq 'CAN_ANSWER') {
433: return &Apache::inputtags::grade;
434: }
435: if ($target eq 'web') {
436: return &Apache::inputtags::gradestatus($Apache::inputtags::part);
437: }
438: return '';
439: }
440:
441: sub start_preduedate {
442: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
443: if ($target eq 'web' || $target eq 'grade') {
444: if ($Apache::inputtags::status['-1'] ne 'CAN_ANSWER' &&
445: $Apache::inputtags::status['-1'] ne 'CANNOT_ANSWER' ) {
446: &Apache::lonxml::get_all_text("/preduedate",$$parser[$#$parser]);
447: }
448: }
449: return '';
450: }
451:
452: sub end_preduedate {
453: return '';
454: }
455:
456: sub start_postanswerdate {
457: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
458: if ($target eq 'web' || $target eq 'grade') {
459: if ($Apache::inputtags::status['-1'] ne 'SHOW_ANSWER') {
460: &Apache::lonxml::get_all_text("/postanswerdate",$$parser[$#$parser]);
461: }
462: }
463: return '';
464: }
465:
466: sub end_postanswerdate {
467: return '';
468: }
469:
470: sub start_notsolved {
471: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
472: if ($target eq 'web' || $target eq 'grade') {
473: my $gradestatus=$Apache::lonhomework::history{"resource.$Apache::inputtags::part.solved"};
474: &Apache::lonxml::debug("not solved has :$gradestatus:");
475: if ($gradestatus =~ /^correct/) {
476: &Apache::lonxml::debug("skipping");
477: &Apache::lonxml::get_all_text("/notsolved",$$parser[$#$parser]);
478: }
479: }
480: return '';
481: }
482:
483: sub end_notsolved {
484: return '';
485: }
486:
487: sub start_solved {
488: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
489: if ($target eq 'web' || $target eq 'grade') {
490: my $gradestatus=$Apache::lonhomework::history{"resource.$Apache::inputtags::part.solved"};
491: if ($gradestatus !~ /^correct/) {
492: &Apache::lonxml::get_all_text("/solved",$$parser[$#$parser]);
493: }
494: }
495: return '';
496: }
497:
498: sub end_solved {
499: return '';
500: }
501:
502: sub start_startouttext {
503: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
504: my @result=(''.'');
505: if ($target eq 'edit' || $target eq 'modified' ) { @result=('','no'); }
506: return (@result);
507: }
508: sub end_startouttext {
509: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
510: my $result='';
511: my $text='';
512:
513: if ($target eq 'edit') {
514: $text=&Apache::lonxml::get_all_text("endouttext",$$parser[$#$parser]);
515: $result.=&Apache::edit::start_table($token)."<tr><td>Text Block</td>
516: <td>Delete:".
517: &Apache::edit::deletelist($target,$token)
518: ."</td>
519: <td>".
520: &Apache::edit::insertlist($target,$token).
521: "</td>
522: </tr><tr><td colspan=\"3\">\n".
523: &Apache::edit::editfield($token->[1],$text,"",50,4);
524: }
525: if ($target eq 'modified') {
526: $text=&Apache::lonxml::get_all_text("endouttext",$$parser['-1']);
527: $result='<startouttext />'.&Apache::edit::modifiedfield();
528: }
529: return $result;
530: }
531: sub start_endouttext {
532: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
533: my $result='';
534: if ($target eq "edit" ) { $result="</td></tr>".&Apache::edit::end_table()."\n"; }
535: if ($target eq "modified") { $result='<endouttext />'; }
536: return $result;
537: }
538: sub end_endouttext {
539: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
540: my @result=('','');
541: if ($target eq "edit" || $target eq 'modified') { @result=('','no'); }
542: return (@result);
543: }
544: sub delete_startouttext {
545: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
546: # my $text=&Apache::lonxml::get_all_text("endouttext",$$parser['-1']);
547: my $text=$$parser['-1']->get_text("/endouttext");
548: my $token=$$parser['-1']->get_token();
549: &Apache::lonxml::debug("Deleting :$text: and :$token->[0]:$token->[1]:$token->[2]: for startouttext");
550: &Apache::lonxml::end_tag($tagstack,$parstack,$token);
551: # Deleting 2 parallel tag pairs, but we need the numbers later to look like
552: # they did the last time round
553: &Apache::lonxml::increasedepth($token);
554: &Apache::lonxml::decreasedepth($token);
555: return 1;
556: }
557:
558: 1;
559: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>