1: # The LON-CAPA homework handler
2: #
3: # Handles homework.
4: #
5: # YEAR=2000
6: # 7/25,8/2,8/7,8/8,8/11,9/14,9/19,10/2,10/5,10/11,11/7,11/21 Guy Albertelli
7: # 11/30 Gerd Kortemeyer
8: # 12/4,12/8,12/12,12/15,12/19,12/21 Guy Albertelli
9: # YEAR=2001
10: # 1/6,1/8,1/9,1/10,1/11,1/12,1/15,1/25,2/7,2/13,2/19,4/16,4/26 Guy Albertelli
11: # 5/4,5/13,5/21 Guy Albertelli
12: # 6/1 Gerd Kortemeyer
13: # 6/5,6/12,6/26,7/2,7/18 Guy Albertelli
14: # 8/6 Scott Harrison
15:
16: package Apache::lonhomework;
17: use strict;
18: use Apache::style;
19: use Apache::lonxml;
20: use Apache::lonnet;
21: use Apache::inputtags;
22: use Apache::structuretags;
23: use Apache::response;
24: use Apache::hint;
25: use Apache::outputtags;
26: use Apache::Constants qw(:common);
27: #use Time::HiRes qw( gettimeofday tv_interval );
28:
29: # ======================================================================= BEGIN
30: sub BEGIN {
31: &Apache::lonxml::register_insert();
32: }
33:
34: # =============================================== Get target (returns an array)
35: sub get_target {
36: if ( $ENV{'request.state'} eq "published") {
37: if ( defined $ENV{'form.submitted'}) {
38: return ('grade','web');
39: } else {
40: return ('web');
41: }
42: } elsif ($ENV{'request.state'} eq "construct") {
43: if ( defined $ENV{'form.preview'}) {
44: if ( defined $ENV{'form.submitted'}) {
45: return ('grade','web');
46: } else {
47: return ('web');
48: }
49: } else {
50: if ( $ENV{'form.problemmode'} eq 'View' ) {
51: if ( defined $ENV{'form.submitted'}) {
52: return ('grade','web');
53: } else {
54: return ('web');
55: }
56: } elsif ( $ENV{'form.problemmode'} eq 'Edit' ) {
57: if ( $ENV{'form.submitted'} eq 'edit' ) {
58: return ('modified','edit');
59: } else {
60: return ('edit');
61: }
62: } else {
63: return ('web');
64: }
65: }
66: }
67: return ();
68: }
69:
70: # ===================================== Set up variables (return scalar string)
71: sub setup_vars {
72: my ($target) = @_;
73: return ';'
74: # return ';$external::target='.$target.';';
75: }
76:
77: # ================================================================= Send header
78: sub send_header {
79: my ($request) = @_;
80: $request->print(&Apache::lontexconvert::header());
81: # $request->print('<form name='.$ENV{'form.request.prefix'}.'lonhomework method="POST" action="'.$request->uri.'">');
82: }
83:
84: # ================================================================= Create menu
85: sub createmenu {
86: my ($which,$request) = @_;
87: if ($which eq 'grade') {
88: $request->print('<script language="JavaScript">'."\n".
89: 'hwkmenu=window.open("/res/adm/pages/homeworkmenu.html'.
90: '","homeworkremote","height=350,width=150,menubar=no");'.
91: '</script>');
92: }
93: }
94:
95: # ================================================================= Send footer
96: sub send_footer {
97: my ($request) = @_;
98: # $request->print('</form>');
99: $request->print(&Apache::lontexconvert::footer());
100: }
101:
102: $Apache::lonxml::browse = '';
103:
104: # =============================================== Check date (returns an array)
105: sub check_date {
106: my ($id) = @_;
107: my $date ='';
108: my $status = '';
109: my $datemsg = '';
110: my $lastdate = '';
111: my $temp;
112: my $type;
113: my $passed;
114: &Apache::lonxml::debug("checking for part :$id:");
115: foreach $temp ("opendate","duedate","answerdate") {
116: $lastdate = $date;
117: $date = &Apache::lonnet::EXT("resource.$id.$temp");
118: &Apache::lonxml::debug("found :$date: for :$temp:");
119: if ($date eq '') {
120: $date = "an unknown date"; $passed = 0;
121: } elsif ($date eq 'con_lost') {
122: $date = "an indeterminate date"; $passed = 0;
123: } else {
124: if (time < $date) { $passed = 0; } else { $passed = 1; }
125: $date = localtime $date;
126: }
127: if (!$passed) { $type = $temp; last; }
128: }
129: &Apache::lonxml::debug("have :$type:$passed:");
130: if ($passed) {
131: $status = 'SHOW_ANSWER';
132: $datemsg = $date;
133: } elsif ($type eq 'opendate') {
134: $status = 'CLOSED';
135: $datemsg = "will open on $date";
136: } elsif ($type eq 'duedate') {
137: $status = 'CAN_ANSWER';
138: $datemsg = "is due at $date";
139: } elsif ($type eq 'answerdate') {
140: $status = 'CLOSED';
141: $datemsg = "was due on $lastdate, and answers will be available on ".
142: "$date";
143: }
144: if ($status eq 'CAN_ANSWER') {
145: #check #tries
146: my $tries = $Apache::lonhomework::history{"resource.$id.tries"};
147: my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries");
148: if ( $tries eq '' ) { $tries = '0'; }
149: if ( $maxtries eq '' ) { $maxtries = '2'; }
150: if ($tries >= $maxtries) { $status = 'CANNOT_ANSWER'; }
151: }
152: &Apache::lonxml::debug("sending back :$status:$datemsg:");
153: if (($Apache::lonhomework::browse eq 'F') && ($status eq 'CLOSED')) {
154: &Apache::lonxml::debug("should be allowed to browse a resource when ".
155: "closed");
156: $status = 'CAN_ANSWER';
157: $datemsg = 'is closed but you are allowed to view it';
158: }
159: if ($ENV{'request.state'} eq "construct") {
160: &Apache::lonxml::debug("in construction ignoring dates");
161: $status = 'CAN_ANSWER';
162: $datemsg = 'is in under construction';
163: }
164: return ($status,$datemsg);
165: }
166:
167: # ================================================================== Shows hash
168: sub showhash {
169: my (%hash) = @_;
170: my $resultkey;
171: foreach $resultkey (sort keys %hash) {
172: &Apache::lonxml::debug("$resultkey ---- $hash{$resultkey}");
173: }
174: &Apache::lonxml::debug("\n<br />restored values^</br>\n");
175: return '';
176: }
177:
178: # =========================================================== Setup permissions
179: sub setuppermissions {
180: $Apache::lonhomework::browse = &Apache::lonnet::allowed('bre',
181: $ENV{'request.filename'});
182: $Apache::lonhomework::viewgrades = &Apache::lonnet::allowed('vgr',
183: $ENV{'request.course.id'});
184: return '';
185: }
186:
187: # ================================================================ Setup header
188: sub setupheader {
189: my $request = $_[0];
190: if ($ENV{'browser.mathml'}) {
191: $request->content_type('text/xml');
192: } else {
193: $request->content_type('text/html');
194: }
195: $request->send_http_header;
196: return OK if $request->header_only;
197: return '';
198: }
199:
200: # ========================================================= Handle save or undo
201: sub handle_save_or_undo {
202: my ($request,$problem,$result) = @_;
203: my $fileout = &Apache::lonnet::filelocation("",$request->uri);
204: my $filesave = $fileout.".bak";
205: if ($ENV{'form.Undo'} eq 'undo') {
206: if (copy($filesave,$fileout)) {
207: $request->print("<b>Undid changes, Copied $filesave to $fileout".
208: "<br /></b>");
209: } else {
210: $request->print("<font color=\"red\" size=\"+1\"><b>Unable to ".
211: "undo, unable to copy $filesave to $fileout<br ".
212: "/></b></font>");
213: }
214: } else {
215: my $fs=Apache::File->new(">$filesave");
216: if (defined($fs)) {
217: print $fs $$problem;
218: $request->print("<b>Making Backup to $filesave</b><br />");
219: } else {
220: $request->print("<font color=\"red\" size=\"+1\"><b>Unable to ".
221: "make backup $filesave</b></font>");
222: }
223: my $fh=Apache::File->new(">$fileout");
224: if (defined($fh)) {
225: print $fh $$result;
226: $request->print("<b>Saving Modifications to $fileout</b><br />");
227: } else {
228: $request->print("<font color=\"red\" size=\"+1\"><b>Unable to ".
229: "write to $fileout</b></font>");
230: }
231: }
232: }
233:
234: # ================================================================= Render page
235: sub renderpage {
236: my ($request,$file) = @_;
237:
238: my (@targets) = &get_target();
239: foreach my $target (@targets) {
240: #my $t0 = [&gettimeofday()];
241: my $problem=&Apache::lonnet::getfile($file);
242: if ($problem == -1) {
243: &Apache::lonxml::error("<b> Unable to find <i>$file</i></b>");
244: $problem='';
245: }
246:
247: my %mystyle;
248: my $result = '';
249: &Apache::inputtags::initialize_inputtags;
250: &Apache::edit::initialize_edit;
251: %Apache::lonhomework::results=();
252: %Apache::lonhomework::history=&Apache::lonnet::restore();
253: #ignore error conditions
254: my ($temp)=keys %Apache::lonhomework::history ;
255: if ($temp =~ m/^error:.*/) { %Apache::lonhomework::history=(); }
256: if ($target eq 'web') {
257: if (&Apache::lonnet::symbread() eq '') {
258: if ($ENV{'request.state'} eq "construct") {
259: $request->print("In construction space, submissions ".
260: "ignored<br />");
261: } else {
262: $request->print("Browsing or <a href=\"/adm/ambiguous\">".
263: "ambiguous</a> reference, submissions ".
264: "ignored<br />");
265: }
266: }
267: #if ($Apache::lonhomework::viewgrades eq 'F') {&createmenu('grade',$request); }
268: }
269: if ($target eq 'grade') { &showhash(%Apache::lonhomework::history); }
270:
271: my $default=&Apache::lonnet::getfile('/home/httpd/html/res/adm/'.
272: 'includes/default_homework.lcpm');
273: if ($default == -1) {
274: &Apache::lonxml::error("<b>Unable to find <i>default_homework.".
275: "lcpm</i></b>");
276: $default='';
277: }
278: $result = &Apache::lonxml::xmlparse($target, $problem,
279: $default.&setup_vars($target),
280: %mystyle);
281: #$request->print("Result follows:");
282: if ($target eq 'modified') {
283: &handle_save_or_undo($request,\$problem,\$result);
284: } else {
285: #my $td=&tv_interval($t0);
286: #if ( $Apache::lonxml::debug) {
287: #$result =~ s:</body>::;
288: #$result.="<br />Spent $td seconds processing target $target\n</body>";
289: #}
290: $request->print($result);
291: }
292: #$request->print(":Result ends");
293: if ($target eq 'grade') { &showhash(%Apache::lonhomework::results); }
294:
295: #store new values
296: my ($temp) = keys %Apache::lonhomework::results;
297: if ( $temp ne '' ) {
298: &Apache::lonxml::debug("Store return message:".
299: &Apache::lonnet::cstore(\%Apache::lonhomework::results));
300: }
301: #my $td=&tv_interval($t0);
302: }
303: }
304:
305: # =========================================================== Get template list
306: # with no arg it returns a HTML <option> list of the template titles
307: # with one arg it returns the filename associated with the arg passed
308: sub get_template_list {
309: my ($namewanted,$extension) = @_;
310: my $result;
311: &Apache::lonxml::debug("Looking for :$extension:");
312: foreach my $file
313: (</home/httpd/html/res/adm/includes/templates/*.$extension>) {
314: my $name=&Apache::lonnet::metadata($file,'title');
315: if ($namewanted && ($name eq $namewanted)) {
316: $result=$file;
317: last;
318: } else {
319: $result.="<option>$name</option>";
320: }
321: }
322: return $result;
323: }
324:
325: # ================================================================= New problem
326: sub newproblem {
327: my ($request) = @_;
328: my $extension = $request->uri;
329: $extension =~ s:^.*\.([\w]+)$:$1:;
330: &Apache::lonxml::debug("Looking for :$extension:");
331: if ($ENV{'form.template'}) {
332: use File::Copy;
333: my $file = &get_template_list($ENV{'form.template'},$extension);
334: my $dest = &Apache::lonnet::filelocation("",$request->uri);
335: copy($file,$dest);
336: &renderpage($request,$file);
337: } else {
338: my $templatelist = &get_template_list('',$extension);
339: my $url = $request->uri;
340: my $dest = &Apache::lonnet::filelocation("",$request->uri);
341: $request->print(<<ENDNEWPROBLEM);
342: <body bgcolor="#FFFFFF">
343: The request file $url doesn\'t exist. You can create a new $extension <br />
344: <form action="$url" method="POST">
345: <input type="submit" value="New $extension"><br />
346: <select name="template">
347: $templatelist
348: </select>
349: </form>
350: </body>
351: ENDNEWPROBLEM
352: }
353:
354: return '';
355: }
356:
357: sub view_or_edit_menu {
358: my ($request) = @_;
359: my $url = $request->uri;
360: $request->print(<<EDITMENU);
361: <body bgcolor="#FFFFFF">
362: <form action="$url" method="POST">
363: Would you like to <input type="submit" name="problemmode" value="View"> or
364: <input type="submit" name="problemmode" value="Edit"> the problem.
365: </form>
366: </body>
367: EDITMENU
368: }
369:
370: # ===================================================================== Handler
371: sub handler {
372: #my $t0 = [&gettimeofday()];
373: my $request = $_[0];
374:
375: if ( $ENV{'user.name'} eq 'albertel' ) {$Apache::lonxml::debug = 1;}
376:
377: if (&setupheader($request)) { return OK; }
378: $ENV{'request.uri'} = $request->uri;
379:
380: #setup permissions
381: $Apache::lonhomework::browse = &Apache::lonnet::allowed('bre',
382: $ENV{'request.filename'});
383: $Apache::lonhomework::viewgrades = &Apache::lonnet::allowed('vgr',
384: $ENV{'request.course.id'});
385: &Apache::lonxml::debug("Permissions:".
386: $Apache::lonhomework::browse.":".
387: $Apache::lonhomework::viewgrades.":");
388:
389: my $file = &Apache::lonnet::filelocation("",$request->uri);
390:
391: #check if we know where we are
392: if ($ENV{'request.course.fn'} && !&Apache::lonnet::symbread()) {
393: # if we are browsing we might not be able to know where we are
394: if ($Apache::lonhomework::browse ne 'F') {
395: #should know where we are, so ask
396: $request->internal_redirect('/adm/ambiguous'); return;
397: }
398: }
399:
400: if ($ENV{'request.state'} eq "construct") {
401: if ( -e $file ) {
402: if (!(defined $ENV{'form.problemmode'})) {
403: #first visit to problem in construction space
404: &view_or_edit_menu($request);
405: #&renderpage($request,$file);
406: } else {
407: &renderpage($request,$file);
408: }
409: } else {
410: # requested file doesn't exist in contruction space
411: &newproblem($request);
412: }
413: } else {
414: # just render the page normally outside of construction space
415: &renderpage($request,$file);
416: }
417: #my $td=&tv_interval($t0);
418: #&Apache::lonxml::debug("Spent $td seconds processing");
419: # &Apache::lonhomework::send_footer($request);
420: # always turn off debug messages
421: $Apache::lonxml::debug=0;
422: return OK;
423: }
424:
425: 1;
426:
427: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>